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.

globalVarDecl

AstGen.globalVarDecl
fn globalVarDecl(
    astgen: *AstGen,
    gz: *GenZir,
    scope: *Scope,
    wip_decls: *WipDecls,
    node: Ast.Node.Index,
    var_decl: Ast.full.VarDecl,
) InnerError!void

File

lib/std/zig/AstGen.zig:4396

Code

fn globalVarDecl(
    astgen: *AstGen,
    gz: *GenZir,
    scope: *Scope,
    wip_decls: *WipDecls,
    node: Ast.Node.Index,
    var_decl: Ast.full.VarDecl,
) InnerError!void {
    const tree = astgen.tree;

    const old_hasher = astgen.src_hasher;
    defer astgen.src_hasher = old_hasher;
    astgen.src_hasher = std.zig.SrcHasher.init(.{});
    astgen.src_hasher.update(tree.getNodeSource(node));
    astgen.src_hasher.update(std.mem.asBytes(&astgen.source_column));

    const is_mutable = tree.tokenTag(var_decl.ast.mut_token) == .keyword_var;
    const name_token = var_decl.ast.mut_token + 1;
    const is_pub = var_decl.visib_token != null;
    const is_export = blk: {
        const maybe_export_token = var_decl.extern_export_token orelse break :blk false;
        break :blk tree.tokenTag(maybe_export_token) == .keyword_export;
    };
    const is_extern = blk: {
        const maybe_extern_token = var_decl.extern_export_token orelse break :blk false;
        break :blk tree.tokenTag(maybe_extern_token) == .keyword_extern;
    };
    const is_threadlocal = if (var_decl.threadlocal_token) |tok| blk: {
        if (!is_mutable) {
            return astgen.failTok(tok, "threadlocal variable cannot be constant", .{});
        }
        break :blk true;
    } else false;
    const lib_name = if (var_decl.lib_name) |lib_name_token| blk: {
        const lib_name_str = try astgen.strLitAsString(lib_name_token);
        const lib_name_slice = astgen.string_bytes.items[@backingInt(lib_name_str.index)..][0..lib_name_str.len];
        if (mem.findScalar(u8, lib_name_slice, 0) != null) {
            return astgen.failTok(lib_name_token, "library name cannot contain null bytes", .{});
        } else if (lib_name_str.len == 0) {
            return astgen.failTok(lib_name_token, "library name cannot be empty", .{});
        }
        break :blk lib_name_str.index;
    } else .empty;

    astgen.advanceSourceCursorToNode(node);

    const decl_column = astgen.source_column;

    const decl_inst = try gz.makeDeclaration(node);
    wip_decls.nextDecl(decl_inst);

    if (var_decl.ast.init_node.unwrap()) |init_node| {
        if (is_extern) {
            return astgen.failNode(
                init_node,
                "extern variables have no initializers",
                .{},
            );
        }
    } else {
        if (!is_extern) {
            return astgen.failNode(node, "variables must be initialized", .{});
        }
    }

    if (is_extern and var_decl.ast.type_node == .none) {
        return astgen.failNode(node, "unable to infer variable type", .{});
    }

    assert(var_decl.comptime_token == null); // handled by parser

    var type_gz: GenZir = .{
        .parent = scope,
        .decl_node_index = node,
        .decl_line = astgen.source_line,
        .astgen = astgen,
        .is_comptime = true,
        .instructions = gz.instructions,
        .instructions_top = gz.instructions.items.len,
    };
    defer type_gz.unstack();

    if (var_decl.ast.type_node.unwrap()) |type_node| {
        const type_inst = try expr(&type_gz, &type_gz.base, coerced_type_ri, type_node);
        _ = try type_gz.addBreakWithSrcNode(.break_inline, decl_inst, type_inst, node);
    }

    var align_gz = type_gz.makeSubBlock(scope);
    defer align_gz.unstack();

    if (var_decl.ast.align_node.unwrap()) |align_node| {
        const align_inst = try expr(&align_gz, &align_gz.base, coerced_align_ri, align_node);
        _ = try align_gz.addBreakWithSrcNode(.break_inline, decl_inst, align_inst, node);
    }

    var linksection_gz = type_gz.makeSubBlock(scope);
    defer linksection_gz.unstack();

    if (var_decl.ast.section_node.unwrap()) |section_node| {
        const linksection_inst = try expr(&linksection_gz, &linksection_gz.base, coerced_linksection_ri, section_node);
        _ = try linksection_gz.addBreakWithSrcNode(.break_inline, decl_inst, linksection_inst, node);
    }

    var addrspace_gz = type_gz.makeSubBlock(scope);
    defer addrspace_gz.unstack();

    if (var_decl.ast.addrspace_node.unwrap()) |addrspace_node| {
        const addrspace_ty = try addrspace_gz.addStdLangValue(addrspace_node, .address_space);
        const addrspace_inst = try expr(&addrspace_gz, &addrspace_gz.base, .{ .rl = .{ .coerced_ty = addrspace_ty } }, addrspace_node);
        _ = try addrspace_gz.addBreakWithSrcNode(.break_inline, decl_inst, addrspace_inst, node);
    }

    var init_gz = type_gz.makeSubBlock(scope);
    defer init_gz.unstack();

    if (var_decl.ast.init_node.unwrap()) |init_node| {
        const init_ri: ResultInfo = if (var_decl.ast.type_node != .none) .{
            .rl = .{ .coerced_ty = decl_inst.toRef() },
        } else .{ .rl = .none };
        const init_inst: Zir.Inst.Ref = try nameStratExpr(&init_gz, &init_gz.base, init_ri, init_node, .parent) orelse init: {
            break :init try expr(&init_gz, &init_gz.base, init_ri, init_node);
        };
        _ = try init_gz.addBreakWithSrcNode(.break_inline, decl_inst, init_inst, node);
    }

    var hash: std.zig.SrcHash = undefined;
    astgen.src_hasher.final(&hash);
    try setDeclaration(decl_inst, .{
        .src_hash = hash,
        .src_line = type_gz.decl_line,
        .src_column = decl_column,

        .kind = if (is_mutable) .@"var" else .@"const",
        .name = try astgen.identAsString(name_token),
        .is_pub = is_pub,
        .is_threadlocal = is_threadlocal,
        .linkage = if (is_extern) .@"extern" else if (is_export) .@"export" else .normal,
        .lib_name = lib_name,

        .type_gz = &type_gz,
        .align_gz = &align_gz,
        .linksection_gz = &linksection_gz,
        .addrspace_gz = &addrspace_gz,
        .value_gz = &init_gz,
    });
}