| 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 | 403 | }; |
| 404 | 404 | |
| 405 | 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 | 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 | 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 | 3277 | IrInstruction *return_value = nullptr; |
| 3273 | 3278 | for (size_t i = 0; i < block_node->data.block.statements.length; i += 1) { |
| 3274 | 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 | 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 | 3302 | IrInstruction *is_comptime = ir_mark_gen(ir_build_const_bool(irb, child_scope, statement_node, |
| 3297 | 3303 | ir_should_inline(irb->exec, child_scope))); |
| 3298 | 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 | 3327 | } |
| 3322 | 3328 | } |
| 3323 | 3329 | |
| 3324 | if (!return_value) | |
| 3325 | return_value = ir_mark_gen(ir_build_const_void(irb, child_scope, block_node)); | |
| 3330 | // labels are never the last statement | |
| 3331 | assert(return_value != nullptr); | |
| 3326 | 3332 | |
| 3327 | 3333 | if (!instr_is_unreachable(return_value)) |
| 3328 | 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 | 2094 | |
| 2095 | 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 | 2097 | for (;;) { |
| 2103 | 2098 | AstNode *statement_node = ast_parse_label(pc, token_index, false); |
| 2099 | bool need_implicit_final_void_statement = false; | |
| 2104 | 2100 | bool semicolon_expected; |
| 2105 | 2101 | if (statement_node) { |
| 2106 | 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 | 2105 | } else { |
| 2108 | 2106 | statement_node = ast_parse_variable_declaration_expr(pc, token_index, false, VisibModPrivate); |
| 2109 | 2107 | if (!statement_node) { |
| ... | ... | @@ -2117,17 +2115,23 @@ static AstNode *ast_parse_block(ParseContext *pc, size_t *token_index, bool mand |
| 2117 | 2115 | if (!statement_node) { |
| 2118 | 2116 | statement_node = ast_parse_non_block_expr(pc, token_index, false); |
| 2119 | 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 | 2127 | last_token = &pc->tokens->at(*token_index); |
| 2128 | 2128 | if (last_token->id == TokenIdRBrace) { |
| 2129 | 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 | 2135 | return node; |
| 2132 | 2136 | } else if (!semicolon_expected) { |
| 2133 | 2137 | continue; |