mirror of
https://github.com/ziglang/zig.git
synced 2026-02-18 23:39:17 +00:00
switch statements resolve peer compatibility
This commit is contained in:
parent
fcbeaddbb2
commit
5490f907fe
@ -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)
|
||||
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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);
|
||||
|
||||
|
||||
@ -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{},
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user