From fcf015508c98d16dd34d87e5df0538b44178143d Mon Sep 17 00:00:00 2001 From: Bad Diode Date: Tue, 26 Oct 2021 15:19:25 +0200 Subject: Checking n_args at runtime for OP_CALL --- src/bytecode/compiler.h | 4 ++-- src/bytecode/vm.h | 47 +++++++++++++++++++++++------------------------ 2 files changed, 25 insertions(+), 26 deletions(-) (limited to 'src/bytecode') 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) { void compile_call_op(Chunk *chunk, Compiler *compiler, Token start, Token name) { - // FIXME: skipping arguments for now. Assuming nil. - // Compile body. size_t n = 0; while (has_next_token(compiler)) { @@ -370,12 +368,14 @@ compile_call_op(Chunk *chunk, Compiler *compiler, Token start, Token name) { break; } parse_tree(chunk, compiler); + n++; } if (name.type == TOKEN_SYMBOL) { Object obj = make_symbol(name.value); emit_constant(chunk, start, obj); add_code(chunk, OP_GET, start.line, start.column); } + emit_constant(chunk, start, FIXNUM_VAL(n)); add_code(chunk, OP_CALL, start.line, start.column); } 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) { } // Helper macros for a more clear VM switch. -#define WRONG_ARG_ERR() \ +#define RUNTIME_ERROR(ERR) \ error_push((Error){ \ .type = ERR_TYPE_RUNTIME, \ - .value = ERR_WRONG_ARG_TYPE, \ + .value = (ERR), \ .line = frame->chunk->lines[vm->pc - frame->chunk->code - 1].line, \ .col = frame->chunk->lines[vm->pc - frame->chunk->code - 1].col, \ }); \ return -#define SYMBOL_NOT_FOUND_ERR() \ - error_push((Error){ \ - .type = ERR_TYPE_RUNTIME, \ - .value = ERR_SYMBOL_NOT_FOUND, \ - .line = frame->chunk->lines[vm->pc - frame->chunk->code - 1].line, \ - .col = frame->chunk->lines[vm->pc - frame->chunk->code - 1].col, \ - }) - #define FIXNUM_ARITHMETIC_OP(OP) \ do { \ ssize_t n = AS_FIXNUM(array_pop(vm->stack)); \ size_t stack_size = array_size(vm->stack) - n; \ Object obj = array_peek(vm->stack, n - 1); \ if (!IS_FIXNUM(obj)) { \ - WRONG_ARG_ERR(); \ + RUNTIME_ERROR(ERR_WRONG_ARG_TYPE); \ return; \ } \ ssize_t acc = AS_FIXNUM(obj); \ while (n > 1) { \ obj = array_peek(vm->stack, n - 2); \ if (!IS_FIXNUM(obj)) { \ - WRONG_ARG_ERR(); \ + RUNTIME_ERROR(ERR_WRONG_ARG_TYPE); \ return; \ } \ ssize_t current = AS_FIXNUM(obj); \ @@ -107,7 +99,7 @@ vm_reset(VM *vm) { size_t stack_size = array_size(vm->stack) - n; \ Object obj = array_peek(vm->stack, n - 1); \ if (!IS_FIXNUM(obj)) { \ - WRONG_ARG_ERR(); \ + RUNTIME_ERROR(ERR_WRONG_ARG_TYPE); \ return; \ } \ ssize_t prev = AS_FIXNUM(obj); \ @@ -115,7 +107,7 @@ vm_reset(VM *vm) { while (n > 1) { \ obj = array_peek(vm->stack, n - 2); \ if (!IS_FIXNUM(obj)) { \ - WRONG_ARG_ERR(); \ + RUNTIME_ERROR(ERR_WRONG_ARG_TYPE); \ return; \ } \ ssize_t current = AS_FIXNUM(obj); \ @@ -184,7 +176,7 @@ vm_interpret(VM *vm) { Object name = array_pop(vm->stack); Object *prev = ht_lookup(vm->globals, name); if (prev == NULL) { - SYMBOL_NOT_FOUND_ERR(); + RUNTIME_ERROR(ERR_SYMBOL_NOT_FOUND); return; } ht_insert(vm->globals, name, value); @@ -193,7 +185,7 @@ vm_interpret(VM *vm) { Object name = array_pop(vm->stack); Object *value = ht_lookup(vm->globals, name); if (value == NULL) { - SYMBOL_NOT_FOUND_ERR(); + RUNTIME_ERROR(ERR_SYMBOL_NOT_FOUND); return; } array_push(vm->stack, *value); @@ -235,7 +227,7 @@ vm_interpret(VM *vm) { case OP_PRINT: { Object obj = array_pop(vm->stack); if (!IS_STRING(obj)) { - WRONG_ARG_ERR(); + RUNTIME_ERROR(ERR_WRONG_ARG_TYPE); } StringView scanner = (StringView) { .start = obj.text, @@ -260,7 +252,20 @@ vm_interpret(VM *vm) { printf("\n"); } break; case OP_CALL: { + ssize_t n_args = AS_FIXNUM(array_pop(vm->stack)); Object proc = array_pop(vm->stack); + + // Check the number of arguments is correct. + // NOTE: This is probably better handled at compilation, but for + // now this is simpler to implement. + ssize_t n_params = array_size(proc.chunk->params); + if (n_args < n_params) { + RUNTIME_ERROR(ERR_NOT_ENOUGH_ARGS); + } else if (n_args > n_params) { + RUNTIME_ERROR(ERR_TOO_MANY_ARGS); + } + + // DEBUG:... // disassemble_chunk(proc.chunk); // Tail-call optimization. @@ -299,13 +304,7 @@ vm_interpret(VM *vm) { array_head(vm->stack)->size = 0; } break; default: { - error_push((Error){ - .type = ERR_TYPE_RUNTIME, - .value = ERR_NOT_IMPLEMENTED, - .line = frame->chunk->lines[vm->pc - frame->chunk->code - 1].line, - .col = frame->chunk->lines[vm->pc - frame->chunk->code - 1].col, - }); - return; + RUNTIME_ERROR(ERR_NOT_IMPLEMENTED); } break; } } -- cgit v1.2.1