diff --git a/examples/input.zn b/examples/input.zn new file mode 100644 index 0000000..1bf245d --- /dev/null +++ b/examples/input.zn @@ -0,0 +1,19 @@ +foreign i32 read(i32, *u8, u64) +foreign u0 printf(*char) +foreign *u8 malloc(u64) +foreign *u8 memset(*u8, i32, u64) + +i32 main() { + buf := malloc(1024) + bytesRead := 1 + + for bytesRead > 0 { + memset(buf, 0, 1024) + bytesRead = read(0, buf, 1024) + printf(buf) + } + + printf("Exited\n") + + return 0 +} diff --git a/tests/pass/13_if_statement.zn b/tests/pass/13_if_statement.zn index 6027188..4365b47 100644 --- a/tests/pass/13_if_statement.zn +++ b/tests/pass/13_if_statement.zn @@ -1,12 +1,36 @@ foreign u0 printf(*char) i32 main(i32 argc) { + u64 val = 0 if argc == 1 { printf("No command provided\n") - } else { - printf("Command provided\n") } + if val == 0 { + } + + if val != 0 { + + } + + if val > 0 { + + } + + if val < 0 { + + } + + if val >= 0 { + + } + + if val <= 0 { + + } + + val = val + 1 + return 0 } diff --git a/zmod.c b/zmod.c index 59bea27..9c3e796 100644 --- a/zmod.c +++ b/zmod.c @@ -692,6 +692,7 @@ void undoVisit(ZState *state) { } static void printLineHighlight(ZToken *tok, const char *color) { + if (!tok || !tok->start) return; char *lineStart = tok->sourceLinePtr; while (*lineStart && *lineStart != '\n') { diff --git a/zsem.c b/zsem.c index ad1ce89..9f41750 100644 --- a/zsem.c +++ b/zsem.c @@ -824,8 +824,36 @@ static ZType *resolveBinary(ZSemantic *semantic, ZNode *curr) { ZType *left = resolveType(semantic, curr->binary.left); ZType *right = resolveType(semantic, curr->binary.right); + + /* Auto promotion rules should be handled by typesCompatible. */ + ZType *promoted = typesCompatible(semantic->state, left, right); + + if (!promoted) { + error(semantic->state, + curr->binary.op, + "Incompatible type '%s' with '%s'", + stype(left), + stype(right) + ); + } + + if (typesEqual(left, right)) { + /* Types are equal. it doesn't matter whether left or right is returned. */ + return left; + } else if (op == TOK_EQ) { + /* Assignment yields the type of the left-hand side. */ + if (!isLvalue(curr->binary.left)) { + error(semantic->state, left->tok, "is not a valid lvalue"); + } + return left; + } + + curr->binary.left = implicitCast(curr->binary.left, promoted); + curr->binary.right = implicitCast(curr->binary.right, promoted); + /* Comparison / logical operators always produce a bool. */ - if (op == TOK_EQEQ || op == TOK_NOTEQ || + if ( + op == TOK_EQEQ || op == TOK_NOTEQ || op == TOK_LT || op == TOK_GT || op == TOK_LTE || op == TOK_GTE || op == TOK_AND || op == TOK_OR || @@ -833,31 +861,9 @@ static ZType *resolveBinary(ZSemantic *semantic, ZNode *curr) { ZType *boolType = maketype(Z_TYPE_PRIMITIVE); boolType->primitive.token = maketoken(TOK_BOOL, NULL); return boolType; - } else if (op == TOK_EQ) { - /* Assignment yields the type of the left-hand side. */ - if (!isLvalue(curr->binary.left)) { - error(semantic->state, left->tok, "is not a valid lvalue"); - } - return left; - } else if (typesEqual(left, right)) { - /* Types are equal. it doesn't matter whether left or right is returned. */ - return left; - } else { - /* Auto promotion rules should be handled by typesCompatible. */ - ZType *result = typesCompatible(semantic->state, left, right); - if (!result) { - error(semantic->state, curr->binary.op, - "%s type incompatible with %s type", - stype(left), stype(right) - ); - } - - curr->binary.left = implicitCast(curr->binary.left, result); - curr->binary.right = implicitCast(curr->binary.right, result); - - return result; } - return NULL; + + return promoted; } static ZType *resolveArrayLiteral(ZSemantic *semantic, ZNode *curr) {