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