diff options
Diffstat (limited to 'com.c')
-rw-r--r-- | com.c | 21 |
1 files changed, 17 insertions, 4 deletions
@@ -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 _) { |