feature. See also
. The project being documented here (as the example) is the Zig library itself.
AstGen.generate
pub fn generate(gpa: Allocator, tree: Ast) Allocator.Error!Zir
File
Code
pub fn generate(gpa: Allocator, tree: Ast) Allocator.Error!Zir {
assert(tree.mode == .zig);
var arena = std.heap.ArenaAllocator.init(gpa);
defer arena.deinit();
var nodes_need_rl = try AstRlAnnotate.annotate(gpa, arena.allocator(), tree);
defer nodes_need_rl.deinit(gpa);
var astgen: AstGen = .{
.gpa = gpa,
.arena = arena.allocator(),
.tree = &tree,
.nodes_need_rl = &nodes_need_rl,
.src_hasher = undefined,
};
defer astgen.deinit(gpa);
try astgen.string_bytes.append(gpa, 0);
// as AST nodes.
try astgen.instructions.ensureTotalCapacity(gpa, tree.nodes.len);
const reserved_count = @typeInfo(Zir.ExtraIndex).@"enum".field_names.len;
try astgen.extra.ensureTotalCapacity(gpa, tree.nodes.len + reserved_count);
astgen.extra.items.len += reserved_count;
var top_scope: Scope.Top = .{};
var gz_instructions: std.ArrayList(Zir.Inst.Index) = .empty;
var gen_scope: GenZir = .{
.is_comptime = true,
.parent = &top_scope.base,
.decl_node_index = .root,
.decl_line = 0,
.astgen = &astgen,
.instructions = &gz_instructions,
.instructions_top = 0,
};
defer gz_instructions.deinit(gpa);
// Parse errors, or AstGen errors in the root struct, are considered "fatal", so we emit no ZIR.
const fatal = if (tree.errors.len == 0) fatal: {
if (AstGen.structDeclInner(
&gen_scope,
&gen_scope.base,
.root,
tree.containerDeclRoot(),
.auto,
.none,
.parent,
)) |struct_decl_ref| {
assert(struct_decl_ref.toIndex().? == .main_struct_inst);
break :fatal false;
} else |err| switch (err) {
error.OutOfMemory => |e| return e,
error.AnalysisFail => break :fatal true,
}
} else fatal: {
try lowerAstErrors(&astgen);
break :fatal true;
};
const err_index = @backingInt(Zir.ExtraIndex.compile_errors);
if (astgen.compile_errors.items.len == 0) {
astgen.extra.items[err_index] = 0;
} else {
try astgen.extra.ensureUnusedCapacity(gpa, 1 + astgen.compile_errors.items.len *
@typeInfo(Zir.Inst.CompileErrors.Item).@"struct".field_names.len);
astgen.extra.items[err_index] = astgen.addExtraAssumeCapacity(Zir.Inst.CompileErrors{
.items_len = @intCast(astgen.compile_errors.items.len),
});
for (astgen.compile_errors.items) |item| {
_ = astgen.addExtraAssumeCapacity(item);
}
}
const imports_index = @backingInt(Zir.ExtraIndex.imports);
if (astgen.imports.count() == 0) {
astgen.extra.items[imports_index] = 0;
} else {
try astgen.extra.ensureUnusedCapacity(gpa, @typeInfo(Zir.Inst.Imports).@"struct".field_names.len +
astgen.imports.count() * @typeInfo(Zir.Inst.Imports.Item).@"struct".field_names.len);
astgen.extra.items[imports_index] = astgen.addExtraAssumeCapacity(Zir.Inst.Imports{
.imports_len = @intCast(astgen.imports.count()),
});
var it = astgen.imports.iterator();
while (it.next()) |entry| {
_ = astgen.addExtraAssumeCapacity(Zir.Inst.Imports.Item{
.name = entry.key_ptr.*,
.token = entry.value_ptr.*,
});
}
}
try astgen.extra.shrinkToLen(gpa);
try astgen.string_bytes.shrinkToLen(gpa);
return .{
.instructions = if (fatal) .empty else astgen.instructions.toOwnedSlice(),
.string_bytes = astgen.string_bytes.toOwnedSliceAssert(),
.extra = astgen.extra.toOwnedSliceAssert(),
};
}