summaryrefslogtreecommitdiff
path: root/uscript/vm.c
diff options
context:
space:
mode:
Diffstat (limited to 'uscript/vm.c')
-rw-r--r--uscript/vm.c65
1 files changed, 47 insertions, 18 deletions
diff --git a/uscript/vm.c b/uscript/vm.c
index 26fccbe..e01d17d 100644
--- a/uscript/vm.c
+++ b/uscript/vm.c
@@ -76,6 +76,51 @@ void close_upvals(struct us_val *to)
vm.open_upvals = upval;
}
+static
+void index_val(struct us_val idx_val, struct us_val idxee_val)
+{
+ switch (idxee_val.type) {
+ case VAL_ARR: {
+ if (idx_val.type != VAL_NUM)
+ log_fatal(1, "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)) {
+ log_fatal(
+ 1,
+ "index out of range (%d/%d)",
+ idx,
+ da_len(arr->e) - 1
+ );
+ }
+ vm_push(arr->e[idx]);
+ break;
+ }
+ case VAL_STR: {
+ if (idx_val.type != VAL_NUM)
+ log_fatal(1, "strings must be indexed by numbers");
+ int idx = (int)get_num(idx_val);
+ struct us_str *str = get_str(idxee_val);
+ if (idx < 0)
+ idx += str->len;
+ if (idx < 0 || (size_t)idx >= str->len) {
+ log_fatal(
+ 1,
+ "index out of range (%d/%d)",
+ idx,
+ str->len - 1
+ );
+ }
+ vm_push(wrap_str(copy_str(&str->chars[idx], 1)));
+ break;
+ }
+ default:
+ log_fatal(1, "cannot index that value");
+ break;
+ }
+}
static
void call_val(struct us_val callee, int argc)
@@ -218,24 +263,8 @@ void us_exec(struct us_func *func)
break;
case BC_GET_INDEX: {
struct us_val idx_val = vm_pop();
- struct us_val arr_val = vm_pop();
- if (idx_val.type != VAL_NUM)
- log_fatal(1, "index type must be number");
- if (arr_val.type != VAL_ARR)
- log_fatal(1, "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)) {
- log_fatal(
- 1,
- "index out of range (%d/%d)",
- idx,
- da_len(arr->e) - 1
- );
- }
- vm_push(arr->e[idx]);
+ struct us_val idxee_val = vm_pop();
+ index_val(idx_val, idxee_val);
break;
}
case BC_SET_INDEX: {