summaryrefslogtreecommitdiff
path: root/com.c
diff options
context:
space:
mode:
authorubq323 <ubq323@ubq323.website>2024-06-30 21:37:14 +0100
committerubq323 <ubq323@ubq323.website>2024-06-30 21:37:14 +0100
commit4cf1e1fa0e11307005a724225ea3ae2f80a5c037 (patch)
tree600c6ddc587f011f10a125e6dd31eb07ca8137b7 /com.c
parent83382cb1b46eb17f94f16fbbf05b5e471284d797 (diff)
add array index setting syntax
Diffstat (limited to 'com.c')
-rw-r--r--com.c43
1 files changed, 29 insertions, 14 deletions
diff --git a/com.c b/com.c
index ff13815..521adec 100644
--- a/com.c
+++ b/com.c
@@ -59,12 +59,15 @@ static int stack_effect_of(Op opcode) {
case OP_MOD:
case OP_ARRAPPEND:
return -1;
+ case OP_SETIDX:
+ return -2;
// these ones depend on their argument. handle them specifically
case OP_CALL:
case OP_TAILCALL:
case OP_ENDSCOPE:
return 0;
+
default:
ERROR("unknown stack effect of opcode %d",opcode);
}
@@ -172,21 +175,31 @@ void single_form(Compiler *C, AstVec l, Op op) {
static Local *locate_local(Compiler *C, char *name);
void set_form(Compiler *C, AstVec l, Op _, int flags) {
- AstNode ident = l.vals[1];
- CHECK(ident.ty == AST_IDENT, "set's first argument must be identifier");
- char *name = ident.as.str;
-
- Local *loc = locate_local(C, name);
- if (loc != NULL) {
- compile_node(C, l.vals[2], 0);
- compile_opcode(C, OP_SETLOCAL);
- compile_byte(C, loc->slot);
- } else {
- // write global
- ObjString *o = objstring_copy_cstr(C->S, name);
+ AstNode target = l.vals[1];
+ if (target.ty == AST_IDENT) {
+ // set variable, local or global
+ char *name = target.as.str;
+
+ Local *loc = locate_local(C, name);
+ if (loc != NULL) {
+ compile_node(C, l.vals[2], 0);
+ compile_opcode(C, OP_SETLOCAL);
+ compile_byte(C, loc->slot);
+ } else {
+ // write global
+ ObjString *o = objstring_copy_cstr(C->S, name);
+ compile_node(C, l.vals[2], 0);
+ compile_opcode(C, OP_SETGLOBAL);
+ compile_byte(C, compile_constant(C, VAL_OBJ(o)));
+ }
+ } else if (target.ty == AST_LIST) {
+ AstVec pair = target.as.list;
+ CHECK(pair.len == 2, "can only set to (arr, ix) 2-pair");
+ // (value arr ix) <- TOS
compile_node(C, l.vals[2], 0);
- compile_opcode(C, OP_SETGLOBAL);
- compile_byte(C, compile_constant(C, VAL_OBJ(o)));
+ compile_node(C, pair.vals[0], 0);
+ compile_node(C, pair.vals[1], 0);
+ compile_opcode(C, OP_SETIDX);
}
}
@@ -332,6 +345,8 @@ void def_form(Compiler *C, AstVec l, Op _, int flags) {
compile_node(C, l.vals[2], 0);
declare_local(C, l.vals[1].as.str);
// whatever is calling us will compile an OP_DROP next
+ // or, well. not if we're in tail position. but i can't see
+ // any circumstance where you'd want that anyway
compile_opcode(C, OP_NIL);
}