#include #include #include #include #include #include "val.h" #include "vm.h" #include "mem.h" #include "dis.h" Chunk chunk_new() { return (Chunk){ .blen = 0, .bcap = 0, .b = NULL, .clen = 0, .ccap = 0, .c = NULL, }; } size_t chunk_wbc(Chunk *ch, uint8_t byte) { if (ch->blen == ch->bcap) { size_t newsz = (ch->bcap == 0 ? 8 : ch->bcap * 2); ch->b = RENEW_ARR(ch->b, uint8_t, ch->bcap, newsz); ch->bcap = newsz; } size_t ix = ch->blen; ch->b[ix] = byte; ch->blen ++; return ix; } size_t chunk_wconst(Chunk *ch, Val v) { if (ch->clen == ch->ccap) { size_t newsz = (ch->ccap == 0 ? 8 : ch->ccap *2); ch->c = RENEW_ARR(ch->c, Val, ch->ccap, newsz); ch->ccap = newsz; } size_t ix = ch->clen; ch->c[ix] = v; ch->clen ++; return ix; } Vm vm_new(Chunk *ch) { Vm vm = (Vm){ .ch = ch, .ip = 0, .sp = 0 }; for (int i = 0; i < STACKSIZE; i++) { vm.stack[i] = VAL_NIL; } return vm; } void runvm(Chunk *ch) { disasm_chunk(ch); Vm vm = vm_new(ch); #define RBYTE() (vm.ch->b[vm.ip++]) #define PUSH(v) vm.stack[vm.sp++] = v; #define POP() (vm.stack[--vm.sp]) puts("---"); while (1) { uint8_t instr = RBYTE(); switch (instr) { case OP_RET: printf("done!\n"); goto done; break; case OP_LOADK:; uint8_t cix = RBYTE(); Val v = vm.ch->c[cix]; PUSH(v); // printf(" (pushing "); // print_val(v); // printf(")\n"); break; case OP_PRINT: println_val(POP()); break; #define ARITH_OP(opcode, OP) \ case opcode: { \ Val b = POP(); \ Val a = POP(); \ if (!IS_NUM(a) || !IS_NUM(b)) { \ printf("can't do arithmetic on %s and %s\n", \ typename_str(a), typename_str(b)); \ goto done; \ } \ PUSH(VAL_NUM(AS_NUM(a) OP AS_NUM(b))); \ } \ break; ARITH_OP(OP_ADD, +) ARITH_OP(OP_SUB, -) ARITH_OP(OP_MUL, *) ARITH_OP(OP_DIV, /) #undef ARITH_OP } } done:; }