#include #include #include #include "object.h" #include "memory.h" #include "value.h" void initValueArray(ValueArray* array) { array->values = NULL; array->capacity = 0; array->count = 0; } void writeValueArray(ValueArray* array, Value value) { if (array->capacity < array->count + 1) { int oldCapacity = array->capacity; array->capacity = GROW_CAPACITY(oldCapacity); array->values = GROW_ARRAY(array->values, Value, oldCapacity, array->capacity); } array->values[array->count] = value; array->count++; } void freeValueArray(ValueArray* array) { FREE_ARRAY(Value, array->values, array->capacity); initValueArray(array); } void printValue(Value value) { switch (value.type) { case VAL_BOOL: printf(AS_BOOL(value) ? "true" : "false"); break; case VAL_NIL: printf("nil"); break; case VAL_NUMBER: printf("%g", AS_NUMBER(value)); break; case VAL_OBJ: printObject(value); break; case VAL_EMPTY: printf(""); break; } } bool valuesEqual(Value a, Value b) { if (a.type != b.type) return false; switch (a.type) { case VAL_BOOL: return AS_BOOL(a) == AS_BOOL(b); case VAL_NIL: return true; case VAL_NUMBER: return AS_NUMBER(a) == AS_NUMBER(b); case VAL_OBJ: { return AS_OBJ(a) == AS_OBJ(b); } case VAL_EMPTY: return true; } return false; } static uint32_t hashDouble(double value) { union BitCast { double value; uint32_t ints[2]; }; union BitCast cast; cast.value = (value) + 1.0; return cast.ints[0] + cast.ints[1]; } static uint32_t hashUint(unsigned int value) { uint8_t bytes[4]; bytes[0] = value & 0xFF; bytes[1] = (value & 0xFF00) >> 8; bytes[2] = (value & 0xFF0000) >> 16; bytes[3] = (value & 0xFF000000) > 24; uint32_t hash = 2166136261u; for (int i = 0; i < 4; i++) { hash ^= bytes[i]; hash *= 16777619; } return hash; } uint32_t hashValue(Value value) { switch (value.type) { case VAL_BOOL: return AS_BOOL(value) ? 3 : 5; case VAL_NIL: return 7; case VAL_NUMBER: return hashDouble(AS_NUMBER(value)); case VAL_OBJ: { Obj* object = AS_OBJ(value); switch (object->type) { case OBJ_STRING: return AS_STRING(value)->hash; break; case OBJ_ARRAY: { ValueArray* valArray = AS_VARRAY(value); unsigned int sum = 0; for (int i = 0; i < valArray->count; i++) { uint32_t valHash = hashValue(valArray->values[i])*i; if ((UINT_MAX - sum) < valHash) { sum = hashUint(sum); } sum += valHash; } return hashUint(sum); break; } case OBJ_HASH: { Table* hash = AS_HASH(value); Entry** entries = getEntries(hash); unsigned int sum = 0; for (int i = 0; entries[i] != NULL; i++) { Entry* entry = entries[i]; uint32_t valHash = hashUint((hashValue(entry->key)*i)+(hashValue(entry->value)*i)); if ((UINT_MAX - sum) < valHash) { sum = hashUint(sum); } sum += valHash; } return hashUint(sum); break; } default: return 0; } break; } case VAL_EMPTY: return 0; } return 0; }