| author | |
| committer | |
| log | 5490f907fe4b5c8323eaf917b1ead8760c9eca34 |
| tree | 33d1326656b91928927b6e58ffcfef776c68db67 |
| parent | fcbeaddbb2321cd1006e0e007144b0f116de80be |
4 files changed, 38 insertions(+), 13 deletions(-)
doc/langref.md+1-1| ... | ... | @@ -79,7 +79,7 @@ BlockExpression = IfExpression | Block | WhileExpression | ForExpression | Switc |
| 79 | 79 | |
| 80 | 80 | SwitchExpression = "switch" "(" Expression ")" "{" many(SwitchProng) "}" |
| 81 | 81 | |
| 82 | SwitchProng = (list(SwitchItem, ",") | "else") option(":" "(" "Symbol" ")") "=>" Expression "," | |
| 82 | SwitchProng = (list(SwitchItem, ",") | "else") "=>" option("|" "Symbol" "|") Expression "," | |
| 83 | 83 | |
| 84 | 84 | SwitchItem = Expression | (Expression "..." Expression) |
| 85 | 85 |
src/analyze.cpp+7-6| ... | ... | @@ -4479,9 +4479,9 @@ static TypeTableEntry *analyze_switch_expr(CodeGen *g, ImportTableEntry *import, |
| 4479 | 4479 | AstNode *expr_node = node->data.switch_expr.expr; |
| 4480 | 4480 | TypeTableEntry *expr_type = analyze_expression(g, import, context, nullptr, expr_node); |
| 4481 | 4481 | |
| 4482 | if (expected_type == nullptr) { | |
| 4483 | zig_panic("TODO resolve peer compatibility of switch prongs"); | |
| 4484 | } | |
| 4482 | int prong_count = node->data.switch_expr.prongs.length; | |
| 4483 | AstNode **peer_nodes = allocate<AstNode*>(prong_count); | |
| 4484 | TypeTableEntry **peer_types = allocate<TypeTableEntry*>(prong_count); | |
| 4485 | 4485 | |
| 4486 | 4486 | if (expr_type->id == TypeTableEntryIdInvalid) { |
| 4487 | 4487 | return expr_type; |
| ... | ... | @@ -4491,7 +4491,7 @@ static TypeTableEntry *analyze_switch_expr(CodeGen *g, ImportTableEntry *import, |
| 4491 | 4491 | return g->builtin_types.entry_invalid; |
| 4492 | 4492 | } else { |
| 4493 | 4493 | AstNode *else_prong = nullptr; |
| 4494 | for (int prong_i = 0; prong_i < node->data.switch_expr.prongs.length; prong_i += 1) { | |
| 4494 | for (int prong_i = 0; prong_i < prong_count; prong_i += 1) { | |
| 4495 | 4495 | AstNode *prong_node = node->data.switch_expr.prongs.at(prong_i); |
| 4496 | 4496 | |
| 4497 | 4497 | TypeTableEntry *var_type; |
| ... | ... | @@ -4528,11 +4528,12 @@ static TypeTableEntry *analyze_switch_expr(CodeGen *g, ImportTableEntry *import, |
| 4528 | 4528 | var_type, true); |
| 4529 | 4529 | } |
| 4530 | 4530 | |
| 4531 | analyze_expression(g, import, child_context, expected_type, | |
| 4531 | peer_types[prong_i] = analyze_expression(g, import, child_context, expected_type, | |
| 4532 | 4532 | prong_node->data.switch_prong.expr); |
| 4533 | peer_nodes[prong_i] = prong_node->data.switch_prong.expr; | |
| 4533 | 4534 | } |
| 4534 | 4535 | } |
| 4535 | return expected_type; | |
| 4536 | return resolve_peer_type_compatibility(g, import, context, node, peer_nodes, peer_types, prong_count); | |
| 4536 | 4537 | } |
| 4537 | 4538 | |
| 4538 | 4539 | static TypeTableEntry *analyze_return_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context, |
src/parser.cpp+6-6| ... | ... | @@ -1834,7 +1834,7 @@ static AstNode *ast_parse_for_expr(ParseContext *pc, int *token_index, bool mand |
| 1834 | 1834 | |
| 1835 | 1835 | /* |
| 1836 | 1836 | SwitchExpression : "switch" "(" Expression ")" "{" many(SwitchProng) "}" |
| 1837 | SwitchProng : (list(SwitchItem, ",") | "else") option("," "(" "Symbol" ")") "=>" Expression "," | |
| 1837 | SwitchProng = (list(SwitchItem, ",") | "else") "=>" option("|" "Symbol" "|") Expression "," | |
| 1838 | 1838 | SwitchItem : Expression | (Expression "..." Expression) |
| 1839 | 1839 | */ |
| 1840 | 1840 | static AstNode *ast_parse_switch_expr(ParseContext *pc, int *token_index, bool mandatory) { |
| ... | ... | @@ -1895,15 +1895,15 @@ static AstNode *ast_parse_switch_expr(ParseContext *pc, int *token_index, bool m |
| 1895 | 1895 | break; |
| 1896 | 1896 | } |
| 1897 | 1897 | |
| 1898 | Token *arrow_or_colon = &pc->tokens->at(*token_index); | |
| 1899 | if (arrow_or_colon->id == TokenIdColon) { | |
| 1898 | ast_eat_token(pc, token_index, TokenIdFatArrow); | |
| 1899 | ||
| 1900 | Token *maybe_bar = &pc->tokens->at(*token_index); | |
| 1901 | if (maybe_bar->id == TokenIdBinOr) { | |
| 1900 | 1902 | *token_index += 1; |
| 1901 | ast_eat_token(pc, token_index, TokenIdLParen); | |
| 1902 | 1903 | prong_node->data.switch_prong.var_symbol = ast_parse_symbol(pc, token_index); |
| 1903 | ast_eat_token(pc, token_index, TokenIdRParen); | |
| 1904 | ast_eat_token(pc, token_index, TokenIdBinOr); | |
| 1904 | 1905 | } |
| 1905 | 1906 | |
| 1906 | ast_eat_token(pc, token_index, TokenIdFatArrow); | |
| 1907 | 1907 | prong_node->data.switch_prong.expr = ast_parse_expression(pc, token_index, true); |
| 1908 | 1908 | ast_eat_token(pc, token_index, TokenIdComma); |
| 1909 | 1909 |
test/self_hosted.zig+24| ... | ... | @@ -105,3 +105,27 @@ fn non_const_cast_bool_to_int(t: bool, f: bool) { |
| 105 | 105 | if (i32(t) != i32(1)) unreachable{} |
| 106 | 106 | if (i32(f) != i32(0)) unreachable{} |
| 107 | 107 | } |
| 108 | ||
| 109 | ||
| 110 | #attribute("test") | |
| 111 | fn switch_on_enum() { | |
| 112 | const fruit = Fruit.Orange; | |
| 113 | switch (fruit) { | |
| 114 | Fruit.Apple => unreachable{}, | |
| 115 | Fruit.Orange => {}, | |
| 116 | Fruit.Banana => unreachable{}, | |
| 117 | } | |
| 118 | non_const_switch_on_enum(fruit); | |
| 119 | } | |
| 120 | enum Fruit { | |
| 121 | Apple, | |
| 122 | Orange, | |
| 123 | Banana, | |
| 124 | } | |
| 125 | fn non_const_switch_on_enum(fruit: Fruit) { | |
| 126 | switch (fruit) { | |
| 127 | Fruit.Apple => unreachable{}, | |
| 128 | Fruit.Orange => {}, | |
| 129 | Fruit.Banana => unreachable{}, | |
| 130 | } | |
| 131 | } |