authorgravatar for thejoshwolfe@gmail.comJosh Wolfe <thejoshwolfe@gmail.com> 2017-04-12 22:18:56-07:00
committergravatar for thejoshwolfe@gmail.comJosh Wolfe <thejoshwolfe@gmail.com> 2017-04-12 23:22:32-07:00
log356424916ced599852e2c38265eebe7a1fc1637d
tree2bec2154f1e4bbb93b0f9d5e959aaf491240ccd0
parent919910312d7d25fe8f894adbc9ff8a449ac26281

block statement lists never get fake expressions

instead blocks have a field that encodes whether the last statement ended with a semicolon.

4 files changed, 64 insertions(+), 81 deletions(-)

src/all_types.hpp+1-3
......@@ -410,10 +410,8 @@ struct AstNodeParamDecl {
410410};
411411
412412struct AstNodeBlock {
413 // the final statement is the returned expression.
414 // if there are no statements, the returned expression is void.
415 // the final statement is never a label.
416413 ZigList<AstNode *> statements;
414 bool last_statement_is_result_expression;
417415};
418416
419417enum ReturnKind {
src/ast_render.cpp+3-1
......@@ -464,8 +464,10 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) {
464464 }
465465 print_indent(ar);
466466 render_node_grouped(ar, statement);
467 if (i != node->data.block.statements.length - 1)
467 if (!(i == node->data.block.statements.length - 1 &&
468 node->data.block.last_statement_is_result_expression)) {
468469 fprintf(ar->f, ";");
470 }
469471 fprintf(ar->f, "\n");
470472 }
471473 ar->indent -= ar->indent_size;
src/ir.cpp+10-3
......@@ -3378,6 +3378,7 @@ static IrInstruction *ir_gen_block(IrBuilder *irb, Scope *parent_scope, AstNode
33783378
33793379 // a label is an entry point
33803380 is_continuation_unreachable = false;
3381 return_value = nullptr;
33813382 continue;
33823383 }
33833384
......@@ -3406,7 +3407,8 @@ static IrInstruction *ir_gen_block(IrBuilder *irb, Scope *parent_scope, AstNode
34063407 child_scope = decl_var_instruction->var->child_scope;
34073408 } else {
34083409 // label, defer, variable declaration will never be the last statement
3409 if (i == block_node->data.block.statements.length - 1) {
3410 if (block_node->data.block.last_statement_is_result_expression &&
3411 i == block_node->data.block.statements.length - 1) {
34103412 // this is the result value statement
34113413 return_value = statement_value;
34123414 } else {
......@@ -3422,13 +3424,18 @@ static IrInstruction *ir_gen_block(IrBuilder *irb, Scope *parent_scope, AstNode
34223424 }
34233425 }
34243426
3425 assert(return_value != nullptr);
3426
34273427 if (!is_continuation_unreachable) {
34283428 // control flow falls out of block
3429
3430 if (!block_node->data.block.last_statement_is_result_expression) {
3431 assert(return_value == nullptr);
3432 return_value = ir_mark_gen(ir_build_const_void(irb, child_scope, block_node));
3433 }
3434
34293435 ir_gen_defers_for_block(irb, child_scope, outer_block_scope, false, false);
34303436 }
34313437
3438 assert(return_value != nullptr);
34323439 return return_value;
34333440}
34343441
src/parser.cpp+50-74
......@@ -1882,36 +1882,6 @@ static AstNode *ast_parse_switch_expr(ParseContext *pc, size_t *token_index, boo
18821882 }
18831883}
18841884
1885static bool statement_has_block_body(AstNode *node) {
1886 switch (node->type) {
1887 case NodeTypeIfBoolExpr:
1888 if (node->data.if_bool_expr.else_node)
1889 return statement_has_block_body(node->data.if_bool_expr.else_node);
1890 return node->data.if_bool_expr.then_block->type == NodeTypeBlock;
1891 case NodeTypeIfVarExpr:
1892 if (node->data.if_var_expr.else_node)
1893 return statement_has_block_body(node->data.if_var_expr.else_node);
1894 return node->data.if_var_expr.then_block->type == NodeTypeBlock;
1895 case NodeTypeTryExpr:
1896 if (node->data.try_expr.else_node)
1897 return statement_has_block_body(node->data.try_expr.else_node);
1898 return node->data.try_expr.then_node->type == NodeTypeBlock;
1899 case NodeTypeWhileExpr:
1900 return node->data.while_expr.body->type == NodeTypeBlock;
1901 case NodeTypeForExpr:
1902 return node->data.for_expr.body->type == NodeTypeBlock;
1903 case NodeTypeSwitchExpr:
1904 case NodeTypeBlock:
1905 return true;
1906 case NodeTypeCompTime:
1907 return node->data.comptime_expr.expr->type == NodeTypeBlock;
1908 case NodeTypeDefer:
1909 return node->data.defer.expr->type == NodeTypeBlock;
1910 default:
1911 return false;
1912 }
1913}
1914
19151885/*
19161886BlockExpression(body) = Block | IfExpression(body) | TryExpression(body) | WhileExpression(body) | ForExpression(body) | SwitchExpression | CompTimeExpression(body)
19171887*/
......@@ -2124,9 +2094,35 @@ static AstNode *ast_parse_label(ParseContext *pc, size_t *token_index, bool mand
21242094 return node;
21252095}
21262096
2127static AstNode *ast_create_void_expr(ParseContext *pc, Token *token) {
2128 AstNode *node = ast_create_node(pc, NodeTypeBlock, token);
2129 return node;
2097static bool statement_terminates_without_semicolon(AstNode *node) {
2098 switch (node->type) {
2099 case NodeTypeIfBoolExpr:
2100 if (node->data.if_bool_expr.else_node)
2101 return statement_terminates_without_semicolon(node->data.if_bool_expr.else_node);
2102 return node->data.if_bool_expr.then_block->type == NodeTypeBlock;
2103 case NodeTypeIfVarExpr:
2104 if (node->data.if_var_expr.else_node)
2105 return statement_terminates_without_semicolon(node->data.if_var_expr.else_node);
2106 return node->data.if_var_expr.then_block->type == NodeTypeBlock;
2107 case NodeTypeTryExpr:
2108 if (node->data.try_expr.else_node)
2109 return statement_terminates_without_semicolon(node->data.try_expr.else_node);
2110 return node->data.try_expr.then_node->type == NodeTypeBlock;
2111 case NodeTypeWhileExpr:
2112 return node->data.while_expr.body->type == NodeTypeBlock;
2113 case NodeTypeForExpr:
2114 return node->data.for_expr.body->type == NodeTypeBlock;
2115 case NodeTypeCompTime:
2116 return node->data.comptime_expr.expr->type == NodeTypeBlock;
2117 case NodeTypeDefer:
2118 return node->data.defer.expr->type == NodeTypeBlock;
2119 case NodeTypeSwitchExpr:
2120 case NodeTypeBlock:
2121 case NodeTypeLabel:
2122 return true;
2123 default:
2124 return false;
2125 }
21302126}
21312127
21322128/*
......@@ -2149,56 +2145,36 @@ static AstNode *ast_parse_block(ParseContext *pc, size_t *token_index, bool mand
21492145
21502146 for (;;) {
21512147 AstNode *statement_node = ast_parse_label(pc, token_index, false);
2152 bool need_implicit_final_void_statement = false;
2148 if (!statement_node)
2149 statement_node = ast_parse_variable_declaration_expr(pc, token_index, false, VisibModPrivate);
2150 if (!statement_node)
2151 statement_node = ast_parse_defer_expr(pc, token_index);
2152 if (!statement_node)
2153 statement_node = ast_parse_block_expr(pc, token_index, false);
2154 if (!statement_node)
2155 statement_node = ast_parse_expression(pc, token_index, false);
2156
21532157 bool semicolon_expected = true;
21542158 if (statement_node) {
2155 // label
2156 semicolon_expected = false;
2157 // if a label is the last thing in a block, add a void statement.
2158 need_implicit_final_void_statement = true;
2159 } else {
2160 statement_node = ast_parse_variable_declaration_expr(pc, token_index, false, VisibModPrivate);
2161 if (!statement_node) {
2162 statement_node = ast_parse_defer_expr(pc, token_index);
2163 if (statement_node) {
2164 // defer
2165 if (statement_has_block_body(statement_node)) {
2166 // don't let defer be the last statement in a block
2167 need_implicit_final_void_statement = true;
2168 semicolon_expected = false;
2169 } else {
2170 // defer without a block body requires a semicolon
2171 Token *token = &pc->tokens->at(*token_index);
2172 ast_expect_token(pc, token, TokenIdSemicolon);
2173 }
2174 } else {
2175 statement_node = ast_parse_block_expr(pc, token_index, false);
2176 if (statement_node) {
2177 // block expr
2178 if (statement_has_block_body(statement_node))
2179 semicolon_expected = false;
2180 } else {
2181 statement_node = ast_parse_expression(pc, token_index, false);
2182 if (!statement_node) {
2183 // no statement.
2184 // final semicolon means add a void statement.
2185 need_implicit_final_void_statement = true;
2186 }
2187 }
2159 node->data.block.statements.append(statement_node);
2160 if (statement_terminates_without_semicolon(statement_node)) {
2161 semicolon_expected = false;
2162 } else {
2163 if (statement_node->type == NodeTypeDefer) {
2164 // defer without a block body requires a semicolon
2165 Token *token = &pc->tokens->at(*token_index);
2166 ast_expect_token(pc, token, TokenIdSemicolon);
21882167 }
21892168 }
21902169 }
2191 if (statement_node)
2192 node->data.block.statements.append(statement_node);
2170
2171 node->data.block.last_statement_is_result_expression = statement_node && !(
2172 statement_node->type == NodeTypeLabel ||
2173 statement_node->type == NodeTypeDefer);
21932174
21942175 last_token = &pc->tokens->at(*token_index);
21952176 if (last_token->id == TokenIdRBrace) {
21962177 *token_index += 1;
2197
2198 if (node->data.block.statements.length > 0 && need_implicit_final_void_statement) {
2199 node->data.block.statements.append(ast_create_void_expr(pc, last_token));
2200 }
2201
22022178 return node;
22032179 } else if (!semicolon_expected) {
22042180 continue;