authorgravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2020-10-12 12:53:44+03:00
committergravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2020-10-30 15:58:12+02:00
log7e2774367e5420a8f388b57f80bede8f0f680ca7
tree47f966b88724981829ae0d5a8ad8509f537d61bb
parent27d233cef76f9ae3086a6ec5e33c347e2af64796
signaturelock-open Commit is signed but in an unrecognized format.

stage2: implement Value.hash


1 files changed, 133 insertions(+), 2 deletions(-)

src/value.zig+133-2
......@@ -1242,8 +1242,139 @@ pub const Value = extern union {
12421242 return compare(a, .eq, b);
12431243 }
12441244
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();
12471378 }
12481379
12491380 /// Asserts the value is a pointer and dereferences it.