| author | |
| committer | |
| log | 208258820108b1e921d456e99d48844ebbe91040 |
| tree | 5d5f0da845b80920933d56396c6506c3d63017fa |
| parent | 64dd0b8d9535672484512a4a9957a63c08a32f3f |
4 files changed, 40 insertions(+), 7 deletions(-)
doc/langref.md+1-1| ... | ... | @@ -140,7 +140,7 @@ ArrayAccessExpression : token(LBracket) Expression token(RBracket) |
| 140 | 140 | |
| 141 | 141 | PrefixOp : token(Not) | token(Dash) | token(Tilde) |
| 142 | 142 | |
| 143 | PrimaryExpression : token(Number) | token(String) | KeywordLiteral | GroupedExpression | token(Symbol) | Goto | |
| 143 | PrimaryExpression : token(Number) | token(String) | KeywordLiteral | GroupedExpression | token(Symbol) | Goto | BlockExpression | |
| 144 | 144 | |
| 145 | 145 | Goto: token(Goto) token(Symbol) |
| 146 | 146 |
src/codegen.cpp+9-5| ... | ... | @@ -478,8 +478,8 @@ static LLVMValueRef gen_bool_and_expr(CodeGen *g, AstNode *node) { |
| 478 | 478 | assert(node->type == NodeTypeBinOpExpr); |
| 479 | 479 | |
| 480 | 480 | LLVMValueRef val1 = gen_expr(g, node->data.bin_op_expr.op1); |
| 481 | LLVMBasicBlockRef post_val1_block = LLVMGetInsertBlock(g->builder); | |
| 481 | 482 | |
| 482 | LLVMBasicBlockRef orig_block = LLVMGetInsertBlock(g->builder); | |
| 483 | 483 | // block for when val1 == true |
| 484 | 484 | LLVMBasicBlockRef true_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "BoolAndTrue"); |
| 485 | 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 | 490 | |
| 491 | 491 | LLVMPositionBuilderAtEnd(g->builder, true_block); |
| 492 | 492 | LLVMValueRef val2 = gen_expr(g, node->data.bin_op_expr.op2); |
| 493 | LLVMBasicBlockRef post_val2_block = LLVMGetInsertBlock(g->builder); | |
| 494 | ||
| 493 | 495 | add_debug_source_node(g, node); |
| 494 | 496 | LLVMBuildBr(g->builder, false_block); |
| 495 | 497 | |
| ... | ... | @@ -497,7 +499,7 @@ static LLVMValueRef gen_bool_and_expr(CodeGen *g, AstNode *node) { |
| 497 | 499 | add_debug_source_node(g, node); |
| 498 | 500 | LLVMValueRef phi = LLVMBuildPhi(g->builder, LLVMInt1Type(), ""); |
| 499 | 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 | 503 | LLVMAddIncoming(phi, incoming_values, incoming_blocks, 2); |
| 502 | 504 | |
| 503 | 505 | return phi; |
| ... | ... | @@ -507,8 +509,7 @@ static LLVMValueRef gen_bool_or_expr(CodeGen *g, AstNode *expr_node) { |
| 507 | 509 | assert(expr_node->type == NodeTypeBinOpExpr); |
| 508 | 510 | |
| 509 | 511 | LLVMValueRef val1 = gen_expr(g, expr_node->data.bin_op_expr.op1); |
| 510 | ||
| 511 | LLVMBasicBlockRef orig_block = LLVMGetInsertBlock(g->builder); | |
| 512 | LLVMBasicBlockRef post_val1_block = LLVMGetInsertBlock(g->builder); | |
| 512 | 513 | |
| 513 | 514 | // block for when val1 == false |
| 514 | 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 | 521 | |
| 521 | 522 | LLVMPositionBuilderAtEnd(g->builder, false_block); |
| 522 | 523 | LLVMValueRef val2 = gen_expr(g, expr_node->data.bin_op_expr.op2); |
| 524 | ||
| 525 | LLVMBasicBlockRef post_val2_block = LLVMGetInsertBlock(g->builder); | |
| 526 | ||
| 523 | 527 | add_debug_source_node(g, expr_node); |
| 524 | 528 | LLVMBuildBr(g->builder, true_block); |
| 525 | 529 | |
| ... | ... | @@ -527,7 +531,7 @@ static LLVMValueRef gen_bool_or_expr(CodeGen *g, AstNode *expr_node) { |
| 527 | 531 | add_debug_source_node(g, expr_node); |
| 528 | 532 | LLVMValueRef phi = LLVMBuildPhi(g->builder, LLVMInt1Type(), ""); |
| 529 | 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 | 535 | LLVMAddIncoming(phi, incoming_values, incoming_blocks, 2); |
| 532 | 536 | |
| 533 | 537 | return phi; |
src/parser.cpp+7-1| ... | ... | @@ -572,6 +572,7 @@ static void ast_invalid_token_error(ParseContext *pc, Token *token) { |
| 572 | 572 | static AstNode *ast_parse_expression(ParseContext *pc, int *token_index, bool mandatory); |
| 573 | 573 | static AstNode *ast_parse_block(ParseContext *pc, int *token_index, bool mandatory); |
| 574 | 574 | static AstNode *ast_parse_if_expr(ParseContext *pc, int *token_index, bool mandatory); |
| 575 | static AstNode *ast_parse_block_expr(ParseContext *pc, int *token_index, bool mandatory); | |
| 575 | 576 | |
| 576 | 577 | static void ast_expect_token(ParseContext *pc, Token *token, TokenId token_id) { |
| 577 | 578 | if (token->id != token_id) { |
| ... | ... | @@ -809,7 +810,7 @@ static AstNode *ast_parse_grouped_expr(ParseContext *pc, int *token_index, bool |
| 809 | 810 | } |
| 810 | 811 | |
| 811 | 812 | /* |
| 812 | PrimaryExpression : token(Number) | token(String) | token(Unreachable) | GroupedExpression | token(Symbol) | Goto | |
| 813 | PrimaryExpression : token(Number) | token(String) | KeywordLiteral | GroupedExpression | token(Symbol) | Goto | BlockExpression | |
| 813 | 814 | */ |
| 814 | 815 | static AstNode *ast_parse_primary_expr(ParseContext *pc, int *token_index, bool mandatory) { |
| 815 | 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 | 865 | return grouped_expr_node; |
| 865 | 866 | } |
| 866 | 867 | |
| 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 | 873 | if (!mandatory) |
| 868 | 874 | return nullptr; |
| 869 | 875 |
test/run_tests.cpp+23| ... | ... | @@ -431,6 +431,29 @@ export fn main(argc : isize, argv : *mut *mut u8, env : *mut *mut u8) -> i32 { |
| 431 | 431 | } |
| 432 | 432 | )SOURCE", "OK\n"); |
| 433 | 433 | |
| 434 | add_simple_case("short circuit", R"SOURCE( | |
| 435 | use "std.zig"; | |
| 436 | ||
| 437 | export 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 | } |
| 435 | 458 | |
| 436 | 459 | static void add_compile_failure_test_cases(void) { |