From cc766bb6315d457c0ccb777f7ffacaa8e4d0cfe9 Mon Sep 17 00:00:00 2001 From: cassowarii <2374677+cassowarii@users.noreply.github.com> Date: Sun, 5 Jul 2026 21:57:53 -0700 Subject: [PATCH] better/more consistent VM model --- src/compile/emit.c | 1 - src/compile/ir.c | 1 + src/data/hashtable.c | 10 +- src/data/hashtable.h | 4 +- src/data/list.c | 5 +- src/data/list.h | 2 +- src/data/methods.c | 30 +++--- src/data/methods.h | 2 +- src/data/symbol.c | 10 +- src/main.c | 14 +-- src/parse/parser.c | 2 +- src/vm/bytecode.h | 3 +- src/vm/exec.c | 269 ++++++++++++++++++++++++++++----------------------- src/vm/exec.h | 16 +-- src/vm/operations.c | 28 +++--- src/vm/operations.h | 6 +- 16 files changed, 213 insertions(+), 190 deletions(-) diff --git a/src/compile/emit.c b/src/compile/emit.c index cb3688e..d558711 100644 --- a/src/compile/emit.c +++ b/src/compile/emit.c @@ -423,7 +423,6 @@ void compile_op(sbVmCompiler *cm, sbAstOp op) { case AST_OP_LE: EMIT(BC_OP_LE); break; case AST_OP_GE: EMIT(BC_OP_LT, BC_OP_NOT); break; case AST_OP_INDEX: EMIT(BC_OP_INDEX); break; - case AST_OP_SCOPE: EMIT(BC_OP_SCOPE); break; default: PANIC("unknown operation!\n"); } diff --git a/src/compile/ir.c b/src/compile/ir.c index 4bd7a47..2a995a6 100644 --- a/src/compile/ir.c +++ b/src/compile/ir.c @@ -524,6 +524,7 @@ static sbIrChunk *compile_ast_function(hIrProgram ir, sbAst paramsAst, sbAst seq /* compile parameters */ sbIrBindList *arg_binding = compile_ast_bind_list(ck, paramsAst, TRUE, BY_PARAM); if (arg_binding) { + ck->num_args = 1; put_bind(ck, arg_binding, NULL); } diff --git a/src/data/hashtable.c b/src/data/hashtable.c index 3a9b1cf..93978e5 100644 --- a/src/data/hashtable.c +++ b/src/data/hashtable.c @@ -87,19 +87,19 @@ void sbHash_insert(hHash h, hV *key, hV *value) { set_key(t, key, value); } -hV sbHash_find(hHash h, hV *key) { +hV *sbHash_find(hHash h, hV *key) { hashtbl *t = find_tbl_for_handle(h); usize index = find_index_by_key(t, key); hV *keys, *values; get_ptrs_for_tbl(t, &keys, &values); if (keys[index].type == IT_NOTHING) { - return HVNOTHING; + return NULL; } else { - return values[index]; + return &values[index]; } } -hV sbHash_find_or_insert(hHash h, hV *key, hV *value) { +hV *sbHash_find_or_insert(hHash h, hV *key, hV *value) { hashtbl *t = find_tbl_for_handle(h); usize index = find_index_by_key(t, key); hV *keys, *values; @@ -107,7 +107,7 @@ hV sbHash_find_or_insert(hHash h, hV *key, hV *value) { if (keys[index].type == IT_NOTHING) { values[index] = *value; } - return values[index]; + return &values[index]; } void sbHash_delete(hHash h, hV *key, hV *value) { diff --git a/src/data/hashtable.h b/src/data/hashtable.h index e523f95..b2b4f09 100644 --- a/src/data/hashtable.h +++ b/src/data/hashtable.h @@ -16,10 +16,10 @@ sbHashValue sbHash_hash_obj(hV *obj); hHash sbHash_create(usize initial_size); -hV sbHash_find(hHash h, hV *key); +hV *sbHash_find(hHash h, hV *key); void sbHash_insert(hHash h, hV *key, hV *value); -hV sbHash_find_or_insert(hHash h, hV *key, hV *value); +hV *sbHash_find_or_insert(hHash h, hV *key, hV *value); void sbHash_delete(hHash h, hV *key, hV *value); diff --git a/src/data/list.c b/src/data/list.c index 1ea58db..bebb5a2 100644 --- a/src/data/list.c +++ b/src/data/list.c @@ -42,11 +42,10 @@ hV *sbList_get_value(hList list, usize *length) { return (hV*)l->items.data; } -hV sbList_index(hList list, usize index) { +hV *sbList_index(hList list, usize index) { sbList *l = get_list_by_handle(list); hV *item = &((hV*)l->items.data)[index]; - sbV_retain(item); - return *item; + return item; } /* --- */ diff --git a/src/data/list.h b/src/data/list.h index 7a8e102..65e6a1e 100644 --- a/src/data/list.h +++ b/src/data/list.h @@ -10,4 +10,4 @@ void sbList_append(hList list, hV *item); hV *sbList_get_value(hList list, usize *length); -hV sbList_index(hList list, usize index); +hV *sbList_index(hList list, usize index); diff --git a/src/data/methods.c b/src/data/methods.c index d554db3..9194a74 100644 --- a/src/data/methods.c +++ b/src/data/methods.c @@ -9,25 +9,25 @@ void list_each_cfunc(hVm vm, flag init); void list_map_cfunc(hVm vm, flag init); -void sbList_method(hV list, hVm vm) { - if (list.type != IT_LIST) { +void sbList_method(hVm vm) { + hV *list = sbVm_pop(vm); + if (list->type != IT_LIST) { CHECK("can't call sbList_method on something that isn't a list"); } - hV argc = sbVm_pop(vm); - if (argc.type != IT_INTEGER) { + hV *argc = sbVm_pop(vm); + if (argc->type != IT_INTEGER) { CHECK("argc of send should be integer!"); } /* subtract 1 because the method name is itself a param */ - usize num_params = argc.integer - 1; + usize num_params = argc->integer - 1; hV *method_name_val = sbVm_peek(vm, num_params); if (method_name_val->type == IT_SYMBOL) { const char *method_name = sbSymbol_name(method_name_val->symbol); - printf("method name: %s\n", method_name); if (METHOD_IS("each")) { if (num_params != 1) { PANIC("wrong number of arguments passed to list#each!"); } - sbVm_push(vm, list); + sbVm_push_immediate(vm, list); sbVm_call_c_func(vm, list_each_cfunc); } } else { @@ -39,13 +39,13 @@ void list_each_cfunc(hVm vm, flag init) { if (init) { /* store three state variables: the list we're iterating, the index into it, and the callback function */ sbVm_request_var_space(vm, 3); - hV iterating_list = sbVm_pop(vm); - hV loop_func = sbVm_pop(vm); + hV *iterating_list = sbVm_pop(vm); + hV *loop_func = sbVm_pop(vm); sbVm_pop(vm); /* remove method name */ hV index = HVINT(0); - vm->fp->locals[0] = iterating_list; + vm->fp->locals[0] = *iterating_list; vm->fp->locals[1] = index; - vm->fp->locals[2] = loop_func; + vm->fp->locals[2] = *loop_func; } else { /* loop func must have finished, so remove its result */ sbVm_pop(vm); @@ -55,11 +55,11 @@ void list_each_cfunc(hVm vm, flag init) { usize length; hV *iter_values = sbList_get_value(vm->fp->locals[0].list, &length); if (current_index < length) { - sbVm_push(vm, iter_values[current_index]); - sbVm_push(vm, HVINT(1)); - sbVm_call_func(vm, vm->fp->locals[2]); + sbVm_push(vm, &iter_values[current_index]); + sbVm_push_immediate(vm, &HVINT(1)); + sbVm_call_func(vm, &vm->fp->locals[2]); } else { /* if index was past the end, callback function won't be called, and we'll exit. return nil */ - sbVm_push(vm, HVNIL); + sbVm_push_immediate(vm, &HVNIL); } } diff --git a/src/data/methods.h b/src/data/methods.h index c93dc5a..1a4ce1b 100644 --- a/src/data/methods.h +++ b/src/data/methods.h @@ -1,3 +1,3 @@ #include "common.h" -void sbList_method(hV list, hVm vm); +void sbList_method(hVm vm); diff --git a/src/data/symbol.c b/src/data/symbol.c index de7006c..7c8c452 100644 --- a/src/data/symbol.c +++ b/src/data/symbol.c @@ -18,9 +18,9 @@ hSymbol sbSymbol_from_bytes(const char *text, usize length) { .string = sbString_new(text, length), }; - hV result = sbHash_find(symbol_table, &symkey); + hV *result = sbHash_find(symbol_table, &symkey); - if (result.type == IT_NOTHING) { + if (result == NULL) { /* add new symbol */ hV symval = { .type = IT_SYMBOL, @@ -29,11 +29,11 @@ hSymbol sbSymbol_from_bytes(const char *text, usize length) { sbHash_insert(symbol_table, &symkey, &symval); return symval.symbol; - } else if (result.type == IT_SYMBOL) { + } else if (result->type == IT_SYMBOL) { /* return already existing symbol */ - return result.symbol; + return result->symbol; } else { - PANIC("Only symbol values are allowed in the symbol table! (%lld)", (long long)result.type); + PANIC("Only symbol values are allowed in the symbol table! (%lld)", (long long)result->type); } } diff --git a/src/main.c b/src/main.c index b76c2eb..50031ab 100644 --- a/src/main.c +++ b/src/main.c @@ -19,7 +19,7 @@ int main(int argc, char **argv) { filename = argv[1]; } else { printf("usage: %s [-D] \n", argv[0]); - printf("usage: -D = bytecode debugger\n"); + printf("usage: -D = stack debugger\n"); return 0; } @@ -50,11 +50,13 @@ int main(int argc, char **argv) { sbParser_deinitialize(&pr); if (ir.error_count > 0) { - fprintf(stderr, "Could not run '%s' due to errors.\n", filename); + fprintf(stderr, "fatal error: Could not run '%s' due to errors.\n", filename); return -3; } else { - // print out program - sbIrProgram_print(&ir); + if (debugmode) { + // print out program + sbIrProgram_print(&ir); + } } sbVmProgram pm; @@ -70,8 +72,8 @@ int main(int argc, char **argv) { sbVm_execute(&vm, &pm); printf("Stack result: "); - for (u8 *p = vm.stack; p < vm.sp; p++) { - printf("%02X ", *p); + for (hV **p = (hV**)vm.vstack; p < (hV**)vm.vsp; p++) { + printf("%16llx %16llx ", (long long)(*p)->type, (long long)(*p)->data); } printf("\n"); diff --git a/src/parse/parser.c b/src/parse/parser.c index 069580e..30e8c10 100644 --- a/src/parse/parser.c +++ b/src/parse/parser.c @@ -168,7 +168,7 @@ static binop binops[] = { { T_ARROW, 90, 91, AST_OP_NULL }, { T_LPAREN, 90, 91, AST_OP_NULL }, { T_LBRACKET, 90, 91, AST_OP_INDEX }, - { T_PAAMAYIM_NEKUDOTAYIM, 90, 91, AST_OP_SCOPE }, + { T_PAAMAYIM_NEKUDOTAYIM, 90, 91, AST_OP_INDEX }, }; static unop unops[] = { diff --git a/src/vm/bytecode.h b/src/vm/bytecode.h index 89cb296..5e8a48c 100644 --- a/src/vm/bytecode.h +++ b/src/vm/bytecode.h @@ -48,8 +48,7 @@ typedef enum sbOpcode { BC_OP_DEREF, // dereference pointer BC_OP_LT, // less than BC_OP_LE, // less than or equal to - BC_OP_INDEX, // index [] - BC_OP_SCOPE, // index :: + BC_OP_INDEX, // index [] or :: BC_ALLOC_VARS, // create space in rstack for local variables BC_CLOSURE, // create closure from top elements of stack BC_LIST_GATHER, // create list from count + list of values on stack diff --git a/src/vm/exec.c b/src/vm/exec.c index 8be69e4..9a85acb 100644 --- a/src/vm/exec.c +++ b/src/vm/exec.c @@ -8,27 +8,32 @@ void call_block(hVm vm, usize block_id, hClosure closure); void return_from_block(hVm vm); void execute_instruction(hVm vm); -void push_stack(hVm vm, const hV *value); -hV pop_stack(hVm vm); +void push_stack(hVm vm, hV *value); +void push_stack_immediate(hVm vm, const hV *value); +hV *pop_stack(hVm vm); hV *npop_stack(hVm vm, usize count); hV *peek_stack(hVm vm, usize offset); +void print_stack(hVm vm); void sbVm_initialize(hVm vm, usize stacksize, usize rstacksize, flag debugmode) { *vm = (sbVm) {0}; - vm->stack = malloc(stacksize); + vm->vstack = malloc(stacksize); + vm->xstack = malloc(stacksize); vm->stacksize = stacksize; vm->rstack = malloc(rstacksize); vm->rstacksize = rstacksize; - vm->sp = vm->stack; + vm->vsp = vm->vstack; + vm->xsp = vm->xstack; + vm->rsp = vm->rstack; vm->fp = (sbVmStackFrame*)vm->rstack; - vm->rp = vm->rstack; vm->debugmode = debugmode; } void sbVm_deinitialize(hVm vm) { - free(vm->stack); + free(vm->vstack); + free(vm->xstack); free(vm->rstack); *vm = (sbVm) {0}; } @@ -44,22 +49,22 @@ sbVmStatus sbVm_execute(hVm vm, sbVmProgram *pm) { while (vm->running) { execute_instruction(vm); if (vm->debugmode) { - debug("Stack: "); - for (u8 *p = vm->stack; p < vm->sp; p++) { - debug("%02X ", *p); - } - debug("\n"); + print_stack(vm); } } return VM_STAT_SUCCESS; } -void sbVm_push(hVm vm, hV value) { - push_stack(vm, &value); +void sbVm_push(hVm vm, hV *value) { + push_stack(vm, value); +} + +void sbVm_push_immediate(hVm vm, hV *value) { + push_stack_immediate(vm, value); } -hV sbVm_pop(hVm vm) { +hV *sbVm_pop(hVm vm) { return pop_stack(vm); } @@ -67,21 +72,21 @@ hV *sbVm_peek(hVm vm, usize where) { return peek_stack(vm, where); } -void sbVm_call_func(hVm vm, hV func) { - call_block(vm, func.type, func.closure); +void sbVm_call_func(hVm vm, hV *func) { + call_block(vm, func->type, func->closure); } void sbVm_call_c_func(hVm vm, sbRuntimeCFunc func) { sbVmStackFrame frame = { .return_addr = vm->ip, .last_fp = vm->fp, - .last_rp = vm->rp, + .last_rp = vm->rsp, .is_c_func = TRUE, .c_func = func, }; - *(sbVmStackFrame*)vm->rp = frame; - vm->fp = (sbVmStackFrame*)vm->rp; - vm->rp += sizeof(sbVmStackFrame); + *(sbVmStackFrame*)vm->rsp = frame; + vm->fp = (sbVmStackFrame*)vm->rsp; + vm->rsp += sizeof(sbVmStackFrame); func(vm, TRUE); @@ -94,26 +99,34 @@ void sbVm_call_c_func(hVm vm, sbRuntimeCFunc func) { void sbVm_request_var_space(hVm vm, usize amount) { /* have to set new rstack space to 0 so we don't accidentally decrement * the ref count of variables from a previous stack frame (or of just garbage) */ - memset(vm->rp, 0, amount * sizeof(hV)); - vm->rp += amount * sizeof(hV); + memset(vm->rsp, 0, amount * sizeof(hV)); + vm->rsp += amount * sizeof(hV); vm->fp->num_locals += amount; } /* --- */ +void print_stack(hVm vm) { + debug("Stack: "); + for (hV **p = (hV**)vm->vstack; p < (hV**)vm->vsp; p++) { + debug("%16llx %16llx ", (long long)(*p)->type, (long long)(*p)->data); + } + debug("\n"); +} + void call_block(hVm vm, usize block_id, hClosure closure) { sbVmBlock *blk = &vm->program->blocks[block_id]; sbVmStackFrame frame = { .return_addr = vm->ip, .last_fp = vm->fp, - .last_rp = vm->rp, + .last_rp = vm->rsp, .block_func.block = blk, .block_func.closure = closure, }; - *(sbVmStackFrame*)vm->rp = frame; - vm->fp = (sbVmStackFrame*)vm->rp; - vm->rp += sizeof(sbVmStackFrame); + *(sbVmStackFrame*)vm->rsp = frame; + vm->fp = (sbVmStackFrame*)vm->rsp; + vm->rsp += sizeof(sbVmStackFrame); vm->ip = &blk->bytecode[0]; } @@ -129,7 +142,7 @@ void return_from_block(hVm vm) { vm->running = FALSE; } else { vm->fp = frame->last_fp; - vm->rp = frame->last_rp; + vm->rsp = frame->last_rp; vm->ip = frame->return_addr; if (vm->fp->is_c_func) { @@ -155,28 +168,55 @@ void store_local(hVm vm, usize local_index, const hV *value) { vm->fp->locals[local_index] = *value; } -void push_stack(hVm vm, const hV *value) { +void push_stack(hVm vm, hV *value) { sbV_retain(value); - *(hV*)vm->sp = *value; - vm->sp += sizeof(hV); + *(hV**)vm->vsp = value; + vm->vsp += sizeof(hV*); + vm->xsp += sizeof(hV); } -hV pop_stack(hVm vm) { - vm->sp -= sizeof(hV); - sbV_release((hV*)vm->sp); - return *(hV*)vm->sp; +void push_stack_immediate(hVm vm, const hV *value) { + /* save it on our own stack */ + sbV_retain(value); + *(hV*)vm->xsp = *value; + *(hV**)vm->vsp = (hV*)vm->xsp; + vm->vsp += sizeof(hV*); + vm->xsp += sizeof(hV); +} + +hV *pop_stack(hVm vm) { + vm->vsp -= sizeof(hV*); + vm->xsp -= sizeof(hV); + sbV_release(*(hV**)vm->vsp); + return *(hV**)vm->vsp; } hV *npop_stack(hVm vm, usize count) { - vm->sp -= count * sizeof(hV); + vm->vsp -= count * sizeof(hV*); + vm->xsp -= count * sizeof(hV); for (usize i = 0; i < count; i++) { - sbV_release(&((hV*)vm->sp)[i]); + sbV_release(((hV**)vm->vsp)[i]); } - return (hV*)vm->sp; + return *(hV**)vm->vsp; +} + +void swap_stack_top(hVm vm) { + hV **first_v = &((hV**)vm->vsp)[-1]; + hV **second_v = &((hV**)vm->vsp)[-2]; + hV *first_x = &((hV*)vm->xsp)[-1]; + hV *second_x = &((hV*)vm->xsp)[-2]; + + hV *vtmp = *first_v; + *first_v = *second_v; + *second_v = vtmp; + + hV xtmp = *first_x; + *first_x = *second_x; + *second_x = xtmp; } hV *peek_stack(hVm vm, usize offset) { - return (hV*)(vm->sp - (offset + 1) * sizeof(hV)); + return ((hV**)(vm->vsp))[-offset - 1]; } sbOpcode get_opcode(hVm vm) { @@ -239,7 +279,6 @@ void execute_instruction(hVm vm) { u64 param; usize count; hV *v, *w, *x, res; - hV vv, ww, xx; switch (op) { case BC_NOP: @@ -249,11 +288,11 @@ void execute_instruction(hVm vm) { break; case BC_LD_IMM: param = get_param(vm); - push_stack(vm, &HVINT(param)); + push_stack_immediate(vm, &HVINT(param)); break; case BC_LD_CONST: param = get_param(vm); - push_stack(vm, &vm->fp->block_func.block->constants[param]); + push_stack_immediate(vm, &vm->fp->block_func.block->constants[param]); break; case BC_LD_CTX: PANIC("todo"); @@ -280,11 +319,11 @@ void execute_instruction(hVm vm) { case BC_LD_UPREF: param = get_param(vm); res = sbClosure_get_ref(vm->fp->block_func.closure, param); - push_stack(vm, &res); + push_stack_immediate(vm, &res); break; case BC_LD_BLK: param = get_param(vm); - push_stack(vm, &HVFUNC(param, 0)); + push_stack_immediate(vm, &HVFUNC(param, 0)); break; case BC_LD_IND: param = get_param(vm); @@ -296,7 +335,7 @@ void execute_instruction(hVm vm) { push_stack(vm, w); break; case BC_LD_NIL: - push_stack(vm, &HVNIL); + push_stack_immediate(vm, &HVNIL); break; case BC_ST_VAR: param = get_param(vm); @@ -306,8 +345,8 @@ void execute_instruction(hVm vm) { break; case BC_ST_UPVAL: param = get_param(vm); - vv = pop_stack(vm); - sbClosure_set_var(vm->fp->block_func.closure, param, &vv); + v = pop_stack(vm); + sbClosure_set_var(vm->fp->block_func.closure, param, v); break; case BC_ST_IND: param = get_param(vm); @@ -325,24 +364,24 @@ void execute_instruction(hVm vm) { break; case BC_ST_ARG: param = get_param(vm); - vv = pop_stack(vm); /* argument count */ - if (vv.type != IT_INTEGER) { + v = pop_stack(vm); /* argument count */ + if (v->type != IT_INTEGER) { /* internal error! this should be generated correctly */ CHECK("calling convention violation: number of args should be an integer"); } - ww = pop_stack(vm); /* argument value */ - store_local(vm, param, &ww); + w = pop_stack(vm); /* argument value */ + store_local(vm, param, w); /* we track the number of arguments remaining, for variadic functions later */ - vv.integer --; - if (vv.integer > 0) { + v->integer --; + if (v->integer > 0) { /* if last integer, don't put the 0 count back on the stack */ - push_stack(vm, &vv); + push_stack_immediate(vm, v); } break; case BC_ST_ARG_IND: param = get_param(vm); - xx = pop_stack(vm); /* argument count */ - if (xx.type != IT_INTEGER) { + x = pop_stack(vm); /* argument count */ + if (x->type != IT_INTEGER) { /* internal error! this should be generated correctly */ CHECK("calling convention violation: number of args should be an integer"); } @@ -358,10 +397,10 @@ void execute_instruction(hVm vm) { CHECK("indirect variables should be of type reference! (%lld)", (long long)v->type); } pop_stack(vm); - xx.integer --; - if (xx.integer > 0) { + x->integer --; + if (x->integer > 0) { /* if last integer, don't put the 0 count back on the stack */ - push_stack(vm, &xx); + push_stack(vm, x); } break; case BC_POP: @@ -372,37 +411,34 @@ void execute_instruction(hVm vm) { npop_stack(vm, param); break; case BC_SWAP: - vv = pop_stack(vm); - ww = pop_stack(vm); - push_stack(vm, &vv); - push_stack(vm, &ww); + swap_stack_top(vm); break; case BC_CALL: - vv = pop_stack(vm); - if (vv.type <= 0) { + v = pop_stack(vm); + if (v->type <= 0) { /* We need to figure out exception support or some such. * User error should not panic. */ PANIC("attempt to call a non-function value"); } - call_block(vm, vv.type, vv.closure); + call_block(vm, v->type, v->closure); break; case BC_SEND: sbV_message_handler(vm); break; case BC_NUMARG: param = get_param(vm); - vv = pop_stack(vm); - if (vv.type != IT_INTEGER) { + v = pop_stack(vm); + if (v->type != IT_INTEGER) { /* internal error! this should be generated correctly */ CHECK("calling convention violation: number of args should be an integer"); } - if (vv.integer != param) { + if (v->integer != param) { /* This should be an exception. */ PANIC("wrong number of arguments passed to function."); } - if (vv.integer > 0) { + if (v->integer > 0) { /* when 0 arguments, leave this off */ - push_stack(vm, &vv); + push_stack_immediate(vm, v); } break; case BC_JMP: @@ -411,15 +447,15 @@ void execute_instruction(hVm vm) { break; case BC_JT: param = get_param(vm); - vv = pop_stack(vm); - if (!sbV_c_falsy(&vv)) { + v = pop_stack(vm); + if (!sbV_c_falsy(v)) { vm->ip = &vm->fp->block_func.block->bytecode[param]; } break; case BC_JF: param = get_param(vm); - vv = pop_stack(vm); - if (sbV_c_falsy(&vv)) { + v = pop_stack(vm); + if (sbV_c_falsy(v)) { vm->ip = &vm->fp->block_func.block->bytecode[param]; } break; @@ -431,14 +467,14 @@ void execute_instruction(hVm vm) { w = peek_stack(vm, 0); res = sbV_eq(v, w); npop_stack(vm, 2); - push_stack(vm, &res); + push_stack_immediate(vm, &res); break; case BC_OP_NOT: - vv = pop_stack(vm); - if (sbV_c_falsy(&vv)) { - push_stack(vm, &HVBOOL(TRUE)); + v = pop_stack(vm); + if (sbV_c_falsy(v)) { + push_stack_immediate(vm, &HVBOOL(TRUE)); } else { - push_stack(vm, &HVBOOL(FALSE)); + push_stack_immediate(vm, &HVBOOL(FALSE)); } break; case BC_OP_LT: @@ -446,35 +482,35 @@ void execute_instruction(hVm vm) { w = peek_stack(vm, 0); res = sbV_lt(v, w); npop_stack(vm, 2); - push_stack(vm, &res); + push_stack_immediate(vm, &res); break; case BC_OP_LE: v = peek_stack(vm, 1); w = peek_stack(vm, 0); res = sbV_le(v, w); npop_stack(vm, 2); - push_stack(vm, &res); + push_stack_immediate(vm, &res); break; case BC_OP_ADD: v = peek_stack(vm, 1); w = peek_stack(vm, 0); res = sbV_add(v, w); npop_stack(vm, 2); - push_stack(vm, &res); + push_stack_immediate(vm, &res); break; case BC_OP_SUB: v = peek_stack(vm, 1); w = peek_stack(vm, 0); res = sbV_sub(v, w); npop_stack(vm, 2); - push_stack(vm, &res); + push_stack_immediate(vm, &res); break; case BC_OP_MUL: v = peek_stack(vm, 1); w = peek_stack(vm, 0); res = sbV_mul(v, w); npop_stack(vm, 2); - push_stack(vm, &res); + push_stack_immediate(vm, &res); break; case BC_OP_DIV: PANIC("todo"); @@ -483,7 +519,7 @@ void execute_instruction(hVm vm) { w = peek_stack(vm, 0); res = sbV_floordiv(v, w); npop_stack(vm, 2); - push_stack(vm, &res); + push_stack_immediate(vm, &res); break; case BC_OP_NEG: case BC_OP_MOD: @@ -491,29 +527,18 @@ void execute_instruction(hVm vm) { PANIC("todo"); case BC_OP_INCR: v = peek_stack(vm, 0); - res = sbV_incr(v); - pop_stack(vm); - push_stack(vm, &res); + sbV_incr(v); break; case BC_OP_DECR: v = peek_stack(vm, 0); - res = sbV_decr(v); - pop_stack(vm); - push_stack(vm, &res); + sbV_decr(v); break; case BC_OP_INDEX: v = peek_stack(vm, 1); w = peek_stack(vm, 0); - res = sbV_index(v, w); - npop_stack(vm, 2); - push_stack(vm, &res); - break; - case BC_OP_SCOPE: - v = peek_stack(vm, 1); - w = peek_stack(vm, 0); - res = sbV_scope_get(v, w); + x = sbV_index(v, w); npop_stack(vm, 2); - push_stack(vm, &res); + push_stack(vm, x); break; case BC_OP_DEREF: PANIC("todo"); @@ -525,8 +550,8 @@ void execute_instruction(hVm vm) { case BC_CLOSURE: param = get_param(vm); hClosure c = sbClosure_create(param); - vv = pop_stack(vm); /* function to close with */ - if (vv.type <= 0) { + v = pop_stack(vm); /* function to close with */ + if (v->type <= 0) { CHECK("internal violation: a function is required to create a closure!"); } while (param > 0) { @@ -540,16 +565,16 @@ void execute_instruction(hVm vm) { sbClosure_set_ref(c, param, w); pop_stack(vm); } - vv.closure = c; - push_stack(vm, &vv); + v->closure = c; + push_stack_immediate(vm, v); break; case BC_LIST_GATHER: - vv = pop_stack(vm); - if (vv.type != IT_INTEGER) { + v = pop_stack(vm); + if (v->type != IT_INTEGER) { /* internal error! this should be generated correctly */ CHECK("internal violation: LIST_GATHER should receive an integer on top of stack"); } - param = vv.integer; + param = v->integer; count = param; res = sbV_empty_list(param); while (count > 0) { @@ -560,42 +585,42 @@ void execute_instruction(hVm vm) { count --; } npop_stack(vm, param); - push_stack(vm, &res); + push_stack_immediate(vm, &res); break; case BC_HASH_GATHER: - vv = pop_stack(vm); - if (vv.type != IT_INTEGER) { + v = pop_stack(vm); + if (v->type != IT_INTEGER) { /* internal error! this should be generated correctly */ CHECK("internal violation: HASH_GATHER should receive an integer on top of stack"); } - count = vv.integer; + count = v->integer; res = sbV_empty_hash(count * 3 / 2); while (count > 0) { /* values come first, then keys, because of execution order */ - xx = pop_stack(vm); - ww = pop_stack(vm); - sbV_scope_set(&res, &ww, &xx); + x = pop_stack(vm); + w = pop_stack(vm); + sbV_index_set(&res, w, x); count --; } - push_stack(vm, &res); + push_stack_immediate(vm, &res); break; case BC_LIST_SPILL: - vv = pop_stack(vm); /* list to spill */ - if (vv.type != IT_LIST) { + v = pop_stack(vm); /* list to spill */ + if (v->type != IT_LIST) { /* user error */ PANIC("cannot use '...' operator on something that isn't a list"); } - ww = pop_stack(vm); /* current count */ - if (ww.type != IT_INTEGER) { + res = *pop_stack(vm); /* current count */ + if (res.type != IT_INTEGER) { /* internal error! this should be generated correctly */ CHECK("internal violation: LIST_SPILL should receive an integer on top of stack"); } - x = sbList_get_value(vv.list, &count); + x = sbList_get_value(v->list, &count); for (usize i = 0; i < count; i++) { push_stack(vm, &x[i]); } - ww.integer += count; - push_stack(vm, &ww); + res.integer += count; + push_stack_immediate(vm, &res); break; case BC_LONG_NUM: case BC_VLONG_NUM: diff --git a/src/vm/exec.h b/src/vm/exec.h index e110e19..5e49dc3 100644 --- a/src/vm/exec.h +++ b/src/vm/exec.h @@ -61,13 +61,15 @@ typedef struct sbVmStackFrame { } sbVmStackFrame; typedef struct sbVm { - u8 *stack; /* for calculations */ + u8 *vstack; /* for calculations */ + u8 *xstack; /* parallel to vstack, holds immediate values that are pointed to */ u8 *rstack; /* for locals and return addresses, like FORTH */ const u8 *ip; /* instruction pointer */ sbVmStackFrame *fp; /* frame pointer */ - u8 *sp; /* stack pointer */ - u8 *rp; /* rstack pointer */ + u8 *vsp; /* stack pointer */ + u8 *xsp; /* rstack pointer */ + u8 *rsp; /* rstack pointer */ usize stacksize; /* to detect overflow, save these */ usize rstacksize; /* ^^ */ @@ -83,13 +85,15 @@ void sbVm_deinitialize(hVm vm); sbVmStatus sbVm_execute(hVm vm, sbVmProgram *pm); -void sbVm_push(hVm vm, hV value); +void sbVm_push(hVm vm, hV *value); -hV sbVm_pop(hVm vm); +void sbVm_push_immediate(hVm vm, hV *value); + +hV *sbVm_pop(hVm vm); hV *sbVm_peek(hVm vm, usize where); -void sbVm_call_func(hVm vm, hV func); +void sbVm_call_func(hVm vm, hV *func); void sbVm_call_c_func(hVm vm, sbRuntimeCFunc func); diff --git a/src/vm/operations.c b/src/vm/operations.c index 1b73140..5d7fde1 100644 --- a/src/vm/operations.c +++ b/src/vm/operations.c @@ -7,16 +7,16 @@ #include "data/methods.h" void sbV_message_handler(hVm vm) { - hV target = sbVm_pop(vm); - switch(target.type) { + hV *target = sbVm_peek(vm, 0); + switch(target->type) { case IT_LIST: - sbList_method(target, vm); + sbList_method(vm); break; default: - if (target.type < 0) { + if (target->type < 0) { PANIC("haven't implemented method calling for this intrinsic type!"); } - if (target.type & FLAG_SQUIGGLY) { + if (target->type & FLAG_SQUIGGLY) { /* squiggle function */ sbVm_call_func(vm, target); } else { @@ -116,24 +116,20 @@ hV sbV_append(hV *a, hV *b) { } } -hV sbV_index(hV *a, hV *b) { +hV *sbV_index(hV *a, hV *b) { if (a->type == IT_LIST && b->type == IT_INTEGER) { return sbList_index(a->list, b->integer); + } else if (a->type == IT_HASH) { + return sbHash_find(a->hash, b); } else { PANIC("todo %lld %lld", (long long)a->type, (long long)b->type); } } -hV sbV_scope_get(hV *obj, hV *key) { - if (obj->type == IT_HASH) { - return sbHash_find(obj->hash, key); - } else { - PANIC("todo %lld", (long long)obj->type); - } -} - -void sbV_scope_set(hV *obj, hV *key, hV *value) { - if (obj->type == IT_HASH) { +void sbV_index_set(hV *obj, hV *key, hV *value) { + if (obj->type == IT_LIST) { + PANIC("todo"); + } else if (obj->type == IT_HASH) { sbHash_insert(obj->hash, key, value); } else { PANIC("todo %lld", (long long)obj->type); diff --git a/src/vm/operations.h b/src/vm/operations.h index f14c8b8..e9e28af 100644 --- a/src/vm/operations.h +++ b/src/vm/operations.h @@ -22,8 +22,6 @@ hV sbV_le(const hV *a, const hV *b); hV sbV_append(hV *a, hV *b); -hV sbV_index(hV *a, hV *b); +hV *sbV_index(hV *a, hV *b); -hV sbV_scope_get(hV *hash, hV *key); - -void sbV_scope_set(hV *hash, hV *key, hV *value); +void sbV_index_set(hV *obj, hV *key, hV *value); -- 1.8.3.1