From ad8c598e84bd1e5469e2487cc3e4d0ea784d0ff3 Mon Sep 17 00:00:00 2001 From: Bad Diode Date: Mon, 25 Oct 2021 14:32:18 +0200 Subject: Add callframe support for the VM --- src/bytecode/compiler.h | 13 +++++---- src/bytecode/main.c | 15 +++++++---- src/bytecode/vm.h | 70 +++++++++++++++++++++++++++++-------------------- 3 files changed, 57 insertions(+), 41 deletions(-) (limited to 'src/bytecode') diff --git a/src/bytecode/compiler.h b/src/bytecode/compiler.h index 3b68868..4130269 100755 --- a/src/bytecode/compiler.h +++ b/src/bytecode/compiler.h @@ -14,7 +14,7 @@ Token next_token(Compiler *compiler); Token peek_token(const Compiler *compiler); bool has_next_token(const Compiler *compiler); -Chunk * compile(Token *tokens); +Object compile(Token *tokens); Token peek_token(const Compiler *compiler) { @@ -415,20 +415,19 @@ parse_tree(Chunk *chunk, Compiler *compiler) { return; } -Chunk * +Object compile(Token *tokens) { - Chunk *chunk = NULL; - chunk = NEW_CHUNK("main"); + Object main = make_lambda((StringView){"main", sizeof("main")}); Compiler compiler = (Compiler){ .tokens = tokens, .current = 0, }; Token start_tok = peek_token(&compiler); while (has_next_token(&compiler) && peek_token(&compiler).type != TOKEN_EOF) { - parse_tree(chunk, &compiler); + parse_tree(main.chunk, &compiler); } - add_code(chunk, OP_RETURN, start_tok.line, start_tok.column); - return chunk; + add_code(main.chunk, OP_RETURN, start_tok.line, start_tok.column); + return main; } #endif // BDL_COMPILER_H diff --git a/src/bytecode/main.c b/src/bytecode/main.c index d1fbac2..e4cf643 100755 --- a/src/bytecode/main.c +++ b/src/bytecode/main.c @@ -45,22 +45,27 @@ process_source(const StringView *source) { } // Compile chunk. - Chunk *chunk = compile(tokens); + Object main = compile(tokens); if (errors_n != 0) { - chunk_free(chunk); + object_free(main); array_free(tokens); return; } #ifdef DEBUG - disassemble_chunk(chunk); + disassemble_chunk(main.chunk); #endif // Interpret chunk. - vm_interpret(&vm, chunk); + CallFrame frame = (CallFrame){ + .procedure = main, + .pc = main.chunk->code, + }; + array_push(vm.frames, frame); + vm_interpret(&vm); // Free resources. - chunk_free(chunk); + object_free(main); array_free(tokens); } diff --git a/src/bytecode/vm.h b/src/bytecode/vm.h index b6f9848..23c3d89 100755 --- a/src/bytecode/vm.h +++ b/src/bytecode/vm.h @@ -8,13 +8,20 @@ #include "debug.h" #include "hashtable.h" +#define VM_FRAMES_CAP 64 #define VM_STACK_CAP 1024 -typedef struct VM { - // Program code. - Chunk *chunk; - // Program counter. +typedef struct CallFrame { + // Current code being run. + Object procedure; + // Current program counter for this call. u8 *pc; + // Ref to stack. Is this really needed? + // Object *stack; +} CallFrame; + +typedef struct VM { + CallFrame *frames; // Stack. Object *stack; // Global variables. @@ -24,17 +31,22 @@ typedef struct VM { void vm_init(VM *vm); void vm_free(VM *vm); void vm_reset(VM *vm); -void vm_interpret(VM *vm, Chunk *chunk); +void vm_interpret(VM *vm); void vm_init(VM *vm) { *vm = (VM){0}; + array_init(vm->frames, VM_FRAMES_CAP); + for (size_t i = 0; i < array_cap(vm->frames); i++) { + vm->frames[i] = (CallFrame){0}; + } array_init(vm->stack, VM_STACK_CAP); vm->globals = ht_init(); } void vm_free(VM *vm) { + array_free(vm->frames); array_free(vm->stack); ht_free(vm->globals); } @@ -50,16 +62,16 @@ vm_reset(VM *vm) { error_push((Error){ \ .type = ERR_TYPE_RUNTIME, \ .value = ERR_WRONG_ARG_TYPE, \ - .line = vm->chunk->lines[vm->pc - vm->chunk->code - 1].line, \ - .col = vm->chunk->lines[vm->pc - vm->chunk->code - 1].col, \ + .line = chunk->lines[frame->pc - chunk->code - 1].line, \ + .col = chunk->lines[frame->pc - chunk->code - 1].col, \ }) #define SYMBOL_NOT_FOUND_ERR() \ error_push((Error){ \ .type = ERR_TYPE_RUNTIME, \ .value = ERR_SYMBOL_NOT_FOUND, \ - .line = vm->chunk->lines[vm->pc - vm->chunk->code - 1].line, \ - .col = vm->chunk->lines[vm->pc - vm->chunk->code - 1].col, \ + .line = chunk->lines[frame->pc - chunk->code - 1].line, \ + .col = chunk->lines[frame->pc - chunk->code - 1].col, \ }) #define FIXNUM_ARITHMETIC_OP(OP) \ @@ -123,11 +135,11 @@ vm_reset(VM *vm) { } while (false) void -vm_interpret(VM *vm, Chunk *chunk) { - vm->chunk = chunk; - vm->pc = vm->chunk->code; +vm_interpret(VM *vm) { + CallFrame *frame = &vm->frames[array_size(vm->frames) - 1]; + Chunk *chunk = frame->procedure.chunk; - if (vm->chunk->code == NULL || array_size(vm->chunk->code) == 0) { + if (chunk->code == NULL || array_size(chunk->code) == 0) { error_push((Error){ .type = ERR_TYPE_RUNTIME, .value = ERR_EMPTY_CHUNK, @@ -135,8 +147,8 @@ vm_interpret(VM *vm, Chunk *chunk) { return; } - u8 *last = vm->chunk->code + array_size(vm->chunk->code); - while (vm->pc < last) { + u8 *last = chunk->code + array_size(chunk->code); + while (frame->pc < last) { #ifdef DEBUG_TRACE_EXECUTION printf("stack: [ "); for (size_t i = 0; i < array_size(vm->stack); i++) { @@ -146,13 +158,13 @@ vm_interpret(VM *vm, Chunk *chunk) { } } printf(" ]\nop: "); - disassemble_instruction(vm->chunk, (vm->pc - vm->chunk->code)); + disassemble_instruction(chunk, (frame->pc - chunk->code)); #endif - u8 instruction = *vm->pc++; + u8 instruction = *frame->pc++; switch (instruction) { case OP_CONSTANT: { - u8 constant = *vm->pc++; - Object obj = vm->chunk->constants[constant]; + u8 constant = *frame->pc++; + Object obj = chunk->constants[constant]; array_push(vm->stack, obj); } break; case OP_DEF: { @@ -197,17 +209,17 @@ vm_interpret(VM *vm, Chunk *chunk) { case OP_LESS_EQUAL: { FIXNUM_COMPARE_OP(<=); } break; case OP_GREATER_EQUAL: { FIXNUM_COMPARE_OP(>=); } break; case OP_JUMP: { - u16 a = *vm->pc++; - u16 b = *vm->pc++; + u16 a = *frame->pc++; + u16 b = *frame->pc++; s16 offset = (a << 8) | b; - vm->pc += offset; + frame->pc += offset; } break; case OP_JUMP_IF_FALSE: { - u16 a = *vm->pc++; - u16 b = *vm->pc++; + u16 a = *frame->pc++; + u16 b = *frame->pc++; s16 offset = (a << 8) | b; if (IS_FALSE(array_pop(vm->stack))) { - vm->pc += offset; + frame->pc += offset; } } break; case OP_DISPLAY: { @@ -248,8 +260,8 @@ vm_interpret(VM *vm, Chunk *chunk) { error_push((Error){ .type = ERR_TYPE_RUNTIME, .value = ERR_NOT_IMPLEMENTED, - .line = vm->chunk->lines[vm->pc - vm->chunk->code - 1].line, - .col = vm->chunk->lines[vm->pc - vm->chunk->code - 1].col, + .line = chunk->lines[frame->pc - chunk->code - 1].line, + .col = chunk->lines[frame->pc - chunk->code - 1].col, }); return; } break; @@ -259,8 +271,8 @@ vm_interpret(VM *vm, Chunk *chunk) { error_push((Error){ .type = ERR_TYPE_RUNTIME, .value = ERR_PC_OOB, - .line = vm->chunk->lines[0].line, - .col = vm->chunk->lines[0].col, + .line = chunk->lines[0].line, + .col = chunk->lines[0].col, }); } -- cgit v1.2.1