summaryrefslogtreecommitdiff
path: root/uscript/vm.c
diff options
context:
space:
mode:
Diffstat (limited to 'uscript/vm.c')
-rw-r--r--uscript/vm.c90
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;