Implement __eq__ and hashing for tuples

This commit is contained in:
K. Lange 2021-01-12 22:30:06 +09:00
parent f43eff0f2e
commit 975d4dcb9b
2 changed files with 23 additions and 0 deletions

11
table.c
View File

@ -20,6 +20,8 @@ void krk_freeTable(KrkTable * table) {
krk_initTable(table);
}
static uint32_t hashTupleValues(KrkTuple *tuple);
static uint32_t hashValue(KrkValue value) {
if (IS_STRING(value)) return (AS_STRING(value))->hash;
if (IS_INTEGER(value)) return (uint32_t)(AS_INTEGER(value));
@ -27,9 +29,18 @@ static uint32_t hashValue(KrkValue value) {
if (IS_BOOLEAN(value)) return (uint32_t)(AS_BOOLEAN(value));
if (IS_NONE(value)) return 0;
if (IS_BYTES(value)) return (AS_BYTES(value))->hash; /* Same as strings, but we don't have an interning table */
if (IS_TUPLE(value)) return hashTupleValues(AS_TUPLE(value));
return (((uint32_t)(intptr_t)AS_OBJECT(value)) >> 4)| (((uint32_t)(intptr_t)AS_OBJECT(value)) << 28);
}
static uint32_t hashTupleValues(KrkTuple *tuple) {
uint32_t hash = 0;
for (size_t i = 0; i < tuple->values.count; ++i) {
hash += hashValue(tuple->values.values[i]);
}
return hash;
}
KrkTableEntry * krk_findEntry(KrkTableEntry * entries, size_t capacity, KrkValue key) {
uint32_t index = hashValue(key) % capacity;
KrkTableEntry * tombstone = NULL;

12
vm.c
View File

@ -2450,6 +2450,17 @@ static KrkValue _tuple_get(int argc, KrkValue argv[]) {
return tuple->values.values[index];
}
static KrkValue _tuple_eq(int argc, KrkValue argv[]) {
if (!IS_TUPLE(argv[1])) return BOOLEAN_VAL(0);
KrkTuple * self = AS_TUPLE(argv[0]);
KrkTuple * them = AS_TUPLE(argv[1]);
if (self->values.count != them->values.count) return BOOLEAN_VAL(0);
for (size_t i = 0; i < self->values.count; ++i) {
if (!krk_valuesEqual(self->values.values[i], them->values.values[i])) return BOOLEAN_VAL(0);
}
return BOOLEAN_VAL(1);
}
static KrkValue _tuple_repr(int argc, KrkValue argv[]) {
if (argc != 1) {
krk_runtimeError(vm.exceptions.argumentError, "tuple.__repr__ does not expect arguments");
@ -3187,6 +3198,7 @@ void krk_initVM(int flags) {
krk_defineNative(&vm.baseClasses.tupleClass->methods, ".__len__", _tuple_len);
krk_defineNative(&vm.baseClasses.tupleClass->methods, ".__contains__", _tuple_contains);
krk_defineNative(&vm.baseClasses.tupleClass->methods, ".__iter__", _tuple_iter);
krk_defineNative(&vm.baseClasses.tupleClass->methods, ".__eq__", _tuple_eq);
krk_finalizeClass(vm.baseClasses.tupleClass);
ADD_BASE_CLASS(vm.baseClasses.bytesClass, "bytes", vm.objectClass);
krk_defineNative(&vm.baseClasses.bytesClass->methods, ".__init__", _bytes_init);