authorgravatar for thejoshwolfe@gmail.comJosh Wolfe <thejoshwolfe@gmail.com> 2015-12-12 17:33:45-07:00
committergravatar for thejoshwolfe@gmail.comJosh Wolfe <thejoshwolfe@gmail.com> 2015-12-12 17:33:45-07:00
log208258820108b1e921d456e99d48844ebbe91040
tree5d5f0da845b80920933d56396c6506c3d63017fa
parent64dd0b8d9535672484512a4a9957a63c08a32f3f

fix short circuit expressions


4 files changed, 40 insertions(+), 7 deletions(-)

doc/langref.md+1-1
...@@ -140,7 +140,7 @@ ArrayAccessExpression : token(LBracket) Expression token(RBracket)...@@ -140,7 +140,7 @@ ArrayAccessExpression : token(LBracket) Expression token(RBracket)
140140
141PrefixOp : token(Not) | token(Dash) | token(Tilde)141PrefixOp : token(Not) | token(Dash) | token(Tilde)
142142
143PrimaryExpression : token(Number) | token(String) | KeywordLiteral | GroupedExpression | token(Symbol) | Goto143PrimaryExpression : token(Number) | token(String) | KeywordLiteral | GroupedExpression | token(Symbol) | Goto | BlockExpression
144144
145Goto: token(Goto) token(Symbol)145Goto: token(Goto) token(Symbol)
146146
src/codegen.cpp+9-5
...@@ -478,8 +478,8 @@ static LLVMValueRef gen_bool_and_expr(CodeGen *g, AstNode *node) {...@@ -478,8 +478,8 @@ static LLVMValueRef gen_bool_and_expr(CodeGen *g, AstNode *node) {
478 assert(node->type == NodeTypeBinOpExpr);478 assert(node->type == NodeTypeBinOpExpr);
479479
480 LLVMValueRef val1 = gen_expr(g, node->data.bin_op_expr.op1);480 LLVMValueRef val1 = gen_expr(g, node->data.bin_op_expr.op1);
481 LLVMBasicBlockRef post_val1_block = LLVMGetInsertBlock(g->builder);
481482
482 LLVMBasicBlockRef orig_block = LLVMGetInsertBlock(g->builder);
483 // block for when val1 == true483 // block for when val1 == true
484 LLVMBasicBlockRef true_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "BoolAndTrue");484 LLVMBasicBlockRef true_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "BoolAndTrue");
485 // block for when val1 == false (don't even evaluate the second part)485 // block for when val1 == false (don't even evaluate the second part)
...@@ -490,6 +490,8 @@ static LLVMValueRef gen_bool_and_expr(CodeGen *g, AstNode *node) {...@@ -490,6 +490,8 @@ static LLVMValueRef gen_bool_and_expr(CodeGen *g, AstNode *node) {
490490
491 LLVMPositionBuilderAtEnd(g->builder, true_block);491 LLVMPositionBuilderAtEnd(g->builder, true_block);
492 LLVMValueRef val2 = gen_expr(g, node->data.bin_op_expr.op2);492 LLVMValueRef val2 = gen_expr(g, node->data.bin_op_expr.op2);
493 LLVMBasicBlockRef post_val2_block = LLVMGetInsertBlock(g->builder);
494
493 add_debug_source_node(g, node);495 add_debug_source_node(g, node);
494 LLVMBuildBr(g->builder, false_block);496 LLVMBuildBr(g->builder, false_block);
495497
...@@ -497,7 +499,7 @@ static LLVMValueRef gen_bool_and_expr(CodeGen *g, AstNode *node) {...@@ -497,7 +499,7 @@ static LLVMValueRef gen_bool_and_expr(CodeGen *g, AstNode *node) {
497 add_debug_source_node(g, node);499 add_debug_source_node(g, node);
498 LLVMValueRef phi = LLVMBuildPhi(g->builder, LLVMInt1Type(), "");500 LLVMValueRef phi = LLVMBuildPhi(g->builder, LLVMInt1Type(), "");
499 LLVMValueRef incoming_values[2] = {val1, val2};501 LLVMValueRef incoming_values[2] = {val1, val2};
500 LLVMBasicBlockRef incoming_blocks[2] = {orig_block, true_block};502 LLVMBasicBlockRef incoming_blocks[2] = {post_val1_block, post_val2_block};
501 LLVMAddIncoming(phi, incoming_values, incoming_blocks, 2);503 LLVMAddIncoming(phi, incoming_values, incoming_blocks, 2);
502504
503 return phi;505 return phi;
...@@ -507,8 +509,7 @@ static LLVMValueRef gen_bool_or_expr(CodeGen *g, AstNode *expr_node) {...@@ -507,8 +509,7 @@ static LLVMValueRef gen_bool_or_expr(CodeGen *g, AstNode *expr_node) {
507 assert(expr_node->type == NodeTypeBinOpExpr);509 assert(expr_node->type == NodeTypeBinOpExpr);
508510
509 LLVMValueRef val1 = gen_expr(g, expr_node->data.bin_op_expr.op1);511 LLVMValueRef val1 = gen_expr(g, expr_node->data.bin_op_expr.op1);
510512 LLVMBasicBlockRef post_val1_block = LLVMGetInsertBlock(g->builder);
511 LLVMBasicBlockRef orig_block = LLVMGetInsertBlock(g->builder);
512513
513 // block for when val1 == false514 // block for when val1 == false
514 LLVMBasicBlockRef false_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "BoolOrFalse");515 LLVMBasicBlockRef false_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "BoolOrFalse");
...@@ -520,6 +521,9 @@ static LLVMValueRef gen_bool_or_expr(CodeGen *g, AstNode *expr_node) {...@@ -520,6 +521,9 @@ static LLVMValueRef gen_bool_or_expr(CodeGen *g, AstNode *expr_node) {
520521
521 LLVMPositionBuilderAtEnd(g->builder, false_block);522 LLVMPositionBuilderAtEnd(g->builder, false_block);
522 LLVMValueRef val2 = gen_expr(g, expr_node->data.bin_op_expr.op2);523 LLVMValueRef val2 = gen_expr(g, expr_node->data.bin_op_expr.op2);
524
525 LLVMBasicBlockRef post_val2_block = LLVMGetInsertBlock(g->builder);
526
523 add_debug_source_node(g, expr_node);527 add_debug_source_node(g, expr_node);
524 LLVMBuildBr(g->builder, true_block);528 LLVMBuildBr(g->builder, true_block);
525529
...@@ -527,7 +531,7 @@ static LLVMValueRef gen_bool_or_expr(CodeGen *g, AstNode *expr_node) {...@@ -527,7 +531,7 @@ static LLVMValueRef gen_bool_or_expr(CodeGen *g, AstNode *expr_node) {
527 add_debug_source_node(g, expr_node);531 add_debug_source_node(g, expr_node);
528 LLVMValueRef phi = LLVMBuildPhi(g->builder, LLVMInt1Type(), "");532 LLVMValueRef phi = LLVMBuildPhi(g->builder, LLVMInt1Type(), "");
529 LLVMValueRef incoming_values[2] = {val1, val2};533 LLVMValueRef incoming_values[2] = {val1, val2};
530 LLVMBasicBlockRef incoming_blocks[2] = {orig_block, false_block};534 LLVMBasicBlockRef incoming_blocks[2] = {post_val1_block, post_val2_block};
531 LLVMAddIncoming(phi, incoming_values, incoming_blocks, 2);535 LLVMAddIncoming(phi, incoming_values, incoming_blocks, 2);
532536
533 return phi;537 return phi;
src/parser.cpp+7-1
...@@ -572,6 +572,7 @@ static void ast_invalid_token_error(ParseContext *pc, Token *token) {...@@ -572,6 +572,7 @@ static void ast_invalid_token_error(ParseContext *pc, Token *token) {
572static AstNode *ast_parse_expression(ParseContext *pc, int *token_index, bool mandatory);572static AstNode *ast_parse_expression(ParseContext *pc, int *token_index, bool mandatory);
573static AstNode *ast_parse_block(ParseContext *pc, int *token_index, bool mandatory);573static AstNode *ast_parse_block(ParseContext *pc, int *token_index, bool mandatory);
574static AstNode *ast_parse_if_expr(ParseContext *pc, int *token_index, bool mandatory);574static AstNode *ast_parse_if_expr(ParseContext *pc, int *token_index, bool mandatory);
575static AstNode *ast_parse_block_expr(ParseContext *pc, int *token_index, bool mandatory);
575576
576static void ast_expect_token(ParseContext *pc, Token *token, TokenId token_id) {577static void ast_expect_token(ParseContext *pc, Token *token, TokenId token_id) {
577 if (token->id != token_id) {578 if (token->id != token_id) {
...@@ -809,7 +810,7 @@ static AstNode *ast_parse_grouped_expr(ParseContext *pc, int *token_index, bool...@@ -809,7 +810,7 @@ static AstNode *ast_parse_grouped_expr(ParseContext *pc, int *token_index, bool
809}810}
810811
811/*812/*
812PrimaryExpression : token(Number) | token(String) | token(Unreachable) | GroupedExpression | token(Symbol) | Goto813PrimaryExpression : token(Number) | token(String) | KeywordLiteral | GroupedExpression | token(Symbol) | Goto | BlockExpression
813*/814*/
814static AstNode *ast_parse_primary_expr(ParseContext *pc, int *token_index, bool mandatory) {815static AstNode *ast_parse_primary_expr(ParseContext *pc, int *token_index, bool mandatory) {
815 Token *token = &pc->tokens->at(*token_index);816 Token *token = &pc->tokens->at(*token_index);
...@@ -864,6 +865,11 @@ static AstNode *ast_parse_primary_expr(ParseContext *pc, int *token_index, bool...@@ -864,6 +865,11 @@ static AstNode *ast_parse_primary_expr(ParseContext *pc, int *token_index, bool
864 return grouped_expr_node;865 return grouped_expr_node;
865 }866 }
866867
868 AstNode *block_expr_node = ast_parse_block_expr(pc, token_index, false);
869 if (block_expr_node) {
870 return block_expr_node;
871 }
872
867 if (!mandatory)873 if (!mandatory)
868 return nullptr;874 return nullptr;
869875
test/run_tests.cpp+23
...@@ -431,6 +431,29 @@ export fn main(argc : isize, argv : *mut *mut u8, env : *mut *mut u8) -> i32 {...@@ -431,6 +431,29 @@ export fn main(argc : isize, argv : *mut *mut u8, env : *mut *mut u8) -> i32 {
431}431}
432 )SOURCE", "OK\n");432 )SOURCE", "OK\n");
433433
434 add_simple_case("short circuit", R"SOURCE(
435use "std.zig";
436
437export fn main(argc : isize, argv : *mut *mut u8, env : *mut *mut u8) -> i32 {
438 if true || { print_str("BAD 1\n" as string); false } {
439 print_str("OK 1\n" as string);
440 }
441 if false || { print_str("OK 2\n" as string); false } {
442 print_str("BAD 2\n" as string);
443 }
444
445 if true && { print_str("OK 3\n" as string); false } {
446 print_str("BAD 3\n" as string);
447 }
448 if false && { print_str("BAD 4\n" as string); false } {
449 } else {
450 print_str("OK 4\n" as string);
451 }
452
453 return 0;
454}
455 )SOURCE", "OK 1\nOK 2\nOK 3\nOK 4\n");
456
434}457}
435458
436static void add_compile_failure_test_cases(void) {459static void add_compile_failure_test_cases(void) {