authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-02-06 00:56:01-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-02-06 01:00:29-07:00
logec33e5a638b816ab0ba1e4dd3f9433dbb71d7e53
tree72e6b01315b7902290ae6747ea39499fe0818890
parent6a2ede5a6eb17d6b86e6636457710a3583376fa3

simple unconditional defer support

See #110

8 files changed, 103 insertions(+), 75 deletions(-)

doc/langref.md+3-3
...@@ -43,7 +43,7 @@ ParamDecl = option("noalias") option("Symbol" ":") TypeExpr | "..."...@@ -43,7 +43,7 @@ ParamDecl = option("noalias") option("Symbol" ":") TypeExpr | "..."
4343
44Block = "{" list(option(Statement), ";") "}"44Block = "{" list(option(Statement), ";") "}"
4545
46Statement = Label | VariableDeclaration ";" | NonBlockExpression ";" | BlockExpression46Statement = Label | VariableDeclaration ";" | Defer ";" | NonBlockExpression ";" | BlockExpression
4747
48Label = "Symbol" ":"48Label = "Symbol" ":"
4949
...@@ -51,7 +51,7 @@ Expression = BlockExpression | NonBlockExpression...@@ -51,7 +51,7 @@ Expression = BlockExpression | NonBlockExpression
5151
52TypeExpr = PrefixOpExpression52TypeExpr = PrefixOpExpression
5353
54NonBlockExpression = ReturnExpression | AssignmentExpression | DeferExpression54NonBlockExpression = ReturnExpression | AssignmentExpression
5555
56AsmExpression = "asm" option("volatile") "(" "String" option(AsmOutput) ")"56AsmExpression = "asm" option("volatile") "(" "String" option(AsmOutput) ")"
5757
...@@ -91,7 +91,7 @@ BoolOrExpression = BoolAndExpression "||" BoolOrExpression | BoolAndExpression...@@ -91,7 +91,7 @@ BoolOrExpression = BoolAndExpression "||" BoolOrExpression | BoolAndExpression
9191
92ReturnExpression = option("%" | "?") "return" option(Expression)92ReturnExpression = option("%" | "?") "return" option(Expression)
9393
94DeferExpression = option("%" | "?") "defer" option(Expression)94Defer = option("%" | "?") "defer" option(Expression)
9595
96IfExpression = IfVarExpression | IfBoolExpression96IfExpression = IfVarExpression | IfBoolExpression
9797
example/cat/main.zig-1
...@@ -4,7 +4,6 @@ import "std.zig";...@@ -4,7 +4,6 @@ import "std.zig";
44
5// Things to do to make this work:5// Things to do to make this work:
6// * var args printing6// * var args printing
7// * defer
8// * cast err type to string7// * cast err type to string
9// * string equality8// * string equality
109
src/all_types.hpp+14-6
...@@ -117,7 +117,7 @@ enum NodeType {...@@ -117,7 +117,7 @@ enum NodeType {
117 NodeTypeBlock,117 NodeTypeBlock,
118 NodeTypeDirective,118 NodeTypeDirective,
119 NodeTypeReturnExpr,119 NodeTypeReturnExpr,
120 NodeTypeDeferExpr,120 NodeTypeDefer,
121 NodeTypeVariableDeclaration,121 NodeTypeVariableDeclaration,
122 NodeTypeTypeDecl,122 NodeTypeTypeDecl,
123 NodeTypeErrorValueDecl,123 NodeTypeErrorValueDecl,
...@@ -216,7 +216,12 @@ struct AstNodeBlock {...@@ -216,7 +216,12 @@ struct AstNodeBlock {
216 ZigList<AstNode *> statements;216 ZigList<AstNode *> statements;
217217
218 // populated by semantic analyzer218 // populated by semantic analyzer
219 BlockContext *block_context;219 // this one is the scope that the block itself introduces
220 BlockContext *child_block;
221 // this is the innermost scope created by defers and var decls.
222 // you can follow its parents up to child_block. it will equal
223 // child_block if there are no defers or var decls in the block.
224 BlockContext *nested_block;
220 Expr resolved_expr;225 Expr resolved_expr;
221};226};
222227
...@@ -235,7 +240,7 @@ struct AstNodeReturnExpr {...@@ -235,7 +240,7 @@ struct AstNodeReturnExpr {
235 Expr resolved_expr;240 Expr resolved_expr;
236};241};
237242
238struct AstNodeDeferExpr {243struct AstNodeDefer {
239 ReturnKind kind;244 ReturnKind kind;
240 AstNode *expr;245 AstNode *expr;
241246
...@@ -243,6 +248,7 @@ struct AstNodeDeferExpr {...@@ -243,6 +248,7 @@ struct AstNodeDeferExpr {
243 Expr resolved_expr;248 Expr resolved_expr;
244 int index_in_block;249 int index_in_block;
245 LLVMBasicBlockRef basic_block;250 LLVMBasicBlockRef basic_block;
251 BlockContext *child_block;
246};252};
247253
248struct AstNodeVariableDeclaration {254struct AstNodeVariableDeclaration {
...@@ -739,7 +745,7 @@ struct AstNode {...@@ -739,7 +745,7 @@ struct AstNode {
739 AstNodeParamDecl param_decl;745 AstNodeParamDecl param_decl;
740 AstNodeBlock block;746 AstNodeBlock block;
741 AstNodeReturnExpr return_expr;747 AstNodeReturnExpr return_expr;
742 AstNodeDeferExpr defer_expr;748 AstNodeDefer defer;
743 AstNodeVariableDeclaration variable_declaration;749 AstNodeVariableDeclaration variable_declaration;
744 AstNodeTypeDecl type_decl;750 AstNodeTypeDecl type_decl;
745 AstNodeErrorValueDecl error_value_decl;751 AstNodeErrorValueDecl error_value_decl;
...@@ -1157,10 +1163,12 @@ enum BlockExitPath {...@@ -1157,10 +1163,12 @@ enum BlockExitPath {
1157 BlockExitPathFallthrough,1163 BlockExitPathFallthrough,
1158 BlockExitPathReturn,1164 BlockExitPathReturn,
1159 BlockExitPathGoto,1165 BlockExitPathGoto,
1166
1167 BlockExitPathCount,
1160};1168};
11611169
1162struct BlockContext {1170struct BlockContext {
1163 // One of: NodeTypeFnDef, NodeTypeBlock, NodeTypeRoot, NodeTypeDeferExpr, NodeTypeVariableDeclaration1171 // One of: NodeTypeFnDef, NodeTypeBlock, NodeTypeRoot, NodeTypeDefer, NodeTypeVariableDeclaration
1164 AstNode *node;1172 AstNode *node;
11651173
1166 // any variables that are introduced by this scope1174 // any variables that are introduced by this scope
...@@ -1178,7 +1186,7 @@ struct BlockContext {...@@ -1178,7 +1186,7 @@ struct BlockContext {
11781186
1179 LLVMZigDIScope *di_scope;1187 LLVMZigDIScope *di_scope;
1180 Buf *c_import_buf;1188 Buf *c_import_buf;
1181 bool block_exit_paths[3]; // one for each BlockExitPath1189 bool block_exit_paths[BlockExitPathCount];
1182};1190};
11831191
1184enum CIntType {1192enum CIntType {
src/analyze.cpp+35-31
...@@ -57,7 +57,7 @@ static AstNode *first_executing_node(AstNode *node) {...@@ -57,7 +57,7 @@ static AstNode *first_executing_node(AstNode *node) {
57 case NodeTypeBlock:57 case NodeTypeBlock:
58 case NodeTypeDirective:58 case NodeTypeDirective:
59 case NodeTypeReturnExpr:59 case NodeTypeReturnExpr:
60 case NodeTypeDeferExpr:60 case NodeTypeDefer:
61 case NodeTypeVariableDeclaration:61 case NodeTypeVariableDeclaration:
62 case NodeTypeTypeDecl:62 case NodeTypeTypeDecl:
63 case NodeTypeErrorValueDecl:63 case NodeTypeErrorValueDecl:
...@@ -1456,7 +1456,7 @@ static void resolve_top_level_decl(CodeGen *g, ImportTableEntry *import, AstNode...@@ -1456,7 +1456,7 @@ static void resolve_top_level_decl(CodeGen *g, ImportTableEntry *import, AstNode
1456 case NodeTypeParamDecl:1456 case NodeTypeParamDecl:
1457 case NodeTypeFnDecl:1457 case NodeTypeFnDecl:
1458 case NodeTypeReturnExpr:1458 case NodeTypeReturnExpr:
1459 case NodeTypeDeferExpr:1459 case NodeTypeDefer:
1460 case NodeTypeRoot:1460 case NodeTypeRoot:
1461 case NodeTypeBlock:1461 case NodeTypeBlock:
1462 case NodeTypeBinOpExpr:1462 case NodeTypeBinOpExpr:
...@@ -4590,56 +4590,54 @@ static void validate_voided_expr(CodeGen *g, AstNode *source_node, TypeTableEntr...@@ -4590,56 +4590,54 @@ static void validate_voided_expr(CodeGen *g, AstNode *source_node, TypeTableEntr
4590 }4590 }
4591}4591}
45924592
4593static TypeTableEntry *analyze_defer_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,4593static TypeTableEntry *analyze_defer(CodeGen *g, ImportTableEntry *import, BlockContext *parent_context,
4594 TypeTableEntry *expected_type, AstNode *node)4594 TypeTableEntry *expected_type, AstNode *node)
4595{4595{
4596 if (!context->fn_entry) {4596 if (!parent_context->fn_entry) {
4597 add_node_error(g, node, buf_sprintf("defer expression outside function definition"));4597 add_node_error(g, node, buf_sprintf("defer expression outside function definition"));
4598 return g->builtin_types.entry_invalid;4598 return g->builtin_types.entry_invalid;
4599 }4599 }
46004600
4601 if (!node->data.defer_expr.expr) {4601 if (!node->data.defer.expr) {
4602 add_node_error(g, node, buf_sprintf("defer expects an expression"));4602 add_node_error(g, node, buf_sprintf("defer expects an expression"));
4603 return g->builtin_types.entry_void;4603 return g->builtin_types.entry_void;
4604 }4604 }
46054605
4606 node->data.defer.child_block = new_block_context(node, parent_context);
46064607
4607 switch (node->data.defer_expr.kind) {4608 switch (node->data.defer.kind) {
4608 case ReturnKindUnconditional:4609 case ReturnKindUnconditional:
4609 {4610 {
4610 TypeTableEntry *resolved_type = analyze_expression(g, import, context, nullptr,4611 TypeTableEntry *resolved_type = analyze_expression(g, import, parent_context, nullptr,
4611 node->data.defer_expr.expr);4612 node->data.defer.expr);
4612 validate_voided_expr(g, node->data.defer_expr.expr, resolved_type);4613 validate_voided_expr(g, node->data.defer.expr, resolved_type);
4613 zig_panic("TODO");
46144614
4615 //node->data.defer_expr.index_in_block = context->defer_list.length;
4616 //context->defer_list.append(node);
4617 return g->builtin_types.entry_void;4615 return g->builtin_types.entry_void;
4618 }4616 }
4619 case ReturnKindError:4617 case ReturnKindError:
4620 {4618 {
4621 TypeTableEntry *resolved_type = analyze_expression(g, import, context, nullptr,4619 TypeTableEntry *resolved_type = analyze_expression(g, import, parent_context, nullptr,
4622 node->data.defer_expr.expr);4620 node->data.defer.expr);
4623 if (resolved_type->id == TypeTableEntryIdInvalid) {4621 if (resolved_type->id == TypeTableEntryIdInvalid) {
4624 // OK4622 // OK
4625 } else if (resolved_type->id == TypeTableEntryIdErrorUnion) {4623 } else if (resolved_type->id == TypeTableEntryIdErrorUnion) {
4626 // OK4624 // OK
4627 } else {4625 } else {
4628 add_node_error(g, node->data.defer_expr.expr,4626 add_node_error(g, node->data.defer.expr,
4629 buf_sprintf("expected error type, got '%s'", buf_ptr(&resolved_type->name)));4627 buf_sprintf("expected error type, got '%s'", buf_ptr(&resolved_type->name)));
4630 }4628 }
4631 return g->builtin_types.entry_void;4629 return g->builtin_types.entry_void;
4632 }4630 }
4633 case ReturnKindMaybe:4631 case ReturnKindMaybe:
4634 {4632 {
4635 TypeTableEntry *resolved_type = analyze_expression(g, import, context, nullptr,4633 TypeTableEntry *resolved_type = analyze_expression(g, import, parent_context, nullptr,
4636 node->data.defer_expr.expr);4634 node->data.defer.expr);
4637 if (resolved_type->id == TypeTableEntryIdInvalid) {4635 if (resolved_type->id == TypeTableEntryIdInvalid) {
4638 // OK4636 // OK
4639 } else if (resolved_type->id == TypeTableEntryIdMaybe) {4637 } else if (resolved_type->id == TypeTableEntryIdMaybe) {
4640 // OK4638 // OK
4641 } else {4639 } else {
4642 add_node_error(g, node->data.defer_expr.expr,4640 add_node_error(g, node->data.defer.expr,
4643 buf_sprintf("expected maybe type, got '%s'", buf_ptr(&resolved_type->name)));4641 buf_sprintf("expected maybe type, got '%s'", buf_ptr(&resolved_type->name)));
4644 }4642 }
4645 return g->builtin_types.entry_void;4643 return g->builtin_types.entry_void;
...@@ -4657,11 +4655,11 @@ static TypeTableEntry *analyze_string_literal_expr(CodeGen *g, ImportTableEntry...@@ -4657,11 +4655,11 @@ static TypeTableEntry *analyze_string_literal_expr(CodeGen *g, ImportTableEntry
4657 }4655 }
4658}4656}
46594657
4660static TypeTableEntry *analyze_block_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,4658static TypeTableEntry *analyze_block_expr(CodeGen *g, ImportTableEntry *import, BlockContext *parent_context,
4661 TypeTableEntry *expected_type, AstNode *node)4659 TypeTableEntry *expected_type, AstNode *node)
4662{4660{
4663 BlockContext *child_context = new_block_context(node, context);4661 BlockContext *child_context = new_block_context(node, parent_context);
4664 node->data.block.block_context = child_context;4662 node->data.block.child_block = child_context;
4665 TypeTableEntry *return_type = g->builtin_types.entry_void;4663 TypeTableEntry *return_type = g->builtin_types.entry_void;
46664664
4667 for (int i = 0; i < node->data.block.statements.length; i += 1) {4665 for (int i = 0; i < node->data.block.statements.length; i += 1) {
...@@ -4676,7 +4674,7 @@ static TypeTableEntry *analyze_block_expr(CodeGen *g, ImportTableEntry *import,...@@ -4676,7 +4674,7 @@ static TypeTableEntry *analyze_block_expr(CodeGen *g, ImportTableEntry *import,
4676 if (is_node_void_expr(child)) {4674 if (is_node_void_expr(child)) {
4677 // {unreachable;void;void} is allowed.4675 // {unreachable;void;void} is allowed.
4678 // ignore void statements once we enter unreachable land.4676 // ignore void statements once we enter unreachable land.
4679 analyze_expression(g, import, context, g->builtin_types.entry_void, child);4677 analyze_expression(g, import, child_context, g->builtin_types.entry_void, child);
4680 continue;4678 continue;
4681 }4679 }
4682 add_node_error(g, first_executing_node(child), buf_sprintf("unreachable code"));4680 add_node_error(g, first_executing_node(child), buf_sprintf("unreachable code"));
...@@ -4685,10 +4683,16 @@ static TypeTableEntry *analyze_block_expr(CodeGen *g, ImportTableEntry *import,...@@ -4685,10 +4683,16 @@ static TypeTableEntry *analyze_block_expr(CodeGen *g, ImportTableEntry *import,
4685 bool is_last = (i == node->data.block.statements.length - 1);4683 bool is_last = (i == node->data.block.statements.length - 1);
4686 TypeTableEntry *passed_expected_type = is_last ? expected_type : nullptr;4684 TypeTableEntry *passed_expected_type = is_last ? expected_type : nullptr;
4687 return_type = analyze_expression(g, import, child_context, passed_expected_type, child);4685 return_type = analyze_expression(g, import, child_context, passed_expected_type, child);
4686 if (child->type == NodeTypeDefer && return_type->id != TypeTableEntryIdInvalid) {
4687 // defer starts a new block context
4688 child_context = child->data.defer.child_block;
4689 assert(child_context);
4690 }
4688 if (!is_last) {4691 if (!is_last) {
4689 validate_voided_expr(g, child, return_type);4692 validate_voided_expr(g, child, return_type);
4690 }4693 }
4691 }4694 }
4695 node->data.block.nested_block = child_context;
4692 return return_type;4696 return return_type;
4693}4697}
46944698
...@@ -4750,8 +4754,8 @@ static TypeTableEntry *analyze_expression(CodeGen *g, ImportTableEntry *import,...@@ -4750,8 +4754,8 @@ static TypeTableEntry *analyze_expression(CodeGen *g, ImportTableEntry *import,
4750 case NodeTypeReturnExpr:4754 case NodeTypeReturnExpr:
4751 return_type = analyze_return_expr(g, import, context, expected_type, node);4755 return_type = analyze_return_expr(g, import, context, expected_type, node);
4752 break;4756 break;
4753 case NodeTypeDeferExpr:4757 case NodeTypeDefer:
4754 return_type = analyze_defer_expr(g, import, context, expected_type, node);4758 return_type = analyze_defer(g, import, context, expected_type, node);
4755 break;4759 break;
4756 case NodeTypeVariableDeclaration:4760 case NodeTypeVariableDeclaration:
4757 analyze_variable_declaration(g, import, context, expected_type, node);4761 analyze_variable_declaration(g, import, context, expected_type, node);
...@@ -4956,7 +4960,7 @@ static void analyze_top_level_decl(CodeGen *g, ImportTableEntry *import, AstNode...@@ -4956,7 +4960,7 @@ static void analyze_top_level_decl(CodeGen *g, ImportTableEntry *import, AstNode
4956 case NodeTypeParamDecl:4960 case NodeTypeParamDecl:
4957 case NodeTypeFnDecl:4961 case NodeTypeFnDecl:
4958 case NodeTypeReturnExpr:4962 case NodeTypeReturnExpr:
4959 case NodeTypeDeferExpr:4963 case NodeTypeDefer:
4960 case NodeTypeRoot:4964 case NodeTypeRoot:
4961 case NodeTypeBlock:4965 case NodeTypeBlock:
4962 case NodeTypeBinOpExpr:4966 case NodeTypeBinOpExpr:
...@@ -5039,8 +5043,8 @@ static void collect_expr_decl_deps(CodeGen *g, ImportTableEntry *import, AstNode...@@ -5039,8 +5043,8 @@ static void collect_expr_decl_deps(CodeGen *g, ImportTableEntry *import, AstNode
5039 case NodeTypeReturnExpr:5043 case NodeTypeReturnExpr:
5040 collect_expr_decl_deps(g, import, node->data.return_expr.expr, decl_node);5044 collect_expr_decl_deps(g, import, node->data.return_expr.expr, decl_node);
5041 break;5045 break;
5042 case NodeTypeDeferExpr:5046 case NodeTypeDefer:
5043 collect_expr_decl_deps(g, import, node->data.defer_expr.expr, decl_node);5047 collect_expr_decl_deps(g, import, node->data.defer.expr, decl_node);
5044 break;5048 break;
5045 case NodeTypePrefixOpExpr:5049 case NodeTypePrefixOpExpr:
5046 collect_expr_decl_deps(g, import, node->data.prefix_op_expr.primary_expr, decl_node);5050 collect_expr_decl_deps(g, import, node->data.prefix_op_expr.primary_expr, decl_node);
...@@ -5361,7 +5365,7 @@ static void detect_top_level_decl_deps(CodeGen *g, ImportTableEntry *import, Ast...@@ -5361,7 +5365,7 @@ static void detect_top_level_decl_deps(CodeGen *g, ImportTableEntry *import, Ast
5361 case NodeTypeParamDecl:5365 case NodeTypeParamDecl:
5362 case NodeTypeFnDecl:5366 case NodeTypeFnDecl:
5363 case NodeTypeReturnExpr:5367 case NodeTypeReturnExpr:
5364 case NodeTypeDeferExpr:5368 case NodeTypeDefer:
5365 case NodeTypeBlock:5369 case NodeTypeBlock:
5366 case NodeTypeBinOpExpr:5370 case NodeTypeBinOpExpr:
5367 case NodeTypeUnwrapErrorExpr:5371 case NodeTypeUnwrapErrorExpr:
...@@ -5552,8 +5556,8 @@ Expr *get_resolved_expr(AstNode *node) {...@@ -5552,8 +5556,8 @@ Expr *get_resolved_expr(AstNode *node) {
5552 switch (node->type) {5556 switch (node->type) {
5553 case NodeTypeReturnExpr:5557 case NodeTypeReturnExpr:
5554 return &node->data.return_expr.resolved_expr;5558 return &node->data.return_expr.resolved_expr;
5555 case NodeTypeDeferExpr:5559 case NodeTypeDefer:
5556 return &node->data.defer_expr.resolved_expr;5560 return &node->data.defer.resolved_expr;
5557 case NodeTypeBinOpExpr:5561 case NodeTypeBinOpExpr:
5558 return &node->data.bin_op_expr.resolved_expr;5562 return &node->data.bin_op_expr.resolved_expr;
5559 case NodeTypeUnwrapErrorExpr:5563 case NodeTypeUnwrapErrorExpr:
...@@ -5652,7 +5656,7 @@ TopLevelDecl *get_resolved_top_level_decl(AstNode *node) {...@@ -5652,7 +5656,7 @@ TopLevelDecl *get_resolved_top_level_decl(AstNode *node) {
5652 return &node->data.type_decl.top_level_decl;5656 return &node->data.type_decl.top_level_decl;
5653 case NodeTypeNumberLiteral:5657 case NodeTypeNumberLiteral:
5654 case NodeTypeReturnExpr:5658 case NodeTypeReturnExpr:
5655 case NodeTypeDeferExpr:5659 case NodeTypeDefer:
5656 case NodeTypeBinOpExpr:5660 case NodeTypeBinOpExpr:
5657 case NodeTypeUnwrapErrorExpr:5661 case NodeTypeUnwrapErrorExpr:
5658 case NodeTypePrefixOpExpr:5662 case NodeTypePrefixOpExpr:
src/ast_render.cpp+7-7
...@@ -122,8 +122,8 @@ static const char *node_type_str(NodeType node_type) {...@@ -122,8 +122,8 @@ static const char *node_type_str(NodeType node_type) {
122 return "Directive";122 return "Directive";
123 case NodeTypeReturnExpr:123 case NodeTypeReturnExpr:
124 return "ReturnExpr";124 return "ReturnExpr";
125 case NodeTypeDeferExpr:125 case NodeTypeDefer:
126 return "DeferExpr";126 return "Defer";
127 case NodeTypeVariableDeclaration:127 case NodeTypeVariableDeclaration:
128 return "VariableDeclaration";128 return "VariableDeclaration";
129 case NodeTypeTypeDecl:129 case NodeTypeTypeDecl:
...@@ -261,12 +261,12 @@ void ast_print(FILE *f, AstNode *node, int indent) {...@@ -261,12 +261,12 @@ void ast_print(FILE *f, AstNode *node, int indent) {
261 ast_print(f, node->data.return_expr.expr, indent + 2);261 ast_print(f, node->data.return_expr.expr, indent + 2);
262 break;262 break;
263 }263 }
264 case NodeTypeDeferExpr:264 case NodeTypeDefer:
265 {265 {
266 const char *prefix_str = return_prefix_str(node->data.defer_expr.kind);266 const char *prefix_str = return_prefix_str(node->data.defer.kind);
267 fprintf(f, "%s%s\n", prefix_str, node_type_str(node->type));267 fprintf(f, "%s%s\n", prefix_str, node_type_str(node->type));
268 if (node->data.defer_expr.expr)268 if (node->data.defer.expr)
269 ast_print(f, node->data.defer_expr.expr, indent + 2);269 ast_print(f, node->data.defer.expr, indent + 2);
270 break;270 break;
271 }271 }
272 case NodeTypeVariableDeclaration:272 case NodeTypeVariableDeclaration:
...@@ -630,7 +630,7 @@ static void render_node(AstRender *ar, AstNode *node) {...@@ -630,7 +630,7 @@ static void render_node(AstRender *ar, AstNode *node) {
630 break;630 break;
631 case NodeTypeReturnExpr:631 case NodeTypeReturnExpr:
632 zig_panic("TODO");632 zig_panic("TODO");
633 case NodeTypeDeferExpr:633 case NodeTypeDefer:
634 zig_panic("TODO");634 zig_panic("TODO");
635 case NodeTypeVariableDeclaration:635 case NodeTypeVariableDeclaration:
636 {636 {
src/codegen.cpp+26-22
...@@ -1669,11 +1669,9 @@ static LLVMValueRef gen_return_expr(CodeGen *g, AstNode *node) {...@@ -1669,11 +1669,9 @@ static LLVMValueRef gen_return_expr(CodeGen *g, AstNode *node) {
1669 }1669 }
1670}1670}
16711671
1672static LLVMValueRef gen_defer_expr(CodeGen *g, AstNode *node) {1672static LLVMValueRef gen_defer(CodeGen *g, AstNode *node) {
1673 assert(node->type == NodeTypeDeferExpr);1673 assert(node->type == NodeTypeDefer);
16741674
1675 zig_panic("TODO");
1676 //node->block_context->cur_defer_index = node->data.defer_expr.index_in_block;
16771675
1678 return nullptr;1676 return nullptr;
1679}1677}
...@@ -1800,31 +1798,37 @@ static LLVMValueRef gen_if_var_expr(CodeGen *g, AstNode *node) {...@@ -1800,31 +1798,37 @@ static LLVMValueRef gen_if_var_expr(CodeGen *g, AstNode *node) {
1800 return return_value;1798 return return_value;
1801}1799}
18021800
1801//static int block_exit_path_count(BlockContext *block_context) {
1802// int sum = 0;
1803// for (int i = 0; i < BlockExitPathCount; i += 1) {
1804// sum += block_context->block_exit_paths[i] ? 1 : 0;
1805// }
1806// return sum;
1807//}
1808
1803static LLVMValueRef gen_block(CodeGen *g, AstNode *block_node, TypeTableEntry *implicit_return_type) {1809static LLVMValueRef gen_block(CodeGen *g, AstNode *block_node, TypeTableEntry *implicit_return_type) {
1804 assert(block_node->type == NodeTypeBlock);1810 assert(block_node->type == NodeTypeBlock);
18051811
1806 /* TODO
1807 BlockContext *block_context = block_node->data.block.block_context;
1808 if (block_context->defer_list.length > 0) {
1809 LLVMBasicBlockRef exit_scope_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "DeferExitScope");
1810
1811 for (int i = 0; i < block_context->defer_list.length; i += 1) {
1812 AstNode *defer_node = block_context->defer_list.at(i);
1813 defer_node->data.defer_expr.basic_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "DeferExpr");
1814 LLVMPositionBuilderAtEnd(g->builder, body_block);
1815 }
1816
1817 LLVMPositionBuilderAtEnd(g->builder, ?);
1818 }
1819 */
1820
1821 LLVMValueRef return_value;1812 LLVMValueRef return_value;
1822 for (int i = 0; i < block_node->data.block.statements.length; i += 1) {1813 for (int i = 0; i < block_node->data.block.statements.length; i += 1) {
1823 AstNode *statement_node = block_node->data.block.statements.at(i);1814 AstNode *statement_node = block_node->data.block.statements.at(i);
1824 return_value = gen_expr(g, statement_node);1815 return_value = gen_expr(g, statement_node);
1825 }1816 }
18261817
1827 if (implicit_return_type && implicit_return_type->id != TypeTableEntryIdUnreachable) {1818 bool end_unreachable = implicit_return_type && implicit_return_type->id == TypeTableEntryIdUnreachable;
1819 if (end_unreachable) {
1820 return nullptr;
1821 }
1822
1823 BlockContext *block_context = block_node->data.block.nested_block;
1824 while (block_context != block_node->data.block.child_block) {
1825 if (block_context->node->type == NodeTypeDefer) {
1826 gen_expr(g, block_context->node->data.defer.expr);
1827 }
1828 block_context = block_context->parent;
1829 }
1830
1831 if (implicit_return_type) {
1828 return gen_return(g, block_node, return_value);1832 return gen_return(g, block_node, return_value);
1829 } else {1833 } else {
1830 return return_value;1834 return return_value;
...@@ -2475,8 +2479,8 @@ static LLVMValueRef gen_expr(CodeGen *g, AstNode *node) {...@@ -2475,8 +2479,8 @@ static LLVMValueRef gen_expr(CodeGen *g, AstNode *node) {
2475 return gen_unwrap_err_expr(g, node);2479 return gen_unwrap_err_expr(g, node);
2476 case NodeTypeReturnExpr:2480 case NodeTypeReturnExpr:
2477 return gen_return_expr(g, node);2481 return gen_return_expr(g, node);
2478 case NodeTypeDeferExpr:2482 case NodeTypeDefer:
2479 return gen_defer_expr(g, node);2483 return gen_defer(g, node);
2480 case NodeTypeVariableDeclaration:2484 case NodeTypeVariableDeclaration:
2481 return gen_var_decl_expr(g, node);2485 return gen_var_decl_expr(g, node);
2482 case NodeTypePrefixOpExpr:2486 case NodeTypePrefixOpExpr:
src/parser.cpp+5-5
...@@ -1651,7 +1651,7 @@ static AstNode *ast_parse_return_or_defer_expr(ParseContext *pc, int *token_inde...@@ -1651,7 +1651,7 @@ static AstNode *ast_parse_return_or_defer_expr(ParseContext *pc, int *token_inde
1651 *token_index += 2;1651 *token_index += 2;
1652 } else if (next_token->id == TokenIdKeywordDefer) {1652 } else if (next_token->id == TokenIdKeywordDefer) {
1653 kind = ReturnKindError;1653 kind = ReturnKindError;
1654 node_type = NodeTypeDeferExpr;1654 node_type = NodeTypeDefer;
1655 *token_index += 2;1655 *token_index += 2;
1656 } else {1656 } else {
1657 return nullptr;1657 return nullptr;
...@@ -1664,7 +1664,7 @@ static AstNode *ast_parse_return_or_defer_expr(ParseContext *pc, int *token_inde...@@ -1664,7 +1664,7 @@ static AstNode *ast_parse_return_or_defer_expr(ParseContext *pc, int *token_inde
1664 *token_index += 2;1664 *token_index += 2;
1665 } else if (next_token->id == TokenIdKeywordDefer) {1665 } else if (next_token->id == TokenIdKeywordDefer) {
1666 kind = ReturnKindMaybe;1666 kind = ReturnKindMaybe;
1667 node_type = NodeTypeDeferExpr;1667 node_type = NodeTypeDefer;
1668 *token_index += 2;1668 *token_index += 2;
1669 } else {1669 } else {
1670 return nullptr;1670 return nullptr;
...@@ -1675,7 +1675,7 @@ static AstNode *ast_parse_return_or_defer_expr(ParseContext *pc, int *token_inde...@@ -1675,7 +1675,7 @@ static AstNode *ast_parse_return_or_defer_expr(ParseContext *pc, int *token_inde
1675 *token_index += 1;1675 *token_index += 1;
1676 } else if (token->id == TokenIdKeywordDefer) {1676 } else if (token->id == TokenIdKeywordDefer) {
1677 kind = ReturnKindUnconditional;1677 kind = ReturnKindUnconditional;
1678 node_type = NodeTypeDeferExpr;1678 node_type = NodeTypeDefer;
1679 *token_index += 1;1679 *token_index += 1;
1680 } else {1680 } else {
1681 return nullptr;1681 return nullptr;
...@@ -2703,8 +2703,8 @@ void normalize_parent_ptrs(AstNode *node) {...@@ -2703,8 +2703,8 @@ void normalize_parent_ptrs(AstNode *node) {
2703 case NodeTypeReturnExpr:2703 case NodeTypeReturnExpr:
2704 set_field(&node->data.return_expr.expr);2704 set_field(&node->data.return_expr.expr);
2705 break;2705 break;
2706 case NodeTypeDeferExpr:2706 case NodeTypeDefer:
2707 set_field(&node->data.defer_expr.expr);2707 set_field(&node->data.defer.expr);
2708 break;2708 break;
2709 case NodeTypeVariableDeclaration:2709 case NodeTypeVariableDeclaration:
2710 set_list_fields(node->data.variable_declaration.directives);2710 set_list_fields(node->data.variable_declaration.directives);
test/run_tests.cpp+13
...@@ -1519,6 +1519,19 @@ pub fn main(args: [][]u8) -> %void {...@@ -1519,6 +1519,19 @@ pub fn main(args: [][]u8) -> %void {
1519 %%stdout.printf("OK\n");1519 %%stdout.printf("OK\n");
1520}1520}
1521 )SOURCE", "OK\n");1521 )SOURCE", "OK\n");
1522
1523
1524 add_simple_case("defer with only fallthrough", R"SOURCE(
1525import "std.zig";
1526pub fn main(args: [][]u8) -> %void {
1527 %%stdout.printf("before\n");
1528 defer %%stdout.printf("defer1\n");
1529 defer %%stdout.printf("defer2\n");
1530 defer %%stdout.printf("defer3\n");
1531 %%stdout.printf("after\n");
1532}
1533 )SOURCE", "before\nafter\ndefer3\ndefer2\ndefer1\n");
1534
1522}1535}
15231536
15241537