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.

identifier

AstGen.identifier
fn identifier(
    gz: *GenZir,
    scope: *Scope,
    ri: ResultInfo,
    ident: Ast.Node.Index,
    force_comptime: ?ComptimeBlockInfo,
) InnerError!Zir.Inst.Ref

File

lib/std/zig/AstGen.zig:8054

Code

fn identifier(
    gz: *GenZir,
    scope: *Scope,
    ri: ResultInfo,
    ident: Ast.Node.Index,
    force_comptime: ?ComptimeBlockInfo,
) InnerError!Zir.Inst.Ref {
    const astgen = gz.astgen;
    const tree = astgen.tree;

    const ident_token = tree.nodeMainToken(ident);
    const ident_name_raw = tree.tokenSlice(ident_token);
    if (mem.eql(u8, ident_name_raw, "_")) {
        return astgen.failNode(ident, "'_' used as an identifier without @\"_\" syntax", .{});
    }

    // if not @"" syntax, just use raw token slice
    if (ident_name_raw[0] != '@') {
        if (primitive_instrs.get(ident_name_raw)) |zir_const_ref| {
            return rvalue(gz, ri, zir_const_ref, ident);
        }

        int_type: {
            if (ident_name_raw.len < 2) break :int_type;
            const signedness: std.lang.Signedness = switch (ident_name_raw[0]) {
                'u' => .unsigned,
                'i' => .signed,
                else => break :int_type,
            };
            // `u0` already handled by `primitive_instrs`
            if (std.mem.eql(u8, ident_name_raw, "i0")) {
                return astgen.failNode(ident, "signed integer cannot have bit width 0", .{});
            }
            const bit_count = parseBitCount(ident_name_raw[1..]) catch |err| switch (err) {
                error.Overflow => return astgen.failNode(
                    ident,
                    "primitive integer type '{s}' exceeds maximum bit width of 65535",
                    .{ident_name_raw},
                ),
                error.InvalidCharacter => break :int_type,
            };
            if (ident_name_raw[1] == '0') {
                assert(ident_name_raw.len >= 3); // `u0` and `i0` handled
                return astgen.failNode(
                    ident,
                    "primitive integer type '{s}' has leading zero",
                    .{ident_name_raw},
                );
            }
            const result = try gz.add(.{
                .tag = .int_type,
                .data = .{ .int_type = .{
                    .src_node = gz.nodeIndexToRelative(ident),
                    .signedness = signedness,
                    .bit_count = bit_count,
                } },
            });
            return rvalue(gz, ri, result, ident);
        }
    }

    // Local variables, including function parameters, and container-level declarations.

    if (force_comptime) |fc| {
        // Mirrors the logic at the end of `comptimeExpr2`.
        const block_inst = try gz.makeBlockInst(.block_comptime, fc.src_node);

        var comptime_gz = gz.makeSubBlock(scope);
        comptime_gz.is_comptime = true;
        defer comptime_gz.unstack();

        const sub_ri: ResultInfo = .{
            .ctx = ri.ctx,
            .rl = .none, // no point providing a result type, it won't change anything
        };
        const block_result = try localVarRef(&comptime_gz, scope, sub_ri, ident, ident_token);
        assert(!comptime_gz.endsWithNoReturn());
        _ = try comptime_gz.addBreak(.break_inline, block_inst, block_result);

        try comptime_gz.setBlockComptimeBody(block_inst, fc.reason);
        try gz.instructions.append(astgen.gpa, block_inst);

        return rvalue(gz, ri, block_inst.toRef(), fc.src_node);
    } else {
        return localVarRef(gz, scope, ri, ident, ident_token);
    }
}