authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2015-12-24 15:36:49-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2015-12-24 15:36:49-07:00
log5943f995106f9fc2c7c5b416c8d4a2ebba2b8315
treee7c67f1b85260de9b54e22a85de8eb3212788d86
parent44ca5e19dc174383b1b0490e636398092711306d

implement continue expression

closes #6

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

doc/langref.md+1-3
......@@ -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 | Break | BlockExpression | token(Symbol) | StructValueExpression
149PrimaryExpression : token(Number) | token(String) | KeywordLiteral | GroupedExpression | Goto | token(Break) | token(Continue) | BlockExpression | token(Symbol) | StructValueExpression
150150
151151StructValueExpression : token(Type) token(LBrace) list(StructValueExpressionField, token(Comma)) token(RBrace)
152152
......@@ -154,8 +154,6 @@ StructValueExpressionField : token(Dot) token(Symbol) token(Eq) Expression
154154
155155Goto: token(Goto) token(Symbol)
156156
157Break: token(Break)
158
159157GroupedExpression : token(LParen) Expression token(RParen)
160158
161159KeywordLiteral : token(Unreachable) | token(Void) | token(True) | token(False)
src/analyze.cpp+17
......@@ -49,6 +49,7 @@ static AstNode *first_executing_node(AstNode *node) {
4949 case NodeTypeLabel:
5050 case NodeTypeGoto:
5151 case NodeTypeBreak:
52 case NodeTypeContinue:
5253 case NodeTypeAsmExpr:
5354 case NodeTypeFieldAccessExpr:
5455 case NodeTypeStructDecl:
......@@ -532,6 +533,7 @@ static void preview_function_declarations(CodeGen *g, ImportTableEntry *import,
532533 case NodeTypeLabel:
533534 case NodeTypeGoto:
534535 case NodeTypeBreak:
536 case NodeTypeContinue:
535537 case NodeTypeAsmExpr:
536538 case NodeTypeFieldAccessExpr:
537539 case NodeTypeStructField:
......@@ -601,6 +603,7 @@ static void preview_types(CodeGen *g, ImportTableEntry *import, AstNode *node) {
601603 case NodeTypeLabel:
602604 case NodeTypeGoto:
603605 case NodeTypeBreak:
606 case NodeTypeContinue:
604607 case NodeTypeAsmExpr:
605608 case NodeTypeFieldAccessExpr:
606609 case NodeTypeStructField:
......@@ -1381,6 +1384,16 @@ static TypeTableEntry *analyze_break_expr(CodeGen *g, ImportTableEntry *import,
13811384 return g->builtin_types.entry_unreachable;
13821385}
13831386
1387static TypeTableEntry *analyze_continue_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,
1388 TypeTableEntry *expected_type, AstNode *node)
1389{
1390 if (!context->break_allowed) {
1391 add_node_error(g, node,
1392 buf_sprintf("'continue' expression not in loop"));
1393 }
1394 return g->builtin_types.entry_unreachable;
1395}
1396
13841397static TypeTableEntry * analyze_expression(CodeGen *g, ImportTableEntry *import, BlockContext *context,
13851398 TypeTableEntry *expected_type, AstNode *node)
13861399{
......@@ -1463,6 +1476,9 @@ static TypeTableEntry * analyze_expression(CodeGen *g, ImportTableEntry *import,
14631476 case NodeTypeBreak:
14641477 return_type = analyze_break_expr(g, import, context, expected_type, node);
14651478 break;
1479 case NodeTypeContinue:
1480 return_type = analyze_continue_expr(g, import, context, expected_type, node);
1481 break;
14661482 case NodeTypeAsmExpr:
14671483 {
14681484 node->data.asm_expr.return_count = 0;
......@@ -1817,6 +1833,7 @@ static void analyze_top_level_declaration(CodeGen *g, ImportTableEntry *import,
18171833 case NodeTypeLabel:
18181834 case NodeTypeGoto:
18191835 case NodeTypeBreak:
1836 case NodeTypeContinue:
18201837 case NodeTypeAsmExpr:
18211838 case NodeTypeFieldAccessExpr:
18221839 case NodeTypeStructField:
src/analyze.hpp+1
......@@ -197,6 +197,7 @@ struct CodeGen {
197197 LLVMBasicBlockRef cur_basic_block;
198198 BlockContext *cur_block_context;
199199 ZigList<LLVMBasicBlockRef> break_block_stack;
200 ZigList<LLVMBasicBlockRef> continue_block_stack;
200201 bool c_stdint_used;
201202 AstNode *root_export_decl;
202203 int version_major;
src/codegen.cpp+12
......@@ -1025,8 +1025,10 @@ static LLVMValueRef gen_while_expr(CodeGen *g, AstNode *node) {
10251025
10261026 LLVMPositionBuilderAtEnd(g->builder, body_block);
10271027 g->break_block_stack.append(end_block);
1028 g->continue_block_stack.append(cond_block);
10281029 gen_expr(g, node->data.while_expr.body);
10291030 g->break_block_stack.pop();
1031 g->continue_block_stack.pop();
10301032 if (get_expr_type(node->data.while_expr.body)->id != TypeTableEntryIdUnreachable) {
10311033 LLVMBuildBr(g->builder, cond_block);
10321034 }
......@@ -1043,6 +1045,14 @@ static LLVMValueRef gen_break(CodeGen *g, AstNode *node) {
10431045 return LLVMBuildBr(g->builder, dest_block);
10441046}
10451047
1048static LLVMValueRef gen_continue(CodeGen *g, AstNode *node) {
1049 assert(node->type == NodeTypeContinue);
1050 LLVMBasicBlockRef dest_block = g->continue_block_stack.last();
1051
1052 add_debug_source_node(g, node);
1053 return LLVMBuildBr(g->builder, dest_block);
1054}
1055
10461056static LLVMValueRef gen_expr_no_cast(CodeGen *g, AstNode *node) {
10471057 switch (node->type) {
10481058 case NodeTypeBinOpExpr:
......@@ -1174,6 +1184,8 @@ static LLVMValueRef gen_expr_no_cast(CodeGen *g, AstNode *node) {
11741184 return LLVMBuildBr(g->builder, node->codegen_node->data.label_entry->basic_block);
11751185 case NodeTypeBreak:
11761186 return gen_break(g, node);
1187 case NodeTypeContinue:
1188 return gen_continue(g, node);
11771189 case NodeTypeLabel:
11781190 {
11791191 LabelTableEntry *label_entry = node->codegen_node->data.label_entry;
src/parser.cpp+10-1
......@@ -124,6 +124,8 @@ const char *node_type_str(NodeType node_type) {
124124 return "Goto";
125125 case NodeTypeBreak:
126126 return "Break";
127 case NodeTypeContinue:
128 return "Continue";
127129 case NodeTypeAsmExpr:
128130 return "AsmExpr";
129131 case NodeTypeFieldAccessExpr:
......@@ -341,6 +343,9 @@ void ast_print(AstNode *node, int indent) {
341343 case NodeTypeBreak:
342344 fprintf(stderr, "%s\n", node_type_str(node->type));
343345 break;
346 case NodeTypeContinue:
347 fprintf(stderr, "%s\n", node_type_str(node->type));
348 break;
344349 case NodeTypeAsmExpr:
345350 fprintf(stderr, "%s\n", node_type_str(node->type));
346351 break;
......@@ -1107,7 +1112,7 @@ static AstNode *ast_parse_struct_val_expr(ParseContext *pc, int *token_index) {
11071112}
11081113
11091114/*
1110PrimaryExpression : token(Number) | token(String) | KeywordLiteral | GroupedExpression | Goto | Break | BlockExpression | token(Symbol) | StructValueExpression
1115PrimaryExpression : token(Number) | token(String) | KeywordLiteral | GroupedExpression | Goto | token(Break) | token(Continue) | BlockExpression | token(Symbol) | StructValueExpression
11111116*/
11121117static AstNode *ast_parse_primary_expr(ParseContext *pc, int *token_index, bool mandatory) {
11131118 Token *token = &pc->tokens->at(*token_index);
......@@ -1165,6 +1170,10 @@ static AstNode *ast_parse_primary_expr(ParseContext *pc, int *token_index, bool
11651170 AstNode *node = ast_create_node(pc, NodeTypeBreak, token);
11661171 *token_index += 1;
11671172 return node;
1173 } else if (token->id == TokenIdKeywordContinue) {
1174 AstNode *node = ast_create_node(pc, NodeTypeContinue, token);
1175 *token_index += 1;
1176 return node;
11681177 }
11691178
11701179 AstNode *grouped_expr_node = ast_parse_grouped_expr(pc, token_index, false);
src/parser.hpp+1
......@@ -49,6 +49,7 @@ enum NodeType {
4949 NodeTypeLabel,
5050 NodeTypeGoto,
5151 NodeTypeBreak,
52 NodeTypeContinue,
5253 NodeTypeAsmExpr,
5354 NodeTypeStructDecl,
5455 NodeTypeStructField,
test/run_tests.cpp+13-7
......@@ -659,17 +659,15 @@ export fn main(argc : isize, argv : &&u8, env : &&u8) -> i32 {
659659}
660660 )SOURCE", "loop\nloop\nloop\nloop\n");
661661
662 add_simple_case("break out of while loop", R"SOURCE(
662 add_simple_case("continue and break", R"SOURCE(
663663use "std.zig";
664664export fn main(argc : isize, argv : &&u8, env : &&u8) -> i32 {
665665 var i : i32 = 0;
666666 while true {
667 while true {
668 if i >= 4 {
669 break;
670 }
671 print_str("loop\n");
672 i += 1;
667 print_str("loop\n");
668 i += 1;
669 if i < 4 {
670 continue;
673671 }
674672 break;
675673 }
......@@ -678,6 +676,8 @@ export fn main(argc : isize, argv : &&u8, env : &&u8) -> i32 {
678676 )SOURCE", "loop\nloop\nloop\nloop\n");
679677}
680678
679////////////////////////////////////////////////////////////////////////////////////
680
681681static void add_compile_failure_test_cases(void) {
682682 add_compile_fail_case("multiple function definitions", R"SOURCE(
683683fn a() {}
......@@ -958,6 +958,12 @@ fn f() {
958958 break;
959959}
960960 )SOURCE", 1, ".tmp_source.zig:3:5: error: 'break' expression not in loop");
961
962 add_compile_fail_case("invalid continue expression", R"SOURCE(
963fn f() {
964 continue;
965}
966 )SOURCE", 1, ".tmp_source.zig:3:5: error: 'continue' expression not in loop");
961967}
962968
963969static void print_compiler_invocation(TestCase *test_case) {