| ... | ... | @@ -1242,8 +1242,139 @@ pub const Value = extern union { |
| 1242 | 1242 | return compare(a, .eq, b); |
| 1243 | 1243 | } |
| 1244 | 1244 | |
| 1245 | | pub fn hash(a: Value) u64 { |
| 1246 | | @panic("TODO Value.hash"); |
| 1245 | pub fn hash(self: Value) u64 { |
| 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 | 1380 | /// Asserts the value is a pointer and dereferences it. |