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)...@@ -146,7 +146,7 @@ ArrayAccessExpression : token(LBracket) Expression token(RBracket)
146146
147PrefixOp : token(Not) | token(Dash) | token(Tilde) | (token(Ampersand) option(token(Const)))147PrefixOp : token(Not) | token(Dash) | token(Tilde) | (token(Ampersand) option(token(Const)))
148148
149PrimaryExpression : token(Number) | token(String) | KeywordLiteral | GroupedExpression | Goto | BlockExpression | token(Symbol) | StructValueExpression149PrimaryExpression : token(Number) | token(String) | KeywordLiteral | GroupedExpression | Goto | Break | BlockExpression | token(Symbol) | StructValueExpression
150150
151StructValueExpression : token(Type) token(LBrace) list(StructValueExpressionField, token(Comma)) token(RBrace)151StructValueExpression : token(Type) token(LBrace) list(StructValueExpressionField, token(Comma)) token(RBrace)
152152
...@@ -154,6 +154,8 @@ StructValueExpressionField : token(Dot) token(Symbol) token(Eq) Expression...@@ -154,6 +154,8 @@ StructValueExpressionField : token(Dot) token(Symbol) token(Eq) Expression
154154
155Goto: token(Goto) token(Symbol)155Goto: token(Goto) token(Symbol)
156156
157Break: token(Break)
158
157GroupedExpression : token(LParen) Expression token(RParen)159GroupedExpression : token(LParen) Expression token(RParen)
158160
159KeywordLiteral : token(Unreachable) | token(Void) | token(True) | token(False)161KeywordLiteral : token(Unreachable) | token(Void) | token(True) | token(False)
src/analyze.cpp+13
...@@ -48,6 +48,7 @@ static AstNode *first_executing_node(AstNode *node) {...@@ -48,6 +48,7 @@ static AstNode *first_executing_node(AstNode *node) {
48 case NodeTypeIfExpr:48 case NodeTypeIfExpr:
49 case NodeTypeLabel:49 case NodeTypeLabel:
50 case NodeTypeGoto:50 case NodeTypeGoto:
51 case NodeTypeBreak:
51 case NodeTypeAsmExpr:52 case NodeTypeAsmExpr:
52 case NodeTypeFieldAccessExpr:53 case NodeTypeFieldAccessExpr:
53 case NodeTypeStructDecl:54 case NodeTypeStructDecl:
...@@ -530,6 +531,7 @@ static void preview_function_declarations(CodeGen *g, ImportTableEntry *import,...@@ -530,6 +531,7 @@ static void preview_function_declarations(CodeGen *g, ImportTableEntry *import,
530 case NodeTypeWhileExpr:531 case NodeTypeWhileExpr:
531 case NodeTypeLabel:532 case NodeTypeLabel:
532 case NodeTypeGoto:533 case NodeTypeGoto:
534 case NodeTypeBreak:
533 case NodeTypeAsmExpr:535 case NodeTypeAsmExpr:
534 case NodeTypeFieldAccessExpr:536 case NodeTypeFieldAccessExpr:
535 case NodeTypeStructField:537 case NodeTypeStructField:
...@@ -598,6 +600,7 @@ static void preview_types(CodeGen *g, ImportTableEntry *import, AstNode *node) {...@@ -598,6 +600,7 @@ static void preview_types(CodeGen *g, ImportTableEntry *import, AstNode *node) {
598 case NodeTypeWhileExpr:600 case NodeTypeWhileExpr:
599 case NodeTypeLabel:601 case NodeTypeLabel:
600 case NodeTypeGoto:602 case NodeTypeGoto:
603 case NodeTypeBreak:
601 case NodeTypeAsmExpr:604 case NodeTypeAsmExpr:
602 case NodeTypeFieldAccessExpr:605 case NodeTypeFieldAccessExpr:
603 case NodeTypeStructField:606 case NodeTypeStructField:
...@@ -1360,6 +1363,12 @@ static TypeTableEntry *analyze_while_expr(CodeGen *g, ImportTableEntry *import,...@@ -1360,6 +1363,12 @@ static TypeTableEntry *analyze_while_expr(CodeGen *g, ImportTableEntry *import,
1360 return g->builtin_types.entry_void;1363 return g->builtin_types.entry_void;
1361}1364}
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
1363static TypeTableEntry * analyze_expression(CodeGen *g, ImportTableEntry *import, BlockContext *context,1372static TypeTableEntry * analyze_expression(CodeGen *g, ImportTableEntry *import, BlockContext *context,
1364 TypeTableEntry *expected_type, AstNode *node)1373 TypeTableEntry *expected_type, AstNode *node)
1365{1374{
...@@ -1439,6 +1448,9 @@ static TypeTableEntry * analyze_expression(CodeGen *g, ImportTableEntry *import,...@@ -1439,6 +1448,9 @@ static TypeTableEntry * analyze_expression(CodeGen *g, ImportTableEntry *import,
1439 return_type = g->builtin_types.entry_unreachable;1448 return_type = g->builtin_types.entry_unreachable;
1440 break;1449 break;
1441 }1450 }
1451 case NodeTypeBreak:
1452 return_type = analyze_break_expr(g, import, context, expected_type, node);
1453 break;
1442 case NodeTypeAsmExpr:1454 case NodeTypeAsmExpr:
1443 {1455 {
1444 node->data.asm_expr.return_count = 0;1456 node->data.asm_expr.return_count = 0;
...@@ -1792,6 +1804,7 @@ static void analyze_top_level_declaration(CodeGen *g, ImportTableEntry *import,...@@ -1792,6 +1804,7 @@ static void analyze_top_level_declaration(CodeGen *g, ImportTableEntry *import,
1792 case NodeTypeWhileExpr:1804 case NodeTypeWhileExpr:
1793 case NodeTypeLabel:1805 case NodeTypeLabel:
1794 case NodeTypeGoto:1806 case NodeTypeGoto:
1807 case NodeTypeBreak:
1795 case NodeTypeAsmExpr:1808 case NodeTypeAsmExpr:
1796 case NodeTypeFieldAccessExpr:1809 case NodeTypeFieldAccessExpr:
1797 case NodeTypeStructField:1810 case NodeTypeStructField:
src/analyze.hpp+1
...@@ -196,6 +196,7 @@ struct CodeGen {...@@ -196,6 +196,7 @@ struct CodeGen {
196 FnTableEntry *cur_fn;196 FnTableEntry *cur_fn;
197 LLVMBasicBlockRef cur_basic_block;197 LLVMBasicBlockRef cur_basic_block;
198 BlockContext *cur_block_context;198 BlockContext *cur_block_context;
199 LLVMBasicBlockRef cur_break_block;
199 bool c_stdint_used;200 bool c_stdint_used;
200 AstNode *root_export_decl;201 AstNode *root_export_decl;
201 int version_major;202 int version_major;
src/codegen.cpp+12
...@@ -1024,13 +1024,23 @@ static LLVMValueRef gen_while_expr(CodeGen *g, AstNode *node) {...@@ -1024,13 +1024,23 @@ static LLVMValueRef gen_while_expr(CodeGen *g, AstNode *node) {
1024 LLVMBuildCondBr(g->builder, cond_val, body_block, end_block);1024 LLVMBuildCondBr(g->builder, cond_val, body_block, end_block);
10251025
1026 LLVMPositionBuilderAtEnd(g->builder, body_block);1026 LLVMPositionBuilderAtEnd(g->builder, body_block);
1027 g->cur_break_block = end_block;
1027 gen_expr(g, node->data.while_expr.body);1028 gen_expr(g, node->data.while_expr.body);
1029 g->cur_break_block = nullptr;
1028 LLVMBuildBr(g->builder, cond_block);1030 LLVMBuildBr(g->builder, cond_block);
10291031
1030 LLVMPositionBuilderAtEnd(g->builder, end_block);1032 LLVMPositionBuilderAtEnd(g->builder, end_block);
1031 return nullptr;1033 return nullptr;
1032}1034}
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
1034static LLVMValueRef gen_expr_no_cast(CodeGen *g, AstNode *node) {1044static LLVMValueRef gen_expr_no_cast(CodeGen *g, AstNode *node) {
1035 switch (node->type) {1045 switch (node->type) {
1036 case NodeTypeBinOpExpr:1046 case NodeTypeBinOpExpr:
...@@ -1160,6 +1170,8 @@ static LLVMValueRef gen_expr_no_cast(CodeGen *g, AstNode *node) {...@@ -1160,6 +1170,8 @@ static LLVMValueRef gen_expr_no_cast(CodeGen *g, AstNode *node) {
1160 case NodeTypeGoto:1170 case NodeTypeGoto:
1161 add_debug_source_node(g, node);1171 add_debug_source_node(g, node);
1162 return LLVMBuildBr(g->builder, node->codegen_node->data.label_entry->basic_block);1172 return LLVMBuildBr(g->builder, node->codegen_node->data.label_entry->basic_block);
1173 case NodeTypeBreak:
1174 return gen_break(g, node);
1163 case NodeTypeLabel:1175 case NodeTypeLabel:
1164 {1176 {
1165 LabelTableEntry *label_entry = node->codegen_node->data.label_entry;1177 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) {...@@ -122,6 +122,8 @@ const char *node_type_str(NodeType node_type) {
122 return "Label";122 return "Label";
123 case NodeTypeGoto:123 case NodeTypeGoto:
124 return "Goto";124 return "Goto";
125 case NodeTypeBreak:
126 return "Break";
125 case NodeTypeAsmExpr:127 case NodeTypeAsmExpr:
126 return "AsmExpr";128 return "AsmExpr";
127 case NodeTypeFieldAccessExpr:129 case NodeTypeFieldAccessExpr:
...@@ -336,6 +338,9 @@ void ast_print(AstNode *node, int indent) {...@@ -336,6 +338,9 @@ void ast_print(AstNode *node, int indent) {
336 case NodeTypeGoto:338 case NodeTypeGoto:
337 fprintf(stderr, "%s '%s'\n", node_type_str(node->type), buf_ptr(&node->data.go_to.name));339 fprintf(stderr, "%s '%s'\n", node_type_str(node->type), buf_ptr(&node->data.go_to.name));
338 break;340 break;
341 case NodeTypeBreak:
342 fprintf(stderr, "%s\n", node_type_str(node->type));
343 break;
339 case NodeTypeAsmExpr:344 case NodeTypeAsmExpr:
340 fprintf(stderr, "%s\n", node_type_str(node->type));345 fprintf(stderr, "%s\n", node_type_str(node->type));
341 break;346 break;
...@@ -1102,7 +1107,7 @@ static AstNode *ast_parse_struct_val_expr(ParseContext *pc, int *token_index) {...@@ -1102,7 +1107,7 @@ static AstNode *ast_parse_struct_val_expr(ParseContext *pc, int *token_index) {
1102}1107}
11031108
1104/*1109/*
1105PrimaryExpression : token(Number) | token(String) | KeywordLiteral | GroupedExpression | Goto | BlockExpression | token(Symbol) | StructValueExpression1110PrimaryExpression : token(Number) | token(String) | KeywordLiteral | GroupedExpression | Goto | Break | BlockExpression | token(Symbol) | StructValueExpression
1106*/1111*/
1107static AstNode *ast_parse_primary_expr(ParseContext *pc, int *token_index, bool mandatory) {1112static AstNode *ast_parse_primary_expr(ParseContext *pc, int *token_index, bool mandatory) {
1108 Token *token = &pc->tokens->at(*token_index);1113 Token *token = &pc->tokens->at(*token_index);
...@@ -1156,6 +1161,10 @@ static AstNode *ast_parse_primary_expr(ParseContext *pc, int *token_index, bool...@@ -1156,6 +1161,10 @@ static AstNode *ast_parse_primary_expr(ParseContext *pc, int *token_index, bool
11561161
1157 ast_buf_from_token(pc, dest_symbol, &node->data.go_to.name);1162 ast_buf_from_token(pc, dest_symbol, &node->data.go_to.name);
1158 return node;1163 return node;
1164 } else if (token->id == TokenIdKeywordBreak) {
1165 AstNode *node = ast_create_node(pc, NodeTypeBreak, token);
1166 *token_index += 1;
1167 return node;
1159 }1168 }
11601169
1161 AstNode *grouped_expr_node = ast_parse_grouped_expr(pc, token_index, false);1170 AstNode *grouped_expr_node = ast_parse_grouped_expr(pc, token_index, false);
src/parser.hpp+1
...@@ -48,6 +48,7 @@ enum NodeType {...@@ -48,6 +48,7 @@ enum NodeType {
48 NodeTypeWhileExpr,48 NodeTypeWhileExpr,
49 NodeTypeLabel,49 NodeTypeLabel,
50 NodeTypeGoto,50 NodeTypeGoto,
51 NodeTypeBreak,
51 NodeTypeAsmExpr,52 NodeTypeAsmExpr,
52 NodeTypeStructDecl,53 NodeTypeStructDecl,
53 NodeTypeStructField,54 NodeTypeStructField,
test/run_tests.cpp+15
...@@ -656,6 +656,21 @@ export fn main(argc : isize, argv : &&u8, env : &&u8) -> i32 {...@@ -656,6 +656,21 @@ export fn main(argc : isize, argv : &&u8, env : &&u8) -> i32 {
656 i += 1;656 i += 1;
657 }657 }
658 return 0;658 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;
659}674}
660 )SOURCE", "loop\nloop\nloop\nloop\n");675 )SOURCE", "loop\nloop\nloop\nloop\n");
661}676}