authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2015-12-24 15:09:35-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2015-12-24 15:09:47-07:00
log5ceaae288c4f80fe5ce1449cd9d2efe0e541d629
tree7cf0b1b188c9f9ca8df0d4f379b47a6348adf6fd
parentffc593b8082eb0fa83b1a3d1b63c840379911cd5

add break expression


7 files changed, 55 insertions(+), 2 deletions(-)

doc/langref.md+3-1
......@@ -146,7 +146,7 @@ ArrayAccessExpression : token(LBracket) Expression token(RBracket)
146146
147147PrefixOp : token(Not) | token(Dash) | token(Tilde) | (token(Ampersand) option(token(Const)))
148148
149PrimaryExpression : token(Number) | token(String) | KeywordLiteral | GroupedExpression | Goto | BlockExpression | token(Symbol) | StructValueExpression
149PrimaryExpression : token(Number) | token(String) | KeywordLiteral | GroupedExpression | Goto | Break | BlockExpression | token(Symbol) | StructValueExpression
150150
151151StructValueExpression : token(Type) token(LBrace) list(StructValueExpressionField, token(Comma)) token(RBrace)
152152
......@@ -154,6 +154,8 @@ StructValueExpressionField : token(Dot) token(Symbol) token(Eq) Expression
154154
155155Goto: token(Goto) token(Symbol)
156156
157Break: token(Break)
158
157159GroupedExpression : token(LParen) Expression token(RParen)
158160
159161KeywordLiteral : token(Unreachable) | token(Void) | token(True) | token(False)
src/analyze.cpp+13
......@@ -48,6 +48,7 @@ static AstNode *first_executing_node(AstNode *node) {
4848 case NodeTypeIfExpr:
4949 case NodeTypeLabel:
5050 case NodeTypeGoto:
51 case NodeTypeBreak:
5152 case NodeTypeAsmExpr:
5253 case NodeTypeFieldAccessExpr:
5354 case NodeTypeStructDecl:
......@@ -530,6 +531,7 @@ static void preview_function_declarations(CodeGen *g, ImportTableEntry *import,
530531 case NodeTypeWhileExpr:
531532 case NodeTypeLabel:
532533 case NodeTypeGoto:
534 case NodeTypeBreak:
533535 case NodeTypeAsmExpr:
534536 case NodeTypeFieldAccessExpr:
535537 case NodeTypeStructField:
......@@ -598,6 +600,7 @@ static void preview_types(CodeGen *g, ImportTableEntry *import, AstNode *node) {
598600 case NodeTypeWhileExpr:
599601 case NodeTypeLabel:
600602 case NodeTypeGoto:
603 case NodeTypeBreak:
601604 case NodeTypeAsmExpr:
602605 case NodeTypeFieldAccessExpr:
603606 case NodeTypeStructField:
......@@ -1360,6 +1363,12 @@ static TypeTableEntry *analyze_while_expr(CodeGen *g, ImportTableEntry *import,
13601363 return g->builtin_types.entry_void;
13611364}
13621365
1366static TypeTableEntry *analyze_break_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,
1367 TypeTableEntry *expected_type, AstNode *node)
1368{
1369 return g->builtin_types.entry_unreachable;
1370}
1371
13631372static TypeTableEntry * analyze_expression(CodeGen *g, ImportTableEntry *import, BlockContext *context,
13641373 TypeTableEntry *expected_type, AstNode *node)
13651374{
......@@ -1439,6 +1448,9 @@ static TypeTableEntry * analyze_expression(CodeGen *g, ImportTableEntry *import,
14391448 return_type = g->builtin_types.entry_unreachable;
14401449 break;
14411450 }
1451 case NodeTypeBreak:
1452 return_type = analyze_break_expr(g, import, context, expected_type, node);
1453 break;
14421454 case NodeTypeAsmExpr:
14431455 {
14441456 node->data.asm_expr.return_count = 0;
......@@ -1792,6 +1804,7 @@ static void analyze_top_level_declaration(CodeGen *g, ImportTableEntry *import,
17921804 case NodeTypeWhileExpr:
17931805 case NodeTypeLabel:
17941806 case NodeTypeGoto:
1807 case NodeTypeBreak:
17951808 case NodeTypeAsmExpr:
17961809 case NodeTypeFieldAccessExpr:
17971810 case NodeTypeStructField:
src/analyze.hpp+1
......@@ -196,6 +196,7 @@ struct CodeGen {
196196 FnTableEntry *cur_fn;
197197 LLVMBasicBlockRef cur_basic_block;
198198 BlockContext *cur_block_context;
199 LLVMBasicBlockRef cur_break_block;
199200 bool c_stdint_used;
200201 AstNode *root_export_decl;
201202 int version_major;
src/codegen.cpp+12
......@@ -1024,13 +1024,23 @@ static LLVMValueRef gen_while_expr(CodeGen *g, AstNode *node) {
10241024 LLVMBuildCondBr(g->builder, cond_val, body_block, end_block);
10251025
10261026 LLVMPositionBuilderAtEnd(g->builder, body_block);
1027 g->cur_break_block = end_block;
10271028 gen_expr(g, node->data.while_expr.body);
1029 g->cur_break_block = nullptr;
10281030 LLVMBuildBr(g->builder, cond_block);
10291031
10301032 LLVMPositionBuilderAtEnd(g->builder, end_block);
10311033 return nullptr;
10321034}
10331035
1036static LLVMValueRef gen_break(CodeGen *g, AstNode *node) {
1037 assert(node->type == NodeTypeBreak);
1038 assert(g->cur_break_block);
1039
1040 add_debug_source_node(g, node);
1041 return LLVMBuildBr(g->builder, g->cur_break_block);
1042}
1043
10341044static LLVMValueRef gen_expr_no_cast(CodeGen *g, AstNode *node) {
10351045 switch (node->type) {
10361046 case NodeTypeBinOpExpr:
......@@ -1160,6 +1170,8 @@ static LLVMValueRef gen_expr_no_cast(CodeGen *g, AstNode *node) {
11601170 case NodeTypeGoto:
11611171 add_debug_source_node(g, node);
11621172 return LLVMBuildBr(g->builder, node->codegen_node->data.label_entry->basic_block);
1173 case NodeTypeBreak:
1174 return gen_break(g, node);
11631175 case NodeTypeLabel:
11641176 {
11651177 LabelTableEntry *label_entry = node->codegen_node->data.label_entry;
src/parser.cpp+10-1
......@@ -122,6 +122,8 @@ const char *node_type_str(NodeType node_type) {
122122 return "Label";
123123 case NodeTypeGoto:
124124 return "Goto";
125 case NodeTypeBreak:
126 return "Break";
125127 case NodeTypeAsmExpr:
126128 return "AsmExpr";
127129 case NodeTypeFieldAccessExpr:
......@@ -336,6 +338,9 @@ void ast_print(AstNode *node, int indent) {
336338 case NodeTypeGoto:
337339 fprintf(stderr, "%s '%s'\n", node_type_str(node->type), buf_ptr(&node->data.go_to.name));
338340 break;
341 case NodeTypeBreak:
342 fprintf(stderr, "%s\n", node_type_str(node->type));
343 break;
339344 case NodeTypeAsmExpr:
340345 fprintf(stderr, "%s\n", node_type_str(node->type));
341346 break;
......@@ -1102,7 +1107,7 @@ static AstNode *ast_parse_struct_val_expr(ParseContext *pc, int *token_index) {
11021107}
11031108
11041109/*
1105PrimaryExpression : token(Number) | token(String) | KeywordLiteral | GroupedExpression | Goto | BlockExpression | token(Symbol) | StructValueExpression
1110PrimaryExpression : token(Number) | token(String) | KeywordLiteral | GroupedExpression | Goto | Break | BlockExpression | token(Symbol) | StructValueExpression
11061111*/
11071112static AstNode *ast_parse_primary_expr(ParseContext *pc, int *token_index, bool mandatory) {
11081113 Token *token = &pc->tokens->at(*token_index);
......@@ -1156,6 +1161,10 @@ static AstNode *ast_parse_primary_expr(ParseContext *pc, int *token_index, bool
11561161
11571162 ast_buf_from_token(pc, dest_symbol, &node->data.go_to.name);
11581163 return node;
1164 } else if (token->id == TokenIdKeywordBreak) {
1165 AstNode *node = ast_create_node(pc, NodeTypeBreak, token);
1166 *token_index += 1;
1167 return node;
11591168 }
11601169
11611170 AstNode *grouped_expr_node = ast_parse_grouped_expr(pc, token_index, false);
src/parser.hpp+1
......@@ -48,6 +48,7 @@ enum NodeType {
4848 NodeTypeWhileExpr,
4949 NodeTypeLabel,
5050 NodeTypeGoto,
51 NodeTypeBreak,
5152 NodeTypeAsmExpr,
5253 NodeTypeStructDecl,
5354 NodeTypeStructField,
test/run_tests.cpp+15
......@@ -656,6 +656,21 @@ export fn main(argc : isize, argv : &&u8, env : &&u8) -> i32 {
656656 i += 1;
657657 }
658658 return 0;
659}
660 )SOURCE", "loop\nloop\nloop\nloop\n");
661
662 add_simple_case("break out of while loop", R"SOURCE(
663use "std.zig";
664export fn main(argc : isize, argv : &&u8, env : &&u8) -> i32 {
665 var i : i32 = 0;
666 while true {
667 if i >= 4 {
668 break;
669 }
670 print_str("loop\n");
671 i += 1;
672 }
673 return 0;
659674}
660675 )SOURCE", "loop\nloop\nloop\nloop\n");
661676}