aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBad Diode <bd@badd10de.dev>2021-10-25 15:46:48 +0200
committerBad Diode <bd@badd10de.dev>2021-10-25 15:46:48 +0200
commitd54e595644fcaf6756d53d368213ad3129c49327 (patch)
treecda267ef5ea0676e82ddbb3ebb09de40d522846a
parentad8c598e84bd1e5469e2487cc3e4d0ea784d0ff3 (diff)
downloadbdl-d54e595644fcaf6756d53d368213ad3129c49327.tar.gz
bdl-d54e595644fcaf6756d53d368213ad3129c49327.zip
Add initial `fun` declaration compilation
-rwxr-xr-xsrc/bytecode/compiler.h57
-rw-r--r--src/bytecode/hashtable.h4
-rwxr-xr-xsrc/bytecode/main.c11
-rw-r--r--src/bytecode/objects.c10
-rwxr-xr-xsrc/bytecode/vm.h61
5 files changed, 99 insertions, 44 deletions
diff --git a/src/bytecode/compiler.h b/src/bytecode/compiler.h
index 4130269..2c7827f 100755
--- a/src/bytecode/compiler.h
+++ b/src/bytecode/compiler.h
@@ -14,7 +14,7 @@ Token next_token(Compiler *compiler);
14Token peek_token(const Compiler *compiler); 14Token peek_token(const Compiler *compiler);
15bool has_next_token(const Compiler *compiler); 15bool has_next_token(const Compiler *compiler);
16 16
17Object compile(Token *tokens); 17Chunk * compile(Token *tokens);
18 18
19Token 19Token
20peek_token(const Compiler *compiler) { 20peek_token(const Compiler *compiler) {
@@ -248,6 +248,49 @@ compile_declare_op(Chunk *chunk, Compiler *compiler, Token start, Ops op) {
248} 248}
249 249
250void 250void
251compile_fun_op(Chunk *chunk, Compiler *compiler, Token start) {
252 Token name = peek_token(compiler);
253 if (name.type != TOKEN_SYMBOL) {
254 error_push((Error){
255 .type = ERR_TYPE_COMPILER,
256 .value = ERR_WRONG_ARG_TYPE,
257 .line = start.line,
258 .col = start.column,
259 });
260 return;
261 }
262 parse_tree(chunk, compiler);
263
264 // TODO: compile lambda expression.
265 Object fun = make_lambda(name.value);
266 // FIXME: skipping arguments for now. Assuming nil.
267 next_token(compiler);
268
269 // Compile body.
270 while (has_next_token(compiler)) {
271 Token tok = peek_token(compiler);
272 if (tok.type == TOKEN_EOF) {
273 error_push((Error){
274 .type = ERR_TYPE_COMPILER,
275 .value = ERR_UNBALANCED_PAREN,
276 .line = start.line,
277 .col = start.column,
278 });
279 return;
280 }
281 if (tok.type == TOKEN_RPAREN) {
282 next_token(compiler);
283 break;
284 }
285 parse_tree(fun.chunk, compiler);
286 }
287 add_code(fun.chunk, OP_RETURN, start.line, start.column);
288
289 emit_constant(chunk, start, fun);
290 add_code(chunk, OP_DEF, start.line, start.column);
291}
292
293void
251compile_if_op(Chunk *chunk, Compiler *compiler, Token start) { 294compile_if_op(Chunk *chunk, Compiler *compiler, Token start) {
252 Token tok = peek_token(compiler); 295 Token tok = peek_token(compiler);
253 if (tok.type == TOKEN_EOF) { 296 if (tok.type == TOKEN_EOF) {
@@ -332,6 +375,7 @@ parse_list(Chunk *chunk, Compiler *compiler, Token start) {
332 case TOKEN_NEWLINE: { compile_list_simple_op(chunk, compiler, start, OP_NEWLINE); } break; 375 case TOKEN_NEWLINE: { compile_list_simple_op(chunk, compiler, start, OP_NEWLINE); } break;
333 case TOKEN_DEF: { compile_declare_op(chunk, compiler, start, OP_DEF); } break; 376 case TOKEN_DEF: { compile_declare_op(chunk, compiler, start, OP_DEF); } break;
334 case TOKEN_SET: { compile_declare_op(chunk, compiler, start, OP_SET); } break; 377 case TOKEN_SET: { compile_declare_op(chunk, compiler, start, OP_SET); } break;
378 case TOKEN_FUN: { compile_fun_op(chunk, compiler, start); } break;
335 case TOKEN_IF: { compile_if_op(chunk, compiler, start); } break; 379 case TOKEN_IF: { compile_if_op(chunk, compiler, start); } break;
336 default: { 380 default: {
337 error_push((Error){ 381 error_push((Error){
@@ -415,19 +459,20 @@ parse_tree(Chunk *chunk, Compiler *compiler) {
415 return; 459 return;
416} 460}
417 461
418Object 462Chunk *
419compile(Token *tokens) { 463compile(Token *tokens) {
420 Object main = make_lambda((StringView){"main", sizeof("main")}); 464 Chunk *chunk = NULL;
465 chunk = NEW_CHUNK("main");
421 Compiler compiler = (Compiler){ 466 Compiler compiler = (Compiler){
422 .tokens = tokens, 467 .tokens = tokens,
423 .current = 0, 468 .current = 0,
424 }; 469 };
425 Token start_tok = peek_token(&compiler); 470 Token start_tok = peek_token(&compiler);
426 while (has_next_token(&compiler) && peek_token(&compiler).type != TOKEN_EOF) { 471 while (has_next_token(&compiler) && peek_token(&compiler).type != TOKEN_EOF) {
427 parse_tree(main.chunk, &compiler); 472 parse_tree(chunk, &compiler);
428 } 473 }
429 add_code(main.chunk, OP_RETURN, start_tok.line, start_tok.column); 474 add_code(chunk, OP_RETURN, start_tok.line, start_tok.column);
430 return main; 475 return chunk;
431} 476}
432 477
433#endif // BDL_COMPILER_H 478#endif // BDL_COMPILER_H
diff --git a/src/bytecode/hashtable.h b/src/bytecode/hashtable.h
index 48665d3..1f47666 100644
--- a/src/bytecode/hashtable.h
+++ b/src/bytecode/hashtable.h
@@ -112,7 +112,7 @@ _ht_insert(HashTable *table, Object key, Object value) {
112 112
113 if (!update) { 113 if (!update) {
114 array_push(table->keys, object_copy(key)); 114 array_push(table->keys, object_copy(key));
115 array_push(table->values, object_copy(value)); 115 array_push(table->values, value);
116 pairs[probe_position].key = &table->keys[array_size(table->keys) - 1]; 116 pairs[probe_position].key = &table->keys[array_size(table->keys) - 1];
117 pairs[probe_position].value = &table->values[array_size(table->values) - 1]; 117 pairs[probe_position].value = &table->values[array_size(table->values) - 1];
118 } else { 118 } else {
@@ -155,7 +155,6 @@ _ht_maybe_grow(HashTable *table) {
155 Object key = old_keys[i]; 155 Object key = old_keys[i];
156 Object value = old_values[i]; 156 Object value = old_values[i];
157 object_free(key); 157 object_free(key);
158 object_free(value);
159 } 158 }
160 array_free(old_keys); 159 array_free(old_keys);
161 array_free(old_values); 160 array_free(old_values);
@@ -205,7 +204,6 @@ ht_free(HashTable *table) {
205 Object key = table->keys[i]; 204 Object key = table->keys[i];
206 Object value = table->values[i]; 205 Object value = table->values[i];
207 object_free(key); 206 object_free(key);
208 object_free(value);
209 } 207 }
210 array_free(table->keys); 208 array_free(table->keys);
211 array_free(table->values); 209 array_free(table->values);
diff --git a/src/bytecode/main.c b/src/bytecode/main.c
index e4cf643..7cb0a2a 100755
--- a/src/bytecode/main.c
+++ b/src/bytecode/main.c
@@ -45,27 +45,26 @@ process_source(const StringView *source) {
45 } 45 }
46 46
47 // Compile chunk. 47 // Compile chunk.
48 Object main = compile(tokens); 48 Chunk *main = compile(tokens);
49 if (errors_n != 0) { 49 if (errors_n != 0) {
50 object_free(main); 50 chunk_free(main);
51 array_free(tokens); 51 array_free(tokens);
52 return; 52 return;
53 } 53 }
54 54
55#ifdef DEBUG 55#ifdef DEBUG
56 disassemble_chunk(main.chunk); 56 disassemble_chunk(main);
57#endif 57#endif
58 58
59 // Interpret chunk. 59 // Interpret chunk.
60 CallFrame frame = (CallFrame){ 60 CallFrame frame = (CallFrame){
61 .procedure = main, 61 .chunk = main,
62 .pc = main.chunk->code,
63 }; 62 };
64 array_push(vm.frames, frame); 63 array_push(vm.frames, frame);
65 vm_interpret(&vm); 64 vm_interpret(&vm);
66 65
67 // Free resources. 66 // Free resources.
68 object_free(main); 67 chunk_free(main);
69 array_free(tokens); 68 array_free(tokens);
70} 69}
71 70
diff --git a/src/bytecode/objects.c b/src/bytecode/objects.c
index 14dc057..e446fb0 100644
--- a/src/bytecode/objects.c
+++ b/src/bytecode/objects.c
@@ -120,6 +120,16 @@ object_copy(Object src) {
120 array_insert(copy.text, src.text, array_size(src.text)); 120 array_insert(copy.text, src.text, array_size(src.text));
121 return copy; 121 return copy;
122 } break; 122 } break;
123 case OBJ_TYPE_LAMBDA: {
124 Object copy = src;
125 StringView name = (StringView){
126 .start = src.chunk->name,
127 .n = array_size(src.chunk->name),
128 };
129 // TODO: copy full chunk?
130 // copy.chunk = chunk_init(name);
131 return copy;
132 } break;
123 default: { break; } break; 133 default: { break; } break;
124 } 134 }
125 return src; 135 return src;
diff --git a/src/bytecode/vm.h b/src/bytecode/vm.h
index 23c3d89..f7852de 100755
--- a/src/bytecode/vm.h
+++ b/src/bytecode/vm.h
@@ -13,17 +13,20 @@
13 13
14typedef struct CallFrame { 14typedef struct CallFrame {
15 // Current code being run. 15 // Current code being run.
16 Object procedure; 16 Chunk *chunk;
17 // Current program counter for this call. 17 // Current program counter for this call.
18 u8 *pc;
19 // Ref to stack. Is this really needed? 18 // Ref to stack. Is this really needed?
20 // Object *stack; 19 // Object *locals;
20 // Return counter.
21 u8 *rp;
21} CallFrame; 22} CallFrame;
22 23
23typedef struct VM { 24typedef struct VM {
24 CallFrame *frames; 25 CallFrame *frames;
25 // Stack. 26 // Stack.
26 Object *stack; 27 Object *stack;
28 // Program counter.
29 u8 *pc;
27 // Global variables. 30 // Global variables.
28 HashTable *globals; 31 HashTable *globals;
29} VM; 32} VM;
@@ -37,9 +40,6 @@ void
37vm_init(VM *vm) { 40vm_init(VM *vm) {
38 *vm = (VM){0}; 41 *vm = (VM){0};
39 array_init(vm->frames, VM_FRAMES_CAP); 42 array_init(vm->frames, VM_FRAMES_CAP);
40 for (size_t i = 0; i < array_cap(vm->frames); i++) {
41 vm->frames[i] = (CallFrame){0};
42 }
43 array_init(vm->stack, VM_STACK_CAP); 43 array_init(vm->stack, VM_STACK_CAP);
44 vm->globals = ht_init(); 44 vm->globals = ht_init();
45} 45}
@@ -62,16 +62,16 @@ vm_reset(VM *vm) {
62 error_push((Error){ \ 62 error_push((Error){ \
63 .type = ERR_TYPE_RUNTIME, \ 63 .type = ERR_TYPE_RUNTIME, \
64 .value = ERR_WRONG_ARG_TYPE, \ 64 .value = ERR_WRONG_ARG_TYPE, \
65 .line = chunk->lines[frame->pc - chunk->code - 1].line, \ 65 .line = frame->chunk->lines[vm->pc - frame->chunk->code - 1].line, \
66 .col = chunk->lines[frame->pc - chunk->code - 1].col, \ 66 .col = frame->chunk->lines[vm->pc - frame->chunk->code - 1].col, \
67 }) 67 })
68 68
69#define SYMBOL_NOT_FOUND_ERR() \ 69#define SYMBOL_NOT_FOUND_ERR() \
70 error_push((Error){ \ 70 error_push((Error){ \
71 .type = ERR_TYPE_RUNTIME, \ 71 .type = ERR_TYPE_RUNTIME, \
72 .value = ERR_SYMBOL_NOT_FOUND, \ 72 .value = ERR_SYMBOL_NOT_FOUND, \
73 .line = chunk->lines[frame->pc - chunk->code - 1].line, \ 73 .line = frame->chunk->lines[vm->pc - frame->chunk->code - 1].line, \
74 .col = chunk->lines[frame->pc - chunk->code - 1].col, \ 74 .col = frame->chunk->lines[vm->pc - frame->chunk->code - 1].col, \
75 }) 75 })
76 76
77#define FIXNUM_ARITHMETIC_OP(OP) \ 77#define FIXNUM_ARITHMETIC_OP(OP) \
@@ -137,9 +137,9 @@ vm_reset(VM *vm) {
137void 137void
138vm_interpret(VM *vm) { 138vm_interpret(VM *vm) {
139 CallFrame *frame = &vm->frames[array_size(vm->frames) - 1]; 139 CallFrame *frame = &vm->frames[array_size(vm->frames) - 1];
140 Chunk *chunk = frame->procedure.chunk; 140 vm->pc = frame->chunk->code;
141 141
142 if (chunk->code == NULL || array_size(chunk->code) == 0) { 142 if (frame->chunk->code == NULL || array_size(frame->chunk->code) == 0) {
143 error_push((Error){ 143 error_push((Error){
144 .type = ERR_TYPE_RUNTIME, 144 .type = ERR_TYPE_RUNTIME,
145 .value = ERR_EMPTY_CHUNK, 145 .value = ERR_EMPTY_CHUNK,
@@ -147,8 +147,8 @@ vm_interpret(VM *vm) {
147 return; 147 return;
148 } 148 }
149 149
150 u8 *last = chunk->code + array_size(chunk->code); 150 u8 *last = frame->chunk->code + array_size(frame->chunk->code);
151 while (frame->pc < last) { 151 while (vm->pc < last) {
152#ifdef DEBUG_TRACE_EXECUTION 152#ifdef DEBUG_TRACE_EXECUTION
153 printf("stack: [ "); 153 printf("stack: [ ");
154 for (size_t i = 0; i < array_size(vm->stack); i++) { 154 for (size_t i = 0; i < array_size(vm->stack); i++) {
@@ -158,13 +158,13 @@ vm_interpret(VM *vm) {
158 } 158 }
159 } 159 }
160 printf(" ]\nop: "); 160 printf(" ]\nop: ");
161 disassemble_instruction(chunk, (frame->pc - chunk->code)); 161 disassemble_instruction(frame->chunk, (vm->pc - frame->chunk->code));
162#endif 162#endif
163 u8 instruction = *frame->pc++; 163 u8 instruction = *vm->pc++;
164 switch (instruction) { 164 switch (instruction) {
165 case OP_CONSTANT: { 165 case OP_CONSTANT: {
166 u8 constant = *frame->pc++; 166 u8 constant = *vm->pc++;
167 Object obj = chunk->constants[constant]; 167 Object obj = frame->chunk->constants[constant];
168 array_push(vm->stack, obj); 168 array_push(vm->stack, obj);
169 } break; 169 } break;
170 case OP_DEF: { 170 case OP_DEF: {
@@ -209,17 +209,17 @@ vm_interpret(VM *vm) {
209 case OP_LESS_EQUAL: { FIXNUM_COMPARE_OP(<=); } break; 209 case OP_LESS_EQUAL: { FIXNUM_COMPARE_OP(<=); } break;
210 case OP_GREATER_EQUAL: { FIXNUM_COMPARE_OP(>=); } break; 210 case OP_GREATER_EQUAL: { FIXNUM_COMPARE_OP(>=); } break;
211 case OP_JUMP: { 211 case OP_JUMP: {
212 u16 a = *frame->pc++; 212 u16 a = *vm->pc++;
213 u16 b = *frame->pc++; 213 u16 b = *vm->pc++;
214 s16 offset = (a << 8) | b; 214 s16 offset = (a << 8) | b;
215 frame->pc += offset; 215 vm->pc += offset;
216 } break; 216 } break;
217 case OP_JUMP_IF_FALSE: { 217 case OP_JUMP_IF_FALSE: {
218 u16 a = *frame->pc++; 218 u16 a = *vm->pc++;
219 u16 b = *frame->pc++; 219 u16 b = *vm->pc++;
220 s16 offset = (a << 8) | b; 220 s16 offset = (a << 8) | b;
221 if (IS_FALSE(array_pop(vm->stack))) { 221 if (IS_FALSE(array_pop(vm->stack))) {
222 frame->pc += offset; 222 vm->pc += offset;
223 } 223 }
224 } break; 224 } break;
225 case OP_DISPLAY: { 225 case OP_DISPLAY: {
@@ -253,15 +253,18 @@ vm_interpret(VM *vm) {
253 printf("\n"); 253 printf("\n");
254 } break; 254 } break;
255 case OP_RETURN: { 255 case OP_RETURN: {
256 printf("\n"); 256 if (frame->rp != NULL) {
257 // TODO: restore previous call frame.
258 vm->pc = frame->rp;
259 }
257 return; 260 return;
258 } break; 261 } break;
259 default: { 262 default: {
260 error_push((Error){ 263 error_push((Error){
261 .type = ERR_TYPE_RUNTIME, 264 .type = ERR_TYPE_RUNTIME,
262 .value = ERR_NOT_IMPLEMENTED, 265 .value = ERR_NOT_IMPLEMENTED,
263 .line = chunk->lines[frame->pc - chunk->code - 1].line, 266 .line = frame->chunk->lines[vm->pc - frame->chunk->code - 1].line,
264 .col = chunk->lines[frame->pc - chunk->code - 1].col, 267 .col = frame->chunk->lines[vm->pc - frame->chunk->code - 1].col,
265 }); 268 });
266 return; 269 return;
267 } break; 270 } break;
@@ -271,8 +274,8 @@ vm_interpret(VM *vm) {
271 error_push((Error){ 274 error_push((Error){
272 .type = ERR_TYPE_RUNTIME, 275 .type = ERR_TYPE_RUNTIME,
273 .value = ERR_PC_OOB, 276 .value = ERR_PC_OOB,
274 .line = chunk->lines[0].line, 277 .line = frame->chunk->lines[0].line,
275 .col = chunk->lines[0].col, 278 .col = frame->chunk->lines[0].col,
276 }); 279 });
277} 280}
278 281