split concept of variables vs values. compiler not working yet though
authorcassowarii <2374677+cassowarii@users.noreply.github.com>
Sat, 18 Jul 2026 23:59:20 +0000 (16:59 -0700)
committercassowarii <2374677+cassowarii@users.noreply.github.com>
Sat, 18 Jul 2026 23:59:20 +0000 (16:59 -0700)
17 files changed:
src/data/closure.c
src/data/closure.h
src/data/data.h
src/data/hashtable.c
src/data/hashtable.h
src/data/list.c
src/data/list.h
src/data/value.c
src/data/value.h
src/data/variable.c [new file with mode: 0644]
src/data/variable.h [new file with mode: 0644]
src/lib/lib.c
src/lib/method/list.c
src/vm/bytecode.h
src/vm/exec.c
src/vm/exec.h
src/vm/operations.c

index 2603382..4029d9b 100644 (file)
@@ -15,8 +15,8 @@ typedef struct sbClosure {
   GCINFO info;
   usize num_vars;
   union {
-    hRef internal_vars[INLINE_VAR_COUNT];
-    hRef *external_vars;
+    sbVar internal_vars[INLINE_VAR_COUNT];
+    sbVar *external_vars;
   };
 } sbClosure;
 
@@ -35,49 +35,46 @@ hClosure sbClosure_create(usize num_vars) {
   sbClosure *c = sbPool_alloc(&g_closure_pool, &index);
   c->num_vars = num_vars;
   if (num_vars > INLINE_VAR_COUNT) {
-    c->external_vars = calloc(num_vars, sizeof(hRef));
+    c->external_vars = calloc(num_vars, sizeof(sbVar));
   }
   return index | FLAG_REAL;
 }
 
 /* set the variable in the closure behind the pointer */
-void sbClosure_set_var(hClosure which, usize index, hVal *what) {
+void sbClosure_set_value(hClosure which, usize index, hVal *what) {
   sbClosure *c = find_closure_by_handle(which);
   if (c->num_vars <= INLINE_VAR_COUNT) {
-    sbRef_set_ref(c->internal_vars[index], what);
+    sbVar_set_value(&c->internal_vars[index], what);
   } else {
-    sbRef_set_ref(c->external_vars[index], what);
+    sbVar_set_value(&c->external_vars[index], what);
   }
 }
 
 /* set the pointer itself */
-void sbClosure_set_ref(hClosure which, usize index, hVal *what) {
-  if (what->type != IT_REF) {
-    PANIC("must pass an indirect variable to be the subject of a closure");
-  }
+void sbClosure_set_var(hClosure which, usize index, hVar what) {
   sbClosure *c = find_closure_by_handle(which);
   if (c->num_vars <= INLINE_VAR_COUNT) {
-    c->internal_vars[index] = what->ref;
+    c->internal_vars[index] = sbVar_retain(what);
   } else {
-    c->external_vars[index] = what->ref;
+    c->external_vars[index] = sbVar_retain(what);
   }
 }
 
-hVal *sbClosure_get_var(hClosure which, usize index) {
+hVal sbClosure_get_value(hClosure which, usize index) {
   sbClosure *c = find_closure_by_handle(which);
   if (c->num_vars <= INLINE_VAR_COUNT) {
-    return sbRef_deref(c->internal_vars[index]);
+    return sbVar_get_value(&c->internal_vars[index]);
   } else {
-    return sbRef_deref(c->external_vars[index]);
+    return sbVar_get_value(&c->external_vars[index]);
   }
 }
 
-hVal sbClosure_get_ref(hClosure which, usize index) {
+hVar sbClosure_get_var(hClosure which, usize index) {
   sbClosure *c = find_closure_by_handle(which);
   if (c->num_vars <= INLINE_VAR_COUNT) {
-    return HVREF(c->internal_vars[index]);
+    return &c->internal_vars[index];
   } else {
-    return HVREF(c->external_vars[index]);
+    return &c->external_vars[index];
   }
 }
 
index 1bdc995..1acfb8d 100644 (file)
@@ -6,10 +6,10 @@ void sbClosure_sys_deinit();
 
 hClosure sbClosure_create(usize num_vars);
 
-void sbClosure_set_var(hClosure which, usize index, hVal *var);
+void sbClosure_set_value(hClosure which, usize index, hVal *var);
 
-void sbClosure_set_ref(hClosure which, usize index, hVal *what);
+void sbClosure_set_var(hClosure which, usize index, hVar what);
 
-hVal *sbClosure_get_var(hClosure which, usize index);
+hVal sbClosure_get_value(hClosure which, usize index);
 
-hVal sbClosure_get_ref(hClosure which, usize index);
+hVar sbClosure_get_var(hClosure which, usize index);
index 9130b59..fce4350 100644 (file)
@@ -2,6 +2,7 @@
 #define __SARABANDE_DATA_H__
 
 #include "data/value.h"
+#include "data/variable.h"
 
 void data_sys_init();
 
index d89b2e5..602ddf1 100644 (file)
@@ -18,23 +18,24 @@ typedef struct hashtbl {
   union {
     struct {
       hVal keys[INLINE_TABLE_LENGTH];
-      hVal values[INLINE_TABLE_LENGTH];
+      sbVar values[INLINE_TABLE_LENGTH];
     } internal;
     struct {
       hVal *keys;
-      hVal *values;
+      sbVar *values;
     } external;
   };
 } hashtbl;
 
 static hashtbl *new_tbl(usize initial_size);
 static hVal *get_key_ptr_for_tbl(hashtbl *t, usize *length_out);
-static void get_ptrs_for_tbl(hashtbl *t, hVal **keys, hVal **values);
+static void get_ptrs_for_tbl(hashtbl *t, hVal **keys, sbVar **values);
 static hashtbl *find_tbl_for_handle(hHash handle);
 static usize set_key(hashtbl *t, hVal *key, hVal *value);
-static hVal delete_key(hashtbl *t, hVal *key);
+static void delete_key(hashtbl *t, hVal *key);
+static hVal delete_key_and_return(hashtbl *t, hVal *key);
 static void set_hashtbl_size(hashtbl *t, usize new_size, flag rehash_all);
-static usize set_key_in_array(hVal *keys, hVal *values, usize length, hVal *key, hVal *value);
+static usize set_key_for_rehash(hVal *keys, sbVar *values, usize length, hVal *key, sbVar *value);
 static usize find_index_by_key(hashtbl *t, hVal *key);
 
 void sbHash_sys_init() {
@@ -88,19 +89,38 @@ void sbHash_insert(hHash h, hVal *key, hVal *value) {
   set_key(t, key, value);
 }
 
-hVal *sbHash_find(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, *values;
+  hVal *keys;
+  sbVar *values;
   get_ptrs_for_tbl(t, &keys, &values);
   if (keys[index].type == IT_NOTHING) {
-    return NULL;
+    return HVNOTHING;
   } else {
-    return &values[index];
+    return sbVar_get_value(&values[index]);
   }
 }
 
-hVal *sbHash_find_or_insert(hHash h, hVal *key, hVal *value) {
+hVal sbHash_find_lvalue_ref(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);
+  return sbVar_get_lvalue_ref(&values[index]);
+}
+
+hVal sbHash_find_rvalue_ref(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);
+  return sbVar_get_rvalue_ref(&values[index]);
+}
+
+/*hVal *sbHash_find_or_insert(hHash h, hVal *key, hVal *value) {
   hashtbl *t = find_tbl_for_handle(h);
   usize index = find_index_by_key(t, key);
   hVal *keys, *values;
@@ -109,13 +129,18 @@ hVal *sbHash_find_or_insert(hHash h, hVal *key, hVal *value) {
     values[index] = *value;
   }
   return &values[index];
-}
+}*/
 
-void sbHash_delete(hHash h, hVal *key, hVal *value) {
+void sbHash_delete(hHash h, hVal *key) {
   hashtbl *t = find_tbl_for_handle(h);
   delete_key(t, key);
 }
 
+hVal sbHash_delete_and_return(hHash h, hVal *key) {
+  hashtbl *t = find_tbl_for_handle(h);
+  return delete_key_and_return(t, key);
+}
+
 usize sbHash_get_size(hHash h) {
   hashtbl *t = find_tbl_for_handle(h);
   return t->n_elems;
@@ -131,17 +156,14 @@ static void set_hashtbl_size(hashtbl *t, usize new_size, flag rehash_all) {
     t->is_inline = 1;
   } else {
     hVal *new_keys = calloc(new_size, sizeof(hVal));
-    hVal *new_values = calloc(new_size, sizeof(hVal));
+    sbVar *new_values = calloc(new_size, sizeof(sbVar));
     if (rehash_all) {
-      hVal *current_keys, *current_values;
+      hVal *current_keys;
+      sbVar *current_values;
       get_ptrs_for_tbl(t, &current_keys, &current_values);
       for (usize i = 0; i < t->capacity; i++) {
         if (current_keys[i].type == IT_NOTHING || current_keys[i].type == ITX_TOMBSTONE) continue;
-        set_key_in_array(new_keys, new_values, new_size, &current_keys[i], &current_values[i]);
-        /* adding a new k/v pair will retain the values, so we need to release them
-         * from the previous allocation */
-        sbV_release(&current_keys[i]);
-        sbV_release(&current_values[i]);
+        set_key_for_rehash(new_keys, new_values, new_size, &current_keys[i], &current_values[i]);
       }
       /* now that we've migrated all our things to the new version, we can free the old
        * version (unless it was not alloc'd to begin with) */
@@ -166,7 +188,7 @@ static hVal *get_key_ptr_for_tbl(hashtbl *t, usize *length_out) {
   }
 }
 
-static void get_ptrs_for_tbl(hashtbl *t, hVal **keys, hVal **values) {
+static void get_ptrs_for_tbl(hashtbl *t, hVal **keys, sbVar **values) {
   if (t->is_inline) {
     if (keys) *keys = t->internal.keys;
     if (values) *values = t->internal.values;
@@ -195,7 +217,9 @@ static usize find_index_by_key(hashtbl *t, hVal *key) {
   return find_key_index_in_array(get_key_ptr_for_tbl(t, NULL), t->capacity, key);
 }
 
-static usize set_key_in_array(hVal *keys, hVal *values, usize length, hVal *key, hVal *value) {
+/* NOTE: This is used for rehashing, so it doesn't update reference counts on values.
+ * Use set_key for actually retaining refcounts properly. */
+static usize set_key_for_rehash(hVal *keys, sbVar *values, usize length, hVal *key, sbVar *value) {
   usize index = find_key_index_in_array(keys, length, key);
 
   /* now, we either found the current entry for this key,
@@ -203,24 +227,19 @@ static usize set_key_in_array(hVal *keys, hVal *values, usize length, hVal *key,
   if (keys[index].type == IT_NOTHING) {
     /* key was not here before, so we need to retain the key
      * as well so it doesn't change out from under us */
-    sbV_retain(key);
     keys[index] = *key;
+    values[index] = *value;
+    return index;
   } else {
-    /* replacing something that already exists. we can keep
-     * the key the same, but need to release the previous value. */
-    sbV_release(&values[index]);
+    PANIC("Duplicate key found while rehashing hash table somehow!");
   }
-
-  sbV_retain(value);
-  values[index] = *value;
-
-  return index;
 }
 
 static usize set_key(hashtbl *t, hVal *key, hVal *value) {
   usize index = find_index_by_key(t, key);
 
-  hVal *keys, *values;
+  hVal *keys;
+  sbVar *values;
   get_ptrs_for_tbl(t, &keys, &values);
 
   /* now, we either found the current entry for this key,
@@ -230,7 +249,6 @@ static usize set_key(hashtbl *t, hVal *key, hVal *value) {
      * as well so it doesn't change out from under us */
     sbV_retain(key);
     keys[index] = *key;
-    values[index] = *value;
     t->used ++;
     t->n_elems ++;
     if (t->used >= t->capacity * 3 / 4) {
@@ -239,20 +257,33 @@ static usize set_key(hashtbl *t, hVal *key, hVal *value) {
   } else {
     /* replacing something that already exists. we can keep
      * the key the same, but need to release the previous value. */
-    sbV_release(&values[index]);
+    hVal to_replace = sbVar_get_value(&values[index]);
+    sbV_release(&to_replace);
   }
 
   sbV_retain(value);
-  values[index] = *value;
+  values[index] = (sbVar) { .value = *value };
 
   return index;
 }
 
-static hVal delete_key(hashtbl *t, hVal *key) {
+static void delete_key(hashtbl *t, hVal *key) {
   usize index = find_index_by_key(t, key);
-  hVal *keys, *values;
+  hVal *keys;
+  sbVar *values;
+  get_ptrs_for_tbl(t, &keys, &values);
+  hVal to_delete = sbVar_get_value(&values[index]);
+  sbV_release(&to_delete);
+  keys[index].type = ITX_TOMBSTONE;
+  t->n_elems --;
+}
+
+static hVal delete_key_and_return(hashtbl *t, hVal *key) {
+  usize index = find_index_by_key(t, key);
+  hVal *keys;
+  sbVar *values;
   get_ptrs_for_tbl(t, &keys, &values);
-  hVal to_return = values[index];
+  hVal to_return = sbVar_get_value(&values[index]);
   keys[index].type = ITX_TOMBSTONE;
   t->n_elems --;
   return to_return;
index e5dd026..f60f3bc 100644 (file)
@@ -22,6 +22,8 @@ void sbHash_insert(hHash h, hVal *key, hVal *value);
 
 hVal *sbHash_find_or_insert(hHash h, hVal *key, hVal *value);
 
-void sbHash_delete(hHash h, hVal *key, hVal *value);
+void sbHash_delete(hHash h, hVal *key);
+
+hVal sbHash_delete_and_return(hHash h, hVal *key);
 
 usize sbHash_get_size(hHash h);
index df67f67..79419e7 100644 (file)
@@ -30,37 +30,50 @@ hList sbList_new(usize capacity) {
   usize index;
   sbList *l = sbPool_alloc(&g_list_pool, &index);
   if (capacity < 4) capacity = 4;
-  sbBuffer_initialize(&l->items, capacity * sizeof(hVal));
+  sbBuffer_initialize(&l->items, capacity * sizeof(sbVar));
   return index;
 }
 
-hList sbList_of(usize length, hVal *items) {
+hList sbList_of(usize length, hVaitems) {
   usize index;
   usize capacity = length;
   sbList *l = sbPool_alloc(&g_list_pool, &index);
   if (capacity < 4) capacity = 4;
-  sbBuffer_initialize(&l->items, capacity * sizeof(hVal));
-  sbBuffer_set_size(&l->items, length * sizeof(hVal));
-  memcpy(l->items.data, items, length * sizeof(hVal));
+  sbBuffer_initialize(&l->items, capacity * sizeof(sbVar));
+  sbBuffer_set_size(&l->items, length * sizeof(sbVar));
+  memcpy(l->items.data, items, length * sizeof(sbVar));
   return index;
 }
 
 void sbList_append(hList list, hVal *item) {
   sbList *l = get_list_by_handle(list);
   sbV_retain(item);
-  sbBuffer_append(&l->items, item, sizeof(hVal));
+  sbVar new_var = { .value = *item };
+  sbBuffer_append(&l->items, &new_var, sizeof(sbVar));
 }
 
-hVal *sbList_get_value(hList list, usize *length) {
+sbVar *sbList_get_value(hList list, usize *length) {
   sbList *l = get_list_by_handle(list);
-  if (length) *length = l->items.size / sizeof(hVal);
-  return (hVal*)l->items.data;
+  if (length) *length = l->items.size / sizeof(sbVar);
+  return (sbVar*)l->items.data;
 }
 
-hVal *sbList_index(hList list, usize index) {
+hVal sbList_index_value(hList list, usize index) {
   sbList *l = get_list_by_handle(list);
-  hVal *item = &((hVal*)l->items.data)[index];
-  return item;
+  hVar item = &((sbVar*)l->items.data)[index];
+  return sbVar_get_value(item);
+}
+
+hVal sbList_index_lvalue_ref(hList list, usize index) {
+  sbList *l = get_list_by_handle(list);
+  hVar item = &((sbVar*)l->items.data)[index];
+  return sbVar_get_lvalue_ref(item);
+}
+
+hVal sbList_index_rvalue_ref(hList list, usize index) {
+  sbList *l = get_list_by_handle(list);
+  hVar item = &((sbVar*)l->items.data)[index];
+  return sbVar_get_rvalue_ref(item);
 }
 
 /* --- */
index f3da532..cd6d446 100644 (file)
@@ -6,12 +6,16 @@ void sbList_sys_deinit();
 
 hList sbList_new(usize capacity);
 
-hList sbList_of(usize length, hVal *items);
+hList sbList_of(usize length, hVaitems);
 
 void sbList_append(hList list, hVal *item);
 
-hVal *sbList_get_value(hList list, usize *length);
+sbVar *sbList_get_value(hList list, usize *length);
 
-hVal *sbList_index(hList list, usize index);
+hVal sbList_index_value(hList list, usize index);
+
+hVal sbList_index_lvalue_ref(hList list, usize index);
+
+hVal sbList_index_rvalue_ref(hList list, usize index);
 
 void sbList_method(hVm vm);
index de404c7..12d2887 100644 (file)
@@ -1,5 +1,6 @@
 #include "data/value.h"
 
+#include "data/variable.h"
 #include "data/string.h"
 #include "data/list.h"
 #include "data/hashtable.h"
@@ -77,6 +78,9 @@ void sbV_retain(const hVal *a) {
     case IT_INTEGER:
       sbInteger_retain(a->string);
       break;
+    case ITX_HEAPVAR:
+      sbVar_retain(sbVar_deref(a));
+      break;
     default:
       /* nothing */
       break;
@@ -91,6 +95,9 @@ void sbV_release(const hVal *a) {
     case IT_INTEGER:
       sbInteger_release(a->string);
       break;
+    case ITX_HEAPVAR:
+      sbVar_release(sbVar_deref(a));
+      break;
     default:
       /* nothing */
       break;
index 6c1a277..d398b24 100644 (file)
 #define HVSYM(s) ((hVal) { .type = IT_SYMBOL, .symbol = s })
 #define HVBOOL(b) ((hVal) { .type = IT_BOOLEAN, .boolean = b })
 #define HVLIST(l) ((hVal) { .type = IT_LIST, .list = l })
-#define HVREF(r) ((hVal) { .type = IT_REF, .ref = r })
+#define HVREF(r) ((hVal) { .type = IT_REF, .ptrdata = r })
 #define HVNIL ((hVal) { .type = IT_NIL })
 #define HVNOTHING ((hVal) {0})
 #define HVFUNC(i, c) ((hVal) { .type = i, .closure = c })
 #define HVBUILTIN(b) ((hVal) { .type = IT_BUILTIN, .builtin = b })
-#define HVBOUNDMETHOD(m, t) ((hVal) { .type = m | IT_FLAG_BOUND_METHOD, .ref = t })
+#define HVBOUNDMETHOD(m) ((hVal) { .type = m | IT_FLAG_BOUND_METHOD })
 #define HVMODULE(m) ((hVal) { .type = IT_MODULE, .module = m })
 
 struct sbVm;
 struct sbLibTable;
+struct sbVar;
 
 typedef u64 hHash;
 typedef u64 hString;
@@ -46,9 +47,10 @@ enum intrinsic_type {
   IT_BUILTIN = -11,    // c function
   IT_MODULE = -12,     // builtin module (math, op...)
   ITX_TOMBSTONE = -13, // <hashtable_tombstone>
+  ITX_HEAPVAR = -14    // <hVar_moved_to_heap>
 };
 
-typedef struct hVal {
+typedef struct hval {
   i64 type;
   union {
     hString string;
@@ -57,12 +59,12 @@ typedef struct hVal {
     hList list;
     hInteger integer;
     hClosure closure;
-    hRef ref;
     u64 boolean;
     double float_val;
     sbBuiltinFunc builtin;
     struct sbLibTable *module;
     u64 data;
+    void *ptrdata;
   };
 } hVal;
 
diff --git a/src/data/variable.c b/src/data/variable.c
new file mode 100644 (file)
index 0000000..a5d793a
--- /dev/null
@@ -0,0 +1,106 @@
+#include "common.h"
+
+#include "gc/gcinfo.h"
+
+#define VARS_PER_BLOCK 1024
+
+typedef struct HeapVar {
+  GCINFO gcinfo;
+  hVal value;
+} HeapVar;
+
+/* TODO argle bargle */
+sbPool g_heapvar_pool;
+
+HeapVar *new_heapvar(hVal *v);
+
+void sbVar_sys_init() {
+  sbPool_initialize(&g_heapvar_pool, sizeof(HeapVar), VARS_PER_BLOCK);
+}
+
+hVal sbVar_get_value(hVar v) {
+  if (v->value.type == ITX_HEAPVAR) {
+    return ((HeapVar*)v->value.ptrdata)->value;
+  } else {
+    return v->value;
+  }
+}
+
+hVal *sbVar_get_value_ptr(hVar v) {
+  if (v->value.type == ITX_HEAPVAR) {
+    return &((HeapVar*)v->value.ptrdata)->value;
+  } else {
+    return &v->value;
+  }
+}
+
+void sbVar_set_value(hVar v, const hVal *new_value) {
+  /* release whatever was in the slot before */
+  sbV_release(&v->value);
+  sbV_retain(new_value);
+  if (v->value.type == ITX_HEAPVAR) {
+    ((HeapVar*)v->value.ptrdata)->value = *new_value;
+  } else {
+    v->value = *new_value;
+  }
+}
+
+/* for stuff like bound methods: we attach a pointer to a heap var to store
+ * what they're attached to, but don't bother allocating a full variable
+ * anywhere */
+void sbVar_set_attached_ref(hVal *attach_to, hVal *value) {
+  HeapVar *stored = new_heapvar(value);
+  attach_to->ptrdata = stored;
+}
+
+hVal *sbVar_get_attached_ref(const hVal *attached_to) {
+  return &((HeapVar*)attached_to->ptrdata)->value;
+}
+
+hVal sbVar_get_lvalue_ref(hVar v) {
+  return HVREF(v);
+}
+
+void sbVar_move_to_heap(hVar v) {
+  HeapVar *new_entry = new_heapvar(&v->value);
+  v->value.type = ITX_HEAPVAR;
+  v->value.ptrdata = new_entry;
+}
+
+hVar sbVar_deref(const hVal *v) {
+  if (v->type != IT_REF) {
+    CHECK("Internal error: value is not a pointer to variable");
+  }
+
+  /* v is ref */
+  return (hVar)v->ptrdata;
+}
+
+sbVar sbVar_retain(hVar v) {
+  sbVar_move_to_heap(v);
+  ((HeapVar*)v->value.ptrdata)->gcinfo.refcount ++;
+  return *v;
+}
+
+void sbVar_release(hVar v) {
+  if (v->value.type == ITX_HEAPVAR) {
+    ((HeapVar*)v->value.ptrdata)->gcinfo.refcount --;
+  }
+}
+
+hVal sbVar_get_rvalue_ref(hVar v) {
+  if (v->value.type != ITX_HEAPVAR) {
+    sbVar_move_to_heap(v);
+  }
+
+  return HVREF(v);
+}
+
+/* --- */
+
+HeapVar *new_heapvar(hVal *v) {
+  HeapVar *new_entry = sbPool_alloc(&g_heapvar_pool, NULL);
+  new_entry->gcinfo.refcount = 1;
+  new_entry->value = *v;
+  return new_entry;
+}
diff --git a/src/data/variable.h b/src/data/variable.h
new file mode 100644 (file)
index 0000000..2fab14d
--- /dev/null
@@ -0,0 +1,32 @@
+#ifndef __SARABANDE_VARIABLE_H__
+#define __SARABANDE_VARIABLE_H__
+
+typedef struct sbVar {
+  hVal value;
+} sbVar;
+
+typedef sbVar *hVar;
+
+hVal sbVar_get_value(hVar v);
+
+hVal *sbVar_get_value_ptr(hVar v);
+
+void sbVar_set_value(hVar v, const hVal *value);
+
+hVal sbVar_get_lvalue_ref(hVar v);
+
+hVal sbVar_get_rvalue_ref(hVar v);
+
+void sbVar_set_attached_ref(hVal *attach_to, hVal *value);
+
+hVal *sbVar_get_attached_ref(const hVal *attached_to);
+
+void sbVar_move_to_heap(hVar v);
+
+hVar sbVar_deref(const hVal *v);
+
+sbVar sbVar_retain(hVar v);
+
+void sbVar_release(hVar v);
+
+#endif
index 58a71e7..4fc543d 100644 (file)
@@ -136,8 +136,9 @@ void sbLib_resolve_property(hVm vm) {
       } else {
         /* it is a method, but it is being called without parameters.
          * annoyingly, we need to construct a bound version of this method. */
-        hRef ref = sbRef_create(target);
-        sbVm_push_immediate(vm, &HVBOUNDMETHOD(method_name_val->symbol, ref));
+        hVal bound_symbol = HVBOUNDMETHOD(method_name_val->symbol);
+        sbVar_set_attached_ref(&bound_symbol, target);
+        sbVm_push_immediate(vm, &bound_symbol);
       }
     } else {
       PANIC("invalid method name for type %lld: %s", (long long)target->type, sbSymbol_name(method_name_val->symbol));
index b252a22..db3eb42 100644 (file)
@@ -30,10 +30,10 @@ static void push(hVm vm, hVal *list, usize num_params) {
 static void reverse(hVm vm, hVal *list, usize num_params) {
   /* TODO maybe mutate in place if no other refs */
   usize length;
-  hVal *elems = sbList_get_value(list->list, &length);
+  sbVar *elems = sbList_get_value(list->list, &length);
   hList new_list = sbList_new(length);
   for (usize i = length - 1; ; i--) {
-    sbList_append(new_list, &elems[i]);
+    sbList_append(new_list, sbVar_get_value_ptr(&elems[i]));
     if (i == 0) break;
   }
   sbList_get_value(new_list, &length);
@@ -52,13 +52,14 @@ static void join(hVm vm, hVal *list, usize num_params) {
     delimiter = delimiter_v->string;
   }
   usize length;
-  hVal *elems = sbList_get_value(list->list, &length);
+  sbVar *elems = sbList_get_value(list->list, &length);
   hString joined = sbString_new("", 0);
   for (usize i = 0; i < length; i++) {
-    if (elems[i].type != IT_STRING) {
+    hVal *v = sbVar_get_value_ptr(&elems[i]);
+    if (v->type != IT_STRING) {
       PANIC("need string to join");
     }
-    joined = sbString_concat(joined, elems[i].string);
+    joined = sbString_concat(joined, v->string);
     if (join_with && i < length - 1) {
       joined = sbString_concat(joined, delimiter);
     }
@@ -119,21 +120,21 @@ sbCFuncStatus list_each_cfunc(hVm vm, flag init) {
     hVal *iterating_list = sbVm_pop(vm);
     hVal *loop_func = sbVm_pop(vm);
     hVal index = HVINT(0);
-    vm->fp->locals[0] = *iterating_list;
-    vm->fp->locals[1] = index;
-    vm->fp->locals[2] = *loop_func;
+    vm->fp->locals[0].value = *iterating_list;
+    vm->fp->locals[1].value = index;
+    vm->fp->locals[2].value = *loop_func;
   } else {
     /* loop func must have finished, so remove its result */
     sbVm_pop(vm);
   }
 
-  usize current_index = vm->fp->locals[1].integer++;
+  usize current_index = vm->fp->locals[1].value.integer++;
   usize length;
-  hVal *iter_values = sbList_get_value(vm->fp->locals[0].list, &length);
+  sbVar *iter_values = sbList_get_value(vm->fp->locals[0].value.list, &length);
   if (current_index < length) {
-    sbVm_push(vm, &iter_values[current_index]);
+    sbVm_push(vm, sbVar_get_value_ptr(&iter_values[current_index]));
     sbVm_push_immediate(vm, &HVINT(1));
-    sbVm_call_func(vm, &vm->fp->locals[2]);
+    sbVm_call_func(vm, sbVar_get_value_ptr(&vm->fp->locals[2]));
     return CFUNC_NEXT;
   } else {
     /* if index was past the end, callback function won't be called, and we'll exit. return nil */
@@ -150,30 +151,29 @@ sbCFuncStatus list_map_cfunc(hVm vm, flag init) {
     hVal *map_func = sbVm_pop(vm);
     usize length;
     sbList_get_value(iterating_list->list, &length);
-    hVal index = HVINT(0);
     hVal result = sbV_empty_list(length);
 
-    vm->fp->locals[0] = *iterating_list;
-    vm->fp->locals[1] = index;
-    vm->fp->locals[2] = *map_func;
-    vm->fp->locals[3] = result;
+    vm->fp->locals[0].value = *iterating_list;
+    vm->fp->locals[1].value = HVINT(0);
+    vm->fp->locals[2].value = *map_func;
+    vm->fp->locals[3].value = result;
   } else {
     /* get result of map function and append its result to result list */
     hVal *mapped = sbVm_pop(vm);
-    sbList_append(vm->fp->locals[3].list, mapped);
+    sbList_append(vm->fp->locals[3].value.list, mapped);
   }
 
-  usize current_index = vm->fp->locals[1].integer++;
+  usize current_index = vm->fp->locals[1].value.integer++;
   usize length;
-  hVal *iter_values = sbList_get_value(vm->fp->locals[0].list, &length);
+  sbVar *iter_values = sbList_get_value(vm->fp->locals[0].value.list, &length);
   if (current_index < length) {
-    sbVm_push(vm, &iter_values[current_index]);
+    sbVm_push(vm, sbVar_get_value_ptr(&iter_values[current_index]));
     sbVm_push_immediate(vm, &HVINT(1));
-    sbVm_call_func(vm, &vm->fp->locals[2]);
+    sbVm_call_func(vm, &vm->fp->locals[2].value);
     return CFUNC_NEXT;
   } else {
     /* return result list */
-    sbVm_push_immediate(vm, &vm->fp->locals[3]);
+    sbVm_push_immediate(vm, &vm->fp->locals[3].value);
     return CFUNC_END;
   }
 }
@@ -189,32 +189,32 @@ sbCFuncStatus list_filter_cfunc(hVm vm, flag init) {
     hVal index = HVINT(0);
     hVal result = sbV_empty_list(length);
 
-    vm->fp->locals[0] = *iterating_list;
-    vm->fp->locals[1] = index;
-    vm->fp->locals[2] = *filter_func;
-    vm->fp->locals[3] = result;
+    vm->fp->locals[0].value = *iterating_list;
+    vm->fp->locals[1].value = index;
+    vm->fp->locals[2].value = *filter_func;
+    vm->fp->locals[3].value = result;
   } else {
     /* get result of filter function and append element to result if true */
     hVal *mapped = sbVm_pop(vm);
     hVal *element = sbVm_pop(vm);
     if (!sbV_c_falsy(mapped)) {
-      sbList_append(vm->fp->locals[3].list, element);
+      sbList_append(vm->fp->locals[3].value.list, element);
     }
   }
 
-  usize current_index = vm->fp->locals[1].integer++;
+  usize current_index = vm->fp->locals[1].value.integer++;
   usize length;
-  hVal *iter_values = sbList_get_value(vm->fp->locals[0].list, &length);
+  sbVar *iter_values = sbList_get_value(vm->fp->locals[0].value.list, &length);
   if (current_index < length) {
     /* put current value on stack twice: once as parameter for function, once to save for ourselves */
-    sbVm_push(vm, &iter_values[current_index]);
-    sbVm_push(vm, &iter_values[current_index]);
+    sbVm_push(vm, sbVar_get_value_ptr(&iter_values[current_index]));
+    sbVm_push(vm, sbVar_get_value_ptr(&iter_values[current_index]));
     sbVm_push_immediate(vm, &HVINT(1));
-    sbVm_call_func(vm, &vm->fp->locals[2]);
+    sbVm_call_func(vm, &vm->fp->locals[2].value);
     return CFUNC_NEXT;
   } else {
     /* return result list */
-    sbVm_push_immediate(vm, &vm->fp->locals[3]);
+    sbVm_push_immediate(vm, &vm->fp->locals[3].value);
     return CFUNC_END;
   }
 }
@@ -230,29 +230,29 @@ sbCFuncStatus list_reduce_cfunc(hVm vm, flag init) {
     sbList_get_value(iterating_list->list, &length);
     hVal index = HVINT(0);
 
-    vm->fp->locals[0] = *iterating_list;
-    vm->fp->locals[1] = index;
-    vm->fp->locals[2] = *reduce_func;
-    vm->fp->locals[3] = *result;
+    vm->fp->locals[0].value = *iterating_list;
+    vm->fp->locals[1].value = index;
+    vm->fp->locals[2].value = *reduce_func;
+    vm->fp->locals[3].value = *result;
   } else {
     /* get result of reduce function */
     hVal *result = sbVm_pop(vm);
-    vm->fp->locals[3] = *result;
+    vm->fp->locals[3].value = *result;
   }
 
-  usize current_index = vm->fp->locals[1].integer++;
+  usize current_index = vm->fp->locals[1].value.integer++;
   usize length;
-  hVal *iter_values = sbList_get_value(vm->fp->locals[0].list, &length);
+  sbVar *iter_values = sbList_get_value(vm->fp->locals[0].value.list, &length);
   if (current_index < length) {
     /* put current result and new value on stack, then call callback function */
-    sbVm_push(vm, &vm->fp->locals[3]);
-    sbVm_push(vm, &iter_values[current_index]);
+    sbVm_push(vm, &vm->fp->locals[3].value);
+    sbVm_push(vm, sbVar_get_value_ptr(&iter_values[current_index]));
     sbVm_push_immediate(vm, &HVINT(2));
-    sbVm_call_func(vm, &vm->fp->locals[2]);
+    sbVm_call_func(vm, &vm->fp->locals[2].value);
     return CFUNC_NEXT;
   } else {
     /* return result */
-    sbVm_push_immediate(vm, &vm->fp->locals[3]);
+    sbVm_push_immediate(vm, &vm->fp->locals[3].value);
     return CFUNC_END;
   }
 }
@@ -265,9 +265,9 @@ sbCFuncStatus list_any_cfunc(hVm vm, flag init) {
     hVal *pred_func = sbVm_pop(vm);
     hVal index = HVINT(0);
 
-    vm->fp->locals[0] = *iterating_list;
-    vm->fp->locals[1] = index;
-    vm->fp->locals[2] = *pred_func;
+    vm->fp->locals[0].value = *iterating_list;
+    vm->fp->locals[1].value = index;
+    vm->fp->locals[2].value = *pred_func;
   } else {
     /* get result of predicate function */
     hVal *mapped = sbVm_pop(vm);
@@ -279,14 +279,14 @@ sbCFuncStatus list_any_cfunc(hVm vm, flag init) {
   }
 
   /* haven't found any yet... */
-  usize current_index = vm->fp->locals[1].integer++;
+  usize current_index = vm->fp->locals[1].value.integer++;
   usize length;
-  hVal *iter_values = sbList_get_value(vm->fp->locals[0].list, &length);
+  sbVar *iter_values = sbList_get_value(vm->fp->locals[0].value.list, &length);
   if (current_index < length) {
     /* try next element */
-    sbVm_push(vm, &iter_values[current_index]);
+    sbVm_push(vm, sbVar_get_value_ptr(&iter_values[current_index]));
     sbVm_push_immediate(vm, &HVINT(1));
-    sbVm_call_func(vm, &vm->fp->locals[2]);
+    sbVm_call_func(vm, &vm->fp->locals[2].value);
     return CFUNC_NEXT;
   } else {
     /* no result found */
@@ -303,9 +303,9 @@ sbCFuncStatus list_all_cfunc(hVm vm, flag init) {
     hVal *pred_func = sbVm_pop(vm);
     hVal index = HVINT(0);
 
-    vm->fp->locals[0] = *iterating_list;
-    vm->fp->locals[1] = index;
-    vm->fp->locals[2] = *pred_func;
+    vm->fp->locals[0].value = *iterating_list;
+    vm->fp->locals[1].value = index;
+    vm->fp->locals[2].value = *pred_func;
   } else {
     /* get result of predicate function */
     hVal *mapped = sbVm_pop(vm);
@@ -317,14 +317,14 @@ sbCFuncStatus list_all_cfunc(hVm vm, flag init) {
   }
 
   /* all true so far */
-  usize current_index = vm->fp->locals[1].integer++;
+  usize current_index = vm->fp->locals[1].value.integer++;
   usize length;
-  hVal *iter_values = sbList_get_value(vm->fp->locals[0].list, &length);
+  sbVar *iter_values = sbList_get_value(vm->fp->locals[0].value.list, &length);
   if (current_index < length) {
     /* try next element */
-    sbVm_push(vm, &iter_values[current_index]);
+    sbVm_push(vm, sbVar_get_value_ptr(&iter_values[current_index]));
     sbVm_push_immediate(vm, &HVINT(1));
-    sbVm_call_func(vm, &vm->fp->locals[2]);
+    sbVm_call_func(vm, &vm->fp->locals[2].value);
     return CFUNC_NEXT;
   } else {
     /* all passed */
index b994d95..8bf019e 100644 (file)
@@ -9,19 +9,17 @@ 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_REF,            // push reference 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_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
-  BC_LD_IND,            // push value behind pointer variable onto stack
   BC_LD_NIL,            // push nil onto stack
   BC_LD_TRUE,           // push true onto stack
   BC_LD_FALSE,          // push false onto stack
   BC_ST_VAR,            // pop value from stack into variable
   BC_ST_UPVAL,          // pop value from stack into closure
-  BC_ST_IND,            // pop and store as reference (closure/pointer construction)
   BC_ST_ARG,            // decrement TOS and store NOS in variable
-  BC_ST_ARG_IND,        // decrement TOS and store NOS in variable indirectly
   BC_POP,               // pop value from stack
   BC_NPOP,              // pop N values from stack given by top number
   BC_SWAP,              // swap top two values on stack
index 3ff238c..14df61f 100644 (file)
@@ -23,13 +23,11 @@ void print_stack(hVm vm);
 void sbVm_initialize(hVm vm, usize stacksize, usize rstacksize, flag debugmode) {
   *vm = (sbVm) {0};
   vm->vstack = malloc(stacksize);
-  vm->xstack = malloc(stacksize);
   vm->stacksize = stacksize;
   vm->rstack = malloc(rstacksize);
   vm->rstacksize = rstacksize;
 
   vm->vsp = vm->vstack;
-  vm->xsp = vm->xstack;
   vm->rsp = vm->rstack;
   vm->fp = (sbVmStackFrame*)vm->rstack;
 
@@ -38,7 +36,6 @@ void sbVm_initialize(hVm vm, usize stacksize, usize rstacksize, flag debugmode)
 
 void sbVm_deinitialize(hVm vm) {
   free(vm->vstack);
-  free(vm->xstack);
   free(vm->rstack);
   *vm = (sbVm) {0};
 }
@@ -183,7 +180,6 @@ void call_bound_method(hVm vm, hVal *to_call) {
 
   /* bound method is just a symbol + a closure containing one variable */
   hSymbol sym = (hSymbol)(to_call->type & ~IT_FLAG_BOUND_METHOD);
-  hRef ref = (to_call->ref);
 
   /* we should already have parameters, so we just need to line it back up
    * on the stack and call the method again */
@@ -193,7 +189,7 @@ void call_bound_method(hVm vm, hVal *to_call) {
     CHECK("bound method call should receive an integer arg count!");
   }
   peek_stack(vm, 0)->integer ++;
-  push_stack(vm, sbRef_deref(ref));
+  push_stack(vm, sbVar_get_attached_ref(to_call));
 
   /* resolve method normally */
   sbLib_resolve_method(vm);
@@ -201,16 +197,9 @@ void call_bound_method(hVm vm, hVal *to_call) {
 
 void return_from_block(hVm vm) {
   for (usize i = 0; i < vm->fp->num_locals; i++) {
-    sbV_release(&vm->fp->locals[i]);
+    sbV_release(&vm->fp->locals[i].value);
   }
 
-  /* move thing that is being returned to the xstack: if we were
-   * originally returning a local variable, we don't want it to get
-   * overwritten by a subsequent function call (and if we were
-   * already returning an immediate value, it does nothing) */
-  ((hVal*)(vm->xsp))[-1] = *((hVal**)(vm->vsp))[-1];
-  ((hVal**)(vm->vsp))[-1] = &((hVal*)(vm->xsp))[-1];
-
   sbVmStackFrame *frame = (sbVmStackFrame*)vm->fp;
 
   if (frame->return_addr == NULL) {
@@ -228,75 +217,40 @@ void debug_print_hv(const hVal *value) {
 }
 
 void store_local(hVm vm, usize local_index, const hVal *value) {
-  /* release whatever was in the slot before */
-  sbV_release(&vm->fp->locals[local_index]);
-  sbV_retain(value);
-  vm->fp->locals[local_index] = *value;
+  sbVar_set_value(&vm->fp->locals[local_index], value);
 }
 
 void push_stack(hVm vm, hVal *value) {
-  *(hVal**)vm->vsp = value;
+  *(hVal*)vm->vsp = *value;
   vm->vsp += sizeof(hVal*);
-  vm->xsp += sizeof(hVal);
 }
 
 void push_stack_immediate(hVm vm, const hVal *value) {
-  /* save it on our own stack */
-  *(hVal*)vm->xsp = *value;
-  *(hVal**)vm->vsp = (hVal*)vm->xsp;
+  *(hVal*)vm->vsp = *value;
   vm->vsp += sizeof(hVal*);
-  vm->xsp += sizeof(hVal);
 }
 
 hVal *pop_stack(hVm vm) {
   vm->vsp -= sizeof(hVal*);
-  vm->xsp -= sizeof(hVal);
-  return *(hVal**)vm->vsp;
+  return (hVal*)vm->vsp;
 }
 
 hVal *npop_stack(hVm vm, usize count) {
   vm->vsp -= count * sizeof(hVal*);
-  vm->xsp -= count * sizeof(hVal);
-  return *(hVal**)vm->vsp;
+  return (hVal*)vm->vsp;
 }
 
 void swap_stack_top(hVm vm) {
-  hVal **first_v = &((hVal**)vm->vsp)[-1];
-  hVal **second_v = &((hVal**)vm->vsp)[-2];
-  hVal *first_x = &((hVal*)vm->xsp)[-1];
-  hVal *second_x = &((hVal*)vm->xsp)[-2];
-
-  /* if we're swapping things that are allocated on the x-stack,
-   * we have to swap their pointers as well so we don't accidentally
-   * overwrite what they're pointing to. but if they're pointing
-   * somewhere else, we don't care */
-
-  /* x2 x1    &v2 &v1 (might be &x2 &x1)*/
-
-  hVal xtmp = *second_x;
-  if (*first_v == first_x) {
-                          /* x2a x1a   &v2  &x1a */
-    *second_x = *first_x; /* x1b x1a   &v2  &x1a */
-    *first_v = second_x;  /* x1b x1a   &v2  &x1b */
-  }
-
-  if (*second_v == second_x) {
-                          /* x2a x1a   &x2a &v1  */
-    *first_x = xtmp;      /* x2a x2b   &x2a &v1  */
-    *second_v = first_x;  /* x2a x2b   &x2b &v1  */
-  }
+  hVal *first_v = &((hVal*)vm->vsp)[-1];
+  hVal *second_v = &((hVal*)vm->vsp)[-2];
 
-  hVal *vtmp = *first_v;    /* x2  x1    &v2  &v1  */
-  *first_v = *second_v;   /* x2  x1    &v2  &v2  */
-  *second_v = vtmp;       /* x2  x1    &v1  &v2  */
+  hVal tmp = *first_v;   /* x2  x1    &v2  &v1  */
+  *first_v = *second_v;  /* x2  x1    &v2  &v2  */
+  *second_v = tmp;       /* x2  x1    &v1  &v2  */
 }
 
 hVal *peek_stack(hVm vm, isize offset) {
-  return ((hVal**)(vm->vsp))[-offset - 1];
-}
-
-hVal *peek_xstack(hVm vm, isize offset) {
-  return &((hVal*)(vm->xsp))[-offset - 1];
+  return &((hVal*)(vm->vsp))[-offset - 1];
 }
 
 sbOpcode get_opcode(hVm vm) {
@@ -373,6 +327,7 @@ void execute_instruction(hVm vm) {
   u64 param;
   usize count;
   hVal *v, *w, *x, res;
+  sbVar *vars;
 
   switch (op) {
     case BC_NOP:
@@ -395,42 +350,33 @@ void execute_instruction(hVm vm) {
       break;
     case BC_LD_VAR:
       param = get_param(vm);
-      push_stack(vm, &vm->fp->locals[param]);
+      res = sbVar_get_value(&vm->fp->locals[param]);
+      push_stack(vm, &res);
       break;
-    case BC_LD_REF:
+    case BC_LD_LREF:
       param = get_param(vm);
-      w = &vm->fp->locals[param];
-      if (w->type == IT_NOTHING) {
-        /* create new ref */
-        store_local(vm, param, &HVREF(sbRef_create(&HVNIL)));
-        w = &vm->fp->locals[param];
-      }
-      push_stack(vm, w);
+      res = sbVar_get_lvalue_ref(&vm->fp->locals[param]);
+      push_stack(vm, &res);
+      break;
+    case BC_LD_RREF:
+      param = get_param(vm);
+      res = sbVar_get_rvalue_ref(&vm->fp->locals[param]);
+      push_stack(vm, &res);
       break;
     case BC_LD_UPVAL:
       /* Hey, was there upval in there? */
       param = get_param(vm);
-      v = sbClosure_get_var(vm->fp->block_func.closure, param);
-      push_stack(vm, v);
+      res = sbClosure_get_value(vm->fp->block_func.closure, param);
+      push_stack(vm, &res);
       break;
     case BC_LD_UPREF:
       param = get_param(vm);
-      res = sbClosure_get_ref(vm->fp->block_func.closure, param);
-      push_stack_immediate(vm, &res);
+      push_stack(vm, &HVREF(sbClosure_get_var(vm->fp->block_func.closure, param)));
       break;
     case BC_LD_BLK:
       param = get_param(vm);
       push_stack_immediate(vm, &HVFUNC(param, 0));
       break;
-    case BC_LD_IND:
-      param = get_param(vm);
-      v = &vm->fp->locals[param];
-      if (v->type != IT_REF) {
-        CHECK("indirect variables should be of type reference! (%lld)", (long long)v->type);
-      }
-      w = sbRef_deref(v->ref);
-      push_stack(vm, w);
-      break;
     case BC_LD_TRUE:
       push_stack_immediate(vm, &HVBOOL(1));
       break;
@@ -449,21 +395,7 @@ void execute_instruction(hVm vm) {
     case BC_ST_UPVAL:
       param = get_param(vm);
       v = pop_stack(vm);
-      sbClosure_set_var(vm->fp->block_func.closure, param, v);
-      break;
-    case BC_ST_IND:
-      param = get_param(vm);
-      v = &vm->fp->locals[param];
-      w = peek_stack(vm, 0);
-      if (v->type == IT_NOTHING) {
-        hRef new_ref = sbRef_create(w);
-        store_local(vm, param, &HVREF(new_ref));
-      } else if (v->type == IT_REF) {
-        sbRef_set_ref(v->ref, w);
-      } else {
-        CHECK("indirect variables should be of type reference! (%lld)", (long long)v->type);
-      }
-      pop_stack(vm);
+      sbClosure_set_value(vm->fp->block_func.closure, param, v);
       break;
     case BC_ST_ARG:
       param = get_param(vm);
@@ -481,31 +413,6 @@ void execute_instruction(hVm vm) {
         push_stack_immediate(vm, v);
       }
       break;
-    case BC_ST_ARG_IND:
-      param = get_param(vm);
-      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");
-      }
-
-      v = &vm->fp->locals[param];
-      w = peek_stack(vm, 0); /* argument value */
-      if (v->type == IT_NOTHING) {
-        hRef new_ref = sbRef_create(w);
-        store_local(vm, param, &HVREF(new_ref));
-      } else if (v->type == IT_REF) {
-        sbRef_set_ref(v->ref, w);
-      } else {
-        CHECK("indirect variables should be of type reference! (%lld)", (long long)v->type);
-      }
-      pop_stack(vm);
-      x->integer --;
-      if (x->integer > 0) {
-        /* if last integer, don't put the 0 count back on the stack */
-        push_stack(vm, x);
-      }
-      break;
     case BC_POP:
       pop_stack(vm);
       break;
@@ -684,7 +591,7 @@ void execute_instruction(hVm vm) {
         if (w->type != IT_REF) {
           CHECK("internal violation: closure should receive a set of reference variables (got %lld)", (long long)w->type);
         }
-        sbClosure_set_ref(c, param, w);
+        sbClosure_set_var(c, param, sbVar_deref(w));
         pop_stack(vm);
       }
       v->closure = c;
@@ -735,9 +642,9 @@ void execute_instruction(hVm vm) {
         /* internal error! this should be generated correctly */
         CHECK("internal violation: LIST_SPILL should receive an integer on top of stack");
       }
-      x = sbList_get_value(v->list, &count);
+      vars = sbList_get_value(v->list, &count);
       for (usize i = count - 1; ; i--) {
-        push_stack(vm, &x[i]);
+        push_stack(vm, &vars[i].value);
         if (i == 0) break;
       }
       res.integer += count;
index b3b143e..86e8564 100644 (file)
@@ -63,18 +63,16 @@ typedef struct sbVmStackFrame {
     sbRuntimeCFunc c_func;
   };
   usize num_locals;
-  hVal locals[];
+  sbVar locals[];
 } sbVmStackFrame;
 
 typedef struct sbVm {
   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 *vsp;            /* vstack pointer */
-  u8 *xsp;            /* xstack pointer */
   u8 *rsp;            /* rstack pointer */
 
   usize stacksize;    /* to detect overflow, save these */
index 7626a5c..d299bfe 100644 (file)
@@ -127,13 +127,13 @@ hVal sbV_append(hVal *a, hVal *b) {
   }
 }
 
-void sbV_index(hVm vm) {
+void sbV_index_value(hVm vm) {
   hVal *a = sbVm_peek(vm, 1);
   hVal *b = sbVm_peek(vm, 0);
   if (a->type == IT_LIST && b->type == IT_INTEGER) {
     sbVm_npop(vm, 2);
-    hVal *result = sbList_index(a->list, b->integer);
-    sbVm_push(vm, result);
+    hVal result = sbList_index_value(a->list, b->integer);
+    sbVm_push(vm, &result);
   } else if (a->type == IT_MODULE && b->type == IT_SYMBOL) {
     sbVm_npop(vm, 2);
     hVal *result = sbLibTable_find_value(a->module, b->symbol);
@@ -154,7 +154,7 @@ hVal sbV_rangeindex(hVal *a, hVal *b, hVal *c) {
     i64 min = sbInteger_get_value(b->integer);
     i64 max = sbInteger_get_value(c->integer);
     if (a->type == IT_LIST) {
-      hVal *elements = sbList_get_value(a->list, &length);
+      sbVar *elements = sbList_get_value(a->list, &length);
       if (min >= max || min >= length || max < 0) {
         /* backwards or out of range */
         return sbV_empty_list(0);