diff options
Diffstat (limited to 'src/interpret.c')
-rw-r--r-- | src/interpret.c | 407 |
1 files changed, 0 insertions, 407 deletions
diff --git a/src/interpret.c b/src/interpret.c deleted file mode 100644 index 580303e..0000000 --- a/src/interpret.c +++ /dev/null @@ -1,407 +0,0 @@ -#include <math.h> -#include <stdio.h> - -#include <posthaste/execute.h> -#include <posthaste/lower.h> -#include <posthaste/utils.h> -#include <posthaste/date.h> -#include <posthaste/vec.h> - -static int64_t load(struct loc l, size_t sp, struct vec *stack, - struct vec *globals) -{ - /* extra runtime branches is another reason this bytecode instruction - * set is slow to interpret. To get rid of this if (), one - * option would be to add LOAD/STORE_GLOBAL instructions that move data - * between the global array and the stack, but this would make the JIT - * slower */ - if (l.l) - return vect_at(int64_t, *stack, l.o + sp); - - return vect_at(int64_t, *globals, l.o); -} - -static void store(struct loc l, int64_t v, size_t sp, struct vec *stack, - struct vec *globals) -{ - if (l.l) { - vect_at(int64_t, *stack, l.o + sp) = v; - return; - } - - vect_at(int64_t, *globals, l.o) = v; -} - -static int64_t interpret_func(struct fn *f, struct vec *args, size_t sp, - struct vec *stack, struct vec *globals) -{ - /* move args to formal locations */ - size_t formal = 0; - foreach_vec(ai, *args) { - int64_t a = vect_at(int64_t, *args, ai); - vect_at(int64_t, *stack, sp + formal) = a; - formal += 1; - } - - vec_reset(args); - - /* load/store from location, selecting between global array and stack. Assumes - * parameter names, generally frowned upon. */ -#define get(l) \ - load(l, sp, stack, globals) - -#define put(l, v) \ - store(l, v, sp, stack, globals) - - /* use computed gotos to avoid extra overhead of loops/switch statements. - * Usually I'm not a huge fan of massive single functions and from a - * stylistic viewpoint maybe prefer breaking each instruction out into - * its own procedure, but this at least saves a bit of typing */ -#define LINK(x) [x] = &&CASE_##x - static void *labels[] = { - LINK(LABEL), - LINK(CALL), - LINK(MOVE), - LINK(ADD), - LINK(SUB), - LINK(MUL), - LINK(DIV), - LINK(ARG), - LINK(RETVAL), - LINK(PRINT_STRING), - LINK(PRINT_INT), - LINK(PRINT_BOOL), - LINK(PRINT_DATE), - LINK(PRINT_NEWLINE), - LINK(PRINT_SPACE), - LINK(DATE_ADD), - LINK(DATE_SUB), - LINK(DATE_DIFF), - LINK(STORE_DAY), - LINK(STORE_MONTH), - LINK(STORE_YEAR), - LINK(LOAD_DAY), - LINK(LOAD_MONTH), - LINK(LOAD_YEAR), - LINK(LOAD_WEEKDAY), - LINK(LOAD_WEEKNUM), - LINK(TODAY), - LINK(RET), - LINK(STOP), - LINK(CONST), - LINK(EQ), - LINK(LT), - LINK(NEG), - LINK(B), - LINK(BZ), - LINK(J), - }; -#undef LINK - -#define JUMP() i = vect_at(struct insn, insns, pc); goto *labels[i.k]; -#define DISPATCH() pc++; JUMP(); - -#define CASE(x) CASE_##x - - size_t pc = 0; - int64_t retval = 0; - struct vec insns = f->insns; - struct insn i = {0}; - /* jump to first instruction */ - JUMP(); - - CASE(STOP) : {return 0;} - CASE(RET) : {return get(i.i0);} - - CASE(LABEL) : {DISPATCH();} - CASE(RETVAL) : {put(i.o, retval); DISPATCH();} - - CASE(J) : {pc = i.v; JUMP();} - - CASE(B) : { - int64_t i0 = get(i.i0); - if (i0) { - pc = i.v; - JUMP(); - } - - DISPATCH(); - } - - CASE(BZ) : { - int64_t i0 = get(i.i0); - if (!i0) { - pc = i.v; - JUMP(); - } - - DISPATCH(); - } - - CASE(ARG) : { - int64_t a = get(i.i0); - vect_append(int64_t, *args, &a); - DISPATCH(); - } - - CASE(CALL) : { - struct fn *cf = find_fn(i.v); - assert(cf); - - retval = interpret_func(cf, args, sp + f->max_sp + 1, stack, - globals); - DISPATCH(); - } - - CASE(MOVE) : { - int64_t i0 = get(i.i0); - put(i.o, i0); - DISPATCH(); - } - - - CASE(ADD) : { - int64_t i0 = get(i.i0); - int64_t i1 = get(i.i1); - int64_t o = i0 + i1; - put(i.o, o); - DISPATCH(); - } - - CASE(SUB) : { - int64_t i0 = get(i.i0); - int64_t i1 = get(i.i1); - int64_t o = i0 - i1; - put(i.o, o); - DISPATCH(); - } - - CASE(MUL) : { - int64_t i0 = get(i.i0); - int64_t i1 = get(i.i1); - int64_t o = i0 * i1; - put(i.o, o); - DISPATCH(); - } - - CASE(DIV) : { - int64_t i0 = get(i.i0); - int64_t i1 = get(i.i1); - int64_t o = i0 / i1; - put(i.o, o); - DISPATCH(); - } - - CASE(CONST) : { - put(i.o, i.v); - DISPATCH(); - } - - CASE(PRINT_DATE) : { - int64_t i0 = get(i.i0); - char str[11] = {0}; - date_to_string(str, i0); - printf("%s", str); - DISPATCH(); - } - - CASE(PRINT_INT) : { - int64_t i0 = get(i.i0); - printf("%lli", (long long)i0); - DISPATCH(); - } - - CASE(PRINT_BOOL) : { - int64_t i0 = get(i.i0); - printf("%s", i0 ? "true" : "false"); - DISPATCH(); - } - - CASE(PRINT_STRING) : { - int64_t i0 = get(i.i0); - printf("%s", (const char *)i0); - DISPATCH(); - } - - CASE(PRINT_NEWLINE) : { - putchar('\n'); - DISPATCH(); - } - - CASE(PRINT_SPACE) : { - putchar(' '); - DISPATCH(); - } - - CASE(LOAD_DAY) : { - int64_t i0 = get(i.i0); - unsigned day = 0; - date_split((ph_date_t)i0, NULL, NULL, &day); - put(i.o, (int64_t)day); - DISPATCH(); - } - - CASE(LOAD_MONTH) : { - int64_t i0 = get(i.i0); - unsigned month = 0; - date_split((ph_date_t)i0, NULL, &month, NULL); - put(i.o, (int64_t)month); - DISPATCH(); - } - - CASE(LOAD_YEAR) : { - int64_t i0 = get(i.i0); - unsigned year = 0; - date_split((ph_date_t)i0, &year, NULL, NULL); - put(i.o, (int64_t)year); - DISPATCH(); - } - - CASE(LOAD_WEEKDAY) : { - int64_t i0 = get(i.i0); - struct tm time = tm_from_date((ph_date_t)i0); - put(i.o, (int64_t)time.tm_wday); - DISPATCH(); - } - - CASE(LOAD_WEEKNUM) : { - int64_t i0 = get(i.i0); - struct tm time = tm_from_date((ph_date_t)i0); - put(i.o, time.tm_yday / 7); - DISPATCH(); - } - - CASE(STORE_DAY) : { - int64_t i0 = get(i.i0); - int64_t i1 = get(i.i1); - - unsigned year = 0; - unsigned month = 0; - date_split((ph_date_t)i0, &year, &month, NULL); - ph_date_t date = date_from_numbers(year, month, i1); - put(i.o, (int64_t)date); - DISPATCH(); - } - - CASE(STORE_MONTH) : { - int64_t i0 = get(i.i0); - int64_t i1 = get(i.i1); - - unsigned year = 0; - unsigned day = 0; - date_split((ph_date_t)i0, &year, NULL, &day); - ph_date_t date = date_from_numbers(year, i1, day); - put(i.o, (int64_t)date); - DISPATCH(); - } - - CASE(STORE_YEAR) : { - int64_t i0 = get(i.i0); - int64_t i1 = get(i.i1); - - unsigned month = 0; - unsigned day = 0; - date_split((ph_date_t)i0, NULL, &month, &day); - ph_date_t date = date_from_numbers(i1, month, day); - put(i.o, (int64_t)date); - DISPATCH(); - } - - CASE(DATE_ADD) : { - int64_t i0 = get(i.i0); - int64_t i1 = get(i.i1); - - struct tm time = tm_from_date((ph_date_t)i0); - time.tm_mday += i1; - mktime(&time); - - ph_date_t date = date_from_tm(time); - put(i.o, (int64_t)date); - DISPATCH(); - } - - CASE(DATE_SUB) : { - int64_t i0 = get(i.i0); - int64_t i1 = get(i.i1); - - struct tm time = tm_from_date((ph_date_t)i0); - time.tm_mday -= i1; - mktime(&time); - - ph_date_t date = date_from_tm(time); - put(i.o, (int64_t)date); - DISPATCH(); - } - - CASE(DATE_DIFF) : { - int64_t i0 = get(i.i0); - int64_t i1 = get(i.i1); - - struct tm time0 = tm_from_date((ph_date_t)i0); - struct tm time1 = tm_from_date((ph_date_t)i1); - - /* close enough at least */ - time_t t0 = mktime(&time0); - time_t t1 = mktime(&time1); - double seconds = difftime(t0, t1); - int64_t days = round(seconds / 86400); - put(i.o, days); - DISPATCH(); - } - - CASE(TODAY) : { - ph_date_t date = current_date(); - put(i.o, (int64_t)date); - DISPATCH(); - } - - CASE(EQ) : { - int64_t i0 = get(i.i0); - int64_t i1 = get(i.i1); - int64_t b = i0 == i1; - put(i.o, b); - DISPATCH(); - } - - CASE(LT) : { - int64_t i0 = get(i.i0); - int64_t i1 = get(i.i1); - int64_t b = i0 < i1; - put(i.o, b); - DISPATCH(); - } - - CASE(NEG) : { - int64_t i0 = get(i.i0); - put(i.o, -i0); - DISPATCH(); - } - -#undef CASE -#undef JUMP -#undef DISPATCH -#undef get -#undef put -} - -void interpret() -{ - struct fn *f = find_fn(0); - assert(f); - - struct vec stack = vec_create(sizeof(int64_t)); - /* arbitrary amount of stack space, could potentially even be expanded - * if we run out but that's currently not implemented */ - vec_reserve(&stack, 65535); - - struct vec globals = vec_create(sizeof(int64_t)); - vec_reserve(&globals, num_globals()); - - struct vec args = vec_create(sizeof(int64_t)); - - interpret_func(f, &args, 0, &stack, &globals); - - vec_destroy(&args); - vec_destroy(&stack); - vec_destroy(&globals); -} |