diff options
Diffstat (limited to 'src/bytecode')
-rwxr-xr-x | src/bytecode/compiler.h | 46 | ||||
-rwxr-xr-x | src/bytecode/debug.h | 3 | ||||
-rw-r--r-- | src/bytecode/hashtable.h | 8 | ||||
-rw-r--r-- | src/bytecode/objects.c | 22 | ||||
-rwxr-xr-x | src/bytecode/objects.h | 8 | ||||
-rwxr-xr-x | src/bytecode/ops.h | 3 | ||||
-rwxr-xr-x | src/bytecode/vm.h | 19 |
7 files changed, 75 insertions, 34 deletions
diff --git a/src/bytecode/compiler.h b/src/bytecode/compiler.h index 2c7827f..6dab1fe 100755 --- a/src/bytecode/compiler.h +++ b/src/bytecode/compiler.h | |||
@@ -291,6 +291,43 @@ compile_fun_op(Chunk *chunk, Compiler *compiler, Token start) { | |||
291 | } | 291 | } |
292 | 292 | ||
293 | void | 293 | void |
294 | compile_call_op(Chunk *chunk, Compiler *compiler, Token start, Token name) { | ||
295 | if (name.type != TOKEN_SYMBOL) { | ||
296 | error_push((Error){ | ||
297 | .type = ERR_TYPE_COMPILER, | ||
298 | .value = ERR_WRONG_ARG_TYPE, | ||
299 | .line = start.line, | ||
300 | .col = start.column, | ||
301 | }); | ||
302 | return; | ||
303 | } | ||
304 | |||
305 | // FIXME: skipping arguments for now. Assuming nil. | ||
306 | |||
307 | // Compile body. | ||
308 | while (has_next_token(compiler)) { | ||
309 | Token tok = peek_token(compiler); | ||
310 | if (tok.type == TOKEN_EOF) { | ||
311 | error_push((Error){ | ||
312 | .type = ERR_TYPE_COMPILER, | ||
313 | .value = ERR_UNBALANCED_PAREN, | ||
314 | .line = start.line, | ||
315 | .col = start.column, | ||
316 | }); | ||
317 | return; | ||
318 | } | ||
319 | if (tok.type == TOKEN_RPAREN) { | ||
320 | next_token(compiler); | ||
321 | break; | ||
322 | } | ||
323 | } | ||
324 | Object obj = make_symbol(name.value); | ||
325 | emit_constant(chunk, start, obj); | ||
326 | add_code(chunk, OP_GET, start.line, start.column); | ||
327 | add_code(chunk, OP_CALL, start.line, start.column); | ||
328 | } | ||
329 | |||
330 | void | ||
294 | compile_if_op(Chunk *chunk, Compiler *compiler, Token start) { | 331 | compile_if_op(Chunk *chunk, Compiler *compiler, Token start) { |
295 | Token tok = peek_token(compiler); | 332 | Token tok = peek_token(compiler); |
296 | if (tok.type == TOKEN_EOF) { | 333 | if (tok.type == TOKEN_EOF) { |
@@ -378,12 +415,9 @@ parse_list(Chunk *chunk, Compiler *compiler, Token start) { | |||
378 | case TOKEN_FUN: { compile_fun_op(chunk, compiler, start); } break; | 415 | case TOKEN_FUN: { compile_fun_op(chunk, compiler, start); } break; |
379 | case TOKEN_IF: { compile_if_op(chunk, compiler, start); } break; | 416 | case TOKEN_IF: { compile_if_op(chunk, compiler, start); } break; |
380 | default: { | 417 | default: { |
381 | error_push((Error){ | 418 | // TODO: Emit error if compiler knows there hasn't been |
382 | .type = ERR_TYPE_COMPILER, | 419 | // a function delcared with that name. |
383 | .value = ERR_OBJ_NOT_CALLABLE, | 420 | compile_call_op(chunk, compiler, start, tok); |
384 | .line = tok.line, | ||
385 | .col = tok.column, | ||
386 | }); | ||
387 | } break; | 421 | } break; |
388 | } | 422 | } |
389 | } | 423 | } |
diff --git a/src/bytecode/debug.h b/src/bytecode/debug.h index 534ff80..1e0d4d6 100755 --- a/src/bytecode/debug.h +++ b/src/bytecode/debug.h | |||
@@ -36,7 +36,8 @@ static const char* ops_str[] = { | |||
36 | [OP_DISPLAY] = "OP_DISPLAY", | 36 | [OP_DISPLAY] = "OP_DISPLAY", |
37 | [OP_PRINT] = "OP_PRINT", | 37 | [OP_PRINT] = "OP_PRINT", |
38 | [OP_NEWLINE] = "OP_NEWLINE", | 38 | [OP_NEWLINE] = "OP_NEWLINE", |
39 | // Return. | 39 | // Procedures. |
40 | [OP_CALL] = "OP_CALL", | ||
40 | [OP_RETURN] = "OP_RETURN", | 41 | [OP_RETURN] = "OP_RETURN", |
41 | }; | 42 | }; |
42 | 43 | ||
diff --git a/src/bytecode/hashtable.h b/src/bytecode/hashtable.h index 1f47666..81c841e 100644 --- a/src/bytecode/hashtable.h +++ b/src/bytecode/hashtable.h | |||
@@ -152,9 +152,7 @@ _ht_maybe_grow(HashTable *table) { | |||
152 | // Free old arrays. | 152 | // Free old arrays. |
153 | array_free(old_pairs); | 153 | array_free(old_pairs); |
154 | for (size_t i = 0; i < array_size(old_keys); i++) { | 154 | for (size_t i = 0; i < array_size(old_keys); i++) { |
155 | Object key = old_keys[i]; | 155 | object_free(old_keys[i]); |
156 | Object value = old_values[i]; | ||
157 | object_free(key); | ||
158 | } | 156 | } |
159 | array_free(old_keys); | 157 | array_free(old_keys); |
160 | array_free(old_values); | 158 | array_free(old_values); |
@@ -201,9 +199,7 @@ ht_free(HashTable *table) { | |||
201 | } | 199 | } |
202 | array_free(table->pairs); | 200 | array_free(table->pairs); |
203 | for (size_t i = 0; i < array_size(table->keys); i++) { | 201 | for (size_t i = 0; i < array_size(table->keys); i++) { |
204 | Object key = table->keys[i]; | 202 | object_free(table->keys[i]); |
205 | Object value = table->values[i]; | ||
206 | object_free(key); | ||
207 | } | 203 | } |
208 | array_free(table->keys); | 204 | array_free(table->keys); |
209 | array_free(table->values); | 205 | array_free(table->values); |
diff --git a/src/bytecode/objects.c b/src/bytecode/objects.c index e446fb0..3b4a2eb 100644 --- a/src/bytecode/objects.c +++ b/src/bytecode/objects.c | |||
@@ -58,7 +58,8 @@ object_display(Object obj) { | |||
58 | // printf(")"); | 58 | // printf(")"); |
59 | } break; | 59 | } break; |
60 | case OBJ_TYPE_LAMBDA: { | 60 | case OBJ_TYPE_LAMBDA: { |
61 | printf("#{procedure}"); | 61 | printf("#{procedure:%.*s}", |
62 | (int)array_size(obj.chunk->name), obj.chunk->name); | ||
62 | } break; | 63 | } break; |
63 | case OBJ_TYPE_ERR: { | 64 | case OBJ_TYPE_ERR: { |
64 | printf("#{error}"); | 65 | printf("#{error}"); |
@@ -102,6 +103,9 @@ object_equal(Object a, Object b) { | |||
102 | } | 103 | } |
103 | } | 104 | } |
104 | } break; | 105 | } break; |
106 | case OBJ_TYPE_LAMBDA: { | ||
107 | return a.chunk == b.chunk; | ||
108 | } break; | ||
105 | default: { | 109 | default: { |
106 | return false; | 110 | return false; |
107 | } break; | 111 | } break; |
@@ -121,14 +125,14 @@ object_copy(Object src) { | |||
121 | return copy; | 125 | return copy; |
122 | } break; | 126 | } break; |
123 | case OBJ_TYPE_LAMBDA: { | 127 | case OBJ_TYPE_LAMBDA: { |
124 | Object copy = src; | 128 | // Object copy = src; |
125 | StringView name = (StringView){ | 129 | // StringView name = (StringView){ |
126 | .start = src.chunk->name, | 130 | // .start = src.chunk->name, |
127 | .n = array_size(src.chunk->name), | 131 | // .n = array_size(src.chunk->name), |
128 | }; | 132 | // }; |
129 | // TODO: copy full chunk? | 133 | // // TODO: copy full chunk? |
130 | // copy.chunk = chunk_init(name); | 134 | // // copy.chunk = chunk_init(name); |
131 | return copy; | 135 | // return copy; |
132 | } break; | 136 | } break; |
133 | default: { break; } break; | 137 | default: { break; } break; |
134 | } | 138 | } |
diff --git a/src/bytecode/objects.h b/src/bytecode/objects.h index 419a7f8..e0c72b0 100755 --- a/src/bytecode/objects.h +++ b/src/bytecode/objects.h | |||
@@ -26,9 +26,7 @@ typedef struct Object { | |||
26 | 26 | ||
27 | // OBJ_TYPE_STRING | 27 | // OBJ_TYPE_STRING |
28 | // OBJ_TYPE_SYMBOL | 28 | // OBJ_TYPE_SYMBOL |
29 | struct { | 29 | char *text; |
30 | char *text; | ||
31 | }; | ||
32 | 30 | ||
33 | // OBJ_TYPE_PAIR | 31 | // OBJ_TYPE_PAIR |
34 | // struct { | 32 | // struct { |
@@ -37,9 +35,7 @@ typedef struct Object { | |||
37 | // }; | 35 | // }; |
38 | 36 | ||
39 | // OBJ_TYPE_LAMBDA | 37 | // OBJ_TYPE_LAMBDA |
40 | struct { | 38 | Chunk *chunk; |
41 | Chunk *chunk; | ||
42 | }; | ||
43 | // struct { | 39 | // struct { |
44 | // struct Object *params; | 40 | // struct Object *params; |
45 | // struct Object *body; | 41 | // struct Object *body; |
diff --git a/src/bytecode/ops.h b/src/bytecode/ops.h index 5eacaea..d046ca2 100755 --- a/src/bytecode/ops.h +++ b/src/bytecode/ops.h | |||
@@ -30,7 +30,8 @@ typedef enum Ops { | |||
30 | OP_DISPLAY, | 30 | OP_DISPLAY, |
31 | OP_PRINT, | 31 | OP_PRINT, |
32 | OP_NEWLINE, | 32 | OP_NEWLINE, |
33 | // Return. | 33 | // Procedures. |
34 | OP_CALL, | ||
34 | OP_RETURN, | 35 | OP_RETURN, |
35 | } Ops; | 36 | } Ops; |
36 | 37 | ||
diff --git a/src/bytecode/vm.h b/src/bytecode/vm.h index f7852de..63eedfa 100755 --- a/src/bytecode/vm.h +++ b/src/bytecode/vm.h | |||
@@ -136,8 +136,9 @@ vm_reset(VM *vm) { | |||
136 | 136 | ||
137 | void | 137 | void |
138 | vm_interpret(VM *vm) { | 138 | vm_interpret(VM *vm) { |
139 | CallFrame *frame = &vm->frames[array_size(vm->frames) - 1]; | 139 | CallFrame *frame = &vm->frames[0]; |
140 | vm->pc = frame->chunk->code; | 140 | vm->pc = frame->chunk->code; |
141 | frame->rp = NULL; | ||
141 | 142 | ||
142 | if (frame->chunk->code == NULL || array_size(frame->chunk->code) == 0) { | 143 | if (frame->chunk->code == NULL || array_size(frame->chunk->code) == 0) { |
143 | error_push((Error){ | 144 | error_push((Error){ |
@@ -252,12 +253,20 @@ vm_interpret(VM *vm) { | |||
252 | case OP_NEWLINE: { | 253 | case OP_NEWLINE: { |
253 | printf("\n"); | 254 | printf("\n"); |
254 | } break; | 255 | } break; |
256 | case OP_CALL: { | ||
257 | Object proc = array_pop(vm->stack); | ||
258 | CallFrame new_frame = (CallFrame){proc.chunk, vm->pc}; | ||
259 | array_push(vm->frames, new_frame); | ||
260 | frame = &vm->frames[array_size(vm->frames) - 1]; | ||
261 | vm->pc = frame->chunk->code; | ||
262 | } break; | ||
255 | case OP_RETURN: { | 263 | case OP_RETURN: { |
256 | if (frame->rp != NULL) { | 264 | if (frame->rp == NULL) { |
257 | // TODO: restore previous call frame. | 265 | return; |
258 | vm->pc = frame->rp; | ||
259 | } | 266 | } |
260 | return; | 267 | vm->pc = frame->rp; |
268 | array_head(vm->frames)->size--; | ||
269 | frame = &vm->frames[array_size(vm->frames) - 1]; | ||
261 | } break; | 270 | } break; |
262 | default: { | 271 | default: { |
263 | error_push((Error){ | 272 | error_push((Error){ |