We collect the necessary type declarations here for convenience:
typedef unsigned char uchar; struct env; typedef unsigned long
long int nis; typedef uchar * cp; typedef struct{struct env * e;
cp c;} fun; typedef struct val pf(nis); typedef struct val
{uchar tag; union{nis i; fun f; pf * p;} u;} val; // tag=0 for
i; tag=1 for f; tag=2 for p. typedef struct env {val v; struct
env * out;} env; 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;  I just now recalled why mark
and sweep was used rather than the simpler and more obvious
reference count mechanism. Reference counts do not find and
recover the space occupied by isolated loops of linked
structures. A purely functional language, such as our λ calculus
can produce no loops for lack of any structure mutating side-
effects. I now know no reason to i