#include #include #include "memory.h" #include "object.h" #include "table.h" #include "value.h" #include "vm.h" #define ALLOCATE_OBJ(type, objectType) \ (type*)allocateObject(sizeof(type), objectType) static Obj* allocateObject(size_t size, ObjType type) { Obj* object = (Obj*)reallocate(nullptr, 0, size); object->type = type; object->isMarked = false; object->next = vm.objects; vm.objects = object; #ifdef DEBUG_LOG_GC printf("%p allocate %zu for %d\n", (void*)object, size, type); #endif return object; } ObjBoundMethod* newBoundMethod(Value receiver, ObjClosure* method) { ObjBoundMethod* bound = ALLOCATE_OBJ(ObjBoundMethod, OBJ_BOUND_METHOD); bound->receiver = receiver; bound->method = method; return bound; } ObjClass* newClass(ObjString* name) { ObjClass* klass = ALLOCATE_OBJ(ObjClass, OBJ_CLASS); klass->name = name; initTable(&klass->methods); return klass; } ObjClosure* newClosure(ObjFunction* function) { ObjUpvalue** upvalues = ALLOCATE(ObjUpvalue*, function->upvalueCount); for (auto i = 0; i < function->upvalueCount; i++) { upvalues[i] = nullptr; } ObjClosure* closure = ALLOCATE_OBJ(ObjClosure, OBJ_CLOSURE); closure->function = function; closure->upvalues = upvalues; closure->upvalueCount = function->upvalueCount; return closure; } ObjFunction* newFunction() { ObjFunction* function = ALLOCATE_OBJ(ObjFunction, OBJ_FUNCTION); function->arity = 0; function->upvalueCount = 0; function->name = nullptr; initChunk(&function->chunk); return function; } ObjInstance* newInstance(ObjClass* klass) { ObjInstance* instance = ALLOCATE_OBJ(ObjInstance, OBJ_INSTANCE); instance->klass = klass; initTable(&instance->fields); return instance; } ObjNative* newNative(NativeFn function) { ObjNative* native = ALLOCATE_OBJ(ObjNative, OBJ_NATIVE); native->function = function; return native; } static ObjString* allocateString(char* chars, int length, uint32_t hash) { ObjString* string = ALLOCATE_OBJ(ObjString, OBJ_STRING); string->length = length; string->chars = chars; string->hash = hash; push(OBJ_VAL(string)); tableSet(&vm.strings, string, NIL_VAL); pop(); return string; } static uint32_t hashString(const char* key, int length) { uint32_t hash = 2166136261u; for (auto i = 0; i < length; i++) { hash ^= (uint8_t)key[i]; hash *= 16777619; } return hash; } ObjString* takeString(char* chars, int length) { auto hash = hashString(chars, length); ObjString* interned = tableFindString(&vm.strings, chars, length, hash); if (interned != nullptr) { FREE_ARRAY(char, chars, length + 1); return interned; } return allocateString(chars, length, hash); } ObjString* copyString(const char* chars, int length) { auto hash = hashString(chars, length); ObjString* interned = tableFindString(&vm.strings, chars, length, hash); if (interned != nullptr) { return interned; } char* heapChars = ALLOCATE(char, length + 1); memcpy(heapChars, chars, length); heapChars[length] = '\0'; return allocateString(heapChars, length, hash); } ObjUpvalue* newUpvalue(Value* slot) { ObjUpvalue* upvalue = ALLOCATE_OBJ(ObjUpvalue, OBJ_UPVALUE); upvalue->closed = NIL_VAL; upvalue->location = slot; upvalue->next = nullptr; return upvalue; } static void printFunction(ObjFunction* function) { if (function->name == nullptr) { printf("