From 46356365270b71be94097b3c408d5f35a9ebd6ed Mon Sep 17 00:00:00 2001 From: Bad Diode Date: Tue, 26 Oct 2021 08:40:59 +0200 Subject: Add initial function call procedure --- src/bytecode/compiler.h | 46 ++++++++++++++++++++++++++++++++++++++++------ src/bytecode/debug.h | 3 ++- src/bytecode/hashtable.h | 8 ++------ src/bytecode/objects.c | 22 +++++++++++++--------- src/bytecode/objects.h | 8 ++------ src/bytecode/ops.h | 3 ++- src/bytecode/vm.h | 19 ++++++++++++++----- 7 files changed, 75 insertions(+), 34 deletions(-) (limited to 'src/bytecode') 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 @@ -290,6 +290,43 @@ compile_fun_op(Chunk *chunk, Compiler *compiler, Token start) { add_code(chunk, OP_DEF, start.line, start.column); } +void +compile_call_op(Chunk *chunk, Compiler *compiler, Token start, Token name) { + if (name.type != TOKEN_SYMBOL) { + error_push((Error){ + .type = ERR_TYPE_COMPILER, + .value = ERR_WRONG_ARG_TYPE, + .line = start.line, + .col = start.column, + }); + return; + } + + // FIXME: skipping arguments for now. Assuming nil. + + // Compile body. + while (has_next_token(compiler)) { + Token tok = peek_token(compiler); + if (tok.type == TOKEN_EOF) { + error_push((Error){ + .type = ERR_TYPE_COMPILER, + .value = ERR_UNBALANCED_PAREN, + .line = start.line, + .col = start.column, + }); + return; + } + if (tok.type == TOKEN_RPAREN) { + next_token(compiler); + break; + } + } + Object obj = make_symbol(name.value); + emit_constant(chunk, start, obj); + add_code(chunk, OP_GET, start.line, start.column); + add_code(chunk, OP_CALL, start.line, start.column); +} + void compile_if_op(Chunk *chunk, Compiler *compiler, Token start) { Token tok = peek_token(compiler); @@ -378,12 +415,9 @@ parse_list(Chunk *chunk, Compiler *compiler, Token start) { case TOKEN_FUN: { compile_fun_op(chunk, compiler, start); } break; case TOKEN_IF: { compile_if_op(chunk, compiler, start); } break; default: { - error_push((Error){ - .type = ERR_TYPE_COMPILER, - .value = ERR_OBJ_NOT_CALLABLE, - .line = tok.line, - .col = tok.column, - }); + // TODO: Emit error if compiler knows there hasn't been + // a function delcared with that name. + compile_call_op(chunk, compiler, start, tok); } break; } } 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[] = { [OP_DISPLAY] = "OP_DISPLAY", [OP_PRINT] = "OP_PRINT", [OP_NEWLINE] = "OP_NEWLINE", - // Return. + // Procedures. + [OP_CALL] = "OP_CALL", [OP_RETURN] = "OP_RETURN", }; 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) { // Free old arrays. array_free(old_pairs); for (size_t i = 0; i < array_size(old_keys); i++) { - Object key = old_keys[i]; - Object value = old_values[i]; - object_free(key); + object_free(old_keys[i]); } array_free(old_keys); array_free(old_values); @@ -201,9 +199,7 @@ ht_free(HashTable *table) { } array_free(table->pairs); for (size_t i = 0; i < array_size(table->keys); i++) { - Object key = table->keys[i]; - Object value = table->values[i]; - object_free(key); + object_free(table->keys[i]); } array_free(table->keys); 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) { // printf(")"); } break; case OBJ_TYPE_LAMBDA: { - printf("#{procedure}"); + printf("#{procedure:%.*s}", + (int)array_size(obj.chunk->name), obj.chunk->name); } break; case OBJ_TYPE_ERR: { printf("#{error}"); @@ -102,6 +103,9 @@ object_equal(Object a, Object b) { } } } break; + case OBJ_TYPE_LAMBDA: { + return a.chunk == b.chunk; + } break; default: { return false; } break; @@ -121,14 +125,14 @@ object_copy(Object src) { return copy; } break; case OBJ_TYPE_LAMBDA: { - Object copy = src; - StringView name = (StringView){ - .start = src.chunk->name, - .n = array_size(src.chunk->name), - }; - // TODO: copy full chunk? - // copy.chunk = chunk_init(name); - return copy; + // Object copy = src; + // StringView name = (StringView){ + // .start = src.chunk->name, + // .n = array_size(src.chunk->name), + // }; + // // TODO: copy full chunk? + // // copy.chunk = chunk_init(name); + // return copy; } break; default: { break; } break; } 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 { // OBJ_TYPE_STRING // OBJ_TYPE_SYMBOL - struct { - char *text; - }; + char *text; // OBJ_TYPE_PAIR // struct { @@ -37,9 +35,7 @@ typedef struct Object { // }; // OBJ_TYPE_LAMBDA - struct { - Chunk *chunk; - }; + Chunk *chunk; // struct { // struct Object *params; // 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 { OP_DISPLAY, OP_PRINT, OP_NEWLINE, - // Return. + // Procedures. + OP_CALL, OP_RETURN, } Ops; 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) { void vm_interpret(VM *vm) { - CallFrame *frame = &vm->frames[array_size(vm->frames) - 1]; + CallFrame *frame = &vm->frames[0]; vm->pc = frame->chunk->code; + frame->rp = NULL; if (frame->chunk->code == NULL || array_size(frame->chunk->code) == 0) { error_push((Error){ @@ -252,12 +253,20 @@ vm_interpret(VM *vm) { case OP_NEWLINE: { printf("\n"); } break; + case OP_CALL: { + Object proc = array_pop(vm->stack); + CallFrame new_frame = (CallFrame){proc.chunk, vm->pc}; + array_push(vm->frames, new_frame); + frame = &vm->frames[array_size(vm->frames) - 1]; + vm->pc = frame->chunk->code; + } break; case OP_RETURN: { - if (frame->rp != NULL) { - // TODO: restore previous call frame. - vm->pc = frame->rp; + if (frame->rp == NULL) { + return; } - return; + vm->pc = frame->rp; + array_head(vm->frames)->size--; + frame = &vm->frames[array_size(vm->frames) - 1]; } break; default: { error_push((Error){ -- cgit v1.2.1