vm/compiler changes for this (still doesn't work)
authorcassowarii <2374677+cassowarii@users.noreply.github.com>
Sun, 19 Jul 2026 02:21:38 +0000 (19:21 -0700)
committercassowarii <2374677+cassowarii@users.noreply.github.com>
Sun, 19 Jul 2026 02:21:38 +0000 (19:21 -0700)
src/compile/emit.c
src/data/hashtable.c
src/data/hashtable.h
src/data/symbol.c
src/lib/method/hash.c
src/vm/bytecode.h
src/vm/exec.c
src/vm/operations.h

index 37638ba..84b5377 100644 (file)
@@ -176,8 +176,6 @@ void compile_stmt(sbVmCompiler *cm, sbIrStmt *stmt) {
       compile_expr(cm, stmt->assign.expr);
       if (stmt->assign.var->is_upvalue) {
         EMIT(BC_ST_UPVAL);
-      } else if (stmt->assign.var->closed_over) {
-        EMIT(BC_ST_IND);
       } else {
         EMIT(BC_ST_VAR);
       }
@@ -289,11 +287,7 @@ void compile_bind_list(sbVmCompiler *cm, sbIrBindList *list) {
        * we don't actually check that it's a variable that the "..." is
        * attached to, and we may fail in weird cases like "...2". but we
        * need to restructure the BindList data structure. */
-      if (elem->op.left->var->closed_over) {
-        EMIT(BC_ST_IND);
-      } else {
-        EMIT(BC_ST_VAR);
-      }
+      EMIT(BC_ST_VAR);
       EARG(elem->op.left->var->slot_id);
       if (list->pre_splat_count > 0) {
         /* put pre splat count back if we need it, to bind the rest of
@@ -304,11 +298,7 @@ void compile_bind_list(sbVmCompiler *cm, sbIrBindList *list) {
     } else if (elem->type == IR_E_VAR) {
       /* normal sequence, no splat (so far): top thing goes in this
        * variable using ST_ARG */
-      if (elem->var->closed_over) {
-        EMIT(BC_ST_ARG_IND);
-      } else {
-        EMIT(BC_ST_ARG);
-      }
+      EMIT(BC_ST_ARG);
       EARG(elem->var->slot_id);
     } else {
       PANIC("bind todo!");
@@ -344,8 +334,6 @@ void compile_expr(sbVmCompiler *cm, sbIrExpr *expr) {
     case IR_E_VAR:
       if (expr->var->is_upvalue) {
         EMIT(BC_LD_UPVAL);
-      } else if (expr->var->closed_over) {
-        EMIT(BC_LD_IND);
       } else {
         EMIT(BC_LD_VAR);
       }
@@ -355,25 +343,13 @@ void compile_expr(sbVmCompiler *cm, sbIrExpr *expr) {
       if (expr->func.bound.size > 0) {
         BUFFER_ITER(expr->func.bound, sbIrVariable*, var) {
           if ((*var)->is_upvalue) {
-            /* the closure-generator expects a series of values
-             * of type reference to close over. BC_LD_UPVAL normally
-             * pushes whatever is *behind* the reference, which we
-             * don't want. UPREF will push the reference value
-             * itself from the closure so we can close over it
-             * a second time */
+            /* BC_LD_UPREF: closed over variables are always on
+             * the heap, so all upval refs are rrefs */
             EMIT(BC_LD_UPREF);
           } else if ((*var)->closed_over) {
-            /* note: BC_LD_REF here, not BC_LD_IND! this will push
-             * the pointer value, not the variable itself, because
-             * we want to put the pointer (well, the sbRef) inside
-             * the closure, not the value */
-            /* BC_LD_REF is actually almost the same as BC_LD_VAR,
-             * except that if a variable hasn't been initialized
-             * it will create a new reference to nil. (this is
-             * necessary for mutually calling functions, who want to
-             * close over each other before all of them have been
-             * defined.) */
-            EMIT(BC_LD_REF);
+            /* BC_LD_RREF: everything we are closing over from the
+             * current scope needs to move to the heap */
+            EMIT(BC_LD_RREF);
           } else {
             PANIC("cannot have a direct variable in closure!");
           }
@@ -434,7 +410,7 @@ void compile_op(sbVmCompiler *cm, sbAstOp op) {
     case AST_OP_NOT: EMIT(BC_OP_NOT); break;
     case AST_OP_AND: EMIT(BC_OP_AND); break;
     case AST_OP_OR: EMIT(BC_OP_OR); break;
-    case AST_OP_INDEX: EMIT(BC_OP_INDEX); break;
+    case AST_OP_INDEX: EMIT(BC_OP_INDEXVAL); break;
     case AST_OP_RANGEINDEX: EMIT(BC_OP_RANGEINDEX); break;
     /* op range is currently only used in rangeindex; just pass them to it directly */
     case AST_OP_RANGE: break;
index 602ddf1..7d5fa49 100644 (file)
@@ -89,16 +89,16 @@ void sbHash_insert(hHash h, hVal *key, hVal *value) {
   set_key(t, key, value);
 }
 
-hVal sbHash_find_value(hHash h, hVal *key) {
+hVal *sbHash_find_value(hHash h, hVal *key) {
   hashtbl *t = find_tbl_for_handle(h);
   usize index = find_index_by_key(t, key);
   hVal *keys;
   sbVar *values;
   get_ptrs_for_tbl(t, &keys, &values);
   if (keys[index].type == IT_NOTHING) {
-    return HVNOTHING;
+    return NULL;
   } else {
-    return sbVar_get_value(&values[index]);
+    return sbVar_get_value_ptr(&values[index]);
   }
 }
 
index f60f3bc..4734018 100644 (file)
@@ -16,7 +16,11 @@ sbHashValue sbHash_hash_obj(hVal *obj);
 
 hHash sbHash_create(usize initial_size);
 
-hVal *sbHash_find(hHash h, hVal *key);
+hVal *sbHash_find_value(hHash h, hVal *key);
+
+hVal sbHash_find_lvalue_ref(hHash h, hVal *key);
+
+hVal sbHash_find_rvalue_ref(hHash h, hVal *key);
 
 void sbHash_insert(hHash h, hVal *key, hVal *value);
 
index 252ce2c..f54bfb4 100644 (file)
@@ -18,7 +18,7 @@ hSymbol sbSymbol_from_bytes(const char *text, usize length) {
     .string = sbString_new(text, length),
   };
 
-  hVal *result = sbHash_find(symbol_table, &symkey);
+  hVal *result = sbHash_find_value(symbol_table, &symkey);
 
   if (result == NULL) {
     /* add new symbol */
index 431cc09..42e8cd4 100644 (file)
@@ -20,8 +20,8 @@ static void length(hVm vm, hVal *target, usize num_params) {
 
 static void get_index(hVm vm, hVal *target, usize num_params) {
   hVal *key = sbVm_pop(vm);
-  hVal *result = sbHash_find(target->hash, key);
-  if (result == IT_NOTHING) {
+  hVal *result = sbHash_find_value(target->hash, key);
+  if (result == NULL) {
     sbVm_push_immediate(vm, &HVNIL);
   } else {
     sbVm_push(vm, result);
index 8bf019e..bff3a32 100644 (file)
@@ -9,8 +9,8 @@ typedef enum sbOpcode {
   BC_LD_CONST,          // push constants[index] to stack
   BC_LD_CTX,            // look up key in context object and push result
   BC_LD_VAR,            // push value onto stack from variable
-  BC_LD_LREF,           // push lvalue reference onto stack from variable
-  BC_LD_RREF,           // push rvalue reference onto stack from variable
+  BC_LD_LREF,           // push lref to variable onto stack
+  BC_LD_RREF,           // push rref to variable onto stack
   BC_LD_UPVAL,          // push value onto stack from closure
   BC_LD_UPREF,          // push pointer to closure value onto stack (to close over again)
   BC_LD_BLK,            // push reference to function onto stack
@@ -48,7 +48,9 @@ typedef enum sbOpcode {
   BC_OP_LE,             // less than or equal to
   BC_OP_AND,            // logical and
   BC_OP_OR,             // logical or
-  BC_OP_INDEX,          // index [] or ::
+  BC_OP_INDEXVAL,       // a[...]
+  BC_OP_INDEXLREF,      // a[...] = ...
+  BC_OP_INDEXRREF,      // &a[...]
   BC_OP_RANGEINDEX,     // index [a..b]
   BC_ALLOC_VARS,        // create space in rstack for local variables
   BC_CLOSURE,           // create closure from top elements of stack
index 14df61f..c20ffd0 100644 (file)
@@ -558,8 +558,8 @@ void execute_instruction(hVm vm) {
       v = peek_stack(vm, 0);
       sbV_decr(v);
       break;
-    case BC_OP_INDEX:
-      sbV_index(vm);
+    case BC_OP_INDEXVAL:
+      sbV_index_value(vm);
       break;
     case BC_OP_RANGEINDEX:
       v = peek_stack(vm, 2);
index 3b1df1d..c8b9c00 100644 (file)
@@ -24,7 +24,7 @@ hVal sbV_le(const hVal *a, const hVal *b);
 
 hVal sbV_append(hVal *a, hVal *b);
 
-void sbV_index(hVm vm);
+void sbV_index_value(hVm vm);
 
 hVal sbV_rangeindex(hVal *a, hVal *b, hVal *c);