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...@@ -79,7 +79,7 @@ BlockExpression = IfExpression | Block | WhileExpression | ForExpression | Switc
7979
80SwitchExpression = "switch" "(" Expression ")" "{" many(SwitchProng) "}"80SwitchExpression = "switch" "(" Expression ")" "{" many(SwitchProng) "}"
8181
82SwitchProng = (list(SwitchItem, ",") | "else") option(":" "(" "Symbol" ")") "=>" Expression ","82SwitchProng = (list(SwitchItem, ",") | "else") "=>" option("|" "Symbol" "|") Expression ","
8383
84SwitchItem = Expression | (Expression "..." Expression)84SwitchItem = Expression | (Expression "..." Expression)
8585
src/analyze.cpp+7-6
...@@ -4479,9 +4479,9 @@ static TypeTableEntry *analyze_switch_expr(CodeGen *g, ImportTableEntry *import,...@@ -4479,9 +4479,9 @@ static TypeTableEntry *analyze_switch_expr(CodeGen *g, ImportTableEntry *import,
4479 AstNode *expr_node = node->data.switch_expr.expr;4479 AstNode *expr_node = node->data.switch_expr.expr;
4480 TypeTableEntry *expr_type = analyze_expression(g, import, context, nullptr, expr_node);4480 TypeTableEntry *expr_type = analyze_expression(g, import, context, nullptr, expr_node);
44814481
4482 if (expected_type == nullptr) {4482 int prong_count = node->data.switch_expr.prongs.length;
4483 zig_panic("TODO resolve peer compatibility of switch prongs");4483 AstNode **peer_nodes = allocate<AstNode*>(prong_count);
4484 }4484 TypeTableEntry **peer_types = allocate<TypeTableEntry*>(prong_count);
44854485
4486 if (expr_type->id == TypeTableEntryIdInvalid) {4486 if (expr_type->id == TypeTableEntryIdInvalid) {
4487 return expr_type;4487 return expr_type;
...@@ -4491,7 +4491,7 @@ static TypeTableEntry *analyze_switch_expr(CodeGen *g, ImportTableEntry *import,...@@ -4491,7 +4491,7 @@ static TypeTableEntry *analyze_switch_expr(CodeGen *g, ImportTableEntry *import,
4491 return g->builtin_types.entry_invalid;4491 return g->builtin_types.entry_invalid;
4492 } else {4492 } else {
4493 AstNode *else_prong = nullptr;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 AstNode *prong_node = node->data.switch_expr.prongs.at(prong_i);4495 AstNode *prong_node = node->data.switch_expr.prongs.at(prong_i);
44964496
4497 TypeTableEntry *var_type;4497 TypeTableEntry *var_type;
...@@ -4528,11 +4528,12 @@ static TypeTableEntry *analyze_switch_expr(CodeGen *g, ImportTableEntry *import,...@@ -4528,11 +4528,12 @@ static TypeTableEntry *analyze_switch_expr(CodeGen *g, ImportTableEntry *import,
4528 var_type, true);4528 var_type, true);
4529 }4529 }
45304530
4531 analyze_expression(g, import, child_context, expected_type,4531 peer_types[prong_i] = analyze_expression(g, import, child_context, expected_type,
4532 prong_node->data.switch_prong.expr);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}
45374538
4538static TypeTableEntry *analyze_return_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,4539static 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,7 +1834,7 @@ static AstNode *ast_parse_for_expr(ParseContext *pc, int *token_index, bool mand
18341834
1835/*1835/*
1836SwitchExpression : "switch" "(" Expression ")" "{" many(SwitchProng) "}"1836SwitchExpression : "switch" "(" Expression ")" "{" many(SwitchProng) "}"
1837SwitchProng : (list(SwitchItem, ",") | "else") option("," "(" "Symbol" ")") "=>" Expression ","1837SwitchProng = (list(SwitchItem, ",") | "else") "=>" option("|" "Symbol" "|") Expression ","
1838SwitchItem : Expression | (Expression "..." Expression)1838SwitchItem : Expression | (Expression "..." Expression)
1839*/1839*/
1840static AstNode *ast_parse_switch_expr(ParseContext *pc, int *token_index, bool mandatory) {1840static 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,15 +1895,15 @@ static AstNode *ast_parse_switch_expr(ParseContext *pc, int *token_index, bool m
1895 break;1895 break;
1896 }1896 }
18971897
1898 Token *arrow_or_colon = &pc->tokens->at(*token_index);1898 ast_eat_token(pc, token_index, TokenIdFatArrow);
1899 if (arrow_or_colon->id == TokenIdColon) {1899
1900 Token *maybe_bar = &pc->tokens->at(*token_index);
1901 if (maybe_bar->id == TokenIdBinOr) {
1900 *token_index += 1;1902 *token_index += 1;
1901 ast_eat_token(pc, token_index, TokenIdLParen);
1902 prong_node->data.switch_prong.var_symbol = ast_parse_symbol(pc, token_index);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 }
19051906
1906 ast_eat_token(pc, token_index, TokenIdFatArrow);
1907 prong_node->data.switch_prong.expr = ast_parse_expression(pc, token_index, true);1907 prong_node->data.switch_prong.expr = ast_parse_expression(pc, token_index, true);
1908 ast_eat_token(pc, token_index, TokenIdComma);1908 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) {...@@ -105,3 +105,27 @@ fn non_const_cast_bool_to_int(t: bool, f: bool) {
105 if (i32(t) != i32(1)) unreachable{}105 if (i32(t) != i32(1)) unreachable{}
106 if (i32(f) != i32(0)) unreachable{}106 if (i32(f) != i32(0)) unreachable{}
107}107}
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}