stage2: move empty struct type and value to InternPool

This commit is contained in:
Andrew Kelley 2023-05-07 21:48:55 -07:00
parent 2f9b7dc102
commit 3116477dcc
5 changed files with 2104 additions and 2063 deletions

File diff suppressed because it is too large Load Diff

View File

@ -80,67 +80,9 @@ pub fn print(
return writer.writeAll("(variable)");
while (true) switch (val.ip_index) {
.empty_struct => return printAggregate(ty, val, writer, level, mod),
.none => switch (val.tag()) {
.empty_struct_value, .aggregate => {
if (level == 0) {
return writer.writeAll(".{ ... }");
}
if (ty.zigTypeTag(mod) == .Struct) {
try writer.writeAll(".{");
const max_len = std.math.min(ty.structFieldCount(), max_aggregate_items);
var i: u32 = 0;
while (i < max_len) : (i += 1) {
if (i != 0) try writer.writeAll(", ");
switch (ty.tag()) {
.anon_struct, .@"struct" => try writer.print(".{s} = ", .{ty.structFieldName(i)}),
else => {},
}
try print(.{
.ty = ty.structFieldType(i),
.val = try val.fieldValue(ty, mod, i),
}, writer, level - 1, mod);
}
if (ty.structFieldCount() > max_aggregate_items) {
try writer.writeAll(", ...");
}
return writer.writeAll("}");
} else {
const elem_ty = ty.elemType2(mod);
const len = ty.arrayLen(mod);
if (elem_ty.eql(Type.u8, mod)) str: {
const max_len = @intCast(usize, std.math.min(len, max_string_len));
var buf: [max_string_len]u8 = undefined;
var i: u32 = 0;
while (i < max_len) : (i += 1) {
const elem = try val.fieldValue(ty, mod, i);
if (elem.isUndef()) break :str;
buf[i] = std.math.cast(u8, elem.toUnsignedInt(mod)) orelse break :str;
}
const truncated = if (len > max_string_len) " (truncated)" else "";
return writer.print("\"{}{s}\"", .{ std.zig.fmtEscapes(buf[0..max_len]), truncated });
}
try writer.writeAll(".{ ");
const max_len = std.math.min(len, max_aggregate_items);
var i: u32 = 0;
while (i < max_len) : (i += 1) {
if (i != 0) try writer.writeAll(", ");
try print(.{
.ty = elem_ty,
.val = try val.fieldValue(ty, mod, i),
}, writer, level - 1, mod);
}
if (len > max_aggregate_items) {
try writer.writeAll(", ...");
}
return writer.writeAll(" }");
}
},
.aggregate => return printAggregate(ty, val, writer, level, mod),
.@"union" => {
if (level == 0) {
return writer.writeAll(".{ ... }");
@ -426,3 +368,70 @@ pub fn print(
},
};
}
fn printAggregate(
ty: Type,
val: Value,
writer: anytype,
level: u8,
mod: *Module,
) (@TypeOf(writer).Error || Allocator.Error)!void {
if (level == 0) {
return writer.writeAll(".{ ... }");
}
if (ty.zigTypeTag(mod) == .Struct) {
try writer.writeAll(".{");
const max_len = std.math.min(ty.structFieldCount(), max_aggregate_items);
var i: u32 = 0;
while (i < max_len) : (i += 1) {
if (i != 0) try writer.writeAll(", ");
switch (ty.tag()) {
.anon_struct, .@"struct" => try writer.print(".{s} = ", .{ty.structFieldName(i)}),
else => {},
}
try print(.{
.ty = ty.structFieldType(i),
.val = try val.fieldValue(ty, mod, i),
}, writer, level - 1, mod);
}
if (ty.structFieldCount() > max_aggregate_items) {
try writer.writeAll(", ...");
}
return writer.writeAll("}");
} else {
const elem_ty = ty.elemType2(mod);
const len = ty.arrayLen(mod);
if (elem_ty.eql(Type.u8, mod)) str: {
const max_len = @intCast(usize, std.math.min(len, max_string_len));
var buf: [max_string_len]u8 = undefined;
var i: u32 = 0;
while (i < max_len) : (i += 1) {
const elem = try val.fieldValue(ty, mod, i);
if (elem.isUndef()) break :str;
buf[i] = std.math.cast(u8, elem.toUnsignedInt(mod)) orelse break :str;
}
const truncated = if (len > max_string_len) " (truncated)" else "";
return writer.print("\"{}{s}\"", .{ std.zig.fmtEscapes(buf[0..max_len]), truncated });
}
try writer.writeAll(".{ ");
const max_len = std.math.min(len, max_aggregate_items);
var i: u32 = 0;
while (i < max_len) : (i += 1) {
if (i != 0) try writer.writeAll(", ");
try print(.{
.ty = elem_ty,
.val = try val.fieldValue(ty, mod, i),
}, writer, level - 1, mod);
}
if (len > max_aggregate_items) {
try writer.writeAll(", ...");
}
return writer.writeAll(" }");
}
}

View File

@ -1127,8 +1127,19 @@ pub const DeclGen = struct {
try writer.writeByte('}');
return;
},
.empty_struct => {
const ai = ty.arrayInfo(mod);
try writer.writeByte('{');
if (ai.sentinel) |s| {
try dg.renderValue(writer, ai.elem_type, s, initializer_type);
} else {
try writer.writeByte('0');
}
try writer.writeByte('}');
return;
},
.none => switch (val.tag()) {
.empty_struct_value, .empty_array => {
.empty_array => {
const ai = ty.arrayInfo(mod);
try writer.writeByte('{');
if (ai.sentinel) |s| {

File diff suppressed because it is too large Load Diff

View File

@ -36,7 +36,6 @@ pub const Value = struct {
/// The only possible value for a particular type, which is stored externally.
the_only_possible_value,
empty_struct_value,
empty_array, // See last_no_payload_tag below.
// After this, the tag requires a payload.
@ -124,7 +123,6 @@ pub const Value = struct {
pub fn Type(comptime t: Tag) type {
return switch (t) {
.the_only_possible_value,
.empty_struct_value,
.empty_array,
=> @compileError("Value Tag " ++ @tagName(t) ++ " has no payload"),
@ -269,7 +267,6 @@ pub const Value = struct {
} else switch (self.legacy.ptr_otherwise.tag) {
.the_only_possible_value,
.empty_array,
.empty_struct_value,
=> unreachable,
.ty, .lazy_align, .lazy_size => {
@ -488,7 +485,6 @@ pub const Value = struct {
}
var val = start_val;
while (true) switch (val.tag()) {
.empty_struct_value => return out_stream.writeAll("struct {}{}"),
.aggregate => {
return out_stream.writeAll("(aggregate)");
},
@ -1914,7 +1910,7 @@ pub const Value = struct {
const a_tag = a.tag();
const b_tag = b.tag();
if (a_tag == b_tag) switch (a_tag) {
.the_only_possible_value, .empty_struct_value => return true,
.the_only_possible_value => return true,
.enum_literal => {
const a_name = a.castTag(.enum_literal).?.data;
const b_name = b.castTag(.enum_literal).?.data;
@ -2106,7 +2102,6 @@ pub const Value = struct {
},
.Struct => {
// A struct can be represented with one of:
// .empty_struct_value,
// .the_one_possible_value,
// .aggregate,
// Note that we already checked above for matching tags, e.g. both .aggregate.
@ -2254,7 +2249,6 @@ pub const Value = struct {
},
.Struct => {
switch (val.tag()) {
.empty_struct_value => {},
.aggregate => {
const field_values = val.castTag(.aggregate).?.data;
for (field_values, 0..) |field_val, i| {
@ -2587,7 +2581,6 @@ pub const Value = struct {
.none => switch (val.tag()) {
// This is the case of accessing an element of an undef array.
.empty_array => unreachable, // out of bounds array index
.empty_struct_value => unreachable, // out of bounds array index
.empty_array_sentinel => {
assert(index == 0); // The only valid index for an empty array with sentinel.
@ -2749,6 +2742,17 @@ pub const Value = struct {
pub fn fieldValue(val: Value, ty: Type, mod: *Module, index: usize) !Value {
switch (val.ip_index) {
.undef => return Value.undef,
.empty_struct => {
if (ty.isSimpleTupleOrAnonStruct()) {
const tuple = ty.tupleFields();
return tuple.values[index];
}
if (try ty.structFieldValueComptime(mod, index)) |some| {
return some;
}
unreachable;
},
.none => switch (val.tag()) {
.aggregate => {
const field_values = val.castTag(.aggregate).?.data;
@ -2762,17 +2766,6 @@ pub const Value = struct {
.the_only_possible_value => return (try ty.onePossibleValue(mod)).?,
.empty_struct_value => {
if (ty.isSimpleTupleOrAnonStruct()) {
const tuple = ty.tupleFields();
return tuple.values[index];
}
if (try ty.structFieldValueComptime(mod, index)) |some| {
return some;
}
unreachable;
},
else => unreachable,
},
else => unreachable,
@ -5189,6 +5182,7 @@ pub const Value = struct {
pub const generic_poison: Value = .{ .ip_index = .generic_poison, .legacy = undefined };
pub const generic_poison_type: Value = .{ .ip_index = .generic_poison_type, .legacy = undefined };
pub const empty_struct: Value = .{ .ip_index = .empty_struct, .legacy = undefined };
pub fn makeBool(x: bool) Value {
return if (x) Value.true else Value.false;