Commit 706f72f1b4

Andrew Kelley <superjoe30@gmail.com>
2016-01-23 10:45:54
fix hang when returning from while loop
also fixes duplicate error message for function missing return type. also makes guess number game use %void for main return type. closes #58
1 parent c0ea929
Changed files (3)
example
guess_number
src
test
example/guess_number/main.zig
@@ -3,7 +3,10 @@ export executable "guess_number";
 import "std.zig";
 import "rand.zig";
 
-pub fn main(args: [][]u8) i32 => {
+%.GetRandomFail;
+%.ReadInputFail;
+
+pub fn main(args: [][]u8) %void => {
     print_str("Welcome to the Guess Number Game in Zig.\n");
 
     var seed : u32;
@@ -12,7 +15,7 @@ pub fn main(args: [][]u8) i32 => {
     if (err != @sizeof(u32)) {
         // TODO full error message
         fprint_str(stderr_fileno, "unable to get random bytes\n");
-        return 1;
+        return %.GetRandomFail;
     }
 
     var rand : Rand;
@@ -28,7 +31,7 @@ pub fn main(args: [][]u8) i32 => {
         if (readline(line_buf, &line_len) || line_len == line_buf.len) {
             // TODO full error message
             fprint_str(stderr_fileno, "unable to read input\n");
-            return 1;
+            return %.ReadInputFail;
         }
 
         var guess : u64;
@@ -40,7 +43,7 @@ pub fn main(args: [][]u8) i32 => {
             print_str("Guess higher.\n");
         } else {
             print_str("You win!\n");
-            return 0;
+            return;
         }
     }
 }
src/analyze.cpp
@@ -1344,6 +1344,16 @@ static AstNode *create_ast_type_node(CodeGen *g, ImportTableEntry *import, TypeT
     return node;
 }
 
+static AstNode *create_ast_void_node(CodeGen *g, ImportTableEntry *import, AstNode *source_node) {
+    AstNode *node = create_ast_node(g, import, NodeTypeContainerInitExpr);
+    node->data.container_init_expr.kind = ContainerInitKindArray;
+    node->data.container_init_expr.type = create_ast_type_node(g, import, g->builtin_types.entry_void);
+    node->line = source_node->line;
+    node->column = source_node->column;
+    normalize_parent_ptrs(node);
+    return node;
+}
+
 static TypeTableEntry *create_and_analyze_cast_node(CodeGen *g, ImportTableEntry *import,
         BlockContext *context, TypeTableEntry *cast_to_type, AstNode *node)
 {
@@ -3596,25 +3606,17 @@ static TypeTableEntry *analyze_return_expr(CodeGen *g, ImportTableEntry *import,
         return g->builtin_types.entry_invalid;
     }
 
+    if (!node->data.return_expr.expr) {
+        node->data.return_expr.expr = create_ast_void_node(g, import, node);
+        normalize_parent_ptrs(node);
+    }
+
     if (node->data.return_expr.kind != ReturnKindUnconditional) {
         zig_panic("TODO analyze_return_expr conditional");
     }
 
     TypeTableEntry *expected_return_type = get_return_type(context);
-    TypeTableEntry *actual_return_type;
-    if (node->data.return_expr.expr) {
-        actual_return_type = analyze_expression(g, import, context, expected_return_type, node->data.return_expr.expr);
-    } else {
-        actual_return_type = g->builtin_types.entry_void;
-    }
-
-    if (actual_return_type->id == TypeTableEntryIdUnreachable) {
-        // "return exit(0)" should just be "exit(0)".
-        add_node_error(g, node, buf_sprintf("returning is unreachable"));
-        actual_return_type = g->builtin_types.entry_invalid;
-    }
-
-    resolve_type_compatibility(g, import, context, node, expected_return_type, actual_return_type);
+    analyze_expression(g, import, context, expected_return_type, node->data.return_expr.expr);
 
     return g->builtin_types.entry_unreachable;
 }
test/run_tests.cpp
@@ -1226,6 +1226,15 @@ pub fn main(args: [][]u8) %void => {
 }
     )SOURCE", "OK\n");
 
+    add_simple_case("return with implicit cast from while loop", R"SOURCE(
+import "std.zig";
+pub fn main(args: [][]u8) %void => {
+    while (true) {
+        print_str("OK\n");
+        return;
+    }
+}
+    )SOURCE", "OK\n");
 }