diff options
-rw-r--r-- | com.c | 21 | ||||
-rw-r--r-- | dis.c | 5 | ||||
-rw-r--r-- | vm.c | 7 | ||||
-rw-r--r-- | vm.h | 1 |
4 files changed, 30 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 _) { @@ -44,6 +44,11 @@ static size_t disasm_instr_h(Chunk *ch, size_t ip, int depth) { printf("getlocal #%d\n",ix); break; } + case OP_SETLOCAL: { + uint8_t ix = ch->bc.d[ip++]; + printf("setlocal #%d\n",ix); + break; + } case OP_SETGLOBAL: { uint8_t ix = ch->bc.d[ip++]; printf("setglobal #%d\t; ",ix); @@ -45,6 +45,7 @@ int runvm(State *S) { if (S->do_trace) { printf("\t[%lu + %lu] : ",th->fp, th->sp); for (int i = 0; i < th->sp; i++) { + printf("(%d) ",i); print_val(th->stack[th->fp + i]); printf(" ; "); } @@ -124,6 +125,12 @@ int runvm(State *S) { PUSH(th->stack[th->fp + lidx]); break; } + case OP_SETLOCAL: { + uint8_t lidx = RBYTE(); + Val v = PEEK(); + th->stack[th->fp + lidx] = v; + break; + } #define BINARY_OP(opcode, OP, RET_TYPE) \ case opcode: { \ @@ -52,6 +52,7 @@ typedef enum { OP_SETGLOBAL, OP_GETLOCAL, + OP_SETLOCAL, OP_TRUE, OP_FALSE, |