#include #include #include "panic.h" #include "slice.h" #include "value.h" #include "encoding.h" struct reader { struct slice data; int n; }; static void advance(struct reader *r, int size) { r->data = slice1(r->data, size); r->n += size; } static uint8_t parse_byte(struct reader *r) { if (r->data.size < 1) { panicf("read byte: no data!\n"); } uint8_t res = r->data.buf[0]; advance(r, 1); return res; } static local parse_local(struct reader *r) { if (r->data.size < 1) { panicf("local: no data!\n"); } local res = r->data.buf[0]; if (res > 7) { panicf("Invalid local (out of range): %d\n", res); } advance(r, 1); return res; } static value parse_value(struct reader *r) { if (r->data.size < 8) { panicf("value: no data!\n"); } uint64_t res = *(uint64_t *) r->data.buf; advance(r, 8); return res; } static struct arg parse_arg(struct reader *r, bool is_const) { if (is_const) { return (struct arg) { .constant = parse_value(r) }; } return (struct arg) { .local = parse_local(r) }; } static uint8_t parse_offset(struct reader *r) { if (r->data.size < 1) { panicf("offset: no data!\n"); } uint8_t res = r->data.buf[0]; advance(r, 1); return res; } struct result parse(struct slice data) { struct reader r = { .data = data, .n = 0 }; uint8_t codeByte = parse_byte(&r); enum opcode code = codeByte >> 2; bool arg1_const = codeByte & 0x2; // bool arg2_const = codeByte & 0x1; struct op out = { .code = code, }; switch (code) { case OALLOC: out.alloc.out = parse_local(&r); out.alloc.size = parse_arg(&r, arg1_const); break; case OCALL: // No arguments. break; case OPOKE: out.poke.offset = parse_offset(&r); out.poke.pointer = parse_local(&r); out.poke.value = parse_arg(&r, arg1_const); break; case OPEEK: out.peek.out = parse_local(&r); out.peek.offset = parse_offset(&r); out.peek.value = parse_arg(&r, arg1_const); break; case OSHUF: out.shuf.out = parse_local(&r); out.shuf.value = parse_arg(&r, arg1_const); break; case OEXIT: out.exit.value = parse_arg(&r, arg1_const); break; default: panicf("Invalid code %d\n", code); } return (struct result) { .op = out, .n = r.n, }; }