authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-02-04 15:50:06-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-02-04 15:50:06-07:00
log5490f907fe4b5c8323eaf917b1ead8760c9eca34
tree33d1326656b91928927b6e58ffcfef776c68db67
parentfcbeaddbb2321cd1006e0e007144b0f116de80be

switch statements resolve peer compatibility


4 files changed, 38 insertions(+), 13 deletions(-)

doc/langref.md+1-1
......@@ -79,7 +79,7 @@ BlockExpression = IfExpression | Block | WhileExpression | ForExpression | Switc
7979
8080SwitchExpression = "switch" "(" Expression ")" "{" many(SwitchProng) "}"
8181
82SwitchProng = (list(SwitchItem, ",") | "else") option(":" "(" "Symbol" ")") "=>" Expression ","
82SwitchProng = (list(SwitchItem, ",") | "else") "=>" option("|" "Symbol" "|") Expression ","
8383
8484SwitchItem = Expression | (Expression "..." Expression)
8585
src/analyze.cpp+7-6
......@@ -4479,9 +4479,9 @@ static TypeTableEntry *analyze_switch_expr(CodeGen *g, ImportTableEntry *import,
44794479 AstNode *expr_node = node->data.switch_expr.expr;
44804480 TypeTableEntry *expr_type = analyze_expression(g, import, context, nullptr, expr_node);
44814481
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);
44854485
44864486 if (expr_type->id == TypeTableEntryIdInvalid) {
44874487 return expr_type;
......@@ -4491,7 +4491,7 @@ static TypeTableEntry *analyze_switch_expr(CodeGen *g, ImportTableEntry *import,
44914491 return g->builtin_types.entry_invalid;
44924492 } else {
44934493 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) {
44954495 AstNode *prong_node = node->data.switch_expr.prongs.at(prong_i);
44964496
44974497 TypeTableEntry *var_type;
......@@ -4528,11 +4528,12 @@ static TypeTableEntry *analyze_switch_expr(CodeGen *g, ImportTableEntry *import,
45284528 var_type, true);
45294529 }
45304530
4531 analyze_expression(g, import, child_context, expected_type,
4531 peer_types[prong_i] = analyze_expression(g, import, child_context, expected_type,
45324532 prong_node->data.switch_prong.expr);
4533 peer_nodes[prong_i] = prong_node->data.switch_prong.expr;
45334534 }
45344535 }
4535 return expected_type;
4536 return resolve_peer_type_compatibility(g, import, context, node, peer_nodes, peer_types, prong_count);
45364537}
45374538
45384539static 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
18341834
18351835/*
18361836SwitchExpression : "switch" "(" Expression ")" "{" many(SwitchProng) "}"
1837SwitchProng : (list(SwitchItem, ",") | "else") option("," "(" "Symbol" ")") "=>" Expression ","
1837SwitchProng = (list(SwitchItem, ",") | "else") "=>" option("|" "Symbol" "|") Expression ","
18381838SwitchItem : Expression | (Expression "..." Expression)
18391839*/
18401840static 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
18951895 break;
18961896 }
18971897
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) {
19001902 *token_index += 1;
1901 ast_eat_token(pc, token_index, TokenIdLParen);
19021903 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);
19041905 }
19051906
1906 ast_eat_token(pc, token_index, TokenIdFatArrow);
19071907 prong_node->data.switch_prong.expr = ast_parse_expression(pc, token_index, true);
19081908 ast_eat_token(pc, token_index, TokenIdComma);
19091909
test/self_hosted.zig+24
......@@ -105,3 +105,27 @@ fn non_const_cast_bool_to_int(t: bool, f: bool) {
105105 if (i32(t) != i32(1)) unreachable{}
106106 if (i32(f) != i32(0)) unreachable{}
107107}
108
109
110#attribute("test")
111fn 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}
120enum Fruit {
121 Apple,
122 Orange,
123 Banana,
124}
125fn non_const_switch_on_enum(fruit: Fruit) {
126 switch (fruit) {
127 Fruit.Apple => unreachable{},
128 Fruit.Orange => {},
129 Fruit.Banana => unreachable{},
130 }
131}