| ... | @@ -1242,8 +1242,139 @@ pub const Value = extern union { | ... | @@ -1242,8 +1242,139 @@ pub const Value = extern union { |
| 1242 | return compare(a, .eq, b); | 1242 | return compare(a, .eq, b); |
| 1243 | } | 1243 | } |
| 1244 | | 1244 | |
| 1245 | pub fn hash(a: Value) u64 { | 1245 | pub fn hash(self: Value) u64 { |
| 1246 | @panic("TODO Value.hash"); | 1246 | var hasher = std.hash.Wyhash.init(0); |
| | 1247 | std.hash.autoHash(&hasher, self.tag()); |
| | 1248 | |
| | 1249 | switch (self.tag()) { |
| | 1250 | .u8_type, |
| | 1251 | .i8_type, |
| | 1252 | .u16_type, |
| | 1253 | .i16_type, |
| | 1254 | .u32_type, |
| | 1255 | .i32_type, |
| | 1256 | .u64_type, |
| | 1257 | .i64_type, |
| | 1258 | .usize_type, |
| | 1259 | .isize_type, |
| | 1260 | .c_short_type, |
| | 1261 | .c_ushort_type, |
| | 1262 | .c_int_type, |
| | 1263 | .c_uint_type, |
| | 1264 | .c_long_type, |
| | 1265 | .c_ulong_type, |
| | 1266 | .c_longlong_type, |
| | 1267 | .c_ulonglong_type, |
| | 1268 | .c_longdouble_type, |
| | 1269 | .f16_type, |
| | 1270 | .f32_type, |
| | 1271 | .f64_type, |
| | 1272 | .f128_type, |
| | 1273 | .c_void_type, |
| | 1274 | .bool_type, |
| | 1275 | .void_type, |
| | 1276 | .type_type, |
| | 1277 | .anyerror_type, |
| | 1278 | .comptime_int_type, |
| | 1279 | .comptime_float_type, |
| | 1280 | .noreturn_type, |
| | 1281 | .null_type, |
| | 1282 | .undefined_type, |
| | 1283 | .fn_noreturn_no_args_type, |
| | 1284 | .fn_void_no_args_type, |
| | 1285 | .fn_naked_noreturn_no_args_type, |
| | 1286 | .fn_ccc_void_no_args_type, |
| | 1287 | .single_const_pointer_to_comptime_int_type, |
| | 1288 | .const_slice_u8_type, |
| | 1289 | .enum_literal_type, |
| | 1290 | .anyframe_type, |
| | 1291 | .ty, |
| | 1292 | => { |
| | 1293 | // Directly return Type.hash, toType can only fail for .int_type and .error_set. |
| | 1294 | var allocator = std.heap.FixedBufferAllocator.init(&[_]u8{}); |
| | 1295 | return (self.toType(&allocator.allocator) catch unreachable).hash(); |
| | 1296 | }, |
| | 1297 | .error_set => { |
| | 1298 | // Payload.decl should be same for all instances of the type. |
| | 1299 | const payload = @fieldParentPtr(Payload.ErrorSet, "base", self.ptr_otherwise); |
| | 1300 | std.hash.autoHash(&hasher, payload.decl); |
| | 1301 | }, |
| | 1302 | .int_type => { |
| | 1303 | const payload = self.cast(Payload.IntType).?; |
| | 1304 | if (payload.signed) { |
| | 1305 | var new = Type.Payload.IntSigned{ .bits = payload.bits }; |
| | 1306 | return Type.initPayload(&new.base).hash(); |
| | 1307 | } else { |
| | 1308 | var new = Type.Payload.IntUnsigned{ .bits = payload.bits }; |
| | 1309 | return Type.initPayload(&new.base).hash(); |
| | 1310 | } |
| | 1311 | }, |
| | 1312 | |
| | 1313 | .undef, |
| | 1314 | .zero, |
| | 1315 | .one, |
| | 1316 | .void_value, |
| | 1317 | .unreachable_value, |
| | 1318 | .empty_struct_value, |
| | 1319 | .empty_array, |
| | 1320 | .null_value, |
| | 1321 | .bool_true, |
| | 1322 | .bool_false, |
| | 1323 | => {}, |
| | 1324 | |
| | 1325 | .float_16, .float_32, .float_64, .float_128 => {}, |
| | 1326 | .enum_literal, .bytes => { |
| | 1327 | const payload = @fieldParentPtr(Payload.Bytes, "base", self.ptr_otherwise); |
| | 1328 | hasher.update(payload.data); |
| | 1329 | }, |
| | 1330 | .int_u64 => { |
| | 1331 | const payload = @fieldParentPtr(Payload.Int_u64, "base", self.ptr_otherwise); |
| | 1332 | std.hash.autoHash(&hasher, payload.int); |
| | 1333 | }, |
| | 1334 | .int_i64 => { |
| | 1335 | const payload = @fieldParentPtr(Payload.Int_i64, "base", self.ptr_otherwise); |
| | 1336 | std.hash.autoHash(&hasher, payload.int); |
| | 1337 | }, |
| | 1338 | .repeated => { |
| | 1339 | const payload = @fieldParentPtr(Payload.Repeated, "base", self.ptr_otherwise); |
| | 1340 | std.hash.autoHash(&hasher, payload.val.hash()); |
| | 1341 | }, |
| | 1342 | .ref_val => { |
| | 1343 | const payload = @fieldParentPtr(Payload.RefVal, "base", self.ptr_otherwise); |
| | 1344 | std.hash.autoHash(&hasher, payload.val.hash()); |
| | 1345 | }, |
| | 1346 | .int_big_positive, .int_big_negative => { |
| | 1347 | var space: BigIntSpace = undefined; |
| | 1348 | const big = self.toBigInt(&space); |
| | 1349 | std.hash.autoHash(&hasher, big.positive); |
| | 1350 | for (big.limbs) |limb| { |
| | 1351 | std.hash.autoHash(&hasher, limb); |
| | 1352 | } |
| | 1353 | }, |
| | 1354 | .elem_ptr => { |
| | 1355 | const payload = @fieldParentPtr(Payload.ElemPtr, "base", self.ptr_otherwise); |
| | 1356 | std.hash.autoHash(&hasher, payload.array_ptr.hash()); |
| | 1357 | std.hash.autoHash(&hasher, payload.index); |
| | 1358 | }, |
| | 1359 | .decl_ref => { |
| | 1360 | const payload = @fieldParentPtr(Payload.DeclRef, "base", self.ptr_otherwise); |
| | 1361 | std.hash.autoHash(&hasher, payload.decl); |
| | 1362 | }, |
| | 1363 | .function => { |
| | 1364 | const payload = @fieldParentPtr(Payload.Function, "base", self.ptr_otherwise); |
| | 1365 | std.hash.autoHash(&hasher, payload.func); |
| | 1366 | }, |
| | 1367 | .variable => { |
| | 1368 | const payload = @fieldParentPtr(Payload.Variable, "base", self.ptr_otherwise); |
| | 1369 | std.hash.autoHash(&hasher, payload.variable); |
| | 1370 | }, |
| | 1371 | .@"error" => { |
| | 1372 | const payload = @fieldParentPtr(Payload.Error, "base", self.ptr_otherwise); |
| | 1373 | hasher.update(payload.name); |
| | 1374 | std.hash.autoHash(&hasher, payload.value); |
| | 1375 | }, |
| | 1376 | } |
| | 1377 | return hasher.final(); |
| 1247 | } | 1378 | } |
| 1248 | | 1379 | |
| 1249 | /// Asserts the value is a pointer and dereferences it. | 1380 | /// Asserts the value is a pointer and dereferences it. |