summaryrefslogtreecommitdiff
path: root/com.c
diff options
context:
space:
mode:
Diffstat (limited to 'com.c')
-rw-r--r--com.c21
1 files changed, 17 insertions, 4 deletions
diff --git a/com.c b/com.c
index a3cc5a8..66d3941 100644
--- a/com.c
+++ b/com.c
@@ -43,6 +43,7 @@ static int stack_effect_of(Op opcode) {
case OP_SKIP:
case OP_REDO:
case OP_SETGLOBAL:
+ case OP_SETLOCAL:
case OP_RET:
case OP_HALT:
return 0;
@@ -141,13 +142,25 @@ void single_form(Compiler *C, AstVec l, Op op) {
compile_opcode(C, op);
}
+static Local *locate_local(Compiler *C, char *name);
+
void set_form(Compiler *C, AstVec l, Op _) {
AstNode ident = l.vals[1];
CHECK(ident.ty == AST_IDENT, "set's first argument must be identifier");
- ObjString *o = objstring_copy_cstr(C->S, ident.as.str);
- compile_node(C, l.vals[2]);
- compile_opcode(C, OP_SETGLOBAL);
- compile_byte(C, compile_constant(C, VAL_OBJ(o)));
+ char *name = ident.as.str;
+
+ Local *loc = locate_local(C, name);
+ if (loc != NULL) {
+ compile_node(C, l.vals[2]);
+ 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]);
+ compile_opcode(C, OP_SETGLOBAL);
+ compile_byte(C, compile_constant(C, VAL_OBJ(o)));
+ }
}
void do_form(Compiler *C, AstVec l, Op _) {