summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoriamcheeseman <[email protected]>2026-04-14 21:15:38 -0400
committeriamcheeseman <[email protected]>2026-04-14 21:15:38 -0400
commit7752d0b775c4df0de6fec688107e904ad20e1de6 (patch)
tree4255de168db8a527b7e99217021dd052bd2024e2
parenta2ebe62cdbbe12e75e3b5c79de3dce9fbeb1ca20 (diff)
microengine: compound operators
-rw-r--r--uscript/parser.c65
-rw-r--r--uscript/us_debug.c1
-rw-r--r--uscript/uscript.c6
-rw-r--r--uscript/vm.c14
-rw-r--r--uscript/vm.h2
-rw-r--r--uscript/xbytecode.h1
6 files changed, 71 insertions, 18 deletions
diff --git a/uscript/parser.c b/uscript/parser.c
index 5740474..f2c601a 100644
--- a/uscript/parser.c
+++ b/uscript/parser.c
@@ -399,6 +399,18 @@ void parse_arr(struct parser *p)
}
static
+void parser_add_var_access(struct parser *p, u8 acc, int var)
+{
+ parser_add_byte(p, acc);
+ if (acc == BC_SET_GLOBAL || acc == BC_GET_GLOBAL) {
+ parser_add_byte(p, (var >> 8) & 0xFF);
+ parser_add_byte(p, var & 0xFF);
+ } else {
+ parser_add_byte(p, (u8)var);
+ }
+}
+
+static
void parse_ident(struct parser *p)
{
struct token ident = p->prev;
@@ -423,19 +435,31 @@ void parse_ident(struct parser *p)
return;
}
+#define compound_op(op) \
+ do { \
+ parser_add_var_access(p, getter, var); \
+ expr(p); \
+ parser_add_byte(p, op); \
+ parser_add_var_access(p, setter, var); \
+ } while (false)
+
if (p->can_assign && consume(p, '=')) {
expr(p);
- parser_add_byte(p, setter);
+ parser_add_var_access(p, setter, var);
+ } else if (p->can_assign && consume(p, TOKEN_PLUS_EQL)) {
+ compound_op(BC_ADD);
+ } else if (p->can_assign && consume(p, TOKEN_MINUS_EQL)) {
+ compound_op(BC_SUB);
+ } else if (p->can_assign && consume(p, TOKEN_MULT_EQL)) {
+ compound_op(BC_MULT);
+ } else if (p->can_assign && consume(p, TOKEN_DIV_EQL)) {
+ compound_op(BC_DIV);
+ } else if (p->can_assign && consume(p, TOKEN_MOD_EQL)) {
+ compound_op(BC_MOD);
} else {
- parser_add_byte(p, getter);
- }
-
- if (setter == BC_SET_GLOBAL) {
- parser_add_byte(p, (var >> 8) & 0xFF);
- parser_add_byte(p, var & 0xFF);
- } else {
- parser_add_byte(p, (u8)var);
+ parser_add_var_access(p, getter, var);
}
+#undef compound_op
}
static
@@ -503,15 +527,36 @@ void parse_call(struct parser *p)
static
void parse_index(struct parser *p)
{
+ bool can_assign = p->can_assign;
+
expr(p);
expect(p, ']', "expected ']'");
- if (consume(p, '=')) {
+#define compound_op(op) \
+ do { \
+ parser_add_byte(p, BC_PUSH_INDEX); \
+ expr(p); \
+ parser_add_byte(p, op); \
+ parser_add_byte(p, BC_SET_INDEX); \
+ } while (false)
+
+ if (can_assign && consume(p, '=')) {
expr(p);
parser_add_byte(p, BC_SET_INDEX);
+ } else if (can_assign && consume(p, TOKEN_PLUS_EQL)) {
+ compound_op(BC_ADD);
+ } else if (can_assign && consume(p, TOKEN_MINUS_EQL)) {
+ compound_op(BC_SUB);
+ } else if (can_assign && consume(p, TOKEN_MULT_EQL)) {
+ compound_op(BC_MULT);
+ } else if (can_assign && consume(p, TOKEN_DIV_EQL)) {
+ compound_op(BC_DIV);
+ } else if (can_assign && consume(p, TOKEN_MOD_EQL)) {
+ compound_op(BC_MOD);
} else {
parser_add_byte(p, BC_GET_INDEX);
}
+#undef compound_op
}
static
diff --git a/uscript/us_debug.c b/uscript/us_debug.c
index 18be587..8898211 100644
--- a/uscript/us_debug.c
+++ b/uscript/us_debug.c
@@ -80,6 +80,7 @@ int print_instruction(struct us_proto *proto, int idx)
case BC_FALSE:
case BC_TRUE:
case BC_ZILCH:
+ case BC_PUSH_INDEX:
case BC_GET_INDEX:
case BC_SET_INDEX:
case BC_POP:
diff --git a/uscript/uscript.c b/uscript/uscript.c
index 0e6fc4b..d82ce35 100644
--- a/uscript/uscript.c
+++ b/uscript/uscript.c
@@ -12,7 +12,7 @@ void core_print(int argc)
{
(void)argc;
- char *str = val_to_str(vm_peek(), NULL);
+ char *str = val_to_str(vm_peek(0), NULL);
olog(str);
mem_free(str);
@@ -23,7 +23,7 @@ void core_len(int argc)
{
(void)argc;
- struct us_val val = vm_peek();
+ struct us_val val = vm_peek(0);
switch (val.type) {
case VAL_ARR:
vm_push(create_num(da_len(get_arr(val)->e)));
@@ -43,6 +43,7 @@ void core_range_next(int argc)
struct us_cfunc *cfunc = get_cfunc(vm_get(-1));
double min = get_num(cfunc_get_upval(cfunc, 0));
double max = get_num(cfunc_get_upval(cfunc, 1));
+ double inc = get_num(cfunc_get_upval(cfunc, 2));
if (min == max) {
vm_push(create_zilch());
@@ -51,7 +52,6 @@ void core_range_next(int argc)
vm_push(create_num(min));
- int inc = max > min ? 1 : -1;
cfunc_set_upval(cfunc, 0, create_num(min + inc));
}
diff --git a/uscript/vm.c b/uscript/vm.c
index 4064e12..9fbd8c0 100644
--- a/uscript/vm.c
+++ b/uscript/vm.c
@@ -245,20 +245,26 @@ void us_exec(struct us_func *func)
vm_push(vm.cf->stackbot[read_byte()]);
break;
case BC_SET_LOCAL:
- vm.cf->stackbot[read_byte()] = vm_peek();
+ vm.cf->stackbot[read_byte()] = vm_peek(0);
break;
case BC_GET_GLOBAL:
vm_push(get_global(read_short()));
break;
case BC_SET_GLOBAL:
- set_global(read_short(), vm_peek());
+ set_global(read_short(), vm_peek(0));
break;
case BC_GET_UPVAL:
vm_push(*func->upvals[read_byte()]->loc);
break;
case BC_SET_UPVAL:
- *func->upvals[read_byte()]->loc = vm_peek();
+ *func->upvals[read_byte()]->loc = vm_peek(0);
break;
+ case BC_PUSH_INDEX: {
+ struct us_val idx_val = vm_peek(0);
+ struct us_val idxee_val = vm_peek(1);
+ index_val(idx_val, idxee_val);
+ break;
+ }
case BC_GET_INDEX: {
struct us_val idx_val = vm_pop();
struct us_val idxee_val = vm_pop();
@@ -403,7 +409,7 @@ void us_exec(struct us_func *func)
}
case BC_FALSEY_JMP: {
u16 jmp = read_short();
- if (as_bool(vm_peek()))
+ if (as_bool(vm_peek(0)))
break;
i += jmp;
break;
diff --git a/uscript/vm.h b/uscript/vm.h
index 9ab1407..a20aa61 100644
--- a/uscript/vm.h
+++ b/uscript/vm.h
@@ -8,7 +8,7 @@
#define STACK_SIZE (MAX_CALL_FRAMES * 256)
#define vm_pop() (*(--vm.stacktop))
-#define vm_peek() (vm.stacktop[-1])
+#define vm_peek(i) (vm.stacktop[-1 - i])
#define vm_push(v) (*vm.stacktop++ = (v))
#define vm_get(i) (vm.cf->stackbot[i])
diff --git a/uscript/xbytecode.h b/uscript/xbytecode.h
index 34f7f43..1a7f359 100644
--- a/uscript/xbytecode.h
+++ b/uscript/xbytecode.h
@@ -11,6 +11,7 @@ BC(GET_GLOBAL)
BC(SET_GLOBAL)
BC(GET_UPVAL)
BC(SET_UPVAL)
+BC(PUSH_INDEX)
BC(GET_INDEX)
BC(SET_INDEX)
BC(POP)