object.c 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. /**
  2. ******************************************************************************
  3. * @file : object.cpp
  4. * @author : simon
  5. * @brief : None
  6. * @attention : None
  7. * @date : 2023/8/23
  8. ******************************************************************************
  9. */
  10. #include <stdio.h>
  11. #include <string.h>
  12. #include "memory.h"
  13. #include "object.h"
  14. #include "table.h"
  15. #include "vm.h"
  16. static Obj *allocateObject(size_t size, ObjType type);
  17. static uint32_t hashString(const char *key, int length);
  18. #define ALLOCATE_OBJ(type, objectType) \
  19. (type *) allocateObject(sizeof(type), objectType)
  20. static ObjString *allocateString(char *chars, int length,
  21. uint32_t hash) {
  22. ObjString *string = ALLOCATE_OBJ(ObjString, OBJ_STRING);
  23. string->length = length;
  24. string->chars = chars;
  25. string->hash = hash;
  26. push(OBJ_VAL(string));
  27. tableSet(&vm.strings, string, NIL_VAL);
  28. pop();
  29. return string;
  30. }
  31. ObjString *copyString(const char *chars, int length) {
  32. uint32_t hash = hashString(chars, length);
  33. ObjString *interned = tableFindString(&vm.strings, chars, length, hash);
  34. if (interned != NULL) return interned;
  35. char *heapChars = ALLOCATE(char, length + 1);
  36. memcpy(heapChars, chars, length);
  37. heapChars[length] = '\0';
  38. return allocateString(heapChars, length, hash);
  39. }
  40. static void printFunction(ObjFunction *function) {
  41. if (function->name == NULL) {
  42. printf("<script>");
  43. return;
  44. }
  45. printf("<fn %s>", function->name->chars);
  46. }
  47. /// 打印对象
  48. /// \param value
  49. void printObject(Value value) {
  50. switch (OBJ_TYPE(value)) {
  51. case OBJ_NATIVE:
  52. printf("<native fn>");
  53. break;
  54. case OBJ_FUNCTION:
  55. printFunction(AS_FUNCTION(value));
  56. break;
  57. case OBJ_STRING:
  58. printf("%s", AS_CSTRING(value));
  59. break;
  60. case OBJ_CLOSURE:
  61. printFunction(AS_CLOSURE(value)->function);
  62. break;
  63. case OBJ_UPVALUE:
  64. printf("upvalue");
  65. break;
  66. case OBJ_CLASS:
  67. printf("%s class", AS_CLASS(value)->name->chars);
  68. break;
  69. case OBJ_INSTANCE:
  70. printf("%s instance", AS_INSTANCE(value)->klass->name->chars);
  71. break;
  72. case OBJ_BOUND_METHOD:
  73. printFunction(AS_BOUND_METHOD(value)->method->function);
  74. break;
  75. }
  76. }
  77. ObjFunction *newFunction() {
  78. ObjFunction *function = ALLOCATE_OBJ(ObjFunction, OBJ_FUNCTION);
  79. function->arity = 0;
  80. function->upvalueCount = 0;
  81. function->name = NULL;
  82. initChunk(&function->chunk);
  83. return function;
  84. }
  85. ObjString *takeString(char *chars, int length) {
  86. uint32_t hash = hashString(chars, length);
  87. ObjString *interned = tableFindString(&vm.strings, chars, length, hash);
  88. if (interned != NULL) {
  89. FREE_ARRAY(char, chars, length + 1);
  90. return interned;
  91. }
  92. return allocateString(chars, length, hash);
  93. }
  94. ObjNative *newNative(NativeFn function) {
  95. ObjNative *native = ALLOCATE_OBJ(ObjNative, OBJ_NATIVE);
  96. native->function = function;
  97. return native;
  98. }
  99. ObjClosure *newClosure(ObjFunction *function) {
  100. ObjUpvalue **upvalues = ALLOCATE(ObjUpvalue *, function->upvalueCount);
  101. for (int i = 0; i < function->upvalueCount; i++) {
  102. upvalues[i] = NULL;
  103. }
  104. ObjClosure *closure = ALLOCATE_OBJ(ObjClosure, OBJ_CLOSURE);
  105. closure->function = function;
  106. closure->upvalues = upvalues;
  107. closure->upvalueCount = function->upvalueCount;
  108. return closure;
  109. }
  110. ObjUpvalue *newUpvalue(Value *slot) {
  111. ObjUpvalue *upvalue = ALLOCATE_OBJ(ObjUpvalue, OBJ_UPVALUE);
  112. upvalue->closed = NIL_VAL;
  113. upvalue->location = slot;
  114. upvalue->next = NULL;
  115. return upvalue;
  116. }
  117. ObjClass *newClass(ObjString *name) {
  118. ObjClass *klass = ALLOCATE_OBJ(ObjClass, OBJ_CLASS);
  119. klass->name = name;
  120. initTable(&klass->methods);
  121. return klass;
  122. }
  123. ObjInstance *newInstance(ObjClass *klass) {
  124. ObjInstance *instance = ALLOCATE_OBJ(ObjInstance, OBJ_INSTANCE);
  125. instance->klass = klass;
  126. initTable(&instance->fields);
  127. return instance;
  128. }
  129. ObjBoundMethod *newBoundMethod(Value receiver, ObjClosure *method) {
  130. ObjBoundMethod *bound = ALLOCATE_OBJ(ObjBoundMethod, OBJ_BOUND_METHOD);
  131. bound->receiver = receiver;
  132. bound->method = method;
  133. return bound;
  134. }
  135. /// 分配内存空间
  136. /// \param size 空间大小
  137. /// \param type 对象类型
  138. /// \return Obj*
  139. static Obj *allocateObject(size_t size, ObjType type) {
  140. Obj *object = (Obj *) reallocate(NULL, 0, size);
  141. object->type = type;
  142. object->isMarked = false;
  143. object->next = vm.objects;
  144. vm.objects = object;
  145. #ifdef DEBUG_LOG_GC
  146. PRINTLNF("%p allocate %zu for %d\n", (void *) object, size, type);
  147. #endif
  148. return object;
  149. }
  150. /// Hash 函数 -- 使用 FNV-1a 算法
  151. /// \param key
  152. /// \param length
  153. /// \return
  154. static uint32_t hashString(const char *key, int length) {
  155. uint32_t hash = 2166136261u;
  156. for (int i = 0; i < length; i++) {
  157. hash ^= (uint8_t) key[i];
  158. hash *= 16777619;
  159. }
  160. return hash;
  161. }