| ... | @@ -498,6 +498,7 @@ static AstNode *ast_parse_unwrap_expr(ParseContext *pc, int *token_index, bool m | ... | @@ -498,6 +498,7 @@ static AstNode *ast_parse_unwrap_expr(ParseContext *pc, int *token_index, bool m |
| 498 | static AstNode *ast_parse_prefix_op_expr(ParseContext *pc, int *token_index, bool mandatory); | 498 | static AstNode *ast_parse_prefix_op_expr(ParseContext *pc, int *token_index, bool mandatory); |
| 499 | static AstNode *ast_parse_fn_proto(ParseContext *pc, int *token_index, bool mandatory, | 499 | static AstNode *ast_parse_fn_proto(ParseContext *pc, int *token_index, bool mandatory, |
| 500 | ZigList<AstNode*> *directives, VisibMod visib_mod); | 500 | ZigList<AstNode*> *directives, VisibMod visib_mod); |
| | 501 | static AstNode *ast_parse_return_expr(ParseContext *pc, int *token_index); |
| 501 | | 502 | |
| 502 | static void ast_expect_token(ParseContext *pc, Token *token, TokenId token_id) { | 503 | static void ast_expect_token(ParseContext *pc, Token *token, TokenId token_id) { |
| 503 | if (token->id == token_id) { | 504 | if (token->id == token_id) { |
| ... | @@ -1215,8 +1216,17 @@ static AstNode *ast_parse_prefix_op_expr(ParseContext *pc, int *token_index, boo | ... | @@ -1215,8 +1216,17 @@ static AstNode *ast_parse_prefix_op_expr(ParseContext *pc, int *token_index, boo |
| 1215 | if (prefix_op == PrefixOpInvalid) { | 1216 | if (prefix_op == PrefixOpInvalid) { |
| 1216 | return ast_parse_suffix_op_expr(pc, token_index, mandatory); | 1217 | return ast_parse_suffix_op_expr(pc, token_index, mandatory); |
| 1217 | } | 1218 | } |
| | 1219 | |
| | 1220 | if (prefix_op == PrefixOpError || prefix_op == PrefixOpMaybe) { |
| | 1221 | Token *maybe_return = &pc->tokens->at(*token_index + 1); |
| | 1222 | if (maybe_return->id == TokenIdKeywordReturn) { |
| | 1223 | return ast_parse_return_expr(pc, token_index); |
| | 1224 | } |
| | 1225 | } |
| | 1226 | |
| 1218 | *token_index += 1; | 1227 | *token_index += 1; |
| 1219 | | 1228 | |
| | 1229 | |
| 1220 | AstNode *node = ast_create_node(pc, NodeTypePrefixOpExpr, token); | 1230 | AstNode *node = ast_create_node(pc, NodeTypePrefixOpExpr, token); |
| 1221 | AstNode *parent_node = node; | 1231 | AstNode *parent_node = node; |
| 1222 | if (token->id == TokenIdBoolAnd) { | 1232 | if (token->id == TokenIdBoolAnd) { |
| ... | @@ -1635,9 +1645,8 @@ static AstNode *ast_parse_if_expr(ParseContext *pc, int *token_index, bool manda | ... | @@ -1635,9 +1645,8 @@ static AstNode *ast_parse_if_expr(ParseContext *pc, int *token_index, bool manda |
| 1635 | | 1645 | |
| 1636 | /* | 1646 | /* |
| 1637 | ReturnExpression : option("%" | "?") "return" option(Expression) | 1647 | ReturnExpression : option("%" | "?") "return" option(Expression) |
| 1638 | DeferExpression = option("%" | "?") "defer" option(Expression) | | |
| 1639 | */ | 1648 | */ |
| 1640 | static AstNode *ast_parse_return_or_defer_expr(ParseContext *pc, int *token_index) { | 1649 | static AstNode *ast_parse_return_expr(ParseContext *pc, int *token_index) { |
| 1641 | Token *token = &pc->tokens->at(*token_index); | 1650 | Token *token = &pc->tokens->at(*token_index); |
| 1642 | | 1651 | |
| 1643 | NodeType node_type; | 1652 | NodeType node_type; |
| ... | @@ -1649,10 +1658,6 @@ static AstNode *ast_parse_return_or_defer_expr(ParseContext *pc, int *token_inde | ... | @@ -1649,10 +1658,6 @@ static AstNode *ast_parse_return_or_defer_expr(ParseContext *pc, int *token_inde |
| 1649 | kind = ReturnKindError; | 1658 | kind = ReturnKindError; |
| 1650 | node_type = NodeTypeReturnExpr; | 1659 | node_type = NodeTypeReturnExpr; |
| 1651 | *token_index += 2; | 1660 | *token_index += 2; |
| 1652 | } else if (next_token->id == TokenIdKeywordDefer) { | | |
| 1653 | kind = ReturnKindError; | | |
| 1654 | node_type = NodeTypeDefer; | | |
| 1655 | *token_index += 2; | | |
| 1656 | } else { | 1661 | } else { |
| 1657 | return nullptr; | 1662 | return nullptr; |
| 1658 | } | 1663 | } |
| ... | @@ -1662,10 +1667,6 @@ static AstNode *ast_parse_return_or_defer_expr(ParseContext *pc, int *token_inde | ... | @@ -1662,10 +1667,6 @@ static AstNode *ast_parse_return_or_defer_expr(ParseContext *pc, int *token_inde |
| 1662 | kind = ReturnKindMaybe; | 1667 | kind = ReturnKindMaybe; |
| 1663 | node_type = NodeTypeReturnExpr; | 1668 | node_type = NodeTypeReturnExpr; |
| 1664 | *token_index += 2; | 1669 | *token_index += 2; |
| 1665 | } else if (next_token->id == TokenIdKeywordDefer) { | | |
| 1666 | kind = ReturnKindMaybe; | | |
| 1667 | node_type = NodeTypeDefer; | | |
| 1668 | *token_index += 2; | | |
| 1669 | } else { | 1670 | } else { |
| 1670 | return nullptr; | 1671 | return nullptr; |
| 1671 | } | 1672 | } |
| ... | @@ -1673,6 +1674,45 @@ static AstNode *ast_parse_return_or_defer_expr(ParseContext *pc, int *token_inde | ... | @@ -1673,6 +1674,45 @@ static AstNode *ast_parse_return_or_defer_expr(ParseContext *pc, int *token_inde |
| 1673 | kind = ReturnKindUnconditional; | 1674 | kind = ReturnKindUnconditional; |
| 1674 | node_type = NodeTypeReturnExpr; | 1675 | node_type = NodeTypeReturnExpr; |
| 1675 | *token_index += 1; | 1676 | *token_index += 1; |
| | 1677 | } else { |
| | 1678 | return nullptr; |
| | 1679 | } |
| | 1680 | |
| | 1681 | AstNode *node = ast_create_node(pc, node_type, token); |
| | 1682 | node->data.return_expr.kind = kind; |
| | 1683 | node->data.return_expr.expr = ast_parse_expression(pc, token_index, false); |
| | 1684 | |
| | 1685 | normalize_parent_ptrs(node); |
| | 1686 | return node; |
| | 1687 | } |
| | 1688 | |
| | 1689 | /* |
| | 1690 | Defer = option("%" | "?") "defer" option(Expression) |
| | 1691 | */ |
| | 1692 | static AstNode *ast_parse_defer_expr(ParseContext *pc, int *token_index) { |
| | 1693 | Token *token = &pc->tokens->at(*token_index); |
| | 1694 | |
| | 1695 | NodeType node_type; |
| | 1696 | ReturnKind kind; |
| | 1697 | |
| | 1698 | if (token->id == TokenIdPercent) { |
| | 1699 | Token *next_token = &pc->tokens->at(*token_index + 1); |
| | 1700 | if (next_token->id == TokenIdKeywordDefer) { |
| | 1701 | kind = ReturnKindError; |
| | 1702 | node_type = NodeTypeDefer; |
| | 1703 | *token_index += 2; |
| | 1704 | } else { |
| | 1705 | return nullptr; |
| | 1706 | } |
| | 1707 | } else if (token->id == TokenIdMaybe) { |
| | 1708 | Token *next_token = &pc->tokens->at(*token_index + 1); |
| | 1709 | if (next_token->id == TokenIdKeywordDefer) { |
| | 1710 | kind = ReturnKindMaybe; |
| | 1711 | node_type = NodeTypeDefer; |
| | 1712 | *token_index += 2; |
| | 1713 | } else { |
| | 1714 | return nullptr; |
| | 1715 | } |
| 1676 | } else if (token->id == TokenIdKeywordDefer) { | 1716 | } else if (token->id == TokenIdKeywordDefer) { |
| 1677 | kind = ReturnKindUnconditional; | 1717 | kind = ReturnKindUnconditional; |
| 1678 | node_type = NodeTypeDefer; | 1718 | node_type = NodeTypeDefer; |
| ... | @@ -1682,8 +1722,8 @@ static AstNode *ast_parse_return_or_defer_expr(ParseContext *pc, int *token_inde | ... | @@ -1682,8 +1722,8 @@ static AstNode *ast_parse_return_or_defer_expr(ParseContext *pc, int *token_inde |
| 1682 | } | 1722 | } |
| 1683 | | 1723 | |
| 1684 | AstNode *node = ast_create_node(pc, node_type, token); | 1724 | AstNode *node = ast_create_node(pc, node_type, token); |
| 1685 | node->data.return_expr.kind = kind; | 1725 | node->data.defer.kind = kind; |
| 1686 | node->data.return_expr.expr = ast_parse_expression(pc, token_index, false); | 1726 | node->data.defer.expr = ast_parse_expression(pc, token_index, false); |
| 1687 | | 1727 | |
| 1688 | normalize_parent_ptrs(node); | 1728 | normalize_parent_ptrs(node); |
| 1689 | return node; | 1729 | return node; |
| ... | @@ -2068,7 +2108,7 @@ NonBlockExpression : ReturnExpression | AssignmentExpression | ... | @@ -2068,7 +2108,7 @@ NonBlockExpression : ReturnExpression | AssignmentExpression |
| 2068 | static AstNode *ast_parse_non_block_expr(ParseContext *pc, int *token_index, bool mandatory) { | 2108 | static AstNode *ast_parse_non_block_expr(ParseContext *pc, int *token_index, bool mandatory) { |
| 2069 | Token *token = &pc->tokens->at(*token_index); | 2109 | Token *token = &pc->tokens->at(*token_index); |
| 2070 | | 2110 | |
| 2071 | AstNode *return_expr = ast_parse_return_or_defer_expr(pc, token_index); | 2111 | AstNode *return_expr = ast_parse_return_expr(pc, token_index); |
| 2072 | if (return_expr) | 2112 | if (return_expr) |
| 2073 | return return_expr; | 2113 | return return_expr; |
| 2074 | | 2114 | |
| ... | @@ -2142,7 +2182,7 @@ static AstNode *ast_create_void_expr(ParseContext *pc, Token *token) { | ... | @@ -2142,7 +2182,7 @@ static AstNode *ast_create_void_expr(ParseContext *pc, Token *token) { |
| 2142 | | 2182 | |
| 2143 | /* | 2183 | /* |
| 2144 | Block : token(LBrace) list(option(Statement), token(Semicolon)) token(RBrace) | 2184 | Block : token(LBrace) list(option(Statement), token(Semicolon)) token(RBrace) |
| 2145 | Statement : Label | VariableDeclaration token(Semicolon) | NonBlockExpression token(Semicolon) | BlockExpression | 2185 | Statement = Label | VariableDeclaration ";" | Defer ";" | NonBlockExpression ";" | BlockExpression |
| 2146 | */ | 2186 | */ |
| 2147 | static AstNode *ast_parse_block(ParseContext *pc, int *token_index, bool mandatory) { | 2187 | static AstNode *ast_parse_block(ParseContext *pc, int *token_index, bool mandatory) { |
| 2148 | Token *last_token = &pc->tokens->at(*token_index); | 2188 | Token *last_token = &pc->tokens->at(*token_index); |
| ... | @@ -2171,6 +2211,9 @@ static AstNode *ast_parse_block(ParseContext *pc, int *token_index, bool mandato | ... | @@ -2171,6 +2211,9 @@ static AstNode *ast_parse_block(ParseContext *pc, int *token_index, bool mandato |
| 2171 | } else { | 2211 | } else { |
| 2172 | statement_node = ast_parse_variable_declaration_expr(pc, token_index, false, | 2212 | statement_node = ast_parse_variable_declaration_expr(pc, token_index, false, |
| 2173 | nullptr, VisibModPrivate); | 2213 | nullptr, VisibModPrivate); |
| | 2214 | if (!statement_node) { |
| | 2215 | statement_node = ast_parse_defer_expr(pc, token_index); |
| | 2216 | } |
| 2174 | if (statement_node) { | 2217 | if (statement_node) { |
| 2175 | semicolon_expected = true; | 2218 | semicolon_expected = true; |
| 2176 | } else { | 2219 | } else { |