feature. See also
. The project being documented here (as the example) is the Zig library itself.
Translator.transSwitch
fn transSwitch(t: *Translator, scope: *Scope, switch_stmt: Node.SwitchStmt) TransError!ZigNode
File
Code
fn transSwitch(t: *Translator, scope: *Scope, switch_stmt: Node.SwitchStmt) TransError!ZigNode {
var loop_scope: Scope = .{
.parent = scope,
.id = .loop,
};
var block_scope = try Scope.Block.init(t, &loop_scope, false);
defer block_scope.deinit();
const base_scope = &block_scope.base;
var cond_scope: Scope.Condition = .{
.base = .{
.parent = base_scope,
.id = .condition,
},
};
defer cond_scope.deinit();
const switch_expr = try t.transExpr(&cond_scope.base, switch_stmt.cond, .used);
var cases: std.ArrayList(ZigNode) = .empty;
defer cases.deinit(t.gpa);
var has_default = false;
const body_node = switch_stmt.body.get(t.tree);
if (body_node != .compound_stmt) {
return t.fail(error.UnsupportedTranslation, switch_stmt.switch_tok, "TODO complex switch", .{});
}
const body = body_node.compound_stmt.body;
// Fallthrough is handled by duplicating statements.
for (body, 0..) |stmt, i| {
switch (stmt.get(t.tree)) {
.case_stmt => {
var items: std.ArrayList(ZigNode) = .empty;
defer items.deinit(t.gpa);
const sub = try t.transCaseStmt(base_scope, stmt, &items);
const res = try t.transSwitchProngStmt(base_scope, sub, body[i..]);
if (items.items.len == 0) {
has_default = true;
const switch_else = try ZigTag.switch_else.create(t.arena, res);
try cases.append(t.gpa, switch_else);
} else {
const switch_prong = try ZigTag.switch_prong.create(t.arena, .{
.cases = try t.arena.dupe(ZigNode, items.items),
.cond = res,
});
try cases.append(t.gpa, switch_prong);
}
},
.default_stmt => |default_stmt| {
has_default = true;
var sub = default_stmt.body;
while (true) switch (sub.get(t.tree)) {
.case_stmt => |sub_case| sub = sub_case.body,
.default_stmt => |sub_default| sub = sub_default.body,
else => break,
};
const res = try t.transSwitchProngStmt(base_scope, sub, body[i..]);
const switch_else = try ZigTag.switch_else.create(t.arena, res);
try cases.append(t.gpa, switch_else);
},
else => {},
}
}
if (!has_default) {
const else_prong = try ZigTag.switch_else.create(t.arena, ZigTag.empty_block.init());
try cases.append(t.gpa, else_prong);
}
const switch_node = try ZigTag.@"switch".create(t.arena, .{
.cond = switch_expr,
.cases = try t.arena.dupe(ZigNode, cases.items),
});
try block_scope.statements.append(t.gpa, switch_node);
try block_scope.statements.append(t.gpa, ZigTag.@"break".init());
const while_body = try block_scope.complete();
return ZigTag.while_true.create(t.arena, while_body);
}