| author | |
| committer | |
| log | 36a015741db9fbf748fe9ab082f78c5d8663024c |
| tree | 9ed34ffe3f8b4bd3d274bc21d5db6c1d5e336051 |
| parent | d5a6cdb03f874ab53928a67330ebfab1e64fe111 |
* Don't insert void statements all over the place. {} now stays as
{} instead of {{}}, and {;} becomes {} instead of {{};{}}.
* Ensure final statement is always the return value statement, or
the block is empty. This means {label:} becomes {label:{}}.3 files changed, 23 insertions(+), 10 deletions(-)
src/all_types.hpp+3| ... | @@ -403,6 +403,9 @@ struct AstNodeParamDecl { | ... | @@ -403,6 +403,9 @@ struct AstNodeParamDecl { |
| 403 | }; | 403 | }; |
| 404 | 404 | ||
| 405 | struct AstNodeBlock { | 405 | struct AstNodeBlock { |
| 406 | // the final statement is the returned expression. | ||
| 407 | // if there are no statements, the returned expression is void. | ||
| 408 | // the final statement is never a label. | ||
| 406 | ZigList<AstNode *> statements; | 409 | ZigList<AstNode *> statements; |
| 407 | }; | 410 | }; |
| 408 | 411 |
src/ir.cpp+9-3| ... | @@ -3269,6 +3269,11 @@ static IrInstruction *ir_gen_block(IrBuilder *irb, Scope *parent_scope, AstNode | ... | @@ -3269,6 +3269,11 @@ static IrInstruction *ir_gen_block(IrBuilder *irb, Scope *parent_scope, AstNode |
| 3269 | fn_entry->def_scope = scope_block; | 3269 | fn_entry->def_scope = scope_block; |
| 3270 | } | 3270 | } |
| 3271 | 3271 | ||
| 3272 | if (block_node->data.block.statements.length == 0) { | ||
| 3273 | // {} | ||
| 3274 | return ir_mark_gen(ir_build_const_void(irb, child_scope, block_node)); | ||
| 3275 | } | ||
| 3276 | |||
| 3272 | IrInstruction *return_value = nullptr; | 3277 | IrInstruction *return_value = nullptr; |
| 3273 | for (size_t i = 0; i < block_node->data.block.statements.length; i += 1) { | 3278 | for (size_t i = 0; i < block_node->data.block.statements.length; i += 1) { |
| 3274 | AstNode *statement_node = block_node->data.block.statements.at(i); | 3279 | AstNode *statement_node = block_node->data.block.statements.at(i); |
| ... | @@ -3292,7 +3297,8 @@ static IrInstruction *ir_gen_block(IrBuilder *irb, Scope *parent_scope, AstNode | ... | @@ -3292,7 +3297,8 @@ static IrInstruction *ir_gen_block(IrBuilder *irb, Scope *parent_scope, AstNode |
| 3292 | scope_block->label_table.put(label_name, label); | 3297 | scope_block->label_table.put(label_name, label); |
| 3293 | } | 3298 | } |
| 3294 | 3299 | ||
| 3295 | if (!return_value || !instr_is_unreachable(return_value)) { | 3300 | if (!(return_value && instr_is_unreachable(return_value))) { |
| 3301 | // fall through into new labeled basic block | ||
| 3296 | IrInstruction *is_comptime = ir_mark_gen(ir_build_const_bool(irb, child_scope, statement_node, | 3302 | IrInstruction *is_comptime = ir_mark_gen(ir_build_const_bool(irb, child_scope, statement_node, |
| 3297 | ir_should_inline(irb->exec, child_scope))); | 3303 | ir_should_inline(irb->exec, child_scope))); |
| 3298 | ir_mark_gen(ir_build_br(irb, child_scope, statement_node, label_block, is_comptime)); | 3304 | ir_mark_gen(ir_build_br(irb, child_scope, statement_node, label_block, is_comptime)); |
| ... | @@ -3321,8 +3327,8 @@ static IrInstruction *ir_gen_block(IrBuilder *irb, Scope *parent_scope, AstNode | ... | @@ -3321,8 +3327,8 @@ static IrInstruction *ir_gen_block(IrBuilder *irb, Scope *parent_scope, AstNode |
| 3321 | } | 3327 | } |
| 3322 | } | 3328 | } |
| 3323 | 3329 | ||
| 3324 | if (!return_value) | 3330 | // labels are never the last statement |
| 3325 | return_value = ir_mark_gen(ir_build_const_void(irb, child_scope, block_node)); | 3331 | assert(return_value != nullptr); |
| 3326 | 3332 | ||
| 3327 | if (!instr_is_unreachable(return_value)) | 3333 | if (!instr_is_unreachable(return_value)) |
| 3328 | ir_gen_defers_for_block(irb, child_scope, outer_block_scope, false, false); | 3334 | ir_gen_defers_for_block(irb, child_scope, outer_block_scope, false, false); |
src/parser.cpp+11-7| ... | @@ -2094,16 +2094,14 @@ static AstNode *ast_parse_block(ParseContext *pc, size_t *token_index, bool mand | ... | @@ -2094,16 +2094,14 @@ static AstNode *ast_parse_block(ParseContext *pc, size_t *token_index, bool mand |
| 2094 | 2094 | ||
| 2095 | AstNode *node = ast_create_node(pc, NodeTypeBlock, last_token); | 2095 | AstNode *node = ast_create_node(pc, NodeTypeBlock, last_token); |
| 2096 | 2096 | ||
| 2097 | // {} -> {void} | ||
| 2098 | // {;} -> {void;void} | ||
| 2099 | // {2} -> {2} | ||
| 2100 | // {2;} -> {2;void} | ||
| 2101 | // {;2} -> {void;2} | ||
| 2102 | for (;;) { | 2097 | for (;;) { |
| 2103 | AstNode *statement_node = ast_parse_label(pc, token_index, false); | 2098 | AstNode *statement_node = ast_parse_label(pc, token_index, false); |
| 2099 | bool need_implicit_final_void_statement = false; | ||
| 2104 | bool semicolon_expected; | 2100 | bool semicolon_expected; |
| 2105 | if (statement_node) { | 2101 | if (statement_node) { |
| 2106 | semicolon_expected = false; | 2102 | semicolon_expected = false; |
| 2103 | // if a label is the last thing in a block, add a void statement. | ||
| 2104 | need_implicit_final_void_statement = true; | ||
| 2107 | } else { | 2105 | } else { |
| 2108 | statement_node = ast_parse_variable_declaration_expr(pc, token_index, false, VisibModPrivate); | 2106 | statement_node = ast_parse_variable_declaration_expr(pc, token_index, false, VisibModPrivate); |
| 2109 | if (!statement_node) { | 2107 | if (!statement_node) { |
| ... | @@ -2117,17 +2115,23 @@ static AstNode *ast_parse_block(ParseContext *pc, size_t *token_index, bool mand | ... | @@ -2117,17 +2115,23 @@ static AstNode *ast_parse_block(ParseContext *pc, size_t *token_index, bool mand |
| 2117 | if (!statement_node) { | 2115 | if (!statement_node) { |
| 2118 | statement_node = ast_parse_non_block_expr(pc, token_index, false); | 2116 | statement_node = ast_parse_non_block_expr(pc, token_index, false); |
| 2119 | if (!statement_node) { | 2117 | if (!statement_node) { |
| 2120 | statement_node = ast_create_void_expr(pc, last_token); | 2118 | // final semicolon means add a void statement. |
| 2119 | need_implicit_final_void_statement = true; | ||
| 2121 | } | 2120 | } |
| 2122 | } | 2121 | } |
| 2123 | } | 2122 | } |
| 2124 | } | 2123 | } |
| 2125 | node->data.block.statements.append(statement_node); | 2124 | if (statement_node) |
| 2125 | node->data.block.statements.append(statement_node); | ||
| 2126 | 2126 | ||
| 2127 | last_token = &pc->tokens->at(*token_index); | 2127 | last_token = &pc->tokens->at(*token_index); |
| 2128 | if (last_token->id == TokenIdRBrace) { | 2128 | if (last_token->id == TokenIdRBrace) { |
| 2129 | *token_index += 1; | 2129 | *token_index += 1; |
| 2130 | 2130 | ||
| 2131 | if (node->data.block.statements.length > 0 && need_implicit_final_void_statement) { | ||
| 2132 | node->data.block.statements.append(ast_create_void_expr(pc, last_token)); | ||
| 2133 | } | ||
| 2134 | |||
| 2131 | return node; | 2135 | return node; |
| 2132 | } else if (!semicolon_expected) { | 2136 | } else if (!semicolon_expected) { |
| 2133 | continue; | 2137 | continue; |