diff --git a/Makefile b/Makefile index 431fcac..386499d 100644 --- a/Makefile +++ b/Makefile @@ -87,7 +87,7 @@ lib/compiler.o: lib/compiler.c lib/compiler/compiler.lua.h # executable files # -LIB_SRC=lib/value.o lib/stack.o lib/array.o lib/table.o lib/heap.o lib/vm.o lib/compiler.o lib/code.o lib/utils.o +LIB_SRC=lib/value.o lib/stack.o lib/array.o lib/table.o lib/heap.o lib/vm.o lib/step.o lib/compiler.o lib/code.o lib/utils.o tyche: CFLAGS += ${RELEASE_CFLAGS} tyche: LDFLAGS += ${RELEASE_LDFLAGS} diff --git a/lib/priv.h b/lib/priv.h index 4398ce1..36f9af9 100644 --- a/lib/priv.h +++ b/lib/priv.h @@ -225,4 +225,10 @@ const char* code_const_string(Code const* code, size_t n); uint32_t code_n_functions(Code const* code); Instruction code_next_instruction(Code const* code, uint32_t function_id, uint32_t pc); +// +// VM +// + +TYC_RESULT step(TycheVM* T); + #endif //TYCHE_PRIV_H diff --git a/lib/step.c b/lib/step.c new file mode 100644 index 0000000..26249c3 --- /dev/null +++ b/lib/step.c @@ -0,0 +1,10 @@ +#include "priv.h" + +#include + +TYC_RESULT step(TycheVM* T) +{ + abort(); + return T_OK; +} + diff --git a/lib/vm.c b/lib/vm.c index 4b0dd76..ab1fd46 100644 --- a/lib/vm.c +++ b/lib/vm.c @@ -2,39 +2,138 @@ #include +typedef struct Location { + uint32_t function_id; + uint32_t pc; +} Location; + +typedef struct LocationStack { + Location* locations; + size_t sz; + size_t cap; +} LocationStack; + struct TycheVM { - Stack* stack; - Heap* heap; - Code* code; + Stack* stack; + Heap* heap; + Code* code; + LocationStack location_stack; }; +// +// CREATE/DESTROY VM +// + TycheVM* tyc_new(void) { TycheVM* t = xcalloc(1, sizeof(TycheVM)); t->stack = stack_new(); t->heap = heap_new(); t->code = code_new(); + t->location_stack = (LocationStack) { + .locations = xmalloc(4 * sizeof(Location)), + .cap = 4, + .sz = 0, + }; return t; } void tyc_destroy(TycheVM* t) { + free(t->location_stack.locations); code_destroy(t->code); heap_destroy(t->heap); stack_destroy(t->stack); free(t); } +// +// LOCATION STACK +// + +static void push_location(TycheVM* T, uint32_t function_id, uint32_t pc) +{ + if (T->location_stack.sz == T->location_stack.cap) { + T->location_stack.cap *= 2; + T->location_stack.locations = xrealloc(T->location_stack.locations, T->location_stack.cap * sizeof(Location)); + } + + T->location_stack.locations[T->location_stack.sz] = (Location) { + .function_id = function_id, + .pc = pc, + }; + ++T->location_stack.sz; +} + +// +// CODE LOADING AND EXECUTION +// + TYC_RESULT tyc_load_bytecode(TycheVM* T, uint8_t const* bytecode, size_t bytecode_sz) { - return code_load_bytecode(T->code, bytecode, bytecode_sz); + TYC_RESULT r; + if ((r = code_load_bytecode(T->code, bytecode, bytecode_sz)) != T_OK) + return r; + if ((r = stack_push(T->stack, create_value_idx(TT_FUNCTION, 0 /* main */))) != T_OK) + return r; + return T_OK; +} + +static TYC_RESULT enter_function(TycheVM* T, uint16_t n_pars) +{ + TYC_RESULT r; + + // get parameters + VALUE params[n_pars + 1]; + for (uint16_t i = 0; i < n_pars; ++i) + if ((r = stack_pop(T->stack, ¶ms[i])) != T_OK) + return r; + + // get function + VALUE function; + if ((r = stack_pop(T->stack, &function)) != T_OK) + return r; + if (value_type(function) != TT_FUNCTION) + return T_ERR_TYPE_UNEXPECTED; + + // enter function + push_location(T, value_idx(function), 0); + stack_push_fp(T->stack); + + // pass parameters + for (int i = n_pars-1; i >= 0; --i) + if ((r = stack_push(T->stack, params[i])) != T_OK) + return r; + + return T_OK; +} + +static TYC_RESULT run_until_return(TycheVM* T) +{ + TYC_RESULT r; + + size_t level = stack_fp_level(T->stack); + while (stack_fp_level(T->stack) >= level) + if ((r = step(T)) != T_OK) + return r; + + return T_OK; } TYC_RESULT tyc_call(TycheVM* T, uint16_t n_pars) { - abort(); // TODO + TYC_RESULT r; + if ((r = enter_function(T, n_pars)) != T_OK) + return r; + if ((r = run_until_return(T)) != T_OK) + return r; + return T_OK; } +// +// STACK MANIPULATION AND QUERY +// + size_t tyc_stack_size(TycheVM* T) { return stack_len(T->stack);