Commit 5490f907fe
Changed files (4)
doc/langref.md
@@ -79,7 +79,7 @@ BlockExpression = IfExpression | Block | WhileExpression | ForExpression | Switc
SwitchExpression = "switch" "(" Expression ")" "{" many(SwitchProng) "}"
-SwitchProng = (list(SwitchItem, ",") | "else") option(":" "(" "Symbol" ")") "=>" Expression ","
+SwitchProng = (list(SwitchItem, ",") | "else") "=>" option("|" "Symbol" "|") Expression ","
SwitchItem = Expression | (Expression "..." Expression)
src/analyze.cpp
@@ -4479,9 +4479,9 @@ static TypeTableEntry *analyze_switch_expr(CodeGen *g, ImportTableEntry *import,
AstNode *expr_node = node->data.switch_expr.expr;
TypeTableEntry *expr_type = analyze_expression(g, import, context, nullptr, expr_node);
- if (expected_type == nullptr) {
- zig_panic("TODO resolve peer compatibility of switch prongs");
- }
+ int prong_count = node->data.switch_expr.prongs.length;
+ AstNode **peer_nodes = allocate<AstNode*>(prong_count);
+ TypeTableEntry **peer_types = allocate<TypeTableEntry*>(prong_count);
if (expr_type->id == TypeTableEntryIdInvalid) {
return expr_type;
@@ -4491,7 +4491,7 @@ static TypeTableEntry *analyze_switch_expr(CodeGen *g, ImportTableEntry *import,
return g->builtin_types.entry_invalid;
} else {
AstNode *else_prong = nullptr;
- for (int prong_i = 0; prong_i < node->data.switch_expr.prongs.length; prong_i += 1) {
+ for (int prong_i = 0; prong_i < prong_count; prong_i += 1) {
AstNode *prong_node = node->data.switch_expr.prongs.at(prong_i);
TypeTableEntry *var_type;
@@ -4528,11 +4528,12 @@ static TypeTableEntry *analyze_switch_expr(CodeGen *g, ImportTableEntry *import,
var_type, true);
}
- analyze_expression(g, import, child_context, expected_type,
+ peer_types[prong_i] = analyze_expression(g, import, child_context, expected_type,
prong_node->data.switch_prong.expr);
+ peer_nodes[prong_i] = prong_node->data.switch_prong.expr;
}
}
- return expected_type;
+ return resolve_peer_type_compatibility(g, import, context, node, peer_nodes, peer_types, prong_count);
}
static TypeTableEntry *analyze_return_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,
src/parser.cpp
@@ -1834,7 +1834,7 @@ static AstNode *ast_parse_for_expr(ParseContext *pc, int *token_index, bool mand
/*
SwitchExpression : "switch" "(" Expression ")" "{" many(SwitchProng) "}"
-SwitchProng : (list(SwitchItem, ",") | "else") option("," "(" "Symbol" ")") "=>" Expression ","
+SwitchProng = (list(SwitchItem, ",") | "else") "=>" option("|" "Symbol" "|") Expression ","
SwitchItem : Expression | (Expression "..." Expression)
*/
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
break;
}
- Token *arrow_or_colon = &pc->tokens->at(*token_index);
- if (arrow_or_colon->id == TokenIdColon) {
+ ast_eat_token(pc, token_index, TokenIdFatArrow);
+
+ Token *maybe_bar = &pc->tokens->at(*token_index);
+ if (maybe_bar->id == TokenIdBinOr) {
*token_index += 1;
- ast_eat_token(pc, token_index, TokenIdLParen);
prong_node->data.switch_prong.var_symbol = ast_parse_symbol(pc, token_index);
- ast_eat_token(pc, token_index, TokenIdRParen);
+ ast_eat_token(pc, token_index, TokenIdBinOr);
}
- ast_eat_token(pc, token_index, TokenIdFatArrow);
prong_node->data.switch_prong.expr = ast_parse_expression(pc, token_index, true);
ast_eat_token(pc, token_index, TokenIdComma);
test/self_hosted.zig
@@ -105,3 +105,27 @@ fn non_const_cast_bool_to_int(t: bool, f: bool) {
if (i32(t) != i32(1)) unreachable{}
if (i32(f) != i32(0)) unreachable{}
}
+
+
+#attribute("test")
+fn switch_on_enum() {
+ const fruit = Fruit.Orange;
+ switch (fruit) {
+ Fruit.Apple => unreachable{},
+ Fruit.Orange => {},
+ Fruit.Banana => unreachable{},
+ }
+ non_const_switch_on_enum(fruit);
+}
+enum Fruit {
+ Apple,
+ Orange,
+ Banana,
+}
+fn non_const_switch_on_enum(fruit: Fruit) {
+ switch (fruit) {
+ Fruit.Apple => unreachable{},
+ Fruit.Orange => {},
+ Fruit.Banana => unreachable{},
+ }
+}