-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathobject.c
More file actions
252 lines (236 loc) · 7.04 KB
/
object.c
File metadata and controls
252 lines (236 loc) · 7.04 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
//> Strings object-c
#include "memory.h"
#include "object.h"
//> Hash Tables object-include-table
#include "table.h"
//< Hash Tables object-include-table
#include "value.h"
#include "vm.h"
//> allocate-obj
#define ALLOCATE_OBJ(type, objectType) \
(type*)allocateObject(sizeof(type), objectType)
//< allocate-obj
//> allocate-object
static Obj* allocateObject(usize size, ObjType type) {
Obj* object = (Obj*)reallocate(nil, 0, size);
object->type = type;
//> Garbage Collection init-is-marked
object->isMarked = false;
//< Garbage Collection init-is-marked
//> add-to-list
object->next = vm.objects;
vm.objects = object;
//< add-to-list
//> Garbage Collection debug-log-allocate
#ifdef DEBUG_LOG_GC
print("%p allocate %ld for %d\n", (void*)object, size, type);
#endif
//< Garbage Collection debug-log-allocate
return object;
}
//< allocate-object
//> Methods and Initializers new-bound-method
ObjBoundMethod* newBoundMethod(Value receiver, ObjClosure* method) {
ObjBoundMethod* bound = ALLOCATE_OBJ(ObjBoundMethod,
OBJ_BOUND_METHOD);
bound->receiver = receiver;
bound->method = method;
return bound;
}
//< Methods and Initializers new-bound-method
//> Classes and Instances new-class
ObjClass* newClass(ObjString* name) {
ObjClass* klass = ALLOCATE_OBJ(ObjClass, OBJ_CLASS);
klass->name = name; // [klass]
//> Methods and Initializers init-methods
initTable(&klass->methods);
//< Methods and Initializers init-methods
return klass;
}
//< Classes and Instances new-class
//> Closures new-closure
ObjClosure* newClosure(ObjFunction* function) {
//> allocate-upvalue-array
ObjUpvalue** upvalues = ALLOCATE(ObjUpvalue*, function->upvalueCount);
for (int i = 0; i < function->upvalueCount; i++) {
upvalues[i] = nil;
}
//< allocate-upvalue-array
ObjClosure* closure = ALLOCATE_OBJ(ObjClosure, OBJ_CLOSURE);
closure->function = function;
//> init-upvalue-fields
closure->upvalues = upvalues;
closure->upvalueCount = function->upvalueCount;
//< init-upvalue-fields
return closure;
}
//< Closures new-closure
//> Calls and Functions new-function
ObjFunction* newFunction(void) {
ObjFunction* function = ALLOCATE_OBJ(ObjFunction, OBJ_FUNCTION);
function->arity = 0;
//> Closures init-upvalue-count
function->upvalueCount = 0;
//< Closures init-upvalue-count
function->name = nil;
initChunk(&function->chunk);
return function;
}
//< Calls and Functions new-function
//> Classes and Instances new-instance
ObjInstance* newInstance(ObjClass* klass) {
ObjInstance* instance = ALLOCATE_OBJ(ObjInstance, OBJ_INSTANCE);
instance->klass = klass;
initTable(&instance->fields);
return instance;
}
//< Classes and Instances new-instance
//> Calls and Functions new-native
ObjNative* newNative(NativeFn function) {
ObjNative* native = ALLOCATE_OBJ(ObjNative, OBJ_NATIVE);
native->function = function;
return native;
}
//< Calls and Functions new-native
/* Strings allocate-string < Hash Tables allocate-string
static ObjString* allocateString(char* chars, int length) {
*/
//> allocate-string
//> Hash Tables allocate-string
static ObjString* allocateString(char* chars, int length,
u32int hash) {
//< Hash Tables allocate-string
ObjString* string = ALLOCATE_OBJ(ObjString, OBJ_STRING);
string->length = length;
string->chars = chars;
//> Hash Tables allocate-store-hash
string->hash = hash;
//< Hash Tables allocate-store-hash
//> Garbage Collection push-string
push(OBJ_VAL(string));
//< Garbage Collection push-string
//> Hash Tables allocate-store-string
tableSet(&vm.strings, string, NIL_VAL);
//> Garbage Collection pop-string
pop();
//< Garbage Collection pop-string
//< Hash Tables allocate-store-string
return string;
}
//< allocate-string
//> Hash Tables hash-string
static u32int hashString(const char* key, int length) {
u32int hash = 2166136261u;
for (int i = 0; i < length; i++) {
hash ^= key[i];
hash *= 16777619;
}
return hash;
}
//< Hash Tables hash-string
//> take-string
ObjString* takeString(char* chars, int length) {
/* Strings take-string < Hash Tables take-string-hash
return allocateString(chars, length);
*/
//> Hash Tables take-string-hash
u32int hash = hashString(chars, length);
//> take-string-intern
ObjString* interned = tableFindString(&vm.strings, chars, length,
hash);
if (interned != nil) {
FREE_ARRAY(char, chars, length + 1);
return interned;
}
//< take-string-intern
return allocateString(chars, length, hash);
//< Hash Tables take-string-hash
}
//< take-string
ObjString* copyString(const char* chars, int length) {
//> Hash Tables copy-string-hash
u32int hash = hashString(chars, length);
//> copy-string-intern
ObjString* interned = tableFindString(&vm.strings, chars, length,
hash);
if (interned != nil) return interned;
//< copy-string-intern
//< Hash Tables copy-string-hash
char* heapChars = ALLOCATE(char, length + 1);
memcpy(heapChars, chars, length);
heapChars[length] = '\0';
/* Strings object-c < Hash Tables copy-string-allocate
return allocateString(heapChars, length);
*/
//> Hash Tables copy-string-allocate
return allocateString(heapChars, length, hash);
//< Hash Tables copy-string-allocate
}
//> Closures new-upvalue
ObjUpvalue* newUpvalue(Value* slot) {
ObjUpvalue* upvalue = ALLOCATE_OBJ(ObjUpvalue, OBJ_UPVALUE);
//> init-closed
upvalue->closed = NIL_VAL;
//< init-closed
upvalue->location = slot;
//> init-next
upvalue->next = nil;
//< init-next
return upvalue;
}
//< Closures new-upvalue
//> Calls and Functions print-function-helper
static void printFunction(ObjFunction* function) {
//> print-script
if (function->name == nil) {
print("<script>");
return;
}
//< print-script
print("<fn %s>", function->name->chars);
}
//< Calls and Functions print-function-helper
//> print-object
void printObject(Value value) {
switch (OBJ_TYPE(value)) {
//> Classes and Instances print-class
case OBJ_CLASS:
print("%s", AS_CLASS(value)->name->chars);
break;
//< Classes and Instances print-class
//> Methods and Initializers print-bound-method
case OBJ_BOUND_METHOD:
printFunction(AS_BOUND_METHOD(value)->method->function);
break;
//< Methods and Initializers print-bound-method
//> Closures print-closure
case OBJ_CLOSURE:
printFunction(AS_CLOSURE(value)->function);
break;
//< Closures print-closure
//> Calls and Functions print-function
case OBJ_FUNCTION:
printFunction(AS_FUNCTION(value));
break;
//< Calls and Functions print-function
//> Classes and Instances print-instance
case OBJ_INSTANCE:
print("%s instance", AS_INSTANCE(value)->klass->name->chars);
break;
//< Classes and Instances print-instance
//> Calls and Functions print-native
case OBJ_NATIVE:
print("<native fn>");
break;
//< Calls and Functions print-native
case OBJ_STRING:
print("%s", AS_CSTRING(value));
break;
//> Closures print-upvalue
case OBJ_UPVALUE:
print("upvalue");
break;
//< Closures print-upvalue
}
}
//< print-object