Zig 0.17.0-dev (Split by item)

This is an example of documentation generated by ZigDoc, an alternative to Zig's built-in Auto Doc feature. See also examples in other modes/formats. The project being documented here (as the example) is the Zig library itself.

transSwitch

Translator.transSwitch
fn transSwitch(t: *Translator, scope: *Scope, switch_stmt: Node.SwitchStmt) TransError!ZigNode

File

lib/compiler/translate-c/Translator.zig:1932

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;
    // Iterate over switch body and collect all cases.
    // 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 => {}, // collected in transSwitchProngStmt
        }
    }

    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);
}