authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-01-08 03:59:37-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-01-08 03:59:37-07:00
log0c84ecd19d0dbe6a98dd5e3f440cc9d7a78ea7d9
treec05148fa68edb77dbdedb501d590e469e41f8567
parente1f498212c74c48d740b959484123478dec748ff

codegen: fix else if expression and maybe unwrap expr


5 files changed, 92 insertions(+), 33 deletions(-)

example/guess_number/main.zig+14-13
...@@ -30,23 +30,24 @@ pub fn main(argc: isize, argv: &&u8, env: &&u8) -> i32 {...@@ -30,23 +30,24 @@ pub fn main(argc: isize, argv: &&u8, env: &&u8) -> i32 {
30 while (true) {30 while (true) {
31 print_str("\nGuess a number between 1 and 100: ");31 print_str("\nGuess a number between 1 and 100: ");
32 var line_buf : [20]u8;32 var line_buf : [20]u8;
33 const line = readline(line_buf) ?? {33 var line_len : usize;
34 // TODO fix this awkward error handling
35 if (readline(line_buf, &line_len) || line_len == line_buf.len) {
34 // TODO full error message36 // TODO full error message
35 fprint_str(stderr_fileno, "unable to read input\n");37 fprint_str(stderr_fileno, "unable to read input\n");
36 return 1;38 return 1;
37 };39 }
3840
39 if (const guess ?= parse_u64(line)) {41 var guess : u64;
40 if (guess > answer) {42 if (parse_u64(line_buf, 10, &guess)) {
41 print_str("Guess lower.\n");
42 } else if (guess < answer) {
43 print_str("Guess higher.\n");
44 } else {
45 print_str("You win!\n");
46 return 0;
47 }
48 } else {
49 print_str("Invalid number format.\n");43 print_str("Invalid number format.\n");
44 } else if (guess > answer) {
45 print_str("Guess lower.\n");
46 } else if (guess < answer) {
47 print_str("Guess higher.\n");
48 } else {
49 print_str("You win!\n");
50 return 0;
50 }51 }
51 }52 }
52}53}
src/analyze.hpp-1
...@@ -209,7 +209,6 @@ struct CodeGen {...@@ -209,7 +209,6 @@ struct CodeGen {
209209
210 OutType out_type;210 OutType out_type;
211 FnTableEntry *cur_fn;211 FnTableEntry *cur_fn;
212 LLVMBasicBlockRef cur_basic_block;
213 BlockContext *cur_block_context;212 BlockContext *cur_block_context;
214 ZigList<LLVMBasicBlockRef> break_block_stack;213 ZigList<LLVMBasicBlockRef> break_block_stack;
215 ZigList<LLVMBasicBlockRef> continue_block_stack;214 ZigList<LLVMBasicBlockRef> continue_block_stack;
src/codegen.cpp+6-2
...@@ -905,6 +905,7 @@ static LLVMValueRef gen_unwrap_maybe_expr(CodeGen *g, AstNode *node) {...@@ -905,6 +905,7 @@ static LLVMValueRef gen_unwrap_maybe_expr(CodeGen *g, AstNode *node) {
905 add_debug_source_node(g, node);905 add_debug_source_node(g, node);
906 LLVMBuildBr(g->builder, end_block);906 LLVMBuildBr(g->builder, end_block);
907 }907 }
908 LLVMBasicBlockRef post_non_null_result_block = LLVMGetInsertBlock(g->builder);
908909
909 LLVMPositionBuilderAtEnd(g->builder, null_block);910 LLVMPositionBuilderAtEnd(g->builder, null_block);
910 LLVMValueRef null_result = gen_expr(g, op2_node);911 LLVMValueRef null_result = gen_expr(g, op2_node);
...@@ -912,6 +913,7 @@ static LLVMValueRef gen_unwrap_maybe_expr(CodeGen *g, AstNode *node) {...@@ -912,6 +913,7 @@ static LLVMValueRef gen_unwrap_maybe_expr(CodeGen *g, AstNode *node) {
912 add_debug_source_node(g, node);913 add_debug_source_node(g, node);
913 LLVMBuildBr(g->builder, end_block);914 LLVMBuildBr(g->builder, end_block);
914 }915 }
916 LLVMBasicBlockRef post_null_result_block = LLVMGetInsertBlock(g->builder);
915917
916 if (end_reachable) {918 if (end_reachable) {
917 LLVMPositionBuilderAtEnd(g->builder, end_block);919 LLVMPositionBuilderAtEnd(g->builder, end_block);
...@@ -919,7 +921,7 @@ static LLVMValueRef gen_unwrap_maybe_expr(CodeGen *g, AstNode *node) {...@@ -919,7 +921,7 @@ static LLVMValueRef gen_unwrap_maybe_expr(CodeGen *g, AstNode *node) {
919 add_debug_source_node(g, node);921 add_debug_source_node(g, node);
920 LLVMValueRef phi = LLVMBuildPhi(g->builder, LLVMTypeOf(non_null_result), "");922 LLVMValueRef phi = LLVMBuildPhi(g->builder, LLVMTypeOf(non_null_result), "");
921 LLVMValueRef incoming_values[2] = {non_null_result, null_result};923 LLVMValueRef incoming_values[2] = {non_null_result, null_result};
922 LLVMBasicBlockRef incoming_blocks[2] = {non_null_block, null_block};924 LLVMBasicBlockRef incoming_blocks[2] = {post_non_null_result_block, post_null_result_block};
923 LLVMAddIncoming(phi, incoming_values, incoming_blocks, 2);925 LLVMAddIncoming(phi, incoming_values, incoming_blocks, 2);
924 return phi;926 return phi;
925 } else {927 } else {
...@@ -1015,19 +1017,21 @@ static LLVMValueRef gen_if_bool_expr_raw(CodeGen *g, AstNode *source_node, LLVMV...@@ -1015,19 +1017,21 @@ static LLVMValueRef gen_if_bool_expr_raw(CodeGen *g, AstNode *source_node, LLVMV
1015 if (then_endif_reachable) {1017 if (then_endif_reachable) {
1016 LLVMBuildBr(g->builder, endif_block);1018 LLVMBuildBr(g->builder, endif_block);
1017 }1019 }
1020 LLVMBasicBlockRef after_then_block = LLVMGetInsertBlock(g->builder);
10181021
1019 LLVMPositionBuilderAtEnd(g->builder, else_block);1022 LLVMPositionBuilderAtEnd(g->builder, else_block);
1020 LLVMValueRef else_expr_result = gen_expr(g, else_node);1023 LLVMValueRef else_expr_result = gen_expr(g, else_node);
1021 if (else_endif_reachable) {1024 if (else_endif_reachable) {
1022 LLVMBuildBr(g->builder, endif_block);1025 LLVMBuildBr(g->builder, endif_block);
1023 }1026 }
1027 LLVMBasicBlockRef after_else_block = LLVMGetInsertBlock(g->builder);
10241028
1025 if (then_endif_reachable || else_endif_reachable) {1029 if (then_endif_reachable || else_endif_reachable) {
1026 LLVMPositionBuilderAtEnd(g->builder, endif_block);1030 LLVMPositionBuilderAtEnd(g->builder, endif_block);
1027 if (use_expr_value) {1031 if (use_expr_value) {
1028 LLVMValueRef phi = LLVMBuildPhi(g->builder, LLVMTypeOf(then_expr_result), "");1032 LLVMValueRef phi = LLVMBuildPhi(g->builder, LLVMTypeOf(then_expr_result), "");
1029 LLVMValueRef incoming_values[2] = {then_expr_result, else_expr_result};1033 LLVMValueRef incoming_values[2] = {then_expr_result, else_expr_result};
1030 LLVMBasicBlockRef incoming_blocks[2] = {then_block, else_block};1034 LLVMBasicBlockRef incoming_blocks[2] = {after_then_block, after_else_block};
1031 LLVMAddIncoming(phi, incoming_values, incoming_blocks, 2);1035 LLVMAddIncoming(phi, incoming_values, incoming_blocks, 2);
10321036
1033 return phi;1037 return phi;
std/std.zig+52-17
...@@ -39,28 +39,63 @@ pub fn print_i64(x: i64) -> isize {...@@ -39,28 +39,63 @@ pub fn print_i64(x: i64) -> isize {
39 return write(stdout_fileno, buf.ptr, len);39 return write(stdout_fileno, buf.ptr, len);
40}40}
4141
42/*
43// TODO error handling42// TODO error handling
44pub fn readline(buf: []u8) -> ?[]u8 {43pub fn readline(buf: []u8, out_len: &usize) -> bool {
45 var index : usize = 0;44 // TODO unknown size array indexing operator
46 while (index < buf.len) {45 const amt_read = read(stdin_fileno, buf.ptr, buf.len);
47 // TODO unknown size array indexing operator46 if (amt_read < 0) {
48 const err = read(stdin_fileno, &buf.ptr[index], 1);47 return true;
49 if (err != 0) {48 }
50 return null;49 *out_len = amt_read as usize;
50 return false;
51}
52
53// TODO return ?u64 when we support returning struct byval
54pub fn parse_u64(buf: []u8, radix: u8, result: &u64) -> bool {
55 var x : u64 = 0;
56
57 var i : #typeof(buf.len) = 0;
58 while (i < buf.len) {
59 // TODO array indexing operator
60 const c = buf.ptr[i];
61 const digit = char_to_digit(c);
62
63 if (digit > radix) {
64 return true;
65 }
66
67 x *= radix;
68 x += digit;
69
70 /* TODO intrinsics mul and add with overflow
71 // x *= radix
72 if (@mul_with_overflow_u64(x, radix, &x)) {
73 return true;
51 }74 }
52 // TODO unknown size array indexing operator75
53 if (buf.ptr[index] == '\n') {76 // x += digit
54 return buf[0...index + 1];77 if (@add_with_overflow_u64(x, digit, &x)) {
78 return true;
55 }79 }
56 index += 1;80 */
81
82 i += 1;
57 }83 }
58 return null;84
85 *result = x;
86 return false;
59}87}
60*/
6188
62fn digit_to_char(digit: u64) -> u8 {89fn char_to_digit(c: u8) -> u8 {
63 '0' + (digit as u8)90 if ('0' <= c && c <= '9') {
91 c - '0'
92 } else if ('A' <= c && c <= 'Z') {
93 c - 'A' + 10
94 } else if ('a' <= c && c <= 'z') {
95 c - 'a' + 10
96 } else {
97 #max_value(u8)
98 }
64}99}
65100
66const max_u64_base10_digits: usize = 20;101const max_u64_base10_digits: usize = 20;
...@@ -86,7 +121,7 @@ fn buf_print_u64(out_buf: &u8, x: u64) -> usize {...@@ -86,7 +121,7 @@ fn buf_print_u64(out_buf: &u8, x: u64) -> usize {
86 while (true) {121 while (true) {
87 const digit = a % 10;122 const digit = a % 10;
88 index -= 1;123 index -= 1;
89 buf[index] = digit_to_char(digit);124 buf[index] = '0' + (digit as u8);
90 a /= 10;125 a /= 10;
91 if (a == 0)126 if (a == 0)
92 break;127 break;
test/run_tests.cpp+20
...@@ -936,7 +936,27 @@ pub fn main(argc: isize, argv: &&u8, env: &&u8) -> i32 {...@@ -936,7 +936,27 @@ pub fn main(argc: isize, argv: &&u8, env: &&u8) -> i32 {
936}936}
937 )SOURCE", "OK\n");937 )SOURCE", "OK\n");
938938
939
940 add_simple_case("else if expression", R"SOURCE(
941use "std.zig";
942pub fn main(argc: isize, argv: &&u8, env: &&u8) -> i32 {
943 if (f(1) == 1) {
944 print_str("OK\n");
945 }
946 return 0;
939}947}
948fn f(c: u8) -> u8 {
949 if (c == 0) {
950 0
951 } else if (c == 1) {
952 1
953 } else {
954 2
955 }
956}
957 )SOURCE", "OK\n");
958}
959
940960
941////////////////////////////////////////////////////////////////////////////////////961////////////////////////////////////////////////////////////////////////////////////
942962