stage2: implement Value.hash

This commit is contained in:
Vexu 2020-10-12 12:53:44 +03:00
parent 27d233cef7
commit 7e2774367e
No known key found for this signature in database
GPG Key ID: 59AEB8936E16A6AC

View File

@ -1242,8 +1242,139 @@ pub const Value = extern union {
return compare(a, .eq, b);
}
pub fn hash(a: Value) u64 {
@panic("TODO Value.hash");
pub fn hash(self: Value) u64 {
var hasher = std.hash.Wyhash.init(0);
std.hash.autoHash(&hasher, self.tag());
switch (self.tag()) {
.u8_type,
.i8_type,
.u16_type,
.i16_type,
.u32_type,
.i32_type,
.u64_type,
.i64_type,
.usize_type,
.isize_type,
.c_short_type,
.c_ushort_type,
.c_int_type,
.c_uint_type,
.c_long_type,
.c_ulong_type,
.c_longlong_type,
.c_ulonglong_type,
.c_longdouble_type,
.f16_type,
.f32_type,
.f64_type,
.f128_type,
.c_void_type,
.bool_type,
.void_type,
.type_type,
.anyerror_type,
.comptime_int_type,
.comptime_float_type,
.noreturn_type,
.null_type,
.undefined_type,
.fn_noreturn_no_args_type,
.fn_void_no_args_type,
.fn_naked_noreturn_no_args_type,
.fn_ccc_void_no_args_type,
.single_const_pointer_to_comptime_int_type,
.const_slice_u8_type,
.enum_literal_type,
.anyframe_type,
.ty,
=> {
// Directly return Type.hash, toType can only fail for .int_type and .error_set.
var allocator = std.heap.FixedBufferAllocator.init(&[_]u8{});
return (self.toType(&allocator.allocator) catch unreachable).hash();
},
.error_set => {
// Payload.decl should be same for all instances of the type.
const payload = @fieldParentPtr(Payload.ErrorSet, "base", self.ptr_otherwise);
std.hash.autoHash(&hasher, payload.decl);
},
.int_type => {
const payload = self.cast(Payload.IntType).?;
if (payload.signed) {
var new = Type.Payload.IntSigned{ .bits = payload.bits };
return Type.initPayload(&new.base).hash();
} else {
var new = Type.Payload.IntUnsigned{ .bits = payload.bits };
return Type.initPayload(&new.base).hash();
}
},
.undef,
.zero,
.one,
.void_value,
.unreachable_value,
.empty_struct_value,
.empty_array,
.null_value,
.bool_true,
.bool_false,
=> {},
.float_16, .float_32, .float_64, .float_128 => {},
.enum_literal, .bytes => {
const payload = @fieldParentPtr(Payload.Bytes, "base", self.ptr_otherwise);
hasher.update(payload.data);
},
.int_u64 => {
const payload = @fieldParentPtr(Payload.Int_u64, "base", self.ptr_otherwise);
std.hash.autoHash(&hasher, payload.int);
},
.int_i64 => {
const payload = @fieldParentPtr(Payload.Int_i64, "base", self.ptr_otherwise);
std.hash.autoHash(&hasher, payload.int);
},
.repeated => {
const payload = @fieldParentPtr(Payload.Repeated, "base", self.ptr_otherwise);
std.hash.autoHash(&hasher, payload.val.hash());
},
.ref_val => {
const payload = @fieldParentPtr(Payload.RefVal, "base", self.ptr_otherwise);
std.hash.autoHash(&hasher, payload.val.hash());
},
.int_big_positive, .int_big_negative => {
var space: BigIntSpace = undefined;
const big = self.toBigInt(&space);
std.hash.autoHash(&hasher, big.positive);
for (big.limbs) |limb| {
std.hash.autoHash(&hasher, limb);
}
},
.elem_ptr => {
const payload = @fieldParentPtr(Payload.ElemPtr, "base", self.ptr_otherwise);
std.hash.autoHash(&hasher, payload.array_ptr.hash());
std.hash.autoHash(&hasher, payload.index);
},
.decl_ref => {
const payload = @fieldParentPtr(Payload.DeclRef, "base", self.ptr_otherwise);
std.hash.autoHash(&hasher, payload.decl);
},
.function => {
const payload = @fieldParentPtr(Payload.Function, "base", self.ptr_otherwise);
std.hash.autoHash(&hasher, payload.func);
},
.variable => {
const payload = @fieldParentPtr(Payload.Variable, "base", self.ptr_otherwise);
std.hash.autoHash(&hasher, payload.variable);
},
.@"error" => {
const payload = @fieldParentPtr(Payload.Error, "base", self.ptr_otherwise);
hasher.update(payload.name);
std.hash.autoHash(&hasher, payload.value);
},
}
return hasher.final();
}
/// Asserts the value is a pointer and dereferences it.