Commit 0c84ecd19d

Andrew Kelley <superjoe30@gmail.com>
2016-01-08 11:59:37
codegen: fix else if expression and maybe unwrap expr
1 parent e1f4982
Changed files (5)
example
guess_number
src
std
test
example/guess_number/main.zig
@@ -30,23 +30,24 @@ pub fn main(argc: isize, argv: &&u8, env: &&u8) -> i32 {
     while (true) {
         print_str("\nGuess a number between 1 and 100: ");
         var line_buf : [20]u8;
-        const line = readline(line_buf) ?? {
+        var line_len : usize;
+        // TODO fix this awkward error handling
+        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;
-        };
-
-        if (const guess ?= parse_u64(line)) {
-            if (guess > answer) {
-                print_str("Guess lower.\n");
-            } else if (guess < answer) {
-                print_str("Guess higher.\n");
-            } else {
-                print_str("You win!\n");
-                return 0;
-            }
-        } else {
+        }
+
+        var guess : u64;
+        if (parse_u64(line_buf, 10, &guess)) {
             print_str("Invalid number format.\n");
+        } else if (guess > answer) {
+            print_str("Guess lower.\n");
+        } else if (guess < answer) {
+            print_str("Guess higher.\n");
+        } else {
+            print_str("You win!\n");
+            return 0;
         }
     }
 }
src/analyze.hpp
@@ -209,7 +209,6 @@ struct CodeGen {
 
     OutType out_type;
     FnTableEntry *cur_fn;
-    LLVMBasicBlockRef cur_basic_block;
     BlockContext *cur_block_context;
     ZigList<LLVMBasicBlockRef> break_block_stack;
     ZigList<LLVMBasicBlockRef> continue_block_stack;
src/codegen.cpp
@@ -905,6 +905,7 @@ static LLVMValueRef gen_unwrap_maybe_expr(CodeGen *g, AstNode *node) {
         add_debug_source_node(g, node);
         LLVMBuildBr(g->builder, end_block);
     }
+    LLVMBasicBlockRef post_non_null_result_block = LLVMGetInsertBlock(g->builder);
 
     LLVMPositionBuilderAtEnd(g->builder, null_block);
     LLVMValueRef null_result = gen_expr(g, op2_node);
@@ -912,6 +913,7 @@ static LLVMValueRef gen_unwrap_maybe_expr(CodeGen *g, AstNode *node) {
         add_debug_source_node(g, node);
         LLVMBuildBr(g->builder, end_block);
     }
+    LLVMBasicBlockRef post_null_result_block = LLVMGetInsertBlock(g->builder);
 
     if (end_reachable) {
         LLVMPositionBuilderAtEnd(g->builder, end_block);
@@ -919,7 +921,7 @@ static LLVMValueRef gen_unwrap_maybe_expr(CodeGen *g, AstNode *node) {
             add_debug_source_node(g, node);
             LLVMValueRef phi = LLVMBuildPhi(g->builder, LLVMTypeOf(non_null_result), "");
             LLVMValueRef incoming_values[2] = {non_null_result, null_result};
-            LLVMBasicBlockRef incoming_blocks[2] = {non_null_block, null_block};
+            LLVMBasicBlockRef incoming_blocks[2] = {post_non_null_result_block, post_null_result_block};
             LLVMAddIncoming(phi, incoming_values, incoming_blocks, 2);
             return phi;
         } else {
@@ -1015,19 +1017,21 @@ static LLVMValueRef gen_if_bool_expr_raw(CodeGen *g, AstNode *source_node, LLVMV
         if (then_endif_reachable) {
             LLVMBuildBr(g->builder, endif_block);
         }
+        LLVMBasicBlockRef after_then_block = LLVMGetInsertBlock(g->builder);
 
         LLVMPositionBuilderAtEnd(g->builder, else_block);
         LLVMValueRef else_expr_result = gen_expr(g, else_node);
         if (else_endif_reachable) {
             LLVMBuildBr(g->builder, endif_block);
         }
+        LLVMBasicBlockRef after_else_block = LLVMGetInsertBlock(g->builder);
 
         if (then_endif_reachable || else_endif_reachable) {
             LLVMPositionBuilderAtEnd(g->builder, endif_block);
             if (use_expr_value) {
                 LLVMValueRef phi = LLVMBuildPhi(g->builder, LLVMTypeOf(then_expr_result), "");
                 LLVMValueRef incoming_values[2] = {then_expr_result, else_expr_result};
-                LLVMBasicBlockRef incoming_blocks[2] = {then_block, else_block};
+                LLVMBasicBlockRef incoming_blocks[2] = {after_then_block, after_else_block};
                 LLVMAddIncoming(phi, incoming_values, incoming_blocks, 2);
 
                 return phi;
std/std.zig
@@ -39,28 +39,63 @@ pub fn print_i64(x: i64) -> isize {
     return write(stdout_fileno, buf.ptr, len);
 }
 
-/*
 // TODO error handling
-pub fn readline(buf: []u8) -> ?[]u8 {
-    var index : usize = 0;
-    while (index < buf.len) {
-        // TODO unknown size array indexing operator
-        const err = read(stdin_fileno, &buf.ptr[index], 1);
-        if (err != 0) {
-            return null;
+pub fn readline(buf: []u8, out_len: &usize) -> bool {
+    // TODO unknown size array indexing operator
+    const amt_read = read(stdin_fileno, buf.ptr, buf.len);
+    if (amt_read < 0) {
+        return true;
+    }
+    *out_len = amt_read as usize;
+    return false;
+}
+
+// TODO return ?u64 when we support returning struct byval
+pub fn parse_u64(buf: []u8, radix: u8, result: &u64) -> bool {
+    var x : u64 = 0;
+
+    var i : #typeof(buf.len) = 0;
+    while (i < buf.len) {
+        // TODO array indexing operator
+        const c = buf.ptr[i];
+        const digit = char_to_digit(c);
+
+        if (digit > radix) {
+            return true;
+        }
+
+        x *= radix;
+        x += digit;
+
+        /* TODO intrinsics mul and add with overflow
+        // x *= radix
+        if (@mul_with_overflow_u64(x, radix, &x)) {
+            return true;
         }
-        // TODO unknown size array indexing operator
-        if (buf.ptr[index] == '\n') {
-            return buf[0...index + 1];
+
+        // x += digit
+        if (@add_with_overflow_u64(x, digit, &x)) {
+            return true;
         }
-        index += 1;
+        */
+
+        i += 1;
     }
-    return null;
+
+    *result = x;
+    return false;
 }
-*/
 
-fn digit_to_char(digit: u64) -> u8 {
-    '0' + (digit as u8)
+fn char_to_digit(c: u8) -> u8 {
+    if ('0' <= c && c <= '9') {
+        c - '0'
+    } else if ('A' <= c && c <= 'Z') {
+        c - 'A' + 10
+    } else if ('a' <= c && c <= 'z') {
+        c - 'a' + 10
+    } else {
+        #max_value(u8)
+    }
 }
 
 const max_u64_base10_digits: usize = 20;
@@ -86,7 +121,7 @@ fn buf_print_u64(out_buf: &u8, x: u64) -> usize {
     while (true) {
         const digit = a % 10;
         index -= 1;
-        buf[index] = digit_to_char(digit);
+        buf[index] = '0' + (digit as u8);
         a /= 10;
         if (a == 0)
             break;
test/run_tests.cpp
@@ -936,7 +936,27 @@ pub fn main(argc: isize, argv: &&u8, env: &&u8) -> i32 {
 }
     )SOURCE", "OK\n");
 
+
+    add_simple_case("else if expression", R"SOURCE(
+use "std.zig";
+pub fn main(argc: isize, argv: &&u8, env: &&u8) -> i32 {
+    if (f(1) == 1) {
+        print_str("OK\n");
+    }
+    return 0;
 }
+fn f(c: u8) -> u8 {
+    if (c == 0) {
+        0
+    } else if (c == 1) {
+        1
+    } else {
+        2
+    }
+}
+    )SOURCE", "OK\n");
+}
+
 
 ////////////////////////////////////////////////////////////////////////////////////