static sbIrExpr SENTINEL_NIL_EXPR = {
.type = IR_E_VALUE,
- .value = (hV) { .type = IT_NIL }
+ .value = (hVal) { .type = IT_NIL }
};
static sbIrStmt SENTINEL_NO_STMT = {0};
static sbIrVariable SENTINEL_NO_VAR = {0};
});
}
-static sbIrExpr *expr_value(hIrChunk ck, hV *value) {
+static sbIrExpr *expr_value(hIrChunk ck, hVal *value) {
return new_expr(ck, &(sbIrExpr) {
.type = IR_E_VALUE,
.value = *value,
typedef struct sbIrExpr {
sbIrExprType type;
union {
- hV value;
+ hVal value;
sbIrVariable *var;
hSymbol symbol;
struct {
}
/* set the variable in the closure behind the pointer */
-void sbClosure_set_var(hClosure which, usize index, hV *what) {
+void sbClosure_set_var(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);
}
/* set the pointer itself */
-void sbClosure_set_ref(hClosure which, usize index, hV *what) {
+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");
}
}
}
-hV *sbClosure_get_var(hClosure which, usize index) {
+hVal *sbClosure_get_var(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]);
}
}
-hV sbClosure_get_ref(hClosure which, usize index) {
+hVal sbClosure_get_ref(hClosure which, usize index) {
sbClosure *c = find_closure_by_handle(which);
if (c->num_vars <= INLINE_VAR_COUNT) {
return HVREF(c->internal_vars[index]);
hClosure sbClosure_create(usize num_vars);
-void sbClosure_set_var(hClosure which, usize index, hV *var);
+void sbClosure_set_var(hClosure which, usize index, hVal *var);
-void sbClosure_set_ref(hClosure which, usize index, hV *what);
+void sbClosure_set_ref(hClosure which, usize index, hVal *what);
-hV *sbClosure_get_var(hClosure which, usize index);
+hVal *sbClosure_get_var(hClosure which, usize index);
-hV sbClosure_get_ref(hClosure which, usize index);
+hVal sbClosure_get_ref(hClosure which, usize index);
flag is_inline;
union {
struct {
- hV keys[INLINE_TABLE_LENGTH];
- hV values[INLINE_TABLE_LENGTH];
+ hVal keys[INLINE_TABLE_LENGTH];
+ hVal values[INLINE_TABLE_LENGTH];
} internal;
struct {
- hV *keys;
- hV *values;
+ hVal *keys;
+ hVal *values;
} external;
};
} hashtbl;
static hashtbl *new_tbl(usize initial_size);
-static hV *get_key_ptr_for_tbl(hashtbl *t, usize *length_out);
-static void get_ptrs_for_tbl(hashtbl *t, hV **keys, hV **values);
+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 hashtbl *find_tbl_for_handle(hHash handle);
-static usize set_key(hashtbl *t, hV *key, hV *value);
-static hV delete_key(hashtbl *t, hV *key);
+static usize set_key(hashtbl *t, hVal *key, hVal *value);
+static hVal delete_key(hashtbl *t, hVal *key);
static void set_hashtbl_size(hashtbl *t, usize new_size, flag rehash_all);
-static usize set_key_in_array(hV *keys, hV *values, usize length, hV *key, hV *value);
-static usize find_index_by_key(hashtbl *t, hV *key);
+static usize set_key_in_array(hVal *keys, hVal *values, usize length, hVal *key, hVal *value);
+static usize find_index_by_key(hashtbl *t, hVal *key);
void sbHash_sys_init() {
sbPool_initialize(&g_hashtable_pool, sizeof(hashtbl), HASHES_PER_BLOCK);
return result;
}
-flag is_flatly_hashable(hV *obj) {
+flag is_flatly_hashable(hVal *obj) {
return obj->type == IT_NIL
|| obj->type == IT_BOOLEAN
|| obj->type == IT_INTEGER /* todo: wrong for bigints */
|| obj->type == IT_SYMBOL;
}
-sbHashValue sbHash_hash_obj(hV *obj) {
+sbHashValue sbHash_hash_obj(hVal *obj) {
if (is_flatly_hashable(obj)) {
return sbHash_hash_bytes((char*)obj, sizeof(*obj));
} else if (obj->type == IT_STRING) {
return t->handle;
}
-void sbHash_insert(hHash h, hV *key, hV *value) {
+void sbHash_insert(hHash h, hVal *key, hVal *value) {
hashtbl *t = find_tbl_for_handle(h);
set_key(t, key, value);
}
-hV *sbHash_find(hHash h, hV *key) {
+hVal *sbHash_find(hHash h, hVal *key) {
hashtbl *t = find_tbl_for_handle(h);
usize index = find_index_by_key(t, key);
- hV *keys, *values;
+ hVal *keys, *values;
get_ptrs_for_tbl(t, &keys, &values);
if (keys[index].type == IT_NOTHING) {
return NULL;
}
}
-hV *sbHash_find_or_insert(hHash h, hV *key, hV *value) {
+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);
- hV *keys, *values;
+ hVal *keys, *values;
get_ptrs_for_tbl(t, &keys, &values);
if (keys[index].type == IT_NOTHING) {
values[index] = *value;
return &values[index];
}
-void sbHash_delete(hHash h, hV *key, hV *value) {
+void sbHash_delete(hHash h, hVal *key, hVal *value) {
hashtbl *t = find_tbl_for_handle(h);
delete_key(t, key);
}
if (new_size == INLINE_TABLE_LENGTH) {
t->is_inline = 1;
} else {
- hV *new_keys = calloc(new_size, sizeof(hV));
- hV *new_values = calloc(new_size, sizeof(hV));
+ hVal *new_keys = calloc(new_size, sizeof(hVal));
+ hVal *new_values = calloc(new_size, sizeof(hVal));
if (rehash_all) {
- hV *current_keys, *current_values;
+ hVal *current_keys, *current_values;
get_ptrs_for_tbl(t, ¤t_keys, ¤t_values);
for (usize i = 0; i < t->capacity; i++) {
if (current_keys[i].type == IT_NOTHING || current_keys[i].type == ITX_TOMBSTONE) continue;
t->capacity = new_size;
}
-static hV *get_key_ptr_for_tbl(hashtbl *t, usize *length_out) {
+static hVal *get_key_ptr_for_tbl(hashtbl *t, usize *length_out) {
if (length_out) *length_out = t->capacity;
if (t->is_inline) {
return t->internal.keys;
}
}
-static void get_ptrs_for_tbl(hashtbl *t, hV **keys, hV **values) {
+static void get_ptrs_for_tbl(hashtbl *t, hVal **keys, hVal **values) {
if (t->is_inline) {
if (keys) *keys = t->internal.keys;
if (values) *values = t->internal.values;
}
}
-static usize find_key_index_in_array(hV *keys, usize length, hV *key) {
+static usize find_key_index_in_array(hVal *keys, usize length, hVal *key) {
sbHashValue hash = sbHash_hash_obj(key);
u32 start = (hash & 0xFFFFFFFF);
u32 move = (hash >> 32);
return index;
}
-static usize find_index_by_key(hashtbl *t, hV *key) {
+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(hV *keys, hV *values, usize length, hV *key, hV *value) {
+static usize set_key_in_array(hVal *keys, hVal *values, usize length, hVal *key, hVal *value) {
usize index = find_key_index_in_array(keys, length, key);
/* now, we either found the current entry for this key,
return index;
}
-static usize set_key(hashtbl *t, hV *key, hV *value) {
+static usize set_key(hashtbl *t, hVal *key, hVal *value) {
usize index = find_index_by_key(t, key);
- hV *keys, *values;
+ hVal *keys, *values;
get_ptrs_for_tbl(t, &keys, &values);
/* now, we either found the current entry for this key,
return index;
}
-static hV delete_key(hashtbl *t, hV *key) {
+static hVal delete_key(hashtbl *t, hVal *key) {
usize index = find_index_by_key(t, key);
- hV *keys, *values;
+ hVal *keys, *values;
get_ptrs_for_tbl(t, &keys, &values);
- hV to_return = values[index];
+ hVal to_return = values[index];
keys[index].type = ITX_TOMBSTONE;
t->n_elems --;
return to_return;
sbHashValue sbHash_hash_bytes(const char *bytes, usize length);
-sbHashValue sbHash_hash_obj(hV *obj);
+sbHashValue sbHash_hash_obj(hVal *obj);
hHash sbHash_create(usize initial_size);
-hV *sbHash_find(hHash h, hV *key);
+hVal *sbHash_find(hHash h, hVal *key);
-void sbHash_insert(hHash h, hV *key, hV *value);
+void sbHash_insert(hHash h, hVal *key, hVal *value);
-hV *sbHash_find_or_insert(hHash h, hV *key, hV *value);
+hVal *sbHash_find_or_insert(hHash h, hVal *key, hVal *value);
-void sbHash_delete(hHash h, hV *key, hV *value);
+void sbHash_delete(hHash h, hVal *key, hVal *value);
usize sbHash_get_size(hHash h);
usize index;
sbList *l = sbPool_alloc(&g_list_pool, &index);
if (capacity < 4) capacity = 4;
- sbBuffer_initialize(&l->items, capacity * sizeof(hV));
+ sbBuffer_initialize(&l->items, capacity * sizeof(hVal));
return index;
}
-hList sbList_of(usize length, hV *items) {
+hList sbList_of(usize length, hVal *items) {
usize index;
usize capacity = length;
sbList *l = sbPool_alloc(&g_list_pool, &index);
if (capacity < 4) capacity = 4;
- sbBuffer_initialize(&l->items, capacity * sizeof(hV));
- sbBuffer_set_size(&l->items, length * sizeof(hV));
- memcpy(l->items.data, items, length * sizeof(hV));
+ sbBuffer_initialize(&l->items, capacity * sizeof(hVal));
+ sbBuffer_set_size(&l->items, length * sizeof(hVal));
+ memcpy(l->items.data, items, length * sizeof(hVal));
return index;
}
-void sbList_append(hList list, hV *item) {
+void sbList_append(hList list, hVal *item) {
sbList *l = get_list_by_handle(list);
sbV_retain(item);
- sbBuffer_append(&l->items, item, sizeof(hV));
+ sbBuffer_append(&l->items, item, sizeof(hVal));
}
-hV *sbList_get_value(hList list, usize *length) {
+hVal *sbList_get_value(hList list, usize *length) {
sbList *l = get_list_by_handle(list);
- if (length) *length = l->items.size / sizeof(hV);
- return (hV*)l->items.data;
+ if (length) *length = l->items.size / sizeof(hVal);
+ return (hVal*)l->items.data;
}
-hV *sbList_index(hList list, usize index) {
+hVal *sbList_index(hList list, usize index) {
sbList *l = get_list_by_handle(list);
- hV *item = &((hV*)l->items.data)[index];
+ hVal *item = &((hVal*)l->items.data)[index];
return item;
}
hList sbList_new(usize capacity);
-hList sbList_of(usize length, hV *items);
+hList sbList_of(usize length, hVal *items);
-void sbList_append(hList list, hV *item);
+void sbList_append(hList list, hVal *item);
-hV *sbList_get_value(hList list, usize *length);
+hVal *sbList_get_value(hList list, usize *length);
-hV *sbList_index(hList list, usize index);
+hVal *sbList_index(hList list, usize index);
void sbList_method(hVm vm);
typedef struct sbRef {
GCINFO info;
- hV pointed_to;
+ hVal pointed_to;
} sbRef;
static sbRef *find_ref_by_handle(hRef handle);
//sbPool_deinitialize(&g_reference_pool);
}
-hRef sbRef_create(hV *var) {
+hRef sbRef_create(hVal *var) {
usize index;
sbRef *r = sbPool_alloc(&g_reference_pool, &index);
sbV_retain(var);
return index;
}
-void sbRef_set_ref(hRef ref, hV *var) {
+void sbRef_set_ref(hRef ref, hVal *var) {
sbRef *value = find_ref_by_handle(ref);
sbV_release(&value->pointed_to);
sbV_retain(var);
value->pointed_to = *var;
}
-hV *sbRef_deref(hRef ref) {
+hVal *sbRef_deref(hRef ref) {
sbRef *value = find_ref_by_handle(ref);
return &value->pointed_to;
}
void sbRef_sys_deinit();
-hRef sbRef_create(hV *var);
+hRef sbRef_create(hVal *var);
-void sbRef_set_ref(hRef ref, hV *var);
+void sbRef_set_ref(hRef ref, hVal *var);
-hV *sbRef_deref(hRef ref);
+hVal *sbRef_deref(hRef ref);
}
void sbString_method(hVm vm) {
- hV *target = sbVm_pop(vm);
+ hVal *target = sbVm_pop(vm);
if (target->type != IT_STRING) {
CHECK("can't call sbString_method on something that isn't a string");
}
- hV *argc = sbVm_pop(vm);
+ hVal *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;
- hV *method_name_val = sbVm_peek(vm, num_params);
+ hVal *method_name_val = sbVm_peek(vm, num_params);
if (method_name_val->type != IT_SYMBOL) {
/* TODO this may become not true */
PANIC("method name for string must be symbol!");
hSymbol new_symbol(const char *name, usize length);
hSymbol sbSymbol_from_bytes(const char *text, usize length) {
- hV symkey = {
+ hVal symkey = {
.type = IT_STRING,
.string = sbString_new(text, length),
};
- hV *result = sbHash_find(symbol_table, &symkey);
+ hVal *result = sbHash_find(symbol_table, &symkey);
if (result == NULL) {
/* add new symbol */
- hV symval = {
+ hVal symval = {
.type = IT_SYMBOL,
.symbol = new_symbol(text, length),
};
#define FLAG_NONINTRINSIC (1ULL << 63)
-hV sbV_nil() {
- return (hV) {0};
-}
-
-hV sbV_boolean(flag value) {
- return (hV) {
- .type = IT_BOOLEAN,
- .boolean = (value == 0) ? 0 : 1,
- };
-}
-
-hV sbV_string(hString str) {
- return (hV) {
- .type = IT_STRING,
- .string = str,
- };
-}
-
-hV sbV_symbol(hSymbol sym) {
- return (hV) {
- .type = IT_SYMBOL,
- .symbol = sym,
- };
-}
-
-hV sbV_float(double fl) {
- return (hV) {
- .type = IT_FLOAT,
- .float_val = fl,
- };
-}
-
-hV sbV_hash(hHash hash) {
- return (hV) {
- .type = IT_HASH,
- .hash = hash,
- };
-}
-
-hV sbV_int(hInteger i) {
- return (hV) {
- .type = IT_INTEGER,
- .integer = i,
- };
-}
-
-hV sbV_empty_list(usize capacity) {
- return (hV) {
+hVal sbV_empty_list(usize capacity) {
+ return (hVal) {
.type = IT_LIST,
.list = sbList_new(capacity),
};
}
-hV sbV_empty_hash(usize capacity) {
- return (hV) {
+hVal sbV_empty_hash(usize capacity) {
+ return (hVal) {
.type = IT_HASH,
.hash = sbHash_create(capacity),
};
}
-hV sbV_empty_string() {
- return sbV_string((hString)0);
+hVal sbV_empty_string() {
+ return HVSTR((hString)0);
}
-flag sbV_c_eq(const hV *a, const hV *b) {
+flag sbV_c_eq(const hVal *a, const hVal *b) {
if (a->type != b->type) return FALSE;
if (a->type == ITX_TOMBSTONE || b->type == ITX_TOMBSTONE) return FALSE;
if (a->type == IT_NOTHING || b->type == IT_NOTHING) return FALSE;
}
}
-flag sbV_c_falsy(const hV *a) {
+flag sbV_c_falsy(const hVal *a) {
/* only nil and boolean false are false */
if (a->type == IT_NIL) return TRUE;
if (a->type == IT_BOOLEAN && !a->boolean) return TRUE;
return FALSE;
}
-void sbV_retain(const hV *a) {
+void sbV_retain(const hVal *a) {
/* for some classes (e.g. nil, float), we don't need to retain them at all
* because they are trivially copiable. some classes (integer, string) need
* to sometimes be retained but sometimes not, so we delegate to them to
}
}
-void sbV_release(const hV *a) {
+void sbV_release(const hVal *a) {
switch (a->type) {
case IT_STRING:
sbString_release(a->string);
/* --- */
-flag val_is_intrinsic(hV val) {
+flag val_is_intrinsic(hVal val) {
return (val.type & FLAG_NONINTRINSIC) != 0;
}
#define IT_FLAG_BOUND_METHOD (1ULL << 62)
-#define HVINT(n) ((hV) { .type = IT_INTEGER, .integer = n })
-#define HVFLOAT(f) ((hV) { .type = IT_FLOAT, .float_val = f })
-#define HVSTR(s) ((hV) { .type = IT_STRING, .string = s })
-#define HVSYM(s) ((hV) { .type = IT_SYMBOL, .symbol = s })
-#define HVBOOL(b) ((hV) { .type = IT_BOOLEAN, .boolean = b })
-#define HVLIST(l) ((hV) { .type = IT_LIST, .list = l })
-#define HVREF(r) ((hV) { .type = IT_REF, .ref = r })
-#define HVNIL ((hV) { .type = IT_NIL })
-#define HVNOTHING ((hV) {0})
-#define HVFUNC(i, c) ((hV) { .type = i, .closure = c })
-#define HVBUILTIN(b) ((hV) { .type = IT_BUILTIN, .builtin = b })
-#define HVBOUNDMETHOD(m, t) ((hV) { .type = m | IT_FLAG_BOUND_METHOD, .ref = t })
-#define HVMODULE(m) ((hV) { .type = IT_MODULE, .module = m })
+#define HVINT(n) ((hVal) { .type = IT_INTEGER, .integer = n })
+#define HVFLOAT(f) ((hVal) { .type = IT_FLOAT, .float_val = f })
+#define HVSTR(s) ((hVal) { .type = IT_STRING, .string = s })
+#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 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 HVMODULE(m) ((hVal) { .type = IT_MODULE, .module = m })
struct sbVm;
struct sbLibTable;
ITX_TOMBSTONE = -13, // <hashtable_tombstone>
};
-typedef struct hV {
+typedef struct hVal {
i64 type;
union {
hString string;
struct sbLibTable *module;
u64 data;
};
-} hV;
+} hVal;
-hV sbV_nil();
-hV sbV_string(hString str);
-hV sbV_symbol(hSymbol sym);
-hV sbV_float(double fl);
-hV sbV_hash(hHash hash);
-hV sbV_int(hInteger i);
-hV sbV_boolean(flag b);
-hV sbV_empty_list(usize capacity);
-hV sbV_empty_hash(usize capacity);
-hV sbV_empty_string();
+hVal sbV_empty_list(usize capacity);
+hVal sbV_empty_hash(usize capacity);
+hVal sbV_empty_string();
-flag sbV_c_eq(const hV *a, const hV *b);
-flag sbV_c_falsy(const hV *a);
+flag sbV_c_eq(const hVal *a, const hVal *b);
+flag sbV_c_falsy(const hVal *a);
-void sbV_retain(const hV *a);
-void sbV_release(const hV *a);
+void sbV_retain(const hVal *a);
+void sbV_release(const hVal *a);
#endif
#include "lib/method.h"
#include "lib/module.h"
-static sbLibTable *find_method_table(hV *target);
+static sbLibTable *find_method_table(hVal *target);
static sbCFuncStatus please_call_again(hVm vm, flag init);
void sbLib_sys_init() {
}
void sbLib_resolve_method(hVm vm) {
- hV *target = sbVm_pop(vm);
- hV *argc = sbVm_pop(vm);
+ hVal *target = sbVm_pop(vm);
+ hVal *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;
- hV *method_name_val = sbVm_pop(vm);
+ hVal *method_name_val = sbVm_pop(vm);
if (method_name_val->type != IT_SYMBOL) {
PANIC("method name must be symbol!");
}
* (non-intrinsic types are always functions, so they can be resolved just by
* calling them)*/
void sbLib_resolve_property(hVm vm) {
- hV *target = sbVm_pop(vm);
- hV *argc = sbVm_pop(vm);
+ hVal *target = sbVm_pop(vm);
+ hVal *argc = sbVm_pop(vm);
if (argc->type != IT_INTEGER) {
CHECK("argc of send should be integer!");
}
PANIC("Illegal number of arguments!");
}
- hV *method_name_val = sbVm_pop(vm);
+ hVal *method_name_val = sbVm_pop(vm);
if (method_name_val->type != IT_SYMBOL) {
PANIC("method name must be symbol! (is %lld, target %lld)", (long long)method_name_val->type, (long long)target->type);
}
}
void sbLib_resolve_global(hVm vm) {
- hV *target = sbVm_pop(vm);
+ hVal *target = sbVm_pop(vm);
if (target->type != IT_SYMBOL) {
CHECK("global lookup must be symbol!");
}
- hV *v = sbLibTable_find_value(&g_global_module, target->symbol);
+ hVal *v = sbLibTable_find_value(&g_global_module, target->symbol);
if (v) {
sbVm_push_immediate(vm, v);
} else {
/* --- */
/* function that looks up something in a built-in method table */
-static sbLibTable *find_method_table(hV *target) {
+static sbLibTable *find_method_table(hVal *target) {
switch(target->type) {
case IT_LIST:
return &g_list_methods;
/* we have something like a.b(c,d,e), we need to call twice to get result of a(:b)(c,d,e) */
/* resolve_method should have set us up so we can just call in twice */
static sbCFuncStatus please_call_again(hVm vm, flag init) {
- hV *target = sbVm_pop(vm);
+ hVal *target = sbVm_pop(vm);
if (target->type <= 0) {
PANIC("i have not implemented partial methods for builtin types yet! i'll get to it");
}
#define PROPERTY(f) (sbLibMethod) { .behavior = f, .is_property = TRUE }
typedef struct sbLibMethod {
- void (*behavior)(hVm, hV*, usize);
+ void (*behavior)(hVm, hVal*, usize);
flag is_property : 1;
i16 min_args : 15;
i16 max_args;
sbLibTable g_float_methods;
-static void to_string(hVm vm, hV *target, usize num_params) {
+static void to_string(hVm vm, hVal *target, usize num_params) {
char stackbuf[1024];
char *buf = stackbuf;
usize length = snprintf(buf, 1024, "%g", target->float_val);
sbLibTable g_hash_methods;
-static void to_hash(hVm vm, hV *target, usize num_params) {
+static void to_hash(hVm vm, hVal *target, usize num_params) {
/* to_hash for a hash just returns itself */
sbVm_push_immediate(vm, target);
}
-static void length(hVm vm, hV *target, usize num_params) {
+static void length(hVm vm, hVal *target, usize num_params) {
usize length = sbHash_get_size(target->hash);
sbVm_push_immediate(vm, &HVINT(length));
}
-static void get_index(hVm vm, hV *target, usize num_params) {
- hV *key = sbVm_pop(vm);
- hV *result = sbHash_find(target->hash, key);
+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) {
sbVm_push_immediate(vm, &HVNIL);
} else {
sbLibTable g_integer_methods;
-static void to_string(hVm vm, hV *target, usize num_params) {
+static void to_string(hVm vm, hVal *target, usize num_params) {
char stackbuf[1024];
char *buf = stackbuf;
usize length = sbInteger_snprint(buf, 1024, target->integer);
sbLibTable g_list_methods;
-static void length(hVm vm, hV *list, usize num_params) {
+static void length(hVm vm, hVal *list, usize num_params) {
usize length;
sbList_get_value(list->list, &length);
sbVm_push_immediate(vm, &HVINT(length));
}
-static void push(hVm vm, hV *list, usize num_params) {
- hV *to_append = sbVm_pop(vm);
+static void push(hVm vm, hVal *list, usize num_params) {
+ hVal *to_append = sbVm_pop(vm);
sbList_append(list->list, to_append);
sbVm_push_immediate(vm, &HVNIL);
}
-static void reverse(hVm vm, hV *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;
- hV *elems = sbList_get_value(list->list, &length);
+ hVal *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]);
sbVm_push_immediate(vm, &HVLIST(new_list));
}
-static void join(hVm vm, hV *list, usize num_params) {
+static void join(hVm vm, hVal *list, usize num_params) {
flag join_with = FALSE;
hString delimiter;
if (num_params == 1) {
- hV *delimiter_v = sbVm_pop(vm);
+ hVal *delimiter_v = sbVm_pop(vm);
if (delimiter_v->type != IT_STRING) {
PANIC("list#join parameter should be string!");
}
delimiter = delimiter_v->string;
}
usize length;
- hV *elems = sbList_get_value(list->list, &length);
+ hVal *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) {
sbVm_push_immediate(vm, &HVSTR(joined));
}
-static void each(hVm vm, hV *list, usize num_params) {
+static void each(hVm vm, hVal *list, usize num_params) {
sbVm_push_immediate(vm, list);
sbVm_call_c_func(vm, list_each_cfunc);
}
-static void map(hVm vm, hV *list, usize num_params) {
+static void map(hVm vm, hVal *list, usize num_params) {
sbVm_push_immediate(vm, list);
sbVm_call_c_func(vm, list_map_cfunc);
}
-static void filter(hVm vm, hV *list, usize num_params) {
+static void filter(hVm vm, hVal *list, usize num_params) {
sbVm_push_immediate(vm, list);
sbVm_call_c_func(vm, list_filter_cfunc);
}
-static void reduce(hVm vm, hV *list, usize num_params) {
+static void reduce(hVm vm, hVal *list, usize num_params) {
sbVm_push_immediate(vm, list);
sbVm_call_c_func(vm, list_reduce_cfunc);
}
-static void any_p(hVm vm, hV *list, usize num_params) {
+static void any_p(hVm vm, hVal *list, usize num_params) {
sbVm_push_immediate(vm, list);
sbVm_call_c_func(vm, list_any_cfunc);
}
-static void all_p(hVm vm, hV *list, usize num_params) {
+static void all_p(hVm vm, hVal *list, usize num_params) {
sbVm_push_immediate(vm, list);
sbVm_call_c_func(vm, list_all_cfunc);
}
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 index = HVINT(0);
+ 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;
usize current_index = vm->fp->locals[1].integer++;
usize length;
- hV *iter_values = sbList_get_value(vm->fp->locals[0].list, &length);
+ hVal *iter_values = sbList_get_value(vm->fp->locals[0].list, &length);
if (current_index < length) {
sbVm_push(vm, &iter_values[current_index]);
sbVm_push_immediate(vm, &HVINT(1));
if (init) {
/* state: list being mapped, index, callback, result */
sbVm_request_var_space(vm, 4);
- hV *iterating_list = sbVm_pop(vm);
- hV *map_func = sbVm_pop(vm);
+ hVal *iterating_list = sbVm_pop(vm);
+ hVal *map_func = sbVm_pop(vm);
usize length;
sbList_get_value(iterating_list->list, &length);
- hV index = HVINT(0);
- hV result = sbV_empty_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[3] = result;
} else {
/* get result of map function and append its result to result list */
- hV *mapped = sbVm_pop(vm);
+ hVal *mapped = sbVm_pop(vm);
sbList_append(vm->fp->locals[3].list, mapped);
}
usize current_index = vm->fp->locals[1].integer++;
usize length;
- hV *iter_values = sbList_get_value(vm->fp->locals[0].list, &length);
+ hVal *iter_values = sbList_get_value(vm->fp->locals[0].list, &length);
if (current_index < length) {
sbVm_push(vm, &iter_values[current_index]);
sbVm_push_immediate(vm, &HVINT(1));
if (init) {
/* state: list being filtered, index, callback, result */
sbVm_request_var_space(vm, 4);
- hV *iterating_list = sbVm_pop(vm);
- hV *filter_func = sbVm_pop(vm);
+ hVal *iterating_list = sbVm_pop(vm);
+ hVal *filter_func = sbVm_pop(vm);
usize length;
sbList_get_value(iterating_list->list, &length);
- hV index = HVINT(0);
- hV result = sbV_empty_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[3] = result;
} else {
/* get result of filter function and append element to result if true */
- hV *mapped = sbVm_pop(vm);
- hV *element = sbVm_pop(vm);
+ hVal *mapped = sbVm_pop(vm);
+ hVal *element = sbVm_pop(vm);
if (!sbV_c_falsy(mapped)) {
sbList_append(vm->fp->locals[3].list, element);
}
usize current_index = vm->fp->locals[1].integer++;
usize length;
- hV *iter_values = sbList_get_value(vm->fp->locals[0].list, &length);
+ hVal *iter_values = sbList_get_value(vm->fp->locals[0].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]);
if (init) {
/* state: list being reduced, index, callback, result */
sbVm_request_var_space(vm, 4);
- hV *iterating_list = sbVm_pop(vm);
- hV *result = sbVm_pop(vm);
- hV *reduce_func = sbVm_pop(vm);
+ hVal *iterating_list = sbVm_pop(vm);
+ hVal *result = sbVm_pop(vm);
+ hVal *reduce_func = sbVm_pop(vm);
usize length;
sbList_get_value(iterating_list->list, &length);
- hV index = HVINT(0);
+ hVal index = HVINT(0);
vm->fp->locals[0] = *iterating_list;
vm->fp->locals[1] = index;
vm->fp->locals[3] = *result;
} else {
/* get result of reduce function */
- hV *result = sbVm_pop(vm);
+ hVal *result = sbVm_pop(vm);
vm->fp->locals[3] = *result;
}
usize current_index = vm->fp->locals[1].integer++;
usize length;
- hV *iter_values = sbList_get_value(vm->fp->locals[0].list, &length);
+ hVal *iter_values = sbList_get_value(vm->fp->locals[0].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]);
if (init) {
/* state: list being filtered, index, callback */
sbVm_request_var_space(vm, 3);
- hV *iterating_list = sbVm_pop(vm);
- hV *pred_func = sbVm_pop(vm);
- hV index = HVINT(0);
+ hVal *iterating_list = sbVm_pop(vm);
+ 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;
} else {
/* get result of predicate function */
- hV *mapped = sbVm_pop(vm);
+ hVal *mapped = sbVm_pop(vm);
if (!sbV_c_falsy(mapped)) {
/* one was true! return true */
sbVm_push_immediate(vm, &HVBOOL(TRUE));
/* haven't found any yet... */
usize current_index = vm->fp->locals[1].integer++;
usize length;
- hV *iter_values = sbList_get_value(vm->fp->locals[0].list, &length);
+ hVal *iter_values = sbList_get_value(vm->fp->locals[0].list, &length);
if (current_index < length) {
/* try next element */
sbVm_push(vm, &iter_values[current_index]);
if (init) {
/* state: list being filtered, index, callback */
sbVm_request_var_space(vm, 3);
- hV *iterating_list = sbVm_pop(vm);
- hV *pred_func = sbVm_pop(vm);
- hV index = HVINT(0);
+ hVal *iterating_list = sbVm_pop(vm);
+ 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;
} else {
/* get result of predicate function */
- hV *mapped = sbVm_pop(vm);
+ hVal *mapped = sbVm_pop(vm);
if (sbV_c_falsy(mapped)) {
/* one was false; return false */
sbVm_push_immediate(vm, &HVBOOL(FALSE));
/* all true so far */
usize current_index = vm->fp->locals[1].integer++;
usize length;
- hV *iter_values = sbList_get_value(vm->fp->locals[0].list, &length);
+ hVal *iter_values = sbList_get_value(vm->fp->locals[0].list, &length);
if (current_index < length) {
/* try next element */
sbVm_push(vm, &iter_values[current_index]);
sbLibTable g_string_methods;
-static void split(hVm vm, hV *target, usize num_params) {
+static void split(hVm vm, hVal *target, usize num_params) {
usize length;
char scratch[8];
const char *buf = sbString_get_value(target->string, scratch, &length);
sbVm_push_immediate(vm, &HVLIST(l));
}
-static void to_string(hVm vm, hV *target, usize num_params) {
+static void to_string(hVm vm, hVal *target, usize num_params) {
/* to_string for a string just returns itself */
sbVm_push_immediate(vm, target);
}
-static void to_integer(hVm vm, hV *target, usize num_params) {
+static void to_integer(hVm vm, hVal *target, usize num_params) {
char scratch[8];
usize length;
const char *data = sbString_get_value(target->string, scratch, &length);
sbVm_push_immediate(vm, &HVINT(parsed));
}
-static void length(hVm vm, hV *target, usize num_params) {
+static void length(hVm vm, hVal *target, usize num_params) {
usize length;
sbString_get_value(target->string, NULL, &length);
sbVm_push_immediate(vm, &HVINT(length));
/* --- */
sbCFuncStatus print_cfunc(hVm vm, flag init) {
- hV *args_left;
+ hVal *args_left;
if (!init) {
/* get value of previous to_string */
- hV *value = sbVm_pop(vm);
+ hVal *value = sbVm_pop(vm);
/* TODO: We should probably have some kind of 'implicit convert to string'
* thing that checks that it's really a string and throws if not, that we
* can call from multiple places */
static sbCFuncStatus from_cfunc(hVm vm, flag init) {
if (!init) {
/* get value of previous integer::convert */
- hV *value = sbVm_peek(vm, 0);
+ hVal *value = sbVm_peek(vm, 0);
if (value->type != IT_INTEGER) {
PANIC("integer::convert needs to return an integer");
}
}
}
- hV *first = sbVm_pop(vm);
+ hVal *first = sbVm_pop(vm);
hInteger min, max;
if (argc == 1) {
min = offset;
max = first->integer + offset;
} else {
- hV *second = sbVm_pop(vm);
+ hVal *second = sbVm_pop(vm);
if (first->type != IT_INTEGER || second->type != IT_INTEGER) {
if (offset == 1) {
PANIC("list::iota1's arguments must be integers!");
if (argc != 1) {
PANIC("math::sqrt takes one argument");
}
- hV *argument = sbVm_pop(vm);
+ hVal *argument = sbVm_pop(vm);
double original_value;
if (argument->type == IT_INTEGER) {
}
static void sbmax(hVm vm, usize argc) {
- hV *result = &HVNIL;
+ hVal *result = &HVNIL;
while (argc > 0) {
argc --;
- hV *val = sbVm_pop(vm);
+ hVal *val = sbVm_pop(vm);
if (result->type == IT_NIL || sbV_le(result, val).boolean) {
result = val;
}
static sbCFuncStatus from_cfunc(hVm vm, flag init) {
if (!init) {
/* get value of previous to_string */
- hV *value = sbVm_peek(vm, 0);
+ hVal *value = sbVm_peek(vm, 0);
/* TODO: We should probably have some kind of 'implicit convert to string'
* thing that checks that it's really a string and throws if not, that we
* can call from multiple places */
hSymbol *keys;
union {
sbLibMethod *methods;
- hV *values;
+ hVal *values;
};
} sbLibTable;
*/
static void insert_method(hSymbol *keys, sbLibMethod *methods, usize capacity, hSymbol key, sbLibMethod *method);
-static void insert_value(hSymbol *keys, hV *values, usize capacity, hSymbol key, hV *value);
+static void insert_value(hSymbol *keys, hVal *values, usize capacity, hSymbol key, hVal *value);
static void check_grow_table(hLibTable t);
void sbLibTable_initialize(hLibTable t, usize capacity, flag method_table) {
t->method_table = TRUE;
t->methods = calloc(capacity, sizeof(sbLibMethod));
} else {
- t->values = calloc(capacity, sizeof(hV));
+ t->values = calloc(capacity, sizeof(hVal));
}
t->capacity = capacity;
}
}
}
-hV *sbLibTable_find_value(hLibTable t, hSymbol key) {
+hVal *sbLibTable_find_value(hLibTable t, hSymbol key) {
if (t->method_table) CHECK("cannot find value in method table");
sbHashValue hash = sbHash_hash_bytes((const char*)&key, sizeof(hSymbol));
sbLibTable_register_method_sym(t, sym, method);
}
-void sbLibTable_register_value_sym(hLibTable t, hSymbol key, hV *value) {
+void sbLibTable_register_value_sym(hLibTable t, hSymbol key, hVal *value) {
if (t->method_table) CHECK("cannot put value in method table");
check_grow_table(t);
t->used ++;
}
-void sbLibTable_register_value(hLibTable t, const char *value_name, usize value_name_length, hV *value) {
+void sbLibTable_register_value(hLibTable t, const char *value_name, usize value_name_length, hVal *value) {
hSymbol sym = sbSymbol_from_bytes(value_name, value_name_length);
sbLibTable_register_value_sym(t, sym, value);
}
methods[index] = *method;
}
-static void insert_value(hSymbol *keys, hV *values, usize capacity, hSymbol key, hV *value) {
+static void insert_value(hSymbol *keys, hVal *values, usize capacity, hSymbol key, hVal *value) {
sbHashValue hash = sbHash_hash_bytes((const char*)&key, sizeof(hSymbol));
usize index = hash % capacity;
free(t->methods);
t->methods = new_methods;
} else {
- hV *new_values = calloc(new_capacity, sizeof(hV));
+ hVal *new_values = calloc(new_capacity, sizeof(hVal));
for (usize i = 0; i < t->capacity; i++) {
if (t->keys[i] != 0) {
flag method_table;
union {
sbLibMethod *methods;
- hV *values;
+ hVal *values;
};
} sbLibTable;
sbLibMethod *sbLibTable_find_method(hLibTable t, hSymbol key);
-hV *sbLibTable_find_value(hLibTable t, hSymbol key);
+hVal *sbLibTable_find_value(hLibTable t, hSymbol key);
void sbLibTable_register_method(hLibTable t, const char *method_name, usize method_name_length, sbLibMethod *method);
void sbLibTable_register_method_sym(hLibTable t, hSymbol key, sbLibMethod *method);
-void sbLibTable_register_value(hLibTable t, const char *value_name, usize value_name_length, hV *value);
+void sbLibTable_register_value(hLibTable t, const char *value_name, usize value_name_length, hVal *value);
-void sbLibTable_register_value_sym(hLibTable t, hSymbol key, hV *value);
+void sbLibTable_register_value_sym(hLibTable t, hSymbol key, hVal *value);
if (vm.debugmode) {
printf("Stack result: ");
- for (hV **p = (hV**)vm.vstack; p < (hV**)vm.vsp; p++) {
+ for (hVal **p = (hVal**)vm.vstack; p < (hVal**)vm.vsp; p++) {
printf("%16llx %16llx ", (long long)(*p)->type, (long long)(*p)->data);
}
printf("\n");
return cm->bytecode.size;
}
-u32 sbVmCompiler_add_constant(sbVmCompiler *cm, hV *constant) {
+u32 sbVmCompiler_add_constant(sbVmCompiler *cm, hVal *constant) {
sbV_retain(constant);
- sbBuffer_append(&cm->constants, constant, sizeof(hV));
- return cm->constants.size / sizeof(hV) - 1;
+ sbBuffer_append(&cm->constants, constant, sizeof(hVal));
+ return cm->constants.size / sizeof(hVal) - 1;
}
void sbVmProgram_initialize(sbVmProgram *pm, usize initial_arena_size) {
sbVmBlock bk = {
.bytecode = bytecode,
.bytecode_end = bytecode + bytecode_length,
- .constants = (hV*)constants,
- .constants_count = constants_length / sizeof(hV),
+ .constants = (hVal*)constants,
+ .constants_count = constants_length / sizeof(hVal),
};
if (pm->block_count >= pm->block_capacity) {
.bytecode = bc, \
.bytecode_length = sizeof(bc), \
.constants = cn, \
- .constants_count = sizeof(cn)/sizeof(hV) \
+ .constants_count = sizeof(cn)/sizeof(hVal) \
})
/* dynamic sized block that we can more easily add
typedef struct sbVmBlock {
const u8 *bytecode;
const u8 *bytecode_end;
- const hV *constants;
+ const hVal *constants;
usize constants_count;
} sbVmBlock;
usize sbVmCompiler_get_position(sbVmCompiler *cm);
-u32 sbVmCompiler_add_constant(sbVmCompiler *cm, hV *constant);
+u32 sbVmCompiler_add_constant(sbVmCompiler *cm, hVal *constant);
void sbVmProgram_initialize(sbVmProgram *pm, usize initial_arena_size);
#include "lib/sentinel.h"
void call_block(hVm vm, usize block_id, hClosure closure);
-void call_builtin(hVm vm, hV *to_call);
-void call_bound_method(hVm vm, hV *to_call);
+void call_builtin(hVm vm, hVal *to_call);
+void call_bound_method(hVm vm, hVal *to_call);
void return_from_block(hVm vm);
void execute_instruction(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, isize offset);
+void push_stack(hVm vm, hVal *value);
+void push_stack_immediate(hVm vm, const hVal *value);
+hVal *pop_stack(hVm vm);
+hVal *npop_stack(hVm vm, usize count);
+hVal *peek_stack(hVm vm, isize offset);
void swap_stack_top(hVm vm);
void print_stack(hVm vm);
return VM_STAT_SUCCESS;
}
-void sbVm_push(hVm vm, hV *value) {
+void sbVm_push(hVm vm, hVal *value) {
push_stack(vm, value);
}
-void sbVm_push_immediate(hVm vm, hV *value) {
+void sbVm_push_immediate(hVm vm, hVal *value) {
push_stack_immediate(vm, value);
}
-hV *sbVm_pop(hVm vm) {
+hVal *sbVm_pop(hVm vm) {
return pop_stack(vm);
}
-hV *sbVm_npop(hVm vm, usize how_many) {
+hVal *sbVm_npop(hVm vm, usize how_many) {
return npop_stack(vm, how_many);
}
-hV *sbVm_peek(hVm vm, usize where) {
+hVal *sbVm_peek(hVm vm, usize where) {
return peek_stack(vm, where);
}
swap_stack_top(vm);
}
-void sbVm_call_func(hVm vm, hV *func) {
+void sbVm_call_func(hVm vm, hVal *func) {
if (func->type == IT_BUILTIN) {
call_builtin(vm, func);
} else if (func->type <= 0) {
}
}
-void sbVm_transfer_to_func(hVm vm, hV *func) {
+void sbVm_transfer_to_func(hVm vm, hVal *func) {
/* tail call */
return_from_block(vm);
sbVm_call_func(vm, 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->rsp, 0, amount * sizeof(hV));
- vm->rsp += amount * sizeof(hV);
+ memset(vm->rsp, 0, amount * sizeof(hVal));
+ vm->rsp += amount * sizeof(hVal);
vm->fp->num_locals += amount;
}
void print_stack(hVm vm) {
debug("Stack: ");
- for (hV **p = (hV**)vm->vstack; p < (hV**)vm->vsp; p++) {
+ for (hVal **p = (hVal**)vm->vstack; p < (hVal**)vm->vsp; p++) {
debug("%16llx %16llx ", (long long)(*p)->type, (long long)(*p)->data);
}
debug("\n");
}
-void call_builtin(hVm vm, hV *to_call) {
+void call_builtin(hVm vm, hVal *to_call) {
if (to_call->type != IT_BUILTIN) {
CHECK("call_builtin can only call builtins!");
}
- hV *argc = sbVm_pop(vm);
+ hVal *argc = sbVm_pop(vm);
if (argc->type != IT_INTEGER) {
CHECK("argc to builtin needs to be integer!");
}
vm->ip = &blk->bytecode[0];
}
-void call_bound_method(hVm vm, hV *to_call) {
+void call_bound_method(hVm vm, hVal *to_call) {
if (!(to_call->type & IT_FLAG_BOUND_METHOD)) {
CHECK("call_bound_method can only call bound methods!");
}
* 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) */
- ((hV*)(vm->xsp))[-1] = *((hV**)(vm->vsp))[-1];
- ((hV**)(vm->vsp))[-1] = &((hV*)(vm->xsp))[-1];
+ ((hVal*)(vm->xsp))[-1] = *((hVal**)(vm->vsp))[-1];
+ ((hVal**)(vm->vsp))[-1] = &((hVal*)(vm->xsp))[-1];
sbVmStackFrame *frame = (sbVmStackFrame*)vm->fp;
}
}
-void debug_print_hv(const hV *value) {
+void debug_print_hv(const hVal *value) {
debug("%016llx %016llx\n", *(long long*)value, *((long long*)value+1));
}
-void store_local(hVm vm, usize local_index, const hV *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;
}
-void push_stack(hVm vm, hV *value) {
- *(hV**)vm->vsp = value;
- vm->vsp += sizeof(hV*);
- vm->xsp += sizeof(hV);
+void push_stack(hVm vm, hVal *value) {
+ *(hVal**)vm->vsp = value;
+ vm->vsp += sizeof(hVal*);
+ vm->xsp += sizeof(hVal);
}
-void push_stack_immediate(hVm vm, const hV *value) {
+void push_stack_immediate(hVm vm, const hVal *value) {
/* save it on our own stack */
- *(hV*)vm->xsp = *value;
- *(hV**)vm->vsp = (hV*)vm->xsp;
- vm->vsp += sizeof(hV*);
- vm->xsp += sizeof(hV);
+ *(hVal*)vm->xsp = *value;
+ *(hVal**)vm->vsp = (hVal*)vm->xsp;
+ vm->vsp += sizeof(hVal*);
+ vm->xsp += sizeof(hVal);
}
-hV *pop_stack(hVm vm) {
- vm->vsp -= sizeof(hV*);
- vm->xsp -= sizeof(hV);
- return *(hV**)vm->vsp;
+hVal *pop_stack(hVm vm) {
+ vm->vsp -= sizeof(hVal*);
+ vm->xsp -= sizeof(hVal);
+ return *(hVal**)vm->vsp;
}
-hV *npop_stack(hVm vm, usize count) {
- vm->vsp -= count * sizeof(hV*);
- vm->xsp -= count * sizeof(hV);
- return *(hV**)vm->vsp;
+hVal *npop_stack(hVm vm, usize count) {
+ vm->vsp -= count * sizeof(hVal*);
+ vm->xsp -= count * sizeof(hVal);
+ return *(hVal**)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];
+ 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
/* x2 x1 &v2 &v1 (might be &x2 &x1)*/
- hV xtmp = *second_x;
+ hVal xtmp = *second_x;
if (*first_v == first_x) {
/* x2a x1a &v2 &x1a */
*second_x = *first_x; /* x1b x1a &v2 &x1a */
*second_v = first_x; /* x2a x2b &x2b &v1 */
}
- hV *vtmp = *first_v; /* x2 x1 &v2 &v1 */
+ hVal *vtmp = *first_v; /* x2 x1 &v2 &v1 */
*first_v = *second_v; /* x2 x1 &v2 &v2 */
*second_v = vtmp; /* x2 x1 &v1 &v2 */
}
-hV *peek_stack(hVm vm, isize offset) {
- return ((hV**)(vm->vsp))[-offset - 1];
+hVal *peek_stack(hVm vm, isize offset) {
+ return ((hVal**)(vm->vsp))[-offset - 1];
}
-hV *peek_xstack(hVm vm, isize offset) {
- return &((hV*)(vm->xsp))[-offset - 1];
+hVal *peek_xstack(hVm vm, isize offset) {
+ return &((hVal*)(vm->xsp))[-offset - 1];
}
sbOpcode get_opcode(hVm vm) {
if (vm->debugmode) debug("op %02X ", op);
u64 param;
usize count;
- hV *v, *w, *x, res;
+ hVal *v, *w, *x, res;
switch (op) {
case BC_NOP:
sbRuntimeCFunc c_func;
};
usize num_locals;
- hV locals[];
+ hVal locals[];
} sbVmStackFrame;
typedef struct sbVm {
sbVmStatus sbVm_execute(hVm vm, sbVmProgram *pm);
-void sbVm_push(hVm vm, hV *value);
+void sbVm_push(hVm vm, hVal *value);
-void sbVm_push_immediate(hVm vm, hV *value);
+void sbVm_push_immediate(hVm vm, hVal *value);
-hV *sbVm_pop(hVm vm);
+hVal *sbVm_pop(hVm vm);
-hV *sbVm_npop(hVm vm, usize how_many);
+hVal *sbVm_npop(hVm vm, usize how_many);
-hV *sbVm_peek(hVm vm, usize where);
+hVal *sbVm_peek(hVm vm, usize where);
void sbVm_swap(hVm vm);
-void sbVm_call_func(hVm vm, hV *func);
+void sbVm_call_func(hVm vm, hVal *func);
-void sbVm_transfer_to_func(hVm vm, hV *func);
+void sbVm_transfer_to_func(hVm vm, hVal *func);
void sbVm_call_c_func(hVm vm, sbRuntimeCFunc func);
#include "lib/table.h"
#include "lib/sentinel.h"
-hV sbV_add(const hV *a, const hV *b) {
+hVal sbV_add(const hVal *a, const hVal *b) {
if (a->type == IT_INTEGER && b->type == IT_INTEGER) {
- return sbV_int(sbInteger_sum(a->integer, b->integer));
+ return HVINT(sbInteger_sum(a->integer, b->integer));
} else {
PANIC("todo (add type %lld and type %lld)", (long long)a->type, (long long)b->type);
}
}
-hV sbV_sub(const hV *a, const hV *b) {
+hVal sbV_sub(const hVal *a, const hVal *b) {
if (a->type == IT_INTEGER && b->type == IT_INTEGER) {
- return sbV_int(sbInteger_diff(a->integer, b->integer));
+ return HVINT(sbInteger_diff(a->integer, b->integer));
} else {
PANIC("todo (subtract type %llu minus %llu)", (long long)a->type, (long long)b->type);
}
}
-hV sbV_mul(const hV *a, const hV *b) {
+hVal sbV_mul(const hVal *a, const hVal *b) {
if (a->type == IT_INTEGER && b->type == IT_INTEGER) {
- return sbV_int(sbInteger_mul(a->integer, b->integer));
+ return HVINT(sbInteger_mul(a->integer, b->integer));
} else {
PANIC("todo");
}
}
-hV sbV_floordiv(const hV *a, const hV *b) {
+hVal sbV_floordiv(const hVal *a, const hVal *b) {
if (a->type == IT_INTEGER && b->type == IT_INTEGER) {
- return sbV_int(sbInteger_floordiv(a->integer, b->integer));
+ return HVINT(sbInteger_floordiv(a->integer, b->integer));
} else {
PANIC("todo");
}
}
-hV sbV_mod(const hV *a, const hV *b) {
+hVal sbV_mod(const hVal *a, const hVal *b) {
if (a->type == IT_INTEGER && b->type == IT_INTEGER) {
- return sbV_int(a->integer % b->integer);
+ return HVINT(a->integer % b->integer);
} else {
PANIC("todo %lld", (long long)a->type);
}
}
-void sbV_incr(hV *a) {
+void sbV_incr(hVal *a) {
if (a->type == IT_INTEGER) {
a->integer += 1;
} else {
}
}
-void sbV_decr(hV *a) {
+void sbV_decr(hVal *a) {
if (a->type == IT_INTEGER) {
a->integer -= 1;
} else {
}
}
-hV sbV_eq(const hV *a, const hV *b) {
+hVal sbV_eq(const hVal *a, const hVal *b) {
if (sbV_c_eq(a, b)) {
return HVBOOL(TRUE);
} else {
}
}
-hV sbV_lt(const hV *a, const hV *b) {
+hVal sbV_lt(const hVal *a, const hVal *b) {
if (a->type == IT_INTEGER && b->type == IT_INTEGER) {
if (a->integer < b->integer) {
return HVBOOL(TRUE);
}
}
-hV sbV_le(const hV *a, const hV *b) {
+hVal sbV_le(const hVal *a, const hVal *b) {
if (a->type == IT_INTEGER && b->type == IT_INTEGER) {
if (a->integer <= b->integer) {
return HVBOOL(TRUE);
}
}
-hV sbV_append(hV *a, hV *b) {
+hVal sbV_append(hVal *a, hVal *b) {
if (a->type == IT_LIST) {
sbList_append(a->list, b);
return HVNIL;
}
void sbV_index(hVm vm) {
- hV *a = sbVm_peek(vm, 1);
- hV *b = sbVm_peek(vm, 0);
+ 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);
- hV *result = sbList_index(a->list, b->integer);
+ hVal *result = sbList_index(a->list, b->integer);
sbVm_push(vm, result);
} else if (a->type == IT_MODULE && b->type == IT_SYMBOL) {
sbVm_npop(vm, 2);
- hV *result = sbLibTable_find_value(a->module, b->symbol);
+ hVal *result = sbLibTable_find_value(a->module, b->symbol);
sbVm_push(vm, result);
} else {
sbVm_swap(vm); /* b a */
}
}
-hV sbV_rangeindex(hV *a, hV *b, hV *c) {
+hVal sbV_rangeindex(hVal *a, hVal *b, hVal *c) {
if (b->type == IT_INTEGER && c->type == IT_INTEGER) {
usize length;
i64 min = sbInteger_get_value(b->integer);
i64 max = sbInteger_get_value(c->integer);
if (a->type == IT_LIST) {
- hV *elements = sbList_get_value(a->list, &length);
+ hVal *elements = sbList_get_value(a->list, &length);
if (min >= max || min >= length || max < 0) {
/* backwards or out of range */
return sbV_empty_list(0);
}
}
-void sbV_index_set(hV *obj, hV *key, hV *value) {
+void sbV_index_set(hVal *obj, hVal *key, hVal *value) {
if (obj->type == IT_LIST) {
PANIC("todo");
} else if (obj->type == IT_HASH) {
void sbV_message_handler(hVm vm);
-hV sbV_add(const hV *a, const hV *b);
+hVal sbV_add(const hVal *a, const hVal *b);
-hV sbV_sub(const hV *a, const hV *b);
+hVal sbV_sub(const hVal *a, const hVal *b);
-hV sbV_mul(const hV *a, const hV *b);
+hVal sbV_mul(const hVal *a, const hVal *b);
-hV sbV_floordiv(const hV *a, const hV *b);
+hVal sbV_floordiv(const hVal *a, const hVal *b);
-hV sbV_mod(const hV *a, const hV *b);
+hVal sbV_mod(const hVal *a, const hVal *b);
-void sbV_incr(hV *a);
+void sbV_incr(hVal *a);
-void sbV_decr(hV *a);
+void sbV_decr(hVal *a);
-hV sbV_eq(const hV *a, const hV *b);
+hVal sbV_eq(const hVal *a, const hVal *b);
-hV sbV_lt(const hV *a, const hV *b);
+hVal sbV_lt(const hVal *a, const hVal *b);
-hV sbV_le(const hV *a, const hV *b);
+hVal sbV_le(const hVal *a, const hVal *b);
-hV sbV_append(hV *a, hV *b);
+hVal sbV_append(hVal *a, hVal *b);
void sbV_index(hVm vm);
-hV sbV_rangeindex(hV *a, hV *b, hV *c);
+hVal sbV_rangeindex(hVal *a, hVal *b, hVal *c);
-void sbV_index_set(hV *obj, hV *key, hV *value);
+void sbV_index_set(hVal *obj, hVal *key, hVal *value);