aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBad Diode <bd@badd10de.dev>2021-10-26 13:34:44 +0200
committerBad Diode <bd@badd10de.dev>2021-10-26 13:34:44 +0200
commit583e0b431a6581206368968d56287a858d53b10a (patch)
tree1259b57f9890184f2a0ffbd76471d0f4f65372ac
parent19fb6b2d97a970f94854cd17a58639b72d35c052 (diff)
downloadbdl-583e0b431a6581206368968d56287a858d53b10a.tar.gz
bdl-583e0b431a6581206368968d56287a858d53b10a.zip
Add initial parameter support for function calls
-rw-r--r--src/bytecode/chunk.c3
-rwxr-xr-xsrc/bytecode/chunk.h6
-rwxr-xr-xsrc/bytecode/compiler.h83
-rwxr-xr-xsrc/bytecode/debug.h6
-rwxr-xr-xsrc/bytecode/ops.h1
-rwxr-xr-xsrc/bytecode/vm.h18
6 files changed, 95 insertions, 22 deletions
diff --git a/src/bytecode/chunk.c b/src/bytecode/chunk.c
index 8b87d0d..e566e78 100644
--- a/src/bytecode/chunk.c
+++ b/src/bytecode/chunk.c
@@ -9,6 +9,7 @@ chunk_init(StringView name) {
9 array_init(chunk->lines, 0); 9 array_init(chunk->lines, 0);
10 array_init(chunk->name, name.n); 10 array_init(chunk->name, name.n);
11 array_insert(chunk->name, name.start, name.n); 11 array_insert(chunk->name, name.start, name.n);
12 array_init(chunk->params, 0);
12 return chunk; 13 return chunk;
13} 14}
14 15
@@ -22,6 +23,7 @@ chunk_free(Chunk *chunk) {
22 array_free(chunk->constants); 23 array_free(chunk->constants);
23 array_free(chunk->lines); 24 array_free(chunk->lines);
24 array_free(chunk->name); 25 array_free(chunk->name);
26 array_free(chunk->params);
25 free(chunk); 27 free(chunk);
26} 28}
27 29
@@ -43,4 +45,3 @@ add_constant(Chunk *chunk, Object obj) {
43 array_push(chunk->constants, obj); 45 array_push(chunk->constants, obj);
44 return pos; 46 return pos;
45} 47}
46
diff --git a/src/bytecode/chunk.h b/src/bytecode/chunk.h
index 1e88ea0..a3e02d1 100755
--- a/src/bytecode/chunk.h
+++ b/src/bytecode/chunk.h
@@ -12,10 +12,16 @@ typedef struct LineInfo {
12} LineInfo; 12} LineInfo;
13 13
14typedef struct Chunk { 14typedef struct Chunk {
15 // Program code.
15 u8 *code; 16 u8 *code;
17 // Compile time constants.
16 Object *constants; 18 Object *constants;
19 // Contains debugging information for every code operation.
17 LineInfo *lines; 20 LineInfo *lines;
21 // Chunk name.
18 char *name; 22 char *name;
23 // Parameters
24 StringView *params;
19} Chunk; 25} Chunk;
20 26
21#define NEW_CHUNK(NAME) chunk_init((StringView){(NAME), sizeof(NAME)}) 27#define NEW_CHUNK(NAME) chunk_init((StringView){(NAME), sizeof(NAME)})
diff --git a/src/bytecode/compiler.h b/src/bytecode/compiler.h
index e20b4f1..9389ab4 100755
--- a/src/bytecode/compiler.h
+++ b/src/bytecode/compiler.h
@@ -106,9 +106,6 @@ compile_list_binary_op(Chunk *chunk, Compiler *compiler, Token start, Ops op) {
106 break; 106 break;
107 } 107 }
108 parse_tree(chunk, compiler); 108 parse_tree(chunk, compiler);
109 if (tok.type == TOKEN_SYMBOL) {
110 add_code(chunk, OP_GET, tok.line, tok.column);
111 }
112 n++; 109 n++;
113 } 110 }
114 emit_constant(chunk, start, FIXNUM_VAL(n)); 111 emit_constant(chunk, start, FIXNUM_VAL(n));
@@ -142,9 +139,6 @@ compile_list_unary_op(Chunk *chunk, Compiler *compiler, Token start, Ops op) {
142 return; 139 return;
143 } 140 }
144 parse_tree(chunk, compiler); 141 parse_tree(chunk, compiler);
145 if (tok.type == TOKEN_SYMBOL) {
146 add_code(chunk, OP_GET, tok.line, tok.column);
147 }
148 add_code(chunk, op, start.line, start.column); 142 add_code(chunk, op, start.line, start.column);
149 n++; 143 n++;
150 if (n > 1) { 144 if (n > 1) {
@@ -231,9 +225,6 @@ compile_declare_op(Chunk *chunk, Compiler *compiler, Token start, Ops op) {
231 return; 225 return;
232 } 226 }
233 parse_tree(chunk, compiler); 227 parse_tree(chunk, compiler);
234 if (expr.type == TOKEN_SYMBOL) {
235 add_code(chunk, OP_GET, expr.line, expr.column);
236 }
237 if (peek_token(compiler).type != TOKEN_RPAREN) { 228 if (peek_token(compiler).type != TOKEN_RPAREN) {
238 error_push((Error){ 229 error_push((Error){
239 .type = ERR_TYPE_COMPILER, 230 .type = ERR_TYPE_COMPILER,
@@ -250,8 +241,44 @@ compile_declare_op(Chunk *chunk, Compiler *compiler, Token start, Ops op) {
250void 241void
251compile_lambda(Chunk *chunk, Compiler *compiler, Token start, StringView name) { 242compile_lambda(Chunk *chunk, Compiler *compiler, Token start, StringView name) {
252 Object fun = make_lambda(name); 243 Object fun = make_lambda(name);
253 // FIXME: skipping arguments for now. Assuming nil. 244
254 next_token(compiler); 245 // Prepeare parameters.
246 Token tok = next_token(compiler);
247 if (tok.type == TOKEN_LPAREN){
248 while (has_next_token(compiler)) {
249 Token tok = next_token(compiler);
250 if (tok.type == TOKEN_EOF) {
251 error_push((Error){
252 .type = ERR_TYPE_COMPILER,
253 .value = ERR_UNBALANCED_PAREN,
254 .line = start.line,
255 .col = start.column,
256 });
257 return;
258 }
259 if (tok.type == TOKEN_RPAREN) {
260 break;
261 }
262 if (tok.type != TOKEN_SYMBOL) {
263 error_push((Error){
264 .type = ERR_TYPE_COMPILER,
265 .value = ERR_WRONG_ARG_TYPE,
266 .line = tok.line,
267 .col = tok.column,
268 });
269 return;
270 }
271 array_push(fun.chunk->params, tok.value);
272 }
273 } else if (tok.type != TOKEN_NIL) {
274 error_push((Error){
275 .type = ERR_TYPE_COMPILER,
276 .value = ERR_WRONG_ARG_TYPE,
277 .line = tok.line,
278 .col = tok.column,
279 });
280 return;
281 }
255 282
256 // Compile body. 283 // Compile body.
257 while (has_next_token(compiler)) { 284 while (has_next_token(compiler)) {
@@ -297,6 +324,7 @@ compile_call_op(Chunk *chunk, Compiler *compiler, Token start, Token name) {
297 // FIXME: skipping arguments for now. Assuming nil. 324 // FIXME: skipping arguments for now. Assuming nil.
298 325
299 // Compile body. 326 // Compile body.
327 size_t n = 0;
300 while (has_next_token(compiler)) { 328 while (has_next_token(compiler)) {
301 Token tok = peek_token(compiler); 329 Token tok = peek_token(compiler);
302 if (tok.type == TOKEN_EOF) { 330 if (tok.type == TOKEN_EOF) {
@@ -312,6 +340,7 @@ compile_call_op(Chunk *chunk, Compiler *compiler, Token start, Token name) {
312 next_token(compiler); 340 next_token(compiler);
313 break; 341 break;
314 } 342 }
343 parse_tree(chunk, compiler);
315 } 344 }
316 if (name.type == TOKEN_SYMBOL) { 345 if (name.type == TOKEN_SYMBOL) {
317 Object obj = make_symbol(name.value); 346 Object obj = make_symbol(name.value);
@@ -471,8 +500,24 @@ parse_tree(Chunk *chunk, Compiler *compiler) {
471 return; 500 return;
472 } break; 501 } break;
473 case TOKEN_SYMBOL: { 502 case TOKEN_SYMBOL: {
474 Object obj = make_symbol(tok.value); 503 bool found = false;
475 emit_constant(chunk, tok, obj); 504 size_t idx = 0;
505 // NOTE: This is dumb and potentially slow.
506 for (size_t i = 0; i < array_size(chunk->params); i++) {
507 if (sv_equal(&tok.value, &chunk->params[i])) {
508 found = true;
509 idx = i;
510 break;
511 }
512 }
513 if (!found) {
514 Object obj = make_symbol(tok.value);
515 emit_constant(chunk, tok, obj);
516 return;
517 }
518
519 add_code(chunk, OP_LOCAL, tok.line, tok.column);
520 add_code(chunk, idx, tok.line, tok.column);
476 return; 521 return;
477 } break; 522 } break;
478 case TOKEN_NIL: { 523 case TOKEN_NIL: {
@@ -500,14 +545,16 @@ compile(Token *tokens) {
500 .tokens = tokens, 545 .tokens = tokens,
501 .current = 0, 546 .current = 0,
502 }; 547 };
503 Token start_tok = peek_token(&compiler); 548 Token main_start = peek_token(&compiler);
504 while (has_next_token(&compiler) && peek_token(&compiler).type != TOKEN_EOF) { 549 while (has_next_token(&compiler)) {
550 Token start = peek_token(&compiler);
505 parse_tree(chunk, &compiler); 551 parse_tree(chunk, &compiler);
506 if (peek_token(&compiler).type != TOKEN_EOF) { 552 if (peek_token(&compiler).type == TOKEN_EOF) {
507 add_code(chunk, OP_DROP, start_tok.line, start_tok.column); 553 break;
508 } 554 }
555 add_code(chunk, OP_DROP, start.line, start.column);
509 } 556 }
510 add_code(chunk, OP_RETURN, start_tok.line, start_tok.column); 557 add_code(chunk, OP_RETURN, main_start.line, main_start.column);
511 return chunk; 558 return chunk;
512} 559}
513 560
diff --git a/src/bytecode/debug.h b/src/bytecode/debug.h
index 8c4a2eb..06d48b0 100755
--- a/src/bytecode/debug.h
+++ b/src/bytecode/debug.h
@@ -10,6 +10,7 @@ size_t disassemble_instruction(Chunk *chunk, size_t offset);
10static const char* ops_str[] = { 10static const char* ops_str[] = {
11 // Load/store ops. 11 // Load/store ops.
12 [OP_CONSTANT] = "OP_CONSTANT", 12 [OP_CONSTANT] = "OP_CONSTANT",
13 [OP_LOCAL] = "OP_LOCAL",
13 [OP_DEF] = "OP_DEF", 14 [OP_DEF] = "OP_DEF",
14 [OP_SET] = "OP_SET", 15 [OP_SET] = "OP_SET",
15 [OP_GET] = "OP_GET", 16 [OP_GET] = "OP_GET",
@@ -74,6 +75,11 @@ disassemble_instruction(Chunk *chunk, size_t offset) {
74 } 75 }
75 u8 instruction = chunk->code[offset]; 76 u8 instruction = chunk->code[offset];
76 switch (instruction) { 77 switch (instruction) {
78 case OP_LOCAL: {
79 u8 local = chunk->code[offset + 1];
80 printf("%-16s %4d\n", ops_str[instruction], local);
81 return offset + 2;
82 } break;
77 case OP_CONSTANT: { 83 case OP_CONSTANT: {
78 u8 constant = chunk->code[offset + 1]; 84 u8 constant = chunk->code[offset + 1];
79 printf("%-16s %4d -> ", ops_str[instruction], constant); 85 printf("%-16s %4d -> ", ops_str[instruction], constant);
diff --git a/src/bytecode/ops.h b/src/bytecode/ops.h
index 7a43b91..501a37f 100755
--- a/src/bytecode/ops.h
+++ b/src/bytecode/ops.h
@@ -4,6 +4,7 @@
4typedef enum Ops { 4typedef enum Ops {
5 // Load/store ops. 5 // Load/store ops.
6 OP_CONSTANT, 6 OP_CONSTANT,
7 OP_LOCAL,
7 OP_DEF, 8 OP_DEF,
8 OP_SET, 9 OP_SET,
9 OP_GET, 10 OP_GET,
diff --git a/src/bytecode/vm.h b/src/bytecode/vm.h
index 0ce6dec..98c94fa 100755
--- a/src/bytecode/vm.h
+++ b/src/bytecode/vm.h
@@ -19,6 +19,8 @@ typedef struct CallFrame {
19 // Object *locals; 19 // Object *locals;
20 // Return counter. 20 // Return counter.
21 u8 *rp; 21 u8 *rp;
22 // Starting point of the locals for this procedure.
23 size_t stack_offset;
22} CallFrame; 24} CallFrame;
23 25
24typedef struct VM { 26typedef struct VM {
@@ -149,8 +151,7 @@ vm_interpret(VM *vm) {
149 return; 151 return;
150 } 152 }
151 153
152 u8 *last = frame->chunk->code + array_size(frame->chunk->code); 154 while (true) {
153 while (vm->pc < last) {
154#ifdef DEBUG_TRACE_EXECUTION 155#ifdef DEBUG_TRACE_EXECUTION
155 printf("stack: [ "); 156 printf("stack: [ ");
156 for (size_t i = 0; i < array_size(vm->stack); i++) { 157 for (size_t i = 0; i < array_size(vm->stack); i++) {
@@ -164,6 +165,10 @@ vm_interpret(VM *vm) {
164#endif 165#endif
165 u8 instruction = *vm->pc++; 166 u8 instruction = *vm->pc++;
166 switch (instruction) { 167 switch (instruction) {
168 case OP_LOCAL: {
169 u8 local = *vm->pc++;
170 array_push(vm->stack, vm->stack[frame->stack_offset + local]);
171 } break;
167 case OP_CONSTANT: { 172 case OP_CONSTANT: {
168 u8 constant = *vm->pc++; 173 u8 constant = *vm->pc++;
169 Object obj = frame->chunk->constants[constant]; 174 Object obj = frame->chunk->constants[constant];
@@ -256,7 +261,11 @@ vm_interpret(VM *vm) {
256 } break; 261 } break;
257 case OP_CALL: { 262 case OP_CALL: {
258 Object proc = array_pop(vm->stack); 263 Object proc = array_pop(vm->stack);
259 CallFrame new_frame = (CallFrame){proc.chunk, vm->pc}; 264 CallFrame new_frame = (CallFrame){
265 .chunk = proc.chunk,
266 .rp = vm->pc,
267 .stack_offset = array_size(vm->stack) - array_size(proc.chunk->params),
268 };
260 array_push(vm->frames, new_frame); 269 array_push(vm->frames, new_frame);
261 frame = &vm->frames[array_size(vm->frames) - 1]; 270 frame = &vm->frames[array_size(vm->frames) - 1];
262 vm->pc = frame->chunk->code; 271 vm->pc = frame->chunk->code;
@@ -272,6 +281,9 @@ vm_interpret(VM *vm) {
272 } 281 }
273 vm->pc = frame->rp; 282 vm->pc = frame->rp;
274 array_head(vm->frames)->size--; 283 array_head(vm->frames)->size--;
284 Object ret = array_pop(vm->stack);
285 array_head(vm->stack)->size = frame->stack_offset;
286 array_push(vm->stack, ret);
275 frame = &vm->frames[array_size(vm->frames) - 1]; 287 frame = &vm->frames[array_size(vm->frames) - 1];
276 } break; 288 } break;
277 case OP_DROP: { 289 case OP_DROP: {