| author | |
| committer | |
| log | 706f72f1b47ace8c6c9eecde2682ac46389af1ca |
| tree | 18700cad180b70e3a01406e0ffdaf6ed1e2aca69 |
| parent | c0ea9290c4576f2111c8fc6b2d448f278effd80e |
also fixes duplicate error message for function missing
return type.
also makes guess number game use %void for main return type.
closes #583 files changed, 32 insertions(+), 18 deletions(-)
example/guess_number/main.zig+7-4| ... | @@ -3,7 +3,10 @@ export executable "guess_number"; | ... | @@ -3,7 +3,10 @@ export executable "guess_number"; |
| 3 | import "std.zig"; | 3 | import "std.zig"; |
| 4 | import "rand.zig"; | 4 | import "rand.zig"; |
| 5 | 5 | ||
| 6 | pub fn main(args: [][]u8) i32 => { | 6 | %.GetRandomFail; |
| 7 | %.ReadInputFail; | ||
| 8 | |||
| 9 | pub fn main(args: [][]u8) %void => { | ||
| 7 | print_str("Welcome to the Guess Number Game in Zig.\n"); | 10 | print_str("Welcome to the Guess Number Game in Zig.\n"); |
| 8 | 11 | ||
| 9 | var seed : u32; | 12 | var seed : u32; |
| ... | @@ -12,7 +15,7 @@ pub fn main(args: [][]u8) i32 => { | ... | @@ -12,7 +15,7 @@ pub fn main(args: [][]u8) i32 => { |
| 12 | if (err != @sizeof(u32)) { | 15 | if (err != @sizeof(u32)) { |
| 13 | // TODO full error message | 16 | // TODO full error message |
| 14 | fprint_str(stderr_fileno, "unable to get random bytes\n"); | 17 | fprint_str(stderr_fileno, "unable to get random bytes\n"); |
| 15 | return 1; | 18 | return %.GetRandomFail; |
| 16 | } | 19 | } |
| 17 | 20 | ||
| 18 | var rand : Rand; | 21 | var rand : Rand; |
| ... | @@ -28,7 +31,7 @@ pub fn main(args: [][]u8) i32 => { | ... | @@ -28,7 +31,7 @@ pub fn main(args: [][]u8) i32 => { |
| 28 | if (readline(line_buf, &line_len) || line_len == line_buf.len) { | 31 | if (readline(line_buf, &line_len) || line_len == line_buf.len) { |
| 29 | // TODO full error message | 32 | // TODO full error message |
| 30 | fprint_str(stderr_fileno, "unable to read input\n"); | 33 | fprint_str(stderr_fileno, "unable to read input\n"); |
| 31 | return 1; | 34 | return %.ReadInputFail; |
| 32 | } | 35 | } |
| 33 | 36 | ||
| 34 | var guess : u64; | 37 | var guess : u64; |
| ... | @@ -40,7 +43,7 @@ pub fn main(args: [][]u8) i32 => { | ... | @@ -40,7 +43,7 @@ pub fn main(args: [][]u8) i32 => { |
| 40 | print_str("Guess higher.\n"); | 43 | print_str("Guess higher.\n"); |
| 41 | } else { | 44 | } else { |
| 42 | print_str("You win!\n"); | 45 | print_str("You win!\n"); |
| 43 | return 0; | 46 | return; |
| 44 | } | 47 | } |
| 45 | } | 48 | } |
| 46 | } | 49 | } |
src/analyze.cpp+16-14| ... | @@ -1344,6 +1344,16 @@ static AstNode *create_ast_type_node(CodeGen *g, ImportTableEntry *import, TypeT | ... | @@ -1344,6 +1344,16 @@ static AstNode *create_ast_type_node(CodeGen *g, ImportTableEntry *import, TypeT |
| 1344 | return node; | 1344 | return node; |
| 1345 | } | 1345 | } |
| 1346 | 1346 | ||
| 1347 | static AstNode *create_ast_void_node(CodeGen *g, ImportTableEntry *import, AstNode *source_node) { | ||
| 1348 | AstNode *node = create_ast_node(g, import, NodeTypeContainerInitExpr); | ||
| 1349 | node->data.container_init_expr.kind = ContainerInitKindArray; | ||
| 1350 | node->data.container_init_expr.type = create_ast_type_node(g, import, g->builtin_types.entry_void); | ||
| 1351 | node->line = source_node->line; | ||
| 1352 | node->column = source_node->column; | ||
| 1353 | normalize_parent_ptrs(node); | ||
| 1354 | return node; | ||
| 1355 | } | ||
| 1356 | |||
| 1347 | static TypeTableEntry *create_and_analyze_cast_node(CodeGen *g, ImportTableEntry *import, | 1357 | static TypeTableEntry *create_and_analyze_cast_node(CodeGen *g, ImportTableEntry *import, |
| 1348 | BlockContext *context, TypeTableEntry *cast_to_type, AstNode *node) | 1358 | BlockContext *context, TypeTableEntry *cast_to_type, AstNode *node) |
| 1349 | { | 1359 | { |
| ... | @@ -3596,25 +3606,17 @@ static TypeTableEntry *analyze_return_expr(CodeGen *g, ImportTableEntry *import, | ... | @@ -3596,25 +3606,17 @@ static TypeTableEntry *analyze_return_expr(CodeGen *g, ImportTableEntry *import, |
| 3596 | return g->builtin_types.entry_invalid; | 3606 | return g->builtin_types.entry_invalid; |
| 3597 | } | 3607 | } |
| 3598 | 3608 | ||
| 3609 | if (!node->data.return_expr.expr) { | ||
| 3610 | node->data.return_expr.expr = create_ast_void_node(g, import, node); | ||
| 3611 | normalize_parent_ptrs(node); | ||
| 3612 | } | ||
| 3613 | |||
| 3599 | if (node->data.return_expr.kind != ReturnKindUnconditional) { | 3614 | if (node->data.return_expr.kind != ReturnKindUnconditional) { |
| 3600 | zig_panic("TODO analyze_return_expr conditional"); | 3615 | zig_panic("TODO analyze_return_expr conditional"); |
| 3601 | } | 3616 | } |
| 3602 | 3617 | ||
| 3603 | TypeTableEntry *expected_return_type = get_return_type(context); | 3618 | TypeTableEntry *expected_return_type = get_return_type(context); |
| 3604 | TypeTableEntry *actual_return_type; | 3619 | analyze_expression(g, import, context, expected_return_type, node->data.return_expr.expr); |
| 3605 | if (node->data.return_expr.expr) { | ||
| 3606 | actual_return_type = analyze_expression(g, import, context, expected_return_type, node->data.return_expr.expr); | ||
| 3607 | } else { | ||
| 3608 | actual_return_type = g->builtin_types.entry_void; | ||
| 3609 | } | ||
| 3610 | |||
| 3611 | if (actual_return_type->id == TypeTableEntryIdUnreachable) { | ||
| 3612 | // "return exit(0)" should just be "exit(0)". | ||
| 3613 | add_node_error(g, node, buf_sprintf("returning is unreachable")); | ||
| 3614 | actual_return_type = g->builtin_types.entry_invalid; | ||
| 3615 | } | ||
| 3616 | |||
| 3617 | resolve_type_compatibility(g, import, context, node, expected_return_type, actual_return_type); | ||
| 3618 | 3620 | ||
| 3619 | return g->builtin_types.entry_unreachable; | 3621 | return g->builtin_types.entry_unreachable; |
| 3620 | } | 3622 | } |
test/run_tests.cpp+9| ... | @@ -1226,6 +1226,15 @@ pub fn main(args: [][]u8) %void => { | ... | @@ -1226,6 +1226,15 @@ pub fn main(args: [][]u8) %void => { |
| 1226 | } | 1226 | } |
| 1227 | )SOURCE", "OK\n"); | 1227 | )SOURCE", "OK\n"); |
| 1228 | 1228 | ||
| 1229 | add_simple_case("return with implicit cast from while loop", R"SOURCE( | ||
| 1230 | import "std.zig"; | ||
| 1231 | pub fn main(args: [][]u8) %void => { | ||
| 1232 | while (true) { | ||
| 1233 | print_str("OK\n"); | ||
| 1234 | return; | ||
| 1235 | } | ||
| 1236 | } | ||
| 1237 | )SOURCE", "OK\n"); | ||
| 1229 | } | 1238 | } |
| 1230 | 1239 | ||
| 1231 | 1240 |