mirror of
https://github.com/ziglang/zig.git
synced 2026-01-11 18:05:11 +00:00
Merge pull request #11164 from mitchellh/reify-union
stage2: reify unions
This commit is contained in:
commit
f36bf8506c
110
src/Sema.zig
110
src/Sema.zig
@ -12607,18 +12607,16 @@ fn zirReify(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.I
|
||||
enum_obj.tag_ty = try tag_type_val.toType(&buffer).copy(new_decl_arena_allocator);
|
||||
|
||||
// Fields
|
||||
const slice_val = fields_val.castTag(.slice).?.data;
|
||||
const decl = slice_val.ptr.pointerDecl().?;
|
||||
try sema.ensureDeclAnalyzed(decl);
|
||||
const fields_len = try sema.usizeCast(block, src, decl.ty.arrayLen());
|
||||
const fields_len = try sema.usizeCast(block, src, fields_val.sliceLen());
|
||||
if (fields_len > 0) {
|
||||
try enum_obj.fields.ensureTotalCapacity(new_decl_arena_allocator, fields_len);
|
||||
try enum_obj.values.ensureTotalCapacityContext(new_decl_arena_allocator, fields_len, .{
|
||||
.ty = enum_obj.tag_ty,
|
||||
});
|
||||
|
||||
const array_vals = decl.val.castTag(.aggregate).?.data;
|
||||
for (array_vals) |elem_val| {
|
||||
var i: usize = 0;
|
||||
while (i < fields_len) : (i += 1) {
|
||||
const elem_val = try fields_val.elemValue(sema.arena, i);
|
||||
const field_struct_val = elem_val.castTag(.aggregate).?.data;
|
||||
// TODO use reflection instead of magic numbers here
|
||||
// name: []const u8
|
||||
@ -12691,7 +12689,103 @@ fn zirReify(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.I
|
||||
try new_decl.finalizeNewArena(&new_decl_arena);
|
||||
return sema.analyzeDeclVal(block, src, new_decl);
|
||||
},
|
||||
.Union => return sema.fail(block, src, "TODO: Sema.zirReify for Union", .{}),
|
||||
.Union => {
|
||||
// TODO use reflection instead of magic numbers here
|
||||
const struct_val = union_val.val.castTag(.aggregate).?.data;
|
||||
// layout: containerlayout,
|
||||
const layout_val = struct_val[0];
|
||||
// tag_type: ?type,
|
||||
const tag_type_val = struct_val[1];
|
||||
// fields: []const enumfield,
|
||||
const fields_val = struct_val[2];
|
||||
// decls: []const declaration,
|
||||
const decls_val = struct_val[3];
|
||||
|
||||
// Decls
|
||||
if (decls_val.sliceLen() > 0) {
|
||||
return sema.fail(block, src, "reified unions must have no decls", .{});
|
||||
}
|
||||
|
||||
var new_decl_arena = std.heap.ArenaAllocator.init(sema.gpa);
|
||||
errdefer new_decl_arena.deinit();
|
||||
const new_decl_arena_allocator = new_decl_arena.allocator();
|
||||
|
||||
const union_obj = try new_decl_arena_allocator.create(Module.Union);
|
||||
const type_tag: Type.Tag = if (!tag_type_val.isNull()) .union_tagged else .@"union";
|
||||
const union_payload = try new_decl_arena_allocator.create(Type.Payload.Union);
|
||||
union_payload.* = .{
|
||||
.base = .{ .tag = type_tag },
|
||||
.data = union_obj,
|
||||
};
|
||||
const union_ty = Type.initPayload(&union_payload.base);
|
||||
const new_union_val = try Value.Tag.ty.create(new_decl_arena_allocator, union_ty);
|
||||
const type_name = try sema.createTypeName(block, .anon);
|
||||
const new_decl = try sema.mod.createAnonymousDeclNamed(block, .{
|
||||
.ty = Type.type,
|
||||
.val = new_union_val,
|
||||
}, type_name);
|
||||
new_decl.owns_tv = true;
|
||||
errdefer sema.mod.abortAnonDecl(new_decl);
|
||||
union_obj.* = .{
|
||||
.owner_decl = new_decl,
|
||||
.tag_ty = Type.initTag(.@"null"),
|
||||
.fields = .{},
|
||||
.node_offset = src.node_offset,
|
||||
.zir_index = inst,
|
||||
.layout = layout_val.toEnum(std.builtin.Type.ContainerLayout),
|
||||
.status = .have_field_types,
|
||||
.namespace = .{
|
||||
.parent = block.namespace,
|
||||
.ty = union_ty,
|
||||
.file_scope = block.getFileScope(),
|
||||
},
|
||||
};
|
||||
|
||||
// Tag type
|
||||
const fields_len = try sema.usizeCast(block, src, fields_val.sliceLen());
|
||||
union_obj.tag_ty = if (tag_type_val.optionalValue()) |payload_val| blk: {
|
||||
var buffer: Value.ToTypeBuffer = undefined;
|
||||
break :blk try payload_val.toType(&buffer).copy(new_decl_arena_allocator);
|
||||
} else try sema.generateUnionTagTypeSimple(block, fields_len);
|
||||
|
||||
// Fields
|
||||
if (fields_len > 0) {
|
||||
try union_obj.fields.ensureTotalCapacity(new_decl_arena_allocator, fields_len);
|
||||
|
||||
var i: usize = 0;
|
||||
while (i < fields_len) : (i += 1) {
|
||||
const elem_val = try fields_val.elemValue(sema.arena, i);
|
||||
const field_struct_val = elem_val.castTag(.aggregate).?.data;
|
||||
// TODO use reflection instead of magic numbers here
|
||||
// name: []const u8
|
||||
const name_val = field_struct_val[0];
|
||||
// field_type: type,
|
||||
const field_type_val = field_struct_val[1];
|
||||
// alignment: comptime_int,
|
||||
const alignment_val = field_struct_val[2];
|
||||
|
||||
const field_name = try name_val.toAllocatedBytes(
|
||||
Type.initTag(.const_slice_u8),
|
||||
new_decl_arena_allocator,
|
||||
);
|
||||
|
||||
const gop = union_obj.fields.getOrPutAssumeCapacity(field_name);
|
||||
if (gop.found_existing) {
|
||||
// TODO: better source location
|
||||
return sema.fail(block, src, "duplicate union field {s}", .{field_name});
|
||||
}
|
||||
|
||||
var buffer: Value.ToTypeBuffer = undefined;
|
||||
gop.value_ptr.* = .{
|
||||
.ty = try field_type_val.toType(&buffer).copy(new_decl_arena_allocator),
|
||||
.abi_align = try alignment_val.copy(new_decl_arena_allocator),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
try new_decl.finalizeNewArena(&new_decl_arena);
|
||||
return sema.analyzeDeclVal(block, src, new_decl);
|
||||
},
|
||||
.Fn => return sema.fail(block, src, "TODO: Sema.zirReify for Fn", .{}),
|
||||
.BoundFn => @panic("TODO delete BoundFn from the language"),
|
||||
.Frame => @panic("TODO implement https://github.com/ziglang/zig/issues/10710"),
|
||||
@ -20417,7 +20511,7 @@ fn generateUnionTagTypeNumbered(
|
||||
return enum_ty;
|
||||
}
|
||||
|
||||
fn generateUnionTagTypeSimple(sema: *Sema, block: *Block, fields_len: u32) !Type {
|
||||
fn generateUnionTagTypeSimple(sema: *Sema, block: *Block, fields_len: usize) !Type {
|
||||
const mod = sema.mod;
|
||||
|
||||
var new_decl_arena = std.heap.ArenaAllocator.init(sema.gpa);
|
||||
|
||||
@ -395,7 +395,11 @@ test "Type.Enum" {
|
||||
}
|
||||
|
||||
test "Type.Union" {
|
||||
if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
|
||||
|
||||
const Untagged = @Type(.{
|
||||
.Union = .{
|
||||
@ -458,7 +462,11 @@ test "Type.Union" {
|
||||
}
|
||||
|
||||
test "Type.Union from Type.Enum" {
|
||||
if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
|
||||
|
||||
const Tag = @Type(.{
|
||||
.Enum = .{
|
||||
@ -486,7 +494,11 @@ test "Type.Union from Type.Enum" {
|
||||
}
|
||||
|
||||
test "Type.Union from regular enum" {
|
||||
if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
|
||||
|
||||
const E = enum { working_as_expected };
|
||||
const T = @Type(.{
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user