refactor and basic struct/union value implementation

This commit is contained in:
Techatrix 2023-01-06 14:12:29 +01:00
parent 4b4aafb8ee
commit f0c888188a
3 changed files with 179 additions and 148 deletions

View File

@ -289,7 +289,7 @@ pub fn interpret(
}); });
const container_scope = @intCast(u32, interpreter.scopes.len - 1); const container_scope = @intCast(u32, interpreter.scopes.len - 1);
var fields = std.StringArrayHashMapUnmanaged(InternPool.Struct.Field){}; var fields = std.ArrayListUnmanaged(InternPool.Struct.Field){};
var buffer: [2]Ast.Node.Index = undefined; var buffer: [2]Ast.Node.Index = undefined;
const members = ast.declMembers(tree, node_idx, &buffer); const members = ast.declMembers(tree, node_idx, &buffer);
@ -315,21 +315,20 @@ pub fn interpret(
continue; continue;
} }
const name = tree.tokenSlice(container_field.ast.main_token);
const field: InternPool.Struct.Field = .{ const field: InternPool.Struct.Field = .{
.name = tree.tokenSlice(container_field.ast.main_token),
.ty = init_type_value.val, .ty = init_type_value.val,
.default_value = default_value, .default_value = default_value,
.alignent = 0, // TODO, .alignent = 0, // TODO,
.is_comptime = false, // TODO .is_comptime = false, // TODO
}; };
try fields.put(interpreter.arena.allocator(), name, field); try fields.append(interpreter.arena.allocator(), field);
} }
const struct_type = try interpreter.ip.get(interpreter.allocator, IPKey{ const struct_type = try interpreter.ip.get(interpreter.allocator, IPKey{
.struct_type = .{ .struct_type = .{
.fields = fields, .fields = fields.items,
.namespace = .none, // TODO .namespace = .none, // TODO
.layout = .Auto, // TODO .layout = .Auto, // TODO
.backing_int_ty = .none, // TODO .backing_int_ty = .none, // TODO
@ -695,7 +694,7 @@ pub fn interpret(
.interpreter = interpreter, .interpreter = interpreter,
.node_idx = node_idx, .node_idx = node_idx,
.ty = try interpreter.ip.get(interpreter.allocator, IPKey{ .struct_type = .{ .ty = try interpreter.ip.get(interpreter.allocator, IPKey{ .struct_type = .{
.fields = .{}, .fields = &.{},
.namespace = .none, .namespace = .none,
.layout = .Auto, .layout = .Auto,
.backing_int_ty = IPIndex.none, .backing_int_ty = IPIndex.none,
@ -715,7 +714,7 @@ pub fn interpret(
.interpreter = interpreter, .interpreter = interpreter,
.node_idx = node_idx, .node_idx = node_idx,
.ty = try interpreter.ip.get(interpreter.allocator, IPKey{ .simple = .type }), .ty = try interpreter.ip.get(interpreter.allocator, IPKey{ .simple = .type }),
.val = try interpreter.ip.get(interpreter.allocator, IPKey{ .type_value = undefined }), // TODO .val = undefined, // TODO
}, },
}; };
} }
@ -728,7 +727,7 @@ pub fn interpret(
.interpreter = interpreter, .interpreter = interpreter,
.node_idx = node_idx, .node_idx = node_idx,
.ty = try interpreter.ip.get(interpreter.allocator, IPKey{ .simple = .type }), .ty = try interpreter.ip.get(interpreter.allocator, IPKey{ .simple = .type }),
.val = try interpreter.ip.get(interpreter.allocator, IPKey{ .type_value = value.ty }), .val = value.ty,
} }; } };
} }
@ -953,7 +952,7 @@ pub fn interpret(
.interpreter = interpreter, .interpreter = interpreter,
.node_idx = node_idx, .node_idx = node_idx,
.ty = pointer_type, .ty = pointer_type,
.val = try interpreter.ip.get(interpreter.allocator, IPKey{ .one_pointer = value.val }), .val = value.val,
} }; } };
}, },
.deref => { .deref => {
@ -967,13 +966,11 @@ pub fn interpret(
return error.InvalidOperation; return error.InvalidOperation;
} }
// TODO: Check if this is a one_ptr or not
return InterpretResult{ .value = .{ return InterpretResult{ .value = .{
.interpreter = interpreter, .interpreter = interpreter,
.node_idx = node_idx, .node_idx = node_idx,
.ty = type_key.pointer_type.elem_type, .ty = type_key.pointer_type.elem_type,
.val = interpreter.ip.indexToKey(value.val).one_pointer, .val = value.val,
} }; } };
}, },
else => { else => {

View File

@ -48,16 +48,17 @@ pub const Array = struct {
}; };
pub const Struct = struct { pub const Struct = struct {
fields: std.StringArrayHashMapUnmanaged(Field), fields: []const Field,
namespace: NamespaceIndex, namespace: NamespaceIndex,
layout: std.builtin.Type.ContainerLayout, layout: std.builtin.Type.ContainerLayout = .Auto,
backing_int_ty: Index, backing_int_ty: Index,
pub const Field = struct { pub const Field = struct {
name: []const u8,
ty: Index, ty: Index,
default_value: Index, default_value: Index = .none,
alignent: u16, alignment: u16 = 0,
is_comptime: bool, is_comptime: bool = false,
}; };
}; };
@ -76,31 +77,30 @@ pub const ErrorUnion = struct {
pub const ErrorSet = struct { pub const ErrorSet = struct {
/// must be sorted /// must be sorted
names: std.StringArrayHashMapUnmanaged(void), names: [][]const u8,
pub fn sort(self: *ErrorSet) void { pub fn sort(self: *ErrorSet) void {
const Context = struct { std.sort.sort([][]const u8, self.names, u8, std.mem.lessThan);
keys: [][]const u8,
pub fn lessThan(ctx: @This(), a_index: usize, b_index: usize) bool {
return std.mem.lessThan(u8, ctx.keys[a_index], ctx.keys[b_index]);
}
};
self.names.sort(Context{ .keys = self.names.keys() });
} }
}; };
pub const Enum = struct { pub const Enum = struct {
tag_type: Index, tag_type: Index,
fields: std.StringArrayHashMapUnmanaged(Index), fields: []const Field,
namespace: NamespaceIndex, namespace: NamespaceIndex,
tag_type_infered: bool, tag_type_infered: bool,
pub const Field = struct {
name: []const u8,
ty: Index,
};
}; };
pub const Fn = struct { pub const Fn = struct {
calling_convention: std.builtin.CallingConvention, calling_convention: std.builtin.CallingConvention = .Unspecified,
alignment: u16, alignment: u16 = 0,
is_generic: bool, is_generic: bool = false,
is_var_args: bool, is_var_args: bool = false,
return_type: Index, return_type: Index,
args: []const Param, args: []const Param,
@ -114,20 +114,21 @@ pub const Fn = struct {
pub const Union = struct { pub const Union = struct {
tag_type: Index, tag_type: Index,
fields: std.StringArrayHashMapUnmanaged(Field), fields: []const Field,
namespace: NamespaceIndex, namespace: NamespaceIndex,
layout: std.builtin.Type.ContainerLayout, layout: std.builtin.Type.ContainerLayout = .Auto,
pub const Field = struct { pub const Field = struct {
name: []const u8,
ty: Index, ty: Index,
alignment: u16, alignment: u16,
}; };
}; };
pub const Tuple = struct { pub const Tuple = struct {
types: []Index, types: []const Index,
/// unreachable_value elements are used to indicate runtime-known. /// unreachable_value elements are used to indicate runtime-known.
values: []Index, values: []const Index,
}; };
pub const Vector = struct { pub const Vector = struct {
@ -142,6 +143,15 @@ pub const Bytes = struct {
data: []const u8, data: []const u8,
}; };
pub const Aggregate = struct {
data: []const Index,
};
pub const UnionValue = struct {
tag: Index,
val: Index,
};
pub const Key = union(enum) { pub const Key = union(enum) {
simple: Simple, simple: Simple,
@ -168,10 +178,12 @@ pub const Key = union(enum) {
float_64_value: f64, float_64_value: f64,
float_80_value: f80, float_80_value: f80,
float_128_value: f128, float_128_value: f128,
type_value: Index, // type_value: Index,
bytes: Bytes, bytes: Bytes,
one_pointer: Index, // one_pointer: Index,
aggregate: Aggregate,
union_value: UnionValue,
// slice // slice
// error // error
@ -184,54 +196,12 @@ pub const Key = union(enum) {
var hasher = std.hash.Wyhash.init(0); var hasher = std.hash.Wyhash.init(0);
std.hash.autoHash(&hasher, std.meta.activeTag(key)); std.hash.autoHash(&hasher, std.meta.activeTag(key));
switch (key) { switch (key) {
.struct_type => |struct_info| {
var field_it = struct_info.fields.iterator();
while (field_it.next()) |item| {
hasher.update(item.key_ptr.*);
std.hash.autoHash(&hasher, item.value_ptr.*);
}
std.hash.autoHash(&hasher, struct_info.layout);
},
// .error_type => |error_info| hasher.update(error_info.name),
.error_set_type => |error_set_info| {
const names = error_set_info.names.keys();
std.debug.assert(std.sort.isSorted([]const u8, names, u8, std.mem.lessThan));
for (names) |error_name| {
hasher.update(error_name);
}
},
.enum_type => |enum_info| {
std.hash.autoHash(&hasher, enum_info.tag_type);
var field_it = enum_info.fields.iterator();
while (field_it.next()) |item| {
hasher.update(item.key_ptr.*);
std.hash.autoHash(&hasher, item.value_ptr.*);
}
std.hash.autoHash(&hasher, enum_info.tag_type_infered);
},
.function_type => |function_info| std.hash.autoHashStrat(&hasher, function_info, .Deep),
.union_type => |union_info| {
std.hash.autoHash(&hasher, union_info.tag_type);
var field_it = union_info.fields.iterator();
while (field_it.next()) |item| {
hasher.update(item.key_ptr.*);
std.hash.autoHash(&hasher, item.value_ptr.*);
}
std.hash.autoHash(&hasher, union_info.layout);
},
.tuple_type => |tuple_info| std.hash.autoHashStrat(&hasher, tuple_info, .Deep),
.int_big_value => |big_int| {
std.hash.autoHash(&hasher, big_int.positive);
hasher.update(std.mem.sliceAsBytes(big_int.limbs));
},
.float_16_value => |f| std.hash.autoHash(&hasher, @bitCast(u16, f)), .float_16_value => |f| std.hash.autoHash(&hasher, @bitCast(u16, f)),
.float_32_value => |f| std.hash.autoHash(&hasher, @bitCast(u32, f)), .float_32_value => |f| std.hash.autoHash(&hasher, @bitCast(u32, f)),
.float_64_value => |f| std.hash.autoHash(&hasher, @bitCast(u64, f)), .float_64_value => |f| std.hash.autoHash(&hasher, @bitCast(u64, f)),
.float_80_value => |f| std.hash.autoHash(&hasher, @bitCast(u80, f)), .float_80_value => |f| std.hash.autoHash(&hasher, @bitCast(u80, f)),
.float_128_value => |f| std.hash.autoHash(&hasher, @bitCast(u128, f)), .float_128_value => |f| std.hash.autoHash(&hasher, @bitCast(u128, f)),
inline else => |info| std.hash.autoHashStrat(&hasher, info, .Deep), // TODO sad stage1 noises :(
.bytes => |bytes| hasher.update(bytes.data),
inline else => |info| std.hash.autoHash(&hasher, info), // TODO sad stage1 noises :(
} }
return @truncate(u32, hasher.final()); return @truncate(u32, hasher.final());
} }
@ -244,17 +214,17 @@ pub const Key = union(enum) {
return switch (a) { return switch (a) {
.struct_type => |struct_info| { .struct_type => |struct_info| {
if (struct_info.layout != b.struct_type.layout) return false; if (struct_info.layout != b.struct_type.layout) return false;
if (struct_info.fields.count() != b.struct_type.fields.count()) return false; if (struct_info.fields.len != b.struct_type.fields.len) return false;
@panic("TODO: implement field equality check"); for (struct_info.fields) |field, i| {
if (!std.meta.eql(field, b.struct_type.fields[i])) return false;
}
return true;
}, },
// .error_type => |error_info| std.mem.eql(u8, error_info.name, b.error_type.name), // .error_type => |error_info| std.mem.eql(u8, error_info.name, b.error_type.name),
.error_set_type => |error_set_info| { .error_set_type => |error_set_info| {
const a_names = error_set_info.names.keys(); if (error_set_info.names.len != b.error_set_type.names.len) return false;
const b_names = b.error_set_type.names.keys(); for (error_set_info.names) |a_name, i| {
const b_name = b.error_set_type.names[i];
if (a_names.len != b_names.len) return false;
for (a_names) |a_name, i| {
const b_name = b_names[i];
if (!std.mem.eql(u8, a_name, b_name)) return false; if (!std.mem.eql(u8, a_name, b_name)) return false;
} }
return true; return true;
@ -262,7 +232,7 @@ pub const Key = union(enum) {
.enum_type => |enum_info| { .enum_type => |enum_info| {
if (enum_info.tag_type != b.enum_type.tag_type) return false; if (enum_info.tag_type != b.enum_type.tag_type) return false;
if (enum_info.tag_type_infered != b.enum_type.tag_type_infered) return false; if (enum_info.tag_type_infered != b.enum_type.tag_type_infered) return false;
if (enum_info.fields.count() != b.enum_type.fields.count()) return false; if (enum_info.fields.len != b.enum_type.fields.len) return false;
@panic("TODO: implement field equality check"); @panic("TODO: implement field equality check");
}, },
.function_type => |function_info| { .function_type => |function_info| {
@ -281,8 +251,11 @@ pub const Key = union(enum) {
.union_type => |union_info| { .union_type => |union_info| {
if (union_info.tag_type != b.union_type.tag_type) return false; if (union_info.tag_type != b.union_type.tag_type) return false;
if (union_info.layout != b.union_type.layout) return false; if (union_info.layout != b.union_type.layout) return false;
if (union_info.fields.count() != b.union_type.fields.count()) return false; if (union_info.fields.len != b.union_type.fields.len) return false;
@panic("TODO: implement union equality"); for (union_info.fields) |field, i| {
if (!std.meta.eql(field, b.union_type.fields[i])) return false;
}
return true;
}, },
.tuple_type => |tuple_info| { .tuple_type => |tuple_info| {
std.debug.assert(tuple_info.types.len == tuple_info.values.len); std.debug.assert(tuple_info.types.len == tuple_info.values.len);
@ -296,6 +269,14 @@ pub const Key = union(enum) {
} }
return true; return true;
}, },
.bytes => |bytes| std.mem.eql(u8, bytes.data, b.bytes.data),
.aggregate => |aggregate| {
if (aggregate.data.len != b.aggregate.data.len) return false;
for (aggregate.data) |ty, i| {
if (ty != b.aggregate.data[i]) return false;
}
return true;
},
else => std.meta.eql(a, b), else => std.meta.eql(a, b),
}; };
} }
@ -328,10 +309,12 @@ pub const Key = union(enum) {
.float_64_value => .float_f64, .float_64_value => .float_f64,
.float_80_value => .float_f80, .float_80_value => .float_f80,
.float_128_value => .float_f128, .float_128_value => .float_f128,
.type_value => .type, // .type_value => .type,
.bytes => .bytes, .bytes => .bytes,
.one_pointer => .one_pointer, // .one_pointer => .one_pointer,
.aggregate => .aggregate,
.union_value => .union_value,
}; };
} }
@ -402,11 +385,13 @@ pub const Key = union(enum) {
.float_64_value, .float_64_value,
.float_80_value, .float_80_value,
.float_128_value, .float_128_value,
.type_value, // .type_value,
=> unreachable, => unreachable,
.bytes, .bytes,
.one_pointer, // .one_pointer,
.aggregate,
.union_value,
=> unreachable, => unreachable,
}; };
} }
@ -455,7 +440,6 @@ pub const Key = union(enum) {
/// Asserts the type is a fixed-size float or comptime_float. /// Asserts the type is a fixed-size float or comptime_float.
/// Returns 128 for comptime_float types. /// Returns 128 for comptime_float types.
pub fn floatBits(ty: Key, target: std.Target) u16 { pub fn floatBits(ty: Key, target: std.Target) u16 {
std.debug.assert(ty == .simple);
_ = target; _ = target;
return switch (ty.simple) { return switch (ty.simple) {
.f16 => 16, .f16 => 16,
@ -464,31 +448,12 @@ pub const Key = union(enum) {
.f80 => 80, .f80 => 80,
.f128, .comptime_float => 128, .f128, .comptime_float => 128,
// TODO correctly resolve size based on `target` // TODO correctly resolve size based on `target`
.c_longdouble => 80, .c_longdouble => @bitSizeOf(c_longdouble),
else => unreachable, else => unreachable,
}; };
} }
pub fn isCType(ty: Key) bool {
return switch (ty) {
.simple => |simple| switch (simple) {
.c_short,
.c_ushort,
.c_int,
.c_uint,
.c_long,
.c_ulong,
.c_longlong,
.c_ulonglong,
.c_longdouble,
=> true,
else => false,
},
else => false,
};
}
pub fn isConstPtr(ty: Key) bool { pub fn isConstPtr(ty: Key) bool {
return switch (ty) { return switch (ty) {
.pointer_type => |pointer_info| pointer_info.is_const, .pointer_type => |pointer_info| pointer_info.is_const,
@ -496,20 +461,11 @@ pub const Key = union(enum) {
}; };
} }
pub fn isSlice(ty: Key) bool {
return switch (ty) {
.pointer_type => |pointer_info| pointer_info.size == .Slice,
else => false,
};
}
/// For pointer-like optionals, returns true, otherwise returns the allowzero property /// For pointer-like optionals, returns true, otherwise returns the allowzero property
/// of pointers. /// of pointers.
pub fn ptrAllowsZero(ty: Key, ip: *const InternPool) bool { pub fn ptrAllowsZero(ty: Key, ip: *const InternPool) bool {
if (ty.isPtrLikeOptional(ip)) { if (ty.pointer_type.is_allowzero) return true;
return true; return ty.isPtrLikeOptional(ip);
}
return ty.pointer_type.is_allowzero;
} }
/// Returns true if the type is optional and would be lowered to a single pointer /// Returns true if the type is optional and would be lowered to a single pointer
@ -728,7 +684,21 @@ pub const Key = union(enum) {
try printType(function_info.return_type, ip, writer); try printType(function_info.return_type, ip, writer);
}, },
.union_type => @panic("TODO"), .union_type => @panic("TODO"),
.tuple_type => @panic("TODO"), .tuple_type => |tuple_info| {
try writer.writeAll("tuple{");
for (tuple_info.types) |field_ty, i| {
if (i != 0) try writer.writeAll(", ");
const val = tuple_info.values[i];
if (val != Index.none) {
try writer.writeAll("comptime ");
}
try printType(field_ty, ip, writer);
if (val != Index.none) {
try writer.print(" = {}", .{val.fmtValue(field_ty, ip)});
}
}
try writer.writeByte('}');
},
.vector_type => |vector_info| { .vector_type => |vector_info| {
try writer.print("@Vector({d},{})", .{ try writer.print("@Vector({d},{})", .{
vector_info.len, vector_info.len,
@ -746,9 +716,11 @@ pub const Key = union(enum) {
.float_128_value, .float_128_value,
=> unreachable, => unreachable,
.type_value, // .type_value,
.bytes, .bytes,
.one_pointer, // .one_pointer,
.aggregate,
.union_value,
=> unreachable, => unreachable,
} }
} }
@ -770,7 +742,6 @@ pub const Key = union(enum) {
ip: *const InternPool, ip: *const InternPool,
writer: anytype, writer: anytype,
) @TypeOf(writer).Error!void { ) @TypeOf(writer).Error!void {
_ = ty;
const value_key: Key = ip.indexToKey(value); const value_key: Key = ip.indexToKey(value);
switch (value_key) { switch (value_key) {
.simple => |simple| switch (simple) { .simple => |simple| switch (simple) {
@ -837,10 +808,32 @@ pub const Key = union(enum) {
.float_80_value => |float| try writer.print("{d}", .{@floatCast(f64, float)}), .float_80_value => |float| try writer.print("{d}", .{@floatCast(f64, float)}),
.float_128_value => |float| try writer.print("{d}", .{@floatCast(f64, float)}), .float_128_value => |float| try writer.print("{d}", .{@floatCast(f64, float)}),
.type_value, // .type_value => |tty| tty.fmtType(ip),
.bytes, .bytes => |data| try writer.print("\"{}\"", .{std.zig.fmtEscapes(data.data)}),
.one_pointer, // .one_pointer => unreachable,
=> unreachable, .aggregate => |aggregate| {
const struct_info = ip.indexToKey(ty).struct_type;
std.debug.assert(aggregate.data.len == struct_info.fields.len);
try writer.writeAll(".{");
var i: u32 = 0;
while (i < aggregate.data.len) : (i += 1) {
if (i != 0) try writer.writeAll(", ");
try writer.print(".{s} = ", .{struct_info.fields[i].name});
try printValue(aggregate.data[i], struct_info.fields[i].ty, ip, writer);
}
try writer.writeByte('}');
},
.union_value => |union_value| {
const union_info = ip.indexToKey(ty).union_type;
try writer.writeAll(".{ ");
try printValue(union_info.tag_type, union_value.tag, ip, writer);
try writer.writeAll(" = ");
try printValue(union_value.val, @panic("TODO"), ip, writer);
try writer.writeAll(" }");
},
} }
} }
}; };
@ -962,16 +955,22 @@ pub const Tag = enum(u8) {
/// A float value that can be represented by f128. /// A float value that can be represented by f128.
/// data is payload to f128. /// data is payload to f128.
float_f128, float_f128,
/// A type value. // /// A type value.
/// data is Index. // /// data is Index.
type, // type,
/// A byte sequence value. /// A byte sequence value.
/// data is payload to data begin and length. /// data is payload to data begin and length.
bytes, bytes,
/// A single pointer value. // /// A single pointer value.
/// data is index to value. // /// data is index to value.
one_pointer, // one_pointer,
/// A aggregate (struct) value.
/// data is index to Aggregate.
aggregate,
/// A union value.
/// data is index to UnionValue.
union_value,
}; };
pub const Simple = enum(u32) { pub const Simple = enum(u32) {
@ -1060,10 +1059,10 @@ pub fn indexToKey(ip: InternPool, index: Index) Key {
.float_f64 => .{ .float_64_value = ip.extraData(f64, data) }, .float_f64 => .{ .float_64_value = ip.extraData(f64, data) },
.float_f80 => .{ .float_80_value = ip.extraData(f80, data) }, .float_f80 => .{ .float_80_value = ip.extraData(f80, data) },
.float_f128 => .{ .float_128_value = ip.extraData(f128, data) }, .float_f128 => .{ .float_128_value = ip.extraData(f128, data) },
.type => .{ .type_value = @intToEnum(Index, data) }, // .type => .{ .type_value = @intToEnum(Index, data) },
.bytes => unreachable, // TODO .bytes => unreachable, // TODO
.one_pointer => .{ .one_pointer = @intToEnum(Index, data) }, // .one_pointer => .{ .one_pointer = @intToEnum(Index, data) },
else => @panic("TODO"), else => @panic("TODO"),
}; };
} }
@ -1099,9 +1098,9 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {
}, },
.float_16_value => |float_val| .{ .tag = .float_f16, .data = @bitCast(u16, float_val) }, .float_16_value => |float_val| .{ .tag = .float_f16, .data = @bitCast(u16, float_val) },
.float_32_value => |float_val| .{ .tag = .float_f32, .data = @bitCast(u32, float_val) }, .float_32_value => |float_val| .{ .tag = .float_f32, .data = @bitCast(u32, float_val) },
.type_value => |ty| .{ .tag = .type, .data = @enumToInt(ty) }, // .type_value => |ty| .{ .tag = .type, .data = @enumToInt(ty) },
.bytes => unreachable, // TODO .bytes => unreachable, // TODO
.one_pointer => |val| .{ .tag = .one_pointer, .data = @enumToInt(val) }, // .one_pointer => |val| .{ .tag = .one_pointer, .data = @enumToInt(val) },
inline else => |data| .{ .tag = key.tag(), .data = try ip.addExtra(gpa, data) }, // TODO sad stage1 noises :( inline else => |data| .{ .tag = key.tag(), .data = try ip.addExtra(gpa, data) }, // TODO sad stage1 noises :(
}; };
try ip.items.append(gpa, item); try ip.items.append(gpa, item);
@ -2454,6 +2453,42 @@ test "array type" {
try testExpectFmtType(&ip, u32_0_0_array_type, "[3:0]u32"); try testExpectFmtType(&ip, u32_0_0_array_type, "[3:0]u32");
} }
test "struct type" {
const gpa = std.testing.allocator;
var ip: InternPool = .{};
defer ip.deinit(gpa);
const i32_type = try ip.get(gpa, .{ .int_type = .{ .signedness = .signed, .bits = 32 } });
const u64_type = try ip.get(gpa, .{ .int_type = .{ .signedness = .unsigned, .bits = 64 } });
const bool_type = try ip.get(gpa, .{ .simple = .bool });
const field1 = Struct.Field{ .name = "foo", .ty = u64_type };
const field2 = Struct.Field{ .name = "bar", .ty = i32_type };
const field3 = Struct.Field{ .name = "baz", .ty = bool_type };
const struct_type_0 = try ip.get(gpa, Key{
.struct_type = Struct{
.fields = &.{ field1, field2, field3 },
.namespace = .none,
.layout = .Auto,
.backing_int_ty = .none,
},
});
_ = try ip.get(gpa, .{ .simple = .unreachable_value });
const struct_type_1 = try ip.get(gpa, Key{
.struct_type = Struct{
.fields = &.{ field1, field2, field3 },
.namespace = .none,
.layout = .Auto,
.backing_int_ty = .none,
},
});
std.debug.assert(struct_type_0 == struct_type_1);
}
test "resolvePeerTypes" { test "resolvePeerTypes" {
const gpa = std.testing.allocator; const gpa = std.testing.allocator;

View File

@ -586,12 +586,11 @@ fn typeToCompletion(
switch (key) { switch (key) {
.struct_type => |struct_info| { .struct_type => |struct_info| {
var field_it = struct_info.fields.iterator(); for (struct_info.fields) |field| {
while (field_it.next()) |entry| {
try list.append(allocator, .{ try list.append(allocator, .{
.label = entry.key_ptr.*, .label = field.name,
.kind = .Field, .kind = .Field,
.insertText = entry.key_ptr.*, .insertText = field.name,
.insertTextFormat = .PlainText, .insertTextFormat = .PlainText,
}); });
} }