diff options
-rw-r--r-- | com.c | 56 | ||||
-rw-r--r-- | dis.c | 9 | ||||
-rw-r--r-- | todo | 4 | ||||
-rw-r--r-- | vm.c | 19 | ||||
-rw-r--r-- | vm.h | 3 |
5 files changed, 67 insertions, 24 deletions
@@ -35,26 +35,44 @@ static void compile_node(State *S, Chunk *ch, AstNode a) { CK(l.len == 2, "print requires exactly 1 argument"); compile_node(S, ch, l.vals[1]); chunk_wbc(S, ch, OP_PRINT); - break; - } - CK(l.len == 3, "can only compile binary ops"); - char opchar = l.vals[0].as.str[0]; - Op op; - switch (opchar) { - #define OP(char, code) case char: op = code; break; - OP('+', OP_ADD) - OP('-', OP_SUB) - OP('*', OP_MUL) - OP('/', OP_DIV) - #undef OP - default: - printf("unkown op %s\n",l.vals[0].as.str); - exit(1); - break; + } else if (0 == strcmp(l.vals[0].as.str, "set")) { + CK(l.len == 3, "set requires exactly 2 arguments"); + AstNode ident = l.vals[1]; + CK(ident.ty == AST_IDENT, "set's first argument must be identifier"); + + size_t len = strlen(ident.as.str); + ObjString *o = objstring_copy(S, ident.as.str, len); + + compile_node(S, ch, l.vals[2]); + chunk_wbc(S, ch, OP_SETGLOBAL); + chunk_wbc(S, ch, chunk_wconst(S, ch, VAL_OBJ(o))); + } else if (0 == strcmp(l.vals[0].as.str, "do")) { + for (int i = 1; i < l.len - 1; i++) { + compile_node(S, ch, l.vals[i]); + chunk_wbc(S, ch, OP_DROP); + } + compile_node(S, ch, l.vals[l.len - 1]); + } else { + + CK(l.len == 3, "can only compile binary ops"); + char opchar = l.vals[0].as.str[0]; + Op op; + switch (opchar) { + #define OP(char, code) case char: op = code; break; + OP('+', OP_ADD) + OP('-', OP_SUB) + OP('*', OP_MUL) + OP('/', OP_DIV) + #undef OP + default: + printf("unkown op %s\n",l.vals[0].as.str); + exit(1); + break; + } + compile_node(S, ch, l.vals[1]); + compile_node(S, ch, l.vals[2]); + chunk_wbc(S, ch, op); } - compile_node(S, ch, l.vals[1]); - compile_node(S, ch, l.vals[2]); - chunk_wbc(S, ch, op); #undef CK } } @@ -30,7 +30,16 @@ void disasm_chunk(Chunk *ch) { println_val(k); break; } + case OP_SETGLOBAL: { + uint8_t ix = ch->bc.d[ip++]; + printf("setglobal #%d\t; ",ix); + Val k = ch->consts.d[ix]; + printf("%-4s : ",typename_str(k)); + println_val(k); + break; + } SIMPLE_INSTR(OP_PRINT, "print") + SIMPLE_INSTR(OP_DROP, "drop") SIMPLE_INSTR(OP_ADD, "add") SIMPLE_INSTR(OP_SUB, "sub") SIMPLE_INSTR(OP_MUL, "mul") @@ -1,7 +1,3 @@ -string interning - pass state through all allocation things - decide on state vs global state, terminology -globals, getting and setting functions, returning locals, lexical scoping, closures, upvalues lists, hashes, other useful types @@ -56,6 +56,7 @@ void runvm(State *S) { #define PUSH(v) th->stack[th->sp++] = v; #define POP() (th->stack[--th->sp]) +#define PEEK() (th->stack[th->sp-1]) puts("---"); while (1) { @@ -75,7 +76,10 @@ void runvm(State *S) { break; } case OP_PRINT: - println_val(POP()); + println_val(PEEK()); + break; + case OP_DROP: + --th->sp; break; case OP_GETGLOBAL: { @@ -90,6 +94,19 @@ void runvm(State *S) { PUSH(v); break; } + case OP_SETGLOBAL: { + uint8_t cix = RBYTE(); + Val varname = ch->consts.d[cix]; + if (!IS_STRING(varname)) { + printf("global names must be string, not %s\n", + typename_str(varname)); + goto done; + } + Val v = PEEK(); + + ht_put(S, &S->globals, AS_STRING(varname), v); + break; + } #define ARITH_OP(opcode, OP) \ case opcode: { \ @@ -45,7 +45,10 @@ typedef enum { OP_MUL, OP_DIV, + OP_DROP, + OP_GETGLOBAL, + OP_SETGLOBAL, } Op; void runvm(State *S); |