diff options
| author | iamcheeseman <[email protected]> | 2026-04-17 22:48:52 -0400 |
|---|---|---|
| committer | iamcheeseman <[email protected]> | 2026-04-17 22:48:52 -0400 |
| commit | f328d3b2bea11f6b89bf4b3707205ecd8496b93d (patch) | |
| tree | 6d3fdb155a7d4c19332f54790b1d6ae89ae0b04f /uscript/vm.c | |
| parent | de5d3ebdbc674bf8f1e324ee5b43c51af288a286 (diff) | |
microscript: add maps
Diffstat (limited to 'uscript/vm.c')
| -rw-r--r-- | uscript/vm.c | 90 |
1 files changed, 61 insertions, 29 deletions
diff --git a/uscript/vm.c b/uscript/vm.c index c381112..97f4958 100644 --- a/uscript/vm.c +++ b/uscript/vm.c @@ -5,6 +5,7 @@ #include <string.h> #include "dyn_arr.h" +#include "map.h" #include "us_debug.h" #include "uscript.h" @@ -57,16 +58,6 @@ void us_err(const char *msg, ...) } static -bool as_bool(struct us_val v) -{ - if (v.type == VAL_ZILCH) - return false; - if (v.type == VAL_BOOL) - return get_bool(v); - return true; -} - -static struct us_str *concat(struct us_val a, struct us_val b) { int a_len; @@ -99,6 +90,38 @@ void close_upvals(struct us_val *to) } static +void set_index(struct us_val idx_val, struct us_val idxee_val, struct us_val to) +{ + switch (idxee_val.type) { + case VAL_ARR: { + if (idx_val.type != VAL_NUM) + us_err("arrays must be indexed by numbers"); + int idx = (int)get_num(idx_val); + struct us_arr *arr = get_arr(idxee_val); + if (idx < 0) + idx += da_len(arr->e); + if (idx < 0 || idx >= da_len(arr->e)) { + us_err( + "index out of range (%d/%d)", + idx, + da_len(arr->e) - 1 + ); + } + arr->e[idx] = to; + break; + } + case VAL_MAP: { + struct us_map *map = get_map(idxee_val); + map_set_value(map, idx_val, to); + break; + } + default: + us_err("cannot index that value"); + break; + } +} + +static void index_val(struct us_val idx_val, struct us_val idxee_val) { switch (idxee_val.type) { @@ -119,6 +142,17 @@ void index_val(struct us_val idx_val, struct us_val idxee_val) vm_push(arr->e[idx]); break; } + case VAL_MAP: { + struct us_map *map = get_map(idxee_val); + struct us_val out; + bool has = map_get_value(map, idx_val, &out); + if (!has) { + char *val = val_to_str(idx_val, NULL); + us_err("map does not have key '%s'", val); + } + vm_push(out); + break; + } case VAL_STR: { if (idx_val.type != VAL_NUM) us_err("strings must be indexed by numbers"); @@ -265,6 +299,19 @@ void us_exec(struct us_func *func) vm_push(wrap_arr(arr)); break; } + case BC_MAP: { + struct us_map *map = create_map(); + u8 map_len = read_byte(); + int offset = (int)map_len * 2; + for (u8 i = 0; i < map_len; i++) { + struct us_val k = *(vm.stacktop - offset + i*2); + struct us_val v = *(vm.stacktop - offset + i*2+1); + map_set_value(map, k, v); + } + vm.stacktop -= map_len * 2; + vm_push(wrap_map(map)); + break; + } case BC_GET_LOCAL: vm_push(vm.cf->stackbot[read_byte()]); break; @@ -298,23 +345,8 @@ void us_exec(struct us_func *func) case BC_SET_INDEX: { struct us_val set_val = vm_pop(); struct us_val idx_val = vm_pop(); - struct us_val arr_val = vm_pop(); - if (idx_val.type != VAL_NUM) - us_err("index type must be number"); - if (arr_val.type != VAL_ARR) - us_err("only arrays can be indexed"); - int idx = (int)get_num(idx_val); - struct us_arr *arr = get_arr(arr_val); - if (idx < 0) - idx += da_len(arr->e); - if (idx < 0 || idx >= da_len(arr->e)) { - us_err( - "index out of range (%d/%d)", - idx, - da_len(arr->e) - 1 - ); - } - arr->e[idx] = set_val; + struct us_val idxee_val = vm_pop(); + set_index(idx_val, idxee_val, set_val); vm_push(set_val); break; } @@ -403,7 +435,7 @@ void us_exec(struct us_func *func) break; } case BC_NOT: { - bool negated = !as_bool(vm_pop()); + bool negated = !val_as_bool(vm_pop()); vm_push(create_bool(negated)); break; } @@ -432,7 +464,7 @@ void us_exec(struct us_func *func) } case BC_FALSEY_JMP: { u16 jmp = read_short(); - if (as_bool(vm_peek(0))) + if (val_as_bool(vm_peek(0))) break; i += jmp; break; |
