better/more consistent VM model
authorcassowarii <2374677+cassowarii@users.noreply.github.com>
Mon, 6 Jul 2026 04:57:53 +0000 (21:57 -0700)
committercassowarii <2374677+cassowarii@users.noreply.github.com>
Mon, 6 Jul 2026 04:57:53 +0000 (21:57 -0700)
16 files changed:
src/compile/emit.c
src/compile/ir.c
src/data/hashtable.c
src/data/hashtable.h
src/data/list.c
src/data/list.h
src/data/methods.c
src/data/methods.h
src/data/symbol.c
src/main.c
src/parse/parser.c
src/vm/bytecode.h
src/vm/exec.c
src/vm/exec.h
src/vm/operations.c
src/vm/operations.h

index cb3688e..d558711 100644 (file)
@@ -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");
   }
index 4bd7a47..2a995a6 100644 (file)
@@ -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);
   }
 
index 3a9b1cf..93978e5 100644 (file)
@@ -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) {
index e523f95..b2b4f09 100644 (file)
@@ -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);
index 1ea58db..bebb5a2 100644 (file)
@@ -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;
 }
 
 /* --- */
index 7a8e102..65e6a1e 100644 (file)
@@ -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);
index d554db3..9194a74 100644 (file)
@@ -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);
   }
 }
index c93dc5a..1a4ce1b 100644 (file)
@@ -1,3 +1,3 @@
 #include "common.h"
 
-void sbList_method(hV list, hVm vm);
+void sbList_method(hVm vm);
index de7006c..7c8c452 100644 (file)
@@ -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);
   }
 }
 
index b76c2eb..50031ab 100644 (file)
@@ -19,7 +19,7 @@ int main(int argc, char **argv) {
       filename = argv[1];
     } else {
       printf("usage: %s [-D] <filename>\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");
 
index 069580e..30e8c10 100644 (file)
@@ -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[] = {
index 89cb296..5e8a48c 100644 (file)
@@ -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
index 8be69e4..9a85acb 100644 (file)
@@ -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:
index e110e19..5e49dc3 100644 (file)
@@ -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);
 
index 1b73140..5d7fde1 100644 (file)
@@ -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);
index f14c8b8..e9e28af 100644 (file)
@@ -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);