aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBad Diode <bd@badd10de.dev>2021-10-26 15:19:25 +0200
committerBad Diode <bd@badd10de.dev>2021-10-26 15:19:25 +0200
commitfcf015508c98d16dd34d87e5df0538b44178143d (patch)
treef62ad2664952fff00686add4cbbf992a57995189
parent0285f462a0941c2c3b6e679eb239f1fe9cfa3b0e (diff)
downloadbdl-fcf015508c98d16dd34d87e5df0538b44178143d.tar.gz
bdl-fcf015508c98d16dd34d87e5df0538b44178143d.zip
Checking n_args at runtime for OP_CALL
-rwxr-xr-xsrc/bytecode/compiler.h4
-rwxr-xr-xsrc/bytecode/vm.h47
2 files changed, 25 insertions, 26 deletions
diff --git a/src/bytecode/compiler.h b/src/bytecode/compiler.h
index 44f03fc..995a5c1 100755
--- a/src/bytecode/compiler.h
+++ b/src/bytecode/compiler.h
@@ -350,8 +350,6 @@ compile_fun_op(Chunk *chunk, Compiler *compiler, Token start) {
350 350
351void 351void
352compile_call_op(Chunk *chunk, Compiler *compiler, Token start, Token name) { 352compile_call_op(Chunk *chunk, Compiler *compiler, Token start, Token name) {
353 // FIXME: skipping arguments for now. Assuming nil.
354
355 // Compile body. 353 // Compile body.
356 size_t n = 0; 354 size_t n = 0;
357 while (has_next_token(compiler)) { 355 while (has_next_token(compiler)) {
@@ -370,12 +368,14 @@ compile_call_op(Chunk *chunk, Compiler *compiler, Token start, Token name) {
370 break; 368 break;
371 } 369 }
372 parse_tree(chunk, compiler); 370 parse_tree(chunk, compiler);
371 n++;
373 } 372 }
374 if (name.type == TOKEN_SYMBOL) { 373 if (name.type == TOKEN_SYMBOL) {
375 Object obj = make_symbol(name.value); 374 Object obj = make_symbol(name.value);
376 emit_constant(chunk, start, obj); 375 emit_constant(chunk, start, obj);
377 add_code(chunk, OP_GET, start.line, start.column); 376 add_code(chunk, OP_GET, start.line, start.column);
378 } 377 }
378 emit_constant(chunk, start, FIXNUM_VAL(n));
379 add_code(chunk, OP_CALL, start.line, start.column); 379 add_code(chunk, OP_CALL, start.line, start.column);
380} 380}
381 381
diff --git a/src/bytecode/vm.h b/src/bytecode/vm.h
index 2bc5c8a..ed54046 100755
--- a/src/bytecode/vm.h
+++ b/src/bytecode/vm.h
@@ -60,37 +60,29 @@ vm_reset(VM *vm) {
60} 60}
61 61
62// Helper macros for a more clear VM switch. 62// Helper macros for a more clear VM switch.
63#define WRONG_ARG_ERR() \ 63#define RUNTIME_ERROR(ERR) \
64 error_push((Error){ \ 64 error_push((Error){ \
65 .type = ERR_TYPE_RUNTIME, \ 65 .type = ERR_TYPE_RUNTIME, \
66 .value = ERR_WRONG_ARG_TYPE, \ 66 .value = (ERR), \
67 .line = frame->chunk->lines[vm->pc - frame->chunk->code - 1].line, \ 67 .line = frame->chunk->lines[vm->pc - frame->chunk->code - 1].line, \
68 .col = frame->chunk->lines[vm->pc - frame->chunk->code - 1].col, \ 68 .col = frame->chunk->lines[vm->pc - frame->chunk->code - 1].col, \
69 }); \ 69 }); \
70 return 70 return
71 71
72#define SYMBOL_NOT_FOUND_ERR() \
73 error_push((Error){ \
74 .type = ERR_TYPE_RUNTIME, \
75 .value = ERR_SYMBOL_NOT_FOUND, \
76 .line = frame->chunk->lines[vm->pc - frame->chunk->code - 1].line, \
77 .col = frame->chunk->lines[vm->pc - frame->chunk->code - 1].col, \
78 })
79
80#define FIXNUM_ARITHMETIC_OP(OP) \ 72#define FIXNUM_ARITHMETIC_OP(OP) \
81 do { \ 73 do { \
82 ssize_t n = AS_FIXNUM(array_pop(vm->stack)); \ 74 ssize_t n = AS_FIXNUM(array_pop(vm->stack)); \
83 size_t stack_size = array_size(vm->stack) - n; \ 75 size_t stack_size = array_size(vm->stack) - n; \
84 Object obj = array_peek(vm->stack, n - 1); \ 76 Object obj = array_peek(vm->stack, n - 1); \
85 if (!IS_FIXNUM(obj)) { \ 77 if (!IS_FIXNUM(obj)) { \
86 WRONG_ARG_ERR(); \ 78 RUNTIME_ERROR(ERR_WRONG_ARG_TYPE); \
87 return; \ 79 return; \
88 } \ 80 } \
89 ssize_t acc = AS_FIXNUM(obj); \ 81 ssize_t acc = AS_FIXNUM(obj); \
90 while (n > 1) { \ 82 while (n > 1) { \
91 obj = array_peek(vm->stack, n - 2); \ 83 obj = array_peek(vm->stack, n - 2); \
92 if (!IS_FIXNUM(obj)) { \ 84 if (!IS_FIXNUM(obj)) { \
93 WRONG_ARG_ERR(); \ 85 RUNTIME_ERROR(ERR_WRONG_ARG_TYPE); \
94 return; \ 86 return; \
95 } \ 87 } \
96 ssize_t current = AS_FIXNUM(obj); \ 88 ssize_t current = AS_FIXNUM(obj); \
@@ -107,7 +99,7 @@ vm_reset(VM *vm) {
107 size_t stack_size = array_size(vm->stack) - n; \ 99 size_t stack_size = array_size(vm->stack) - n; \
108 Object obj = array_peek(vm->stack, n - 1); \ 100 Object obj = array_peek(vm->stack, n - 1); \
109 if (!IS_FIXNUM(obj)) { \ 101 if (!IS_FIXNUM(obj)) { \
110 WRONG_ARG_ERR(); \ 102 RUNTIME_ERROR(ERR_WRONG_ARG_TYPE); \
111 return; \ 103 return; \
112 } \ 104 } \
113 ssize_t prev = AS_FIXNUM(obj); \ 105 ssize_t prev = AS_FIXNUM(obj); \
@@ -115,7 +107,7 @@ vm_reset(VM *vm) {
115 while (n > 1) { \ 107 while (n > 1) { \
116 obj = array_peek(vm->stack, n - 2); \ 108 obj = array_peek(vm->stack, n - 2); \
117 if (!IS_FIXNUM(obj)) { \ 109 if (!IS_FIXNUM(obj)) { \
118 WRONG_ARG_ERR(); \ 110 RUNTIME_ERROR(ERR_WRONG_ARG_TYPE); \
119 return; \ 111 return; \
120 } \ 112 } \
121 ssize_t current = AS_FIXNUM(obj); \ 113 ssize_t current = AS_FIXNUM(obj); \
@@ -184,7 +176,7 @@ vm_interpret(VM *vm) {
184 Object name = array_pop(vm->stack); 176 Object name = array_pop(vm->stack);
185 Object *prev = ht_lookup(vm->globals, name); 177 Object *prev = ht_lookup(vm->globals, name);
186 if (prev == NULL) { 178 if (prev == NULL) {
187 SYMBOL_NOT_FOUND_ERR(); 179 RUNTIME_ERROR(ERR_SYMBOL_NOT_FOUND);
188 return; 180 return;
189 } 181 }
190 ht_insert(vm->globals, name, value); 182 ht_insert(vm->globals, name, value);
@@ -193,7 +185,7 @@ vm_interpret(VM *vm) {
193 Object name = array_pop(vm->stack); 185 Object name = array_pop(vm->stack);
194 Object *value = ht_lookup(vm->globals, name); 186 Object *value = ht_lookup(vm->globals, name);
195 if (value == NULL) { 187 if (value == NULL) {
196 SYMBOL_NOT_FOUND_ERR(); 188 RUNTIME_ERROR(ERR_SYMBOL_NOT_FOUND);
197 return; 189 return;
198 } 190 }
199 array_push(vm->stack, *value); 191 array_push(vm->stack, *value);
@@ -235,7 +227,7 @@ vm_interpret(VM *vm) {
235 case OP_PRINT: { 227 case OP_PRINT: {
236 Object obj = array_pop(vm->stack); 228 Object obj = array_pop(vm->stack);
237 if (!IS_STRING(obj)) { 229 if (!IS_STRING(obj)) {
238 WRONG_ARG_ERR(); 230 RUNTIME_ERROR(ERR_WRONG_ARG_TYPE);
239 } 231 }
240 StringView scanner = (StringView) { 232 StringView scanner = (StringView) {
241 .start = obj.text, 233 .start = obj.text,
@@ -260,7 +252,20 @@ vm_interpret(VM *vm) {
260 printf("\n"); 252 printf("\n");
261 } break; 253 } break;
262 case OP_CALL: { 254 case OP_CALL: {
255 ssize_t n_args = AS_FIXNUM(array_pop(vm->stack));
263 Object proc = array_pop(vm->stack); 256 Object proc = array_pop(vm->stack);
257
258 // Check the number of arguments is correct.
259 // NOTE: This is probably better handled at compilation, but for
260 // now this is simpler to implement.
261 ssize_t n_params = array_size(proc.chunk->params);
262 if (n_args < n_params) {
263 RUNTIME_ERROR(ERR_NOT_ENOUGH_ARGS);
264 } else if (n_args > n_params) {
265 RUNTIME_ERROR(ERR_TOO_MANY_ARGS);
266 }
267
268 // DEBUG:...
264 // disassemble_chunk(proc.chunk); 269 // disassemble_chunk(proc.chunk);
265 270
266 // Tail-call optimization. 271 // Tail-call optimization.
@@ -299,13 +304,7 @@ vm_interpret(VM *vm) {
299 array_head(vm->stack)->size = 0; 304 array_head(vm->stack)->size = 0;
300 } break; 305 } break;
301 default: { 306 default: {
302 error_push((Error){ 307 RUNTIME_ERROR(ERR_NOT_IMPLEMENTED);
303 .type = ERR_TYPE_RUNTIME,
304 .value = ERR_NOT_IMPLEMENTED,
305 .line = frame->chunk->lines[vm->pc - frame->chunk->code - 1].line,
306 .col = frame->chunk->lines[vm->pc - frame->chunk->code - 1].col,
307 });
308 return;
309 } break; 308 } break;
310 } 309 }
311 } 310 }