refactor InternPool KeyAdapter
This commit is contained in:
parent
04d281340c
commit
1456bfa1c6
@ -705,7 +705,7 @@ pub fn interpret(
|
|||||||
const value_namespace = interpreter.ip.indexToKey(value.val).getNamespace();
|
const value_namespace = interpreter.ip.indexToKey(value.val).getNamespace();
|
||||||
if (value_namespace == .none) return error.InvalidBuiltin;
|
if (value_namespace == .none) return error.InvalidBuiltin;
|
||||||
|
|
||||||
const name = interpreter.ip.indexToKey(field_name.val).bytes.data; // TODO add checks
|
const name = interpreter.ip.indexToKey(field_name.val).bytes; // TODO add checks
|
||||||
|
|
||||||
const decls = interpreter.namespaces.items(.decls)[@enumToInt(value_namespace)];
|
const decls = interpreter.namespaces.items(.decls)[@enumToInt(value_namespace)];
|
||||||
const has_decl = decls.contains(name);
|
const has_decl = decls.contains(name);
|
||||||
@ -764,7 +764,7 @@ pub fn interpret(
|
|||||||
.interpreter = interpreter,
|
.interpreter = interpreter,
|
||||||
.node_idx = node_idx,
|
.node_idx = node_idx,
|
||||||
.ty = string_literal_type,
|
.ty = string_literal_type,
|
||||||
.val = try interpreter.ip.get(interpreter.allocator, IPKey{ .bytes = .{ .data = str } }), // TODO
|
.val = try interpreter.ip.get(interpreter.allocator, IPKey{ .bytes = str }), // TODO
|
||||||
};
|
};
|
||||||
|
|
||||||
// TODO: Add type casting, sentinel
|
// TODO: Add type casting, sentinel
|
||||||
|
@ -10,26 +10,12 @@ const builtin = @import("builtin");
|
|||||||
const Allocator = std.mem.Allocator;
|
const Allocator = std.mem.Allocator;
|
||||||
const assert = std.debug.assert;
|
const assert = std.debug.assert;
|
||||||
|
|
||||||
const KeyAdapter = struct {
|
pub const Int = packed struct {
|
||||||
intern_pool: *const InternPool,
|
|
||||||
|
|
||||||
pub fn eql(ctx: @This(), a: Key, b_void: void, b_map_index: usize) bool {
|
|
||||||
_ = b_void;
|
|
||||||
return ctx.intern_pool.indexToKey(@intToEnum(Index, b_map_index)).eql(a);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn hash(ctx: @This(), a: Key) u32 {
|
|
||||||
_ = ctx;
|
|
||||||
return a.hash();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
pub const Int = struct {
|
|
||||||
signedness: std.builtin.Signedness,
|
signedness: std.builtin.Signedness,
|
||||||
bits: u16,
|
bits: u16,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const Pointer = struct {
|
pub const Pointer = packed struct {
|
||||||
elem_type: Index,
|
elem_type: Index,
|
||||||
sentinel: Index = .none,
|
sentinel: Index = .none,
|
||||||
alignment: u16 = 0,
|
alignment: u16 = 0,
|
||||||
@ -40,7 +26,7 @@ pub const Pointer = struct {
|
|||||||
address_space: std.builtin.AddressSpace = .generic,
|
address_space: std.builtin.AddressSpace = .generic,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const Array = struct {
|
pub const Array = packed struct {
|
||||||
// TODO support big int
|
// TODO support big int
|
||||||
len: u32,
|
len: u32,
|
||||||
child: Index,
|
child: Index,
|
||||||
@ -62,19 +48,15 @@ pub const Struct = struct {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const Optional = struct {
|
pub const Optional = packed struct {
|
||||||
payload_type: Index,
|
payload_type: Index,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const ErrorUnion = struct {
|
pub const ErrorUnion = packed struct {
|
||||||
error_set_type: Index,
|
error_set_type: Index,
|
||||||
payload_type: Index,
|
payload_type: Index,
|
||||||
};
|
};
|
||||||
|
|
||||||
// pub const Error = struct {
|
|
||||||
// name: []const u8,
|
|
||||||
// };
|
|
||||||
|
|
||||||
pub const ErrorSet = struct {
|
pub const ErrorSet = struct {
|
||||||
/// must be sorted
|
/// must be sorted
|
||||||
names: []const []const u8,
|
names: []const []const u8,
|
||||||
@ -104,11 +86,11 @@ pub const Fn = struct {
|
|||||||
return_type: Index,
|
return_type: Index,
|
||||||
args: []const Param,
|
args: []const Param,
|
||||||
|
|
||||||
pub const Param = struct {
|
pub const Param = packed struct {
|
||||||
|
arg_type: Index,
|
||||||
is_comptime: bool = false,
|
is_comptime: bool = false,
|
||||||
is_generic: bool = false,
|
is_generic: bool = false,
|
||||||
is_noalias: bool = false,
|
is_noalias: bool = false,
|
||||||
arg_type: Index,
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -127,31 +109,27 @@ pub const Union = struct {
|
|||||||
|
|
||||||
pub const Tuple = struct {
|
pub const Tuple = struct {
|
||||||
types: []const Index,
|
types: []const Index,
|
||||||
/// unreachable_value elements are used to indicate runtime-known.
|
/// Index.none elements are used to indicate runtime-known.
|
||||||
values: []const Index,
|
values: []const Index,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const Vector = struct {
|
pub const Vector = packed struct {
|
||||||
// TODO support big int
|
// TODO support big int
|
||||||
len: u32,
|
len: u32,
|
||||||
child: Index,
|
child: Index,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const AnyFrame = struct {
|
pub const AnyFrame = packed struct {
|
||||||
child: Index,
|
child: Index,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const BigInt = std.math.big.int.Const;
|
pub const BigInt = std.math.big.int.Const;
|
||||||
|
|
||||||
pub const Bytes = struct {
|
pub const Bytes = []const u8;
|
||||||
data: []const u8,
|
|
||||||
};
|
|
||||||
|
|
||||||
pub const Aggregate = struct {
|
pub const Aggregate = []const Index;
|
||||||
data: []const Index,
|
|
||||||
};
|
|
||||||
|
|
||||||
pub const UnionValue = struct {
|
pub const UnionValue = packed struct {
|
||||||
tag: Index,
|
tag: Index,
|
||||||
val: Index,
|
val: Index,
|
||||||
};
|
};
|
||||||
@ -165,14 +143,13 @@ pub const Key = union(enum) {
|
|||||||
struct_type: Struct,
|
struct_type: Struct,
|
||||||
optional_type: Optional,
|
optional_type: Optional,
|
||||||
error_union_type: ErrorUnion,
|
error_union_type: ErrorUnion,
|
||||||
// error_type: Error,
|
|
||||||
error_set_type: ErrorSet,
|
error_set_type: ErrorSet,
|
||||||
enum_type: Enum,
|
enum_type: Enum,
|
||||||
function_type: Fn,
|
function_type: Fn,
|
||||||
union_type: Union,
|
union_type: Union,
|
||||||
tuple_type: Tuple,
|
tuple_type: Tuple,
|
||||||
vector_type: Vector,
|
vector_type: Vector,
|
||||||
anyframe_t_type: AnyFrame,
|
anyframe_type: AnyFrame,
|
||||||
|
|
||||||
int_u64_value: u64,
|
int_u64_value: u64,
|
||||||
int_i64_value: i64,
|
int_i64_value: i64,
|
||||||
@ -182,10 +159,8 @@ 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,
|
|
||||||
|
|
||||||
bytes: Bytes,
|
bytes: Bytes,
|
||||||
// one_pointer: Index,
|
|
||||||
aggregate: Aggregate,
|
aggregate: Aggregate,
|
||||||
union_value: UnionValue,
|
union_value: UnionValue,
|
||||||
|
|
||||||
@ -193,98 +168,10 @@ pub const Key = union(enum) {
|
|||||||
// error
|
// error
|
||||||
// error union
|
// error union
|
||||||
|
|
||||||
pub fn hash(key: Key) u32 {
|
|
||||||
var hasher = std.hash.Wyhash.init(0);
|
|
||||||
std.hash.autoHash(&hasher, std.meta.activeTag(key));
|
|
||||||
switch (key) {
|
|
||||||
.float_16_value => |f| std.hash.autoHash(&hasher, @bitCast(u16, f)),
|
|
||||||
.float_32_value => |f| std.hash.autoHash(&hasher, @bitCast(u32, f)),
|
|
||||||
.float_64_value => |f| std.hash.autoHash(&hasher, @bitCast(u64, f)),
|
|
||||||
.float_80_value => |f| std.hash.autoHash(&hasher, @bitCast(u80, 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 :(
|
|
||||||
}
|
|
||||||
return @truncate(u32, hasher.final());
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn eql(a: Key, b: Key) bool {
|
|
||||||
const KeyTag = std.meta.Tag(Key);
|
|
||||||
const a_tag: KeyTag = a;
|
|
||||||
const b_tag: KeyTag = b;
|
|
||||||
if (a_tag != b_tag) return false;
|
|
||||||
return switch (a) {
|
|
||||||
.struct_type => |struct_info| {
|
|
||||||
if (struct_info.layout != b.struct_type.layout) return false;
|
|
||||||
if (struct_info.fields.len != b.struct_type.fields.len) return false;
|
|
||||||
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_set_type => |error_set_info| {
|
|
||||||
if (error_set_info.names.len != b.error_set_type.names.len) return false;
|
|
||||||
for (error_set_info.names) |a_name, i| {
|
|
||||||
const b_name = b.error_set_type.names[i];
|
|
||||||
if (!std.mem.eql(u8, a_name, b_name)) return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
},
|
|
||||||
.enum_type => |enum_info| {
|
|
||||||
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.fields.len != b.enum_type.fields.len) return false;
|
|
||||||
@panic("TODO: implement field equality check");
|
|
||||||
},
|
|
||||||
.function_type => |function_info| {
|
|
||||||
if (function_info.calling_convention != b.function_type.calling_convention) return false;
|
|
||||||
if (function_info.alignment != b.function_type.alignment) return false;
|
|
||||||
if (function_info.is_generic != b.function_type.is_generic) return false;
|
|
||||||
if (function_info.is_var_args != b.function_type.is_var_args) return false;
|
|
||||||
if (function_info.return_type != b.function_type.return_type) return false;
|
|
||||||
if (function_info.args.len != b.function_type.args.len) return false;
|
|
||||||
|
|
||||||
for (function_info.args) |arg, i| {
|
|
||||||
if (!std.meta.eql(arg, b.function_type.args[i])) return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
},
|
|
||||||
.union_type => |union_info| {
|
|
||||||
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.fields.len != b.union_type.fields.len) return false;
|
|
||||||
for (union_info.fields) |field, i| {
|
|
||||||
if (!std.meta.eql(field, b.union_type.fields[i])) return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
},
|
|
||||||
.tuple_type => |tuple_info| {
|
|
||||||
std.debug.assert(tuple_info.types.len == tuple_info.values.len);
|
|
||||||
std.debug.assert(b.tuple_type.types.len == b.tuple_type.values.len);
|
|
||||||
if (tuple_info.types.len != b.tuple_type.types.len) return false;
|
|
||||||
for (tuple_info.types) |ty, i| {
|
|
||||||
if (ty != b.tuple_type.types[i]) return false;
|
|
||||||
}
|
|
||||||
for (tuple_info.values) |val, i| {
|
|
||||||
if (val != b.tuple_type.values[i]) return false;
|
|
||||||
}
|
|
||||||
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),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn tag(key: Key) Tag {
|
pub fn tag(key: Key) Tag {
|
||||||
return switch (key) {
|
return switch (key) {
|
||||||
.simple => .simple,
|
.simple => .simple,
|
||||||
|
|
||||||
.int_type => |int_info| switch (int_info.signedness) {
|
.int_type => |int_info| switch (int_info.signedness) {
|
||||||
.signed => .type_int_signed,
|
.signed => .type_int_signed,
|
||||||
.unsigned => .type_int_unsigned,
|
.unsigned => .type_int_unsigned,
|
||||||
@ -294,14 +181,13 @@ pub const Key = union(enum) {
|
|||||||
.struct_type => .type_struct,
|
.struct_type => .type_struct,
|
||||||
.optional_type => .type_optional,
|
.optional_type => .type_optional,
|
||||||
.error_union_type => .type_error_union,
|
.error_union_type => .type_error_union,
|
||||||
// .error_type => .type_error,
|
|
||||||
.error_set_type => .type_error_set,
|
.error_set_type => .type_error_set,
|
||||||
.enum_type => .type_enum,
|
.enum_type => .type_enum,
|
||||||
.function_type => .type_function,
|
.function_type => .type_function,
|
||||||
.union_type => .type_union,
|
.union_type => .type_union,
|
||||||
.tuple_type => .type_tuple,
|
.tuple_type => .type_tuple,
|
||||||
.vector_type => .type_vector,
|
.vector_type => .type_vector,
|
||||||
.anyframe_t_type => .type_anyframe_t,
|
.anyframe_type => .type_anyframe,
|
||||||
|
|
||||||
.int_u64_value => |int| if (int <= std.math.maxInt(u32)) .int_u32 else .int_u64,
|
.int_u64_value => |int| if (int <= std.math.maxInt(u32)) .int_u32 else .int_u64,
|
||||||
.int_i64_value => |int| if (std.math.maxInt(i32) <= int and int <= std.math.maxInt(i32)) .int_i32 else .int_i64,
|
.int_i64_value => |int| if (std.math.maxInt(i32) <= int and int <= std.math.maxInt(i32)) .int_i32 else .int_i64,
|
||||||
@ -311,10 +197,8 @@ 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,
|
|
||||||
|
|
||||||
.bytes => .bytes,
|
.bytes => .bytes,
|
||||||
// .one_pointer => .one_pointer,
|
|
||||||
.aggregate => .aggregate,
|
.aggregate => .aggregate,
|
||||||
.union_value => .union_value,
|
.union_value => .union_value,
|
||||||
};
|
};
|
||||||
@ -378,7 +262,7 @@ pub const Key = union(enum) {
|
|||||||
.union_type => .Union,
|
.union_type => .Union,
|
||||||
.tuple_type => .Struct, // TODO this correct?
|
.tuple_type => .Struct, // TODO this correct?
|
||||||
.vector_type => .Vector,
|
.vector_type => .Vector,
|
||||||
.anyframe_t_type => .AnyFrame,
|
.anyframe_type => .AnyFrame,
|
||||||
|
|
||||||
.int_u64_value,
|
.int_u64_value,
|
||||||
.int_i64_value,
|
.int_i64_value,
|
||||||
@ -500,7 +384,7 @@ pub const Key = union(enum) {
|
|||||||
.array_type => |array_info| array_info.child,
|
.array_type => |array_info| array_info.child,
|
||||||
.optional_type => |optional_info| optional_info.payload_type,
|
.optional_type => |optional_info| optional_info.payload_type,
|
||||||
.vector_type => |vector_info| vector_info.child,
|
.vector_type => |vector_info| vector_info.child,
|
||||||
.anyframe_t_type => |anyframe_t_info| anyframe_t_info.child,
|
.anyframe_type => |anyframe_info| anyframe_info.child,
|
||||||
else => unreachable,
|
else => unreachable,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -717,7 +601,7 @@ pub const Key = union(enum) {
|
|||||||
vector_info.child.fmtType(ip),
|
vector_info.child.fmtType(ip),
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
.anyframe_t_type => |anyframe_info| {
|
.anyframe_type => |anyframe_info| {
|
||||||
try writer.writeAll("anyframe->");
|
try writer.writeAll("anyframe->");
|
||||||
try printType(anyframe_info.child, ip, writer);
|
try printType(anyframe_info.child, ip, writer);
|
||||||
},
|
},
|
||||||
@ -813,7 +697,7 @@ pub const Key = union(enum) {
|
|||||||
.union_type,
|
.union_type,
|
||||||
.tuple_type,
|
.tuple_type,
|
||||||
.vector_type,
|
.vector_type,
|
||||||
.anyframe_t_type,
|
.anyframe_type,
|
||||||
=> unreachable,
|
=> unreachable,
|
||||||
|
|
||||||
.int_u64_value => |int| try std.fmt.formatIntValue(int, "", .{}, writer),
|
.int_u64_value => |int| try std.fmt.formatIntValue(int, "", .{}, writer),
|
||||||
@ -826,19 +710,19 @@ pub const Key = union(enum) {
|
|||||||
.float_128_value => |float| try writer.print("{d}", .{@floatCast(f64, float)}),
|
.float_128_value => |float| try writer.print("{d}", .{@floatCast(f64, float)}),
|
||||||
|
|
||||||
// .type_value => |tty| tty.fmtType(ip),
|
// .type_value => |tty| tty.fmtType(ip),
|
||||||
.bytes => |data| try writer.print("\"{}\"", .{std.zig.fmtEscapes(data.data)}),
|
.bytes => |bytes| try writer.print("\"{}\"", .{std.zig.fmtEscapes(bytes)}),
|
||||||
// .one_pointer => unreachable,
|
// .one_pointer => unreachable,
|
||||||
.aggregate => |aggregate| {
|
.aggregate => |aggregate| {
|
||||||
const struct_info = ip.indexToKey(ty).struct_type;
|
const struct_info = ip.indexToKey(ty).struct_type;
|
||||||
std.debug.assert(aggregate.data.len == struct_info.fields.len);
|
std.debug.assert(aggregate.len == struct_info.fields.len);
|
||||||
|
|
||||||
try writer.writeAll(".{");
|
try writer.writeAll(".{");
|
||||||
var i: u32 = 0;
|
var i: u32 = 0;
|
||||||
while (i < aggregate.data.len) : (i += 1) {
|
while (i < aggregate.len) : (i += 1) {
|
||||||
if (i != 0) try writer.writeAll(", ");
|
if (i != 0) try writer.writeAll(", ");
|
||||||
|
|
||||||
try writer.print(".{s} = ", .{struct_info.fields[i].name});
|
try writer.print(".{s} = ", .{struct_info.fields[i].name});
|
||||||
try printValue(aggregate.data[i], struct_info.fields[i].ty, ip, writer);
|
try printValue(aggregate[i], struct_info.fields[i].ty, ip, writer);
|
||||||
}
|
}
|
||||||
try writer.writeByte('}');
|
try writer.writeByte('}');
|
||||||
},
|
},
|
||||||
@ -917,9 +801,6 @@ pub const Tag = enum(u8) {
|
|||||||
/// An error union type.
|
/// An error union type.
|
||||||
/// data is payload to ErrorUnion.
|
/// data is payload to ErrorUnion.
|
||||||
type_error_union,
|
type_error_union,
|
||||||
/// An error type.
|
|
||||||
/// data is payload to Error.
|
|
||||||
type_error,
|
|
||||||
/// An error set type.
|
/// An error set type.
|
||||||
/// data is payload to ErrorSet.
|
/// data is payload to ErrorSet.
|
||||||
type_error_set,
|
type_error_set,
|
||||||
@ -940,7 +821,7 @@ pub const Tag = enum(u8) {
|
|||||||
type_vector,
|
type_vector,
|
||||||
/// An anyframe->T type.
|
/// An anyframe->T type.
|
||||||
/// data is index to type
|
/// data is index to type
|
||||||
type_anyframe_t,
|
type_anyframe,
|
||||||
|
|
||||||
/// An unsigned integer value that can be represented by u32.
|
/// An unsigned integer value that can be represented by u32.
|
||||||
/// data is integer value
|
/// data is integer value
|
||||||
@ -975,16 +856,10 @@ 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.
|
|
||||||
// /// data is Index.
|
|
||||||
// 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.
|
|
||||||
// /// data is index to value.
|
|
||||||
// one_pointer,
|
|
||||||
/// A aggregate (struct) value.
|
/// A aggregate (struct) value.
|
||||||
/// data is index to Aggregate.
|
/// data is index to Aggregate.
|
||||||
aggregate,
|
aggregate,
|
||||||
@ -1039,12 +914,12 @@ pub fn deinit(ip: *InternPool, gpa: Allocator) void {
|
|||||||
|
|
||||||
// TODO deinit fields
|
// TODO deinit fields
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn indexToKey(ip: InternPool, index: Index) Key {
|
pub fn indexToKey(ip: InternPool, index: Index) Key {
|
||||||
const item = ip.items.get(@enumToInt(index));
|
const item = ip.items.get(@enumToInt(index));
|
||||||
const data = item.data;
|
const data = item.data;
|
||||||
return switch (item.tag) {
|
return switch (item.tag) {
|
||||||
.simple => .{ .simple = @intToEnum(Simple, data) },
|
.simple => .{ .simple = @intToEnum(Simple, data) },
|
||||||
|
|
||||||
.type_int_signed => .{ .int_type = .{
|
.type_int_signed => .{ .int_type = .{
|
||||||
.signedness = .signed,
|
.signedness = .signed,
|
||||||
.bits = @intCast(u16, data),
|
.bits = @intCast(u16, data),
|
||||||
@ -1057,9 +932,8 @@ pub fn indexToKey(ip: InternPool, index: Index) Key {
|
|||||||
.type_array => .{ .array_type = ip.extraData(Array, data) },
|
.type_array => .{ .array_type = ip.extraData(Array, data) },
|
||||||
.type_struct => .{ .struct_type = ip.extraData(Struct, data) },
|
.type_struct => .{ .struct_type = ip.extraData(Struct, data) },
|
||||||
.type_optional => .{ .optional_type = .{ .payload_type = @intToEnum(Index, data) } },
|
.type_optional => .{ .optional_type = .{ .payload_type = @intToEnum(Index, data) } },
|
||||||
.type_anyframe_t => .{ .anyframe_t_type = .{ .child = @intToEnum(Index, data) } },
|
.type_anyframe => .{ .anyframe_type = .{ .child = @intToEnum(Index, data) } },
|
||||||
.type_error_union => .{ .error_union_type = ip.extraData(ErrorUnion, data) },
|
.type_error_union => .{ .error_union_type = ip.extraData(ErrorUnion, data) },
|
||||||
// .type_error => .{ .error_type = ip.extraData(Error, data) },
|
|
||||||
.type_error_set => .{ .error_set_type = ip.extraData(ErrorSet, data) },
|
.type_error_set => .{ .error_set_type = ip.extraData(ErrorSet, data) },
|
||||||
.type_enum => .{ .enum_type = ip.extraData(Enum, data) },
|
.type_enum => .{ .enum_type = ip.extraData(Enum, data) },
|
||||||
.type_function => .{ .function_type = ip.extraData(Fn, data) },
|
.type_function => .{ .function_type = ip.extraData(Fn, data) },
|
||||||
@ -1071,59 +945,51 @@ pub fn indexToKey(ip: InternPool, index: Index) Key {
|
|||||||
.int_i32 => .{ .int_i64_value = @bitCast(i32, data) },
|
.int_i32 => .{ .int_i64_value = @bitCast(i32, data) },
|
||||||
.int_u64 => .{ .int_u64_value = ip.extraData(u64, data) },
|
.int_u64 => .{ .int_u64_value = ip.extraData(u64, data) },
|
||||||
.int_i64 => .{ .int_i64_value = ip.extraData(i64, data) },
|
.int_i64 => .{ .int_i64_value = ip.extraData(i64, data) },
|
||||||
.int_big_positive => unreachable,
|
.int_big_positive => .{ .int_big_value = .{
|
||||||
.int_big_negative => unreachable,
|
.positive = true,
|
||||||
|
.limbs = ip.extraData([]const std.math.big.Limb, data),
|
||||||
|
} },
|
||||||
|
.int_big_negative => .{ .int_big_value = .{
|
||||||
|
.positive = true,
|
||||||
|
.limbs = ip.extraData([]const std.math.big.Limb, data),
|
||||||
|
} },
|
||||||
.float_f16 => .{ .float_16_value = @bitCast(f16, @intCast(u16, data)) },
|
.float_f16 => .{ .float_16_value = @bitCast(f16, @intCast(u16, data)) },
|
||||||
.float_f32 => .{ .float_32_value = @bitCast(f32, data) },
|
.float_f32 => .{ .float_32_value = @bitCast(f32, data) },
|
||||||
.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) },
|
|
||||||
|
|
||||||
.bytes => unreachable, // TODO
|
.bytes => .{ .bytes = ip.extraData([]const u8, data) },
|
||||||
// .one_pointer => .{ .one_pointer = @intToEnum(Index, data) },
|
.aggregate => .{ .aggregate = ip.extraData(Aggregate, data) },
|
||||||
else => @panic("TODO"),
|
.union_value => .{ .union_value = ip.extraData(UnionValue, data) },
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {
|
pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {
|
||||||
const adapter: KeyAdapter = .{ .intern_pool = ip };
|
const adapter: KeyAdapter = .{ .ip = ip };
|
||||||
const gop = try ip.map.getOrPutAdapted(gpa, key, adapter);
|
const gop = try ip.map.getOrPutAdapted(gpa, key, adapter);
|
||||||
if (gop.found_existing) return @intToEnum(Index, gop.index);
|
if (gop.found_existing) return @intToEnum(Index, gop.index);
|
||||||
|
|
||||||
const item: Item = switch (key) {
|
const tag: Tag = key.tag();
|
||||||
.simple => |simple| .{ .tag = .simple, .data = @enumToInt(simple) },
|
const data: u32 = switch (key) {
|
||||||
.int_type => |int_ty| .{
|
.simple => |simple| @enumToInt(simple),
|
||||||
.tag = switch (int_ty.signedness) {
|
|
||||||
.signed => .type_int_signed,
|
.int_type => |int_ty| int_ty.bits,
|
||||||
.unsigned => .type_int_unsigned,
|
.optional_type => |optional_ty| @enumToInt(optional_ty.payload_type),
|
||||||
},
|
.anyframe_type => |anyframe_ty| @enumToInt(anyframe_ty.child),
|
||||||
.data = int_ty.bits,
|
|
||||||
},
|
.int_u64_value => |int_val| if (tag == .int_u32) @intCast(u32, int_val) else try ip.addExtra(gpa, int_val),
|
||||||
.optional_type => |optional_ty| .{ .tag = .type_optional, .data = @enumToInt(optional_ty.payload_type) },
|
.int_i64_value => |int_val| if (tag == .int_i32) @bitCast(u32, @intCast(u32, int_val)) else try ip.addExtra(gpa, int_val),
|
||||||
.anyframe_t_type => |anyframe_t| .{ .tag = .type_anyframe_t, .data = @enumToInt(anyframe_t.child) },
|
.int_big_value => |big_int_val| try ip.addExtra(gpa, big_int_val.limbs),
|
||||||
.int_u64_value => |int_val| if (int_val <= std.math.maxInt(u32)) .{
|
.float_16_value => |float_val| @bitCast(u16, float_val),
|
||||||
.tag = .int_u32,
|
.float_32_value => |float_val| @bitCast(u32, float_val),
|
||||||
.data = @intCast(u32, int_val),
|
inline else => |data| try ip.addExtra(gpa, data), // TODO sad stage1 noises :(
|
||||||
} else .{
|
|
||||||
.tag = .int_u64,
|
|
||||||
.data = try ip.addExtra(gpa, int_val),
|
|
||||||
},
|
|
||||||
.int_i64_value => |int_val| if (std.math.maxInt(i32) <= int_val and int_val <= std.math.maxInt(i32)) .{
|
|
||||||
.tag = .int_i32,
|
|
||||||
.data = @bitCast(u32, @intCast(u32, int_val)),
|
|
||||||
} else .{
|
|
||||||
.tag = .int_i64,
|
|
||||||
.data = try ip.addExtra(gpa, int_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) },
|
|
||||||
// .type_value => |ty| .{ .tag = .type, .data = @enumToInt(ty) },
|
|
||||||
.bytes => unreachable, // TODO
|
|
||||||
// .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 :(
|
|
||||||
};
|
};
|
||||||
try ip.items.append(gpa, item);
|
|
||||||
|
try ip.items.append(gpa, .{
|
||||||
|
.tag = tag,
|
||||||
|
.data = data,
|
||||||
|
});
|
||||||
return @intToEnum(Index, ip.items.len - 1);
|
return @intToEnum(Index, ip.items.len - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1142,6 +1008,135 @@ fn extraData(ip: InternPool, comptime T: type, index: usize) T {
|
|||||||
return std.mem.bytesToValue(T, bytes);
|
return std.mem.bytesToValue(T, bytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const KeyAdapter = struct {
|
||||||
|
ip: *const InternPool,
|
||||||
|
|
||||||
|
pub fn eql(ctx: @This(), a: Key, b_void: void, b_map_index: usize) bool {
|
||||||
|
_ = b_void;
|
||||||
|
|
||||||
|
return deepEql(a, ctx.ip.indexToKey(@intToEnum(Index, b_map_index)));
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn hash(ctx: @This(), a: Key) u32 {
|
||||||
|
_ = ctx;
|
||||||
|
var hasher = std.hash.Wyhash.init(0);
|
||||||
|
deepHash(&hasher, a);
|
||||||
|
return @truncate(u32, hasher.final());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
fn deepEql(a: anytype, b: @TypeOf(a)) bool {
|
||||||
|
const T = @TypeOf(a);
|
||||||
|
|
||||||
|
switch (@typeInfo(T)) {
|
||||||
|
.Struct => |info| {
|
||||||
|
if (info.layout == .Packed) {
|
||||||
|
return std.mem.eql(u8, std.mem.asBytes(&a), std.mem.asBytes(&b));
|
||||||
|
}
|
||||||
|
inline for (info.fields) |field_info| {
|
||||||
|
if (!deepEql(@field(a, field_info.name), @field(b, field_info.name))) return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
.Union => |info| {
|
||||||
|
const UnionTag = info.tag_type.?;
|
||||||
|
|
||||||
|
const tag_a = std.meta.activeTag(a);
|
||||||
|
const tag_b = std.meta.activeTag(b);
|
||||||
|
if (tag_a != tag_b) return false;
|
||||||
|
|
||||||
|
inline for (info.fields) |field_info| {
|
||||||
|
if (@field(UnionTag, field_info.name) == tag_a) {
|
||||||
|
return deepEql(@field(a, field_info.name), @field(b, field_info.name));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
.Pointer => |info| {
|
||||||
|
if (info.size != .Slice) {
|
||||||
|
@compileError("cannot compare non slice pointer type " ++ @typeName(T));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (@typeInfo(info.child) == .Int) {
|
||||||
|
return std.mem.eql(info.child, a, b);
|
||||||
|
}
|
||||||
|
if (a.len != b.len) return false;
|
||||||
|
|
||||||
|
var i: usize = 0;
|
||||||
|
while (i < a.len) : (i += 1) {
|
||||||
|
if (!deepEql(a[i], b[i])) return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
.Enum, .Int => return a == b,
|
||||||
|
else => unreachable,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deepHash(hasher: anytype, key: anytype) void {
|
||||||
|
const Inner = @TypeOf(key);
|
||||||
|
|
||||||
|
switch (@typeInfo(Inner)) {
|
||||||
|
.Int => {
|
||||||
|
if (comptime std.meta.trait.hasUniqueRepresentation(Inner)) {
|
||||||
|
hasher.update(std.mem.asBytes(&key));
|
||||||
|
} else {
|
||||||
|
const byte_size = comptime std.math.divCeil(comptime_int, @bitSizeOf(Inner), 8) catch unreachable;
|
||||||
|
hasher.update(std.mem.asBytes(&key)[0..byte_size]);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
.Bool => deepHash(hasher, @boolToInt(key)),
|
||||||
|
.Enum => deepHash(hasher, @enumToInt(key)),
|
||||||
|
.Float => |info| deepHash(hasher, switch (info.bits) {
|
||||||
|
16 => @bitCast(u16, key),
|
||||||
|
32 => @bitCast(u32, key),
|
||||||
|
64 => @bitCast(u64, key),
|
||||||
|
80 => @bitCast(u80, key),
|
||||||
|
128 => @bitCast(u128, key),
|
||||||
|
else => unreachable,
|
||||||
|
}),
|
||||||
|
|
||||||
|
.Pointer => |info| {
|
||||||
|
if (info.size != .Slice) {
|
||||||
|
@compileError("");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (comptime std.meta.trait.hasUniqueRepresentation(info.child)) {
|
||||||
|
hasher.update(std.mem.sliceAsBytes(key));
|
||||||
|
} else {
|
||||||
|
for (key) |item| {
|
||||||
|
deepHash(hasher, item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
.Struct => |info| {
|
||||||
|
if (info.layout == .Packed) {
|
||||||
|
hasher.update(std.mem.asBytes(&key));
|
||||||
|
} else {
|
||||||
|
inline for (info.fields) |field| {
|
||||||
|
deepHash(hasher, @field(key, field.name));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
.Union => |info| {
|
||||||
|
const TagType = info.tag_type.?;
|
||||||
|
|
||||||
|
const tag = std.meta.activeTag(key);
|
||||||
|
deepHash(hasher, tag);
|
||||||
|
inline for (info.fields) |field| {
|
||||||
|
if (@field(TagType, field.name) == tag) {
|
||||||
|
deepHash(hasher, @field(key, field.name));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
else => unreachable,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// ---------------------------------------------
|
// ---------------------------------------------
|
||||||
// UTILITY
|
// UTILITY
|
||||||
// ---------------------------------------------
|
// ---------------------------------------------
|
||||||
@ -2601,8 +2596,8 @@ test "anyframe type" {
|
|||||||
const i32_type = try ip.get(gpa, .{ .int_type = .{ .signedness = .signed, .bits = 32 } });
|
const i32_type = try ip.get(gpa, .{ .int_type = .{ .signedness = .signed, .bits = 32 } });
|
||||||
const bool_type = try ip.get(gpa, .{ .simple = .bool });
|
const bool_type = try ip.get(gpa, .{ .simple = .bool });
|
||||||
|
|
||||||
const @"anyframe->i32" = try ip.get(gpa, Key{ .anyframe_t_type = .{ .child = i32_type } });
|
const @"anyframe->i32" = try ip.get(gpa, Key{ .anyframe_type = .{ .child = i32_type } });
|
||||||
const @"anyframe->bool" = try ip.get(gpa, Key{ .anyframe_t_type = .{ .child = bool_type } });
|
const @"anyframe->bool" = try ip.get(gpa, Key{ .anyframe_type = .{ .child = bool_type } });
|
||||||
|
|
||||||
try testExpectFmtType(&ip, @"anyframe->i32", "anyframe->i32");
|
try testExpectFmtType(&ip, @"anyframe->i32", "anyframe->i32");
|
||||||
try testExpectFmtType(&ip, @"anyframe->bool", "anyframe->bool");
|
try testExpectFmtType(&ip, @"anyframe->bool", "anyframe->bool");
|
||||||
|
Loading…
Reference in New Issue
Block a user