#include "h.h" #include static env work[worksize]; static int wp; void crsh(char* d, cp c){exit(printf("F %s: compiler bug at %d!", d, c-code));} static env * fl = 0; // free list void init(){fl=0; wp = worksize;} env * gw(){if(fl) {env * t = fl; fl = fl -> out; return t;} if(!wp) {wp=worksize; Bye("Exhausted!");} return &work[--wp];} void dc(env* e){if(e) {--e->refcnt; if(!e->refcnt) {dc(e->out); if(e->v.tag==1 && e->v.u.f.e) dc(e->v.u.f.e); e->v.tag=0x89; // poison! e->out = fl; fl = e;}}} static void nv(val * vp){if(vp->tag==1 && vp->u.f.e) ++vp->u.f.e->refcnt;} void pm(void){int k=0; env* F=fl; while(F) {++k; if(F<&work[wp] || F >= &work[worksize]) printf("Fox\n"); if(F->refcnt) printf("Foo: %d\n", F->v.tag); F=F->out;} if (wp+k != worksize-6) printf("F wp=%d k=%d ws=%d\n", wp, k, worksize);} val eval(cp x, env * e){ // Use the stack at first if(e->v.tag&0x80) crsh("Zilch", x); uchar op = *x; if(op < 0xfd) {env* E=e; while(op--) if (E) E = E->out; else crsh("bad sym\n", x); {val v = E->v; nv(&v); dc(e); return v;}} if(op == 0xfe) {++e->refcnt; val f = eval(x+3, e); // function to apply val a = eval(3+x+*(us *)(x+1), e); // argument to apply it to if (f.tag == 2) { if(a.tag) Bye("Numeric operator applied to function"); {val vv = f.u.p(a.u.i); nv(&vv); return vv;}} if (f.tag == 1) {env * e2 = gw(); *e2 = (env){1, a, f.u.f.e}; // extended environ return eval(f.u.f.c, e2);} if (f.tag == 0) {printf("n=%lld ",f.u.i); Bye("number as function");} crsh("Bogus", 0);} if(op == 0xff) {return (val){1, {.f = {e, x+1}}};} {nis y = 0; dc(e); do y = y<<7 | (*++x & 0x7f); while(*x < 0x80); return (val){0, { .i = y }};}}