#include "h.h" #include static int const bug = 0; typedef struct {cp c; env * e;} Fcont; typedef struct {env * v; env * e;} Acont; // we hold a val v in an env! typedef struct cnt {char tag; union {Fcont f; Acont a;} c; struct cnt * C;} cnt; // tag= [0 for Fcont, 1 for Acont.] typedef union {env e; cnt c;} gws; static gws work[worksize]; static int wp = worksize; static gws * fl = 0; // free list static int sts[5]; static void pstat(){int q=0; char * labs[] = {"var", "invoke prim fun", "invoke lam fun", "lambda", "numeral"}; gws * z = fl; while(z) {++q; z = (gws*)z->e.out;} printf("ws = %d, lst = %d\n", worksize - wp, q); {int j; for(j=0; j<5; ++j) printf("%s: %d\n", labs[j], sts[j]);}} static void By(char * x){pstat(); Bye(x);} env * gw(int s){if(fl) {gws * t = fl; fl = (gws*) fl -> e.out; return (env*)t;} if(!wp) {wp=worksize; By("Exhausted!");} return (env*)&work[--wp];} static void pw(env * x){x -> out = (env*)fl; fl = (gws*)x;} static void pc(cnt* x){pw((env*)x);} void crsh(char* d, cp c){exit(printf("%s: compiler bug at %d!", d, c-code));} val eval(cp x, env * e){ // Use the stack at first uchar op; val v; cnt * c = 0; {int j=5; while(j--) sts[j]=0;} void px() {cnt* t=c; pw(c->c.a.v); c=c->C; pc(t);} top: op = *x; if(bug){printf("(%02x @ %d"/*)*/, op, x-code);} if(op < 253) {env * E = e; ++sts[0]; while(op--) if (E) E = E->out; else crsh("bad sym\n", x); v = E->v;} else if(op == 254) { {cnt * w = (cnt*)gw(1); w -> C = c; c = w;} // Grow chain of continuations. c->tag=0; // Fcont c->c.f = (Fcont){3+x+*(us *)(x+1), e}; // Locate expr for argument. x += 3; goto top; // eval fun. dst0: x = c->c.f.c; e = c->c.f.e; // recover from 'call'. c->tag=1; // Acont {env* ep = gw(2); *ep = (env){v, 0}; c->c.a.v = ep; goto top;} dst1: {val f = c->c.a.v->v; // retrieve fun for this application. if(f.tag == 2) {++sts[1]; // f is prim fun to be applied. if(v.tag) By("Numeric operator applied to function"); else v = f.u.p(v.u.i);} else if(f.tag == 1) {++sts[2]; // The applied fun is a lam expr. {env * ee = gw(3); ee->out = f.u.f.e; e = ee;} // extend the environ e->v = v; // endow environ with argument. {px(); x = f.u.f.c; goto top;}} else By("Number as function"); px();}} else if(op == 255) {++sts[3]; v = (val){1, {.f = {e, x+1}}};} else if(op == 253) {nis y = 0; ++x; ++sts[4]; do y = y<<7 | (*x & 0x7f); while(*(x++) < 0x80); v = (val){0, { .i = y }};} if(bug){cnt * x = c; printf("\n("/*)*/); while(x) {printf("t=%d ", x->tag); x=x->C;} printf(/*(*/")\nvt=%d", v.tag); if(!v.tag) printf(" %d", (int)v.u.i); if(v.tag==1){env * z = v.u.f.e; printf("[%x"/*]*/, v.u.f.c-code); while(z) {printf(" e=%d", z->v.tag); if(!z->v.tag) printf(":%d", (int)z->v.u.i); z = z->out;} printf(/*[*/"]");}} if(c) { if(c->tag==0) goto dst0; if(c->tag==1) goto dst1; exit(printf("Blather\n"));} pstat(); return v;}