Skip to content
Merged

#23 #26

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion grammar.ebnf
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,10 @@ continue_statement = "continue" ;
expression = assignment_expression
| struct_literal
| array_literal
| tuple_literal ;
| tuple_literal
| array_initializer;

array_initializer = [ integer_constant ] arra_type ;

assignment_expression = logical_or_expression, [ "=", assignment_expression ] ;

Expand Down
35 changes: 28 additions & 7 deletions run_tests.sh
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
#!/usr/bin/env bash
# Zinc test runner
# Usage: ./run_tests.sh [--zinc <path>] [--tests <dir>]
# Usage: ./run_tests.sh [<number>] [--zinc <path>] [--tests <dir>]
#
# If <number> is given, only run tests whose filename starts with that number.
# Exit codes:
# 0 - all pass/fail tests succeeded
# 1 - one or more pass/fail tests failed
Expand All @@ -14,6 +15,13 @@ PASS_DIR="$TESTS_DIR/pass"
FAIL_DIR="$TESTS_DIR/fail"
XFAIL_DIR="$TESTS_DIR/xfail"

# Optional test number filter (first argument if it looks like a number)
TEST_FILTER=""
if [[ "${1:-}" =~ ^[0-9]+$ ]]; then
TEST_FILTER="$1"
shift
fi

GREEN='\033[0;32m'
RED='\033[0;31m'
YELLOW='\033[0;33m'
Expand Down Expand Up @@ -173,30 +181,43 @@ if [ ! -x "$ZINC" ]; then
fi

echo -e "${BOLD}Zinc test suite${NC} (zinc: $ZINC)"
[ -n "$TEST_FILTER" ] && echo -e " filter: tests starting with ${BOLD}${TEST_FILTER}${NC}"
echo ""

if [ -d "$PASS_DIR" ] && compgen -G "$PASS_DIR/*.zn" > /dev/null 2>&1; then
echo -e "${BOLD}Pass tests${NC}"
ran=0
for f in "$PASS_DIR"/*.zn; do
name=$(basename "$f")
[ -n "$TEST_FILTER" ] && [[ "$name" != ${TEST_FILTER}_* ]] && continue
[ "$ran" -eq 0 ] && echo -e "${BOLD}Pass tests${NC}"
ran=1
run_pass_test "$f"
done
echo ""
[ "$ran" -eq 1 ] && echo ""
fi

if [ -d "$FAIL_DIR" ] && compgen -G "$FAIL_DIR/*.zn" > /dev/null 2>&1; then
echo -e "${BOLD}Fail tests${NC} (compiler must reject these)"
ran=0
for f in "$FAIL_DIR"/*.zn; do
name=$(basename "$f")
[ -n "$TEST_FILTER" ] && [[ "$name" != ${TEST_FILTER}_* ]] && continue
[ "$ran" -eq 0 ] && echo -e "${BOLD}Fail tests${NC} (compiler must reject these)"
ran=1
run_fail_test "$f"
done
echo ""
[ "$ran" -eq 1 ] && echo ""
fi

if [ -d "$XFAIL_DIR" ] && compgen -G "$XFAIL_DIR/*.zn" > /dev/null 2>&1; then
echo -e "${BOLD}Expected failures${NC} (unimplemented features)"
ran=0
for f in "$XFAIL_DIR"/*.zn; do
name=$(basename "$f")
[ -n "$TEST_FILTER" ] && [[ "$name" != ${TEST_FILTER}_* ]] && continue
[ "$ran" -eq 0 ] && echo -e "${BOLD}Expected failures${NC} (unimplemented features)"
ran=1
run_xfail_test "$f"
done
echo ""
[ "$ran" -eq 1 ] && echo ""
fi

total=$((passed + failed))
Expand Down
3 changes: 3 additions & 0 deletions tests/pass/15_array_subscript.zn
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
foreign u0 printf(*char)

u32 main() {

chars := [65, 66, 67, 68] as []char

arr := ["a", "b", "c", "d"]
arr[0] = "first"
arr[3] = "last"
Expand Down
5 changes: 5 additions & 0 deletions tests/pass/21_array_initializer.ezpected
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
0
1
2
3
4
25 changes: 25 additions & 0 deletions tests/pass/21_array_initializer.zn
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
foreign u0 printf(*char)
foreign i32 putchar(i32)

i32 main() {
arr := [5]i32

arr[0] = 1

i := 0
for i < 5 {
arr[i] = i
i = i + 1
}

i = 0
for i < 5 {
putchar(48 + arr[i])
putchar(10)
i = i + 1
}

arr[5]

return 0
}
6 changes: 0 additions & 6 deletions tests/xfail/04_array_type.zn

This file was deleted.

17 changes: 14 additions & 3 deletions zgen.c
Original file line number Diff line number Diff line change
Expand Up @@ -948,6 +948,14 @@ static LLVMValueRef genMemberAccess(ZCodegen *ctx, ZNode *node) {
);
}

static LLVMValueRef genArrayInit(ZCodegen *ctx, ZNode *node) {
ZLLVMStack *stack = getStackValue(ctx, node);

if (!stack) return NULL;

return stack->stack;
}

static LLVMValueRef genExpr(ZCodegen *ctx, ZNode *node) {
switch (node->type) {
case NODE_STRUCT_LIT: return genStructLit (ctx, node);
Expand All @@ -961,6 +969,7 @@ static LLVMValueRef genExpr(ZCodegen *ctx, ZNode *node) {
case NODE_MEMBER: return genMemberAccess (ctx, node);
case NODE_BINARY: return genBinary (ctx, node);
case NODE_UNARY: return genUnary (ctx, node);
case NODE_ARRAY_INIT: return genArrayInit (ctx, node);

case NODE_SIZEOF: {
usize size = typeSize(ctx, node->sizeofExpr.type);
Expand Down Expand Up @@ -1195,7 +1204,6 @@ static void genStmt(ZCodegen *ctx, ZNode *stmt) {
/* Variable already declared at the start of the function*/
case NODE_VAR_DECL: genVarDecl (ctx, stmt); break;
case NODE_RETURN: genRet (ctx, stmt); break;
case NODE_BINARY: genExpr (ctx, stmt); break;
case NODE_CALL: genCall (ctx, stmt); break;
case NODE_IF: genIf (ctx, stmt); break;
case NODE_BLOCK: genBlock (ctx, stmt); break;
Expand All @@ -1204,11 +1212,14 @@ static void genStmt(ZCodegen *ctx, ZNode *stmt) {
case NODE_BREAK: genBreak (ctx, stmt); break;
case NODE_CONTINUE: genContinue (ctx, stmt); break;
case NODE_DEFER: genDefer (ctx, stmt); break;
default:
printf("Node '%d' does not compile yet\n", stmt->type);
default: {
LLVMValueRef compiled = genExpr(ctx, stmt);
if (compiled) return;
error(ctx->state, stmt->tok,
"Node '%d' does not compile yet",
stmt->type);
break;
}
}
}

Expand Down
3 changes: 3 additions & 0 deletions zinc.h
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,7 @@ typedef enum {
NODE_STRUCT_LIT,
NODE_TUPLE_LIT,
NODE_ARRAY_LIT,
NODE_ARRAY_INIT,
NODE_MACRO,
NODE_GOTO,
NODE_LABEL,
Expand Down Expand Up @@ -379,6 +380,8 @@ struct ZNode {

ZNode **arraylit;

ZType *arrayinit;

struct {
ZToken *ident;
ZNode **fields;
Expand Down
7 changes: 4 additions & 3 deletions zmod.c
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,10 @@ static char *nodeLabels[] = {
"VAR_DECL", "BINARY", "UNARY", "CALL", "FUNC",
"LITERAL", "IDENTIFIER", "STRUCT", "SUBSCRIPT", "MEMBER",
"MODULE", "UNION", "FIELD", "TYPEDEF", "FOREIGN",
"DEFER", "STRUCT_LIT", "TUPLE_LIT", "ARRAY_LIT", "MACRO",
"GOTO", "LABEL", "TYPE", "ENUM", "BREAK",
"CONTINUE", "ENUM_FIELD", "CAST", "SIZEOF", "STATIC_ACCESS"
"DEFER", "STRUCT_LIT", "TUPLE_LIT", "ARRAY_LIT", "ARRAY_INIT",
"MACRO", "GOTO", "LABEL", "TYPE", "ENUM",
"BREAK", "CONTINUE", "ENUM_FIELD", "CAST", "SIZEOF",
"STATIC_ACCESS"

};

Expand Down
17 changes: 17 additions & 0 deletions zparse.c
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ static ZNode *parseBinary (ZParser *);
static ZNode *parseContinue (ZParser *);
static ZNode *parseArrayLit (ZParser *);
static ZNode *parseTupleLit (ZParser *);
static ZType *parseTypeArray (ZParser *);
static ZNode *parseStructLit (ZParser *);
static ZNode *parseVarInferred (ZParser *);
static ZNode *parseVarDefTyped (ZParser *);
Expand Down Expand Up @@ -276,6 +277,18 @@ static ZNode *parseGenericBinary(ZParser *parser,
return node ? node : left;
}

static ZNode *parseArrayInit(ZParser *parser) {
ZType *arr = parseTypeArray(parser);

guard(arr);
guard(arr->array.size > 0);

ZNode *node = makenode(NODE_ARRAY_INIT);
node->arrayinit = arr;

return node;
}

static ZNode *parsePrimary(ZParser *parser) {
ZToken *start = peek(parser);
guard(start);
Expand All @@ -293,6 +306,10 @@ static ZNode *parsePrimary(ZParser *parser) {
expect(parser, TOK_RPAREN);
return node;
} else if (check(parser, TOK_LSBRACKET)) {
return parseOrGrammar(parser, (ZParseFunc[]){
parseArrayInit,
parseArrayLit
}, 2);
return parseArrayLit(parser);
} else if (check(parser, TOK_IDENT)) {
if (checkAhead(parser, TOK_DOUBLE_COLON, 1)) {
Expand Down
17 changes: 12 additions & 5 deletions zsem.c
Original file line number Diff line number Diff line change
Expand Up @@ -914,6 +914,12 @@ static ZType *resolveTupleLiteral(ZSemantic *semantic, ZNode *node) {
return result;
}

static ZType *resolveArrayInit(ZSemantic *semantic, ZNode *node) {
node->arrayinit = resolveTypeRef(semantic, node->arrayinit);
node->resolved = node->arrayinit;
return node->arrayinit;
}

/*
* Resolve the type of any expression node and cache the result in node->resolved.
* Returns the resolved ZType* or NULL on error.
Expand All @@ -925,15 +931,16 @@ ZType *resolveType(ZSemantic *semantic, ZNode *curr) {
ZType *result = NULL;

switch (curr->type) {
case NODE_CALL: result = resolveFuncCall(semantic, curr); break;
case NODE_LITERAL: result = resolveLiteralType(curr); break;
case NODE_CALL: result = resolveFuncCall (semantic, curr); break;
case NODE_LITERAL: result = resolveLiteralType (curr); break;
case NODE_MEMBER: result = resolveMemberAccess(semantic, curr); break;
case NODE_SUBSCRIPT: result = resolveArrSubscript(semantic, curr); break;
case NODE_STRUCT_LIT: result = resolveStructLit(semantic, curr); break;
case NODE_IDENTIFIER: result = resolveIdentifier(semantic, curr); break;
case NODE_STRUCT_LIT: result = resolveStructLit (semantic, curr); break;
case NODE_IDENTIFIER: result = resolveIdentifier (semantic, curr); break;
case NODE_ARRAY_LIT: result = resolveArrayLiteral(semantic, curr); break;
case NODE_TUPLE_LIT: result = resolveTupleLiteral(semantic, curr); break;
case NODE_BINARY: result = resolveBinary(semantic, curr); break;
case NODE_BINARY: result = resolveBinary (semantic, curr); break;
case NODE_ARRAY_INIT: result = resolveArrayInit (semantic, curr); break;

case NODE_UNARY: {
ZType *operand = resolveType(semantic, curr->unary.operand);
Expand Down
Loading