#include #include #include "encoding.h" #include "heap.h" #include "panic.h" #include "slice.h" #include "value.h" #include "oper.h" struct st { size_t i; value locals[NUM_LOCALS]; struct heap heap; }; static value read_arg(struct st *s, struct arg arg) { if (arg.constant) { return arg.constant; } return s->locals[arg.local]; } static void oalloc(struct st *s, struct op oper) { s->locals[oper.alloc.out] = from_pointer(alloc(&s->heap, to_int(read_arg(s, oper.alloc.size)))); } static void call(struct st *s) { s->i = to_int(s->locals[0]); } static void poke(struct st *s, struct op oper) { value *p = to_pointer(s->locals[oper.poke.pointer]); p[oper.poke.offset] = read_arg(s, oper.poke.value); } static void peek(struct st *s, struct op oper) { value *p = to_pointer(read_arg(s, oper.peek.value)); s->locals[oper.peek.out] = p[oper.peek.offset]; } static void shuf(struct st *s, struct op oper) { s->locals[oper.shuf.out] = read_arg(s, oper.shuf.value); } static void oexit(struct st *s, struct op oper) { exit(to_int(read_arg(s, oper.exit.value))); } static void op(struct st *s, struct op oper) { switch (oper.code) { case OALLOC: oalloc(s, oper); break; case OCALL: call(s); break; case OPOKE: poke(s, oper); break; case OPEEK: peek(s, oper); break; case OSHUF: shuf(s, oper); break; case OEXIT: oexit(s, oper); break; default: panicf("Invalid op: %x\n", oper.code); } } void run(struct slice prog) { struct st s = { .i = 0, .locals = { 0 }, }; s.heap = new_heap((struct val_slice) { .size = NUM_LOCALS, .buf = s.locals }); while (true) { struct result oper = parse(slice1(prog, s.i)); s.i += oper.n; op(&s, oper.op); } }