#include "scheme.h" int debug; Biobuf pin, pout, perr;Sexp *empty, *true, *false;Sexp *quote, *quasiquote, *unquote, *unquotesplicing, *λ, *lambda, *beta, *delta; static Sexp *symtab; static Sexp*findsymbol(char *s){ Sexp *e, *sym; for(e = symtab; e != empty; e = e->cdr){ sym = e->car; if(strcmp((char*)sym->cdr, s) == 0) return sym; } return nil;} /* Get a symbol, make one if necessary */Sexp*getsymbol(char *s){ Sexp *e; e = findsymbol(s); if(e == 0){ e = consatom(Symbol, 0, (uintptr)strdup(s)); symtab = cons(e, symtab); } return e;} Sexp*cons(Sexp *a, Sexp *b){ Sexp *e; pushroot(&a); pushroot(&b); e = alloccell(); poproot(); poproot(); e->car = a; e->cdr = b; return e;} Sexp*copycons(Sexp *a){ Sexp *e; pushroot(&a); e = alloccell(); poproot(); e->car = a->car; e->cdr = a->cdr; return e;} Sexp*consatom(int type, uintptr a, uintptr b){ Sexp *e; a <<= 6; a |= 1<<1; a |= type<<2; e = alloccell(); e->cari = a; e->cdri = b; return e;} Sexp*makevector(int len, Sexp *init){ int i; Sexp **vec; vec = malloc(len*sizeof(*vec)); for(i = 0; i < len; i++) vec[i] = init; return consatom(Vector, len, (uintptr)vec);} voidvectorset(Sexp *vec, int i, Sexp *e){ ((Sexp**)vec->cdr)[i] = e;} Sexp*vectorref(Sexp *vec, int i){ return ((Sexp**)vec->cdr)[i];} intvectorlen(Sexp *vec){ return vec->cari >> 6;} intisatom(Sexp *e){ return e->cari & 0x2;} intispair(Sexp *e){ return !(e->cari & 0x2);} intgettype(Sexp *e){ return e->cari>>2 & 0xF;} /* TODO: iterate */intlistlen(Sexp *e){ if(e == empty) return 0; return 1 + listlen(e->cdr);} Sexp*assq(Sexp *obj, Sexp *alist){tail: if(alist == empty) return false; if(alist->car->car == obj) return alist->car; alist = alist->cdr; goto tail;} /* TODO: unused, iterate */Sexp*pairlis(Sexp *keys, Sexp *values, Sexp *alist){ Sexp *ret; if(keys == empty || values == empty) return alist; pushroot(&keys); pushroot(&values); ret = cons(cons(keys->car, cons(values->car, empty)), pairlis(keys->cdr, values->cdr, alist)); poproot(); poproot(); return ret;} /* TODO: check GC, iterate */Sexp*pairargs(Sexp *vars, Sexp *values, Sexp *env){ Sexp *ret, *a, *b; if(vars == empty) return env; if(isatom(vars)) return cons(cons(vars, cons(values, empty)), env); pushroot(&vars); pushroot(&values); a = cons(vars->car, cons(values->car, empty)); pushroot(&a); b = pairargs(vars->cdr, values->cdr, env); pushroot(&b); ret = cons(a, b); poproot(); poproot(); poproot(); poproot(); return ret;} Sexp*reverse(Sexp *lst){ Sexp *rev; rev = empty; // TODO: save lst?tail: if(lst == empty) return rev; rev = cons(lst->car, rev); lst = lst->cdr; goto tail;} Sexp*mapcar(Sexp *(*f)(Sexp *), Sexp *lst){ Sexp *tmp; if(lst == empty) return empty; tmp = f(lst->car); pushroot(&tmp); tmp = cons(tmp, mapcar(f, lst->cdr)); poproot(); return tmp;} voidinit(void){ Binit(&pin, 0, OREAD); Binit(&pout, 1, OWRITE); Binit(&perr, 2, OWRITE); initmem(); empty = consatom(Special, 0, 0); true = consatom(Special, 0, 0); false = consatom(Special, 0, 0); symtab = empty; pushroot(&empty); pushroot(&true); pushroot(&false); pushroot(&symtab); λ = getsymbol("λ"); lambda = getsymbol("lambda"); beta = getsymbol("β"); delta = getsymbol("δ"); quote = getsymbol("quote"); quasiquote = getsymbol("quasiquote"); unquote = getsymbol("unquote"); unquotesplicing = getsymbol("unquotesplicing"); initinterp();} voiddofile(char *name){ Biobuf *f; Sexp *e, *ret; f = Bopen(name, OREAD); if(f == nil){ Bprint(&perr, "couldn't open file %s\n", name); Bflush(&perr); return; } while(e = readsexp(f)) eval(e, &ret); Bterm(f);} voidprintvalues(int n, Sexp *v, Biobuf *f){ if(n == 0) return; if(v->car->car == beta) Bprint(f, "β-closure"); else printsexp(v->car, f); Bprint(f, "\n"); printvalues(n-1, v->cdr, f);} voidmain(int argc, char *argv[]){ Sexp *e, *ret; int n; ARGBEGIN{ case 'd': debug++; break; default: break; }ARGEND; if(sizeof(void*) < sizeof(flonum) || sizeof(void*) < sizeof(fixnum)){ fprint(2, "error: fixnum/flonum have wrong size\n"); exits("size"); } init(); // dofile("lib.scm"); gcenable = 1; while(e = readsexp(&pin)){ if(e == nil) break; n = eval(e, &ret); if(n > 0){ Bprint(&pout, "-> "); printvalues(n, ret, &pout); Bflush(&pout); } } exits(nil);}
#include "scheme.h"
int debug;
Biobuf pin, pout, perr;
Sexp *empty, *true, *false;
Sexp *quote, *quasiquote, *unquote, *unquotesplicing,
*λ, *lambda, *beta, *delta;
static Sexp *symtab;
static Sexp*
findsymbol(char *s)
{
Sexp *e, *sym;
for(e = symtab; e != empty; e = e->cdr){
sym = e->car;
if(strcmp((char*)sym->cdr, s) == 0)
return sym;
}
return nil;
}
/* Get a symbol, make one if necessary */
Sexp*
getsymbol(char *s)
{
Sexp *e;
e = findsymbol(s);
if(e == 0){
e = consatom(Symbol, 0, (uintptr)strdup(s));
symtab = cons(e, symtab);
}
return e;
}
Sexp*
cons(Sexp *a, Sexp *b)
{
Sexp *e;
pushroot(&a);
pushroot(&b);
e = alloccell();
poproot();
poproot();
e->car = a;
e->cdr = b;
return e;
}
Sexp*
copycons(Sexp *a)
{
Sexp *e;
pushroot(&a);
e = alloccell();
poproot();
e->car = a->car;
e->cdr = a->cdr;
return e;
}
Sexp*
consatom(int type, uintptr a, uintptr b)
{
Sexp *e;
a <<= 6;
a |= 1<<1;
a |= type<<2;
e = alloccell();
e->cari = a;
e->cdri = b;
return e;
}
Sexp*
makevector(int len, Sexp *init)
{
int i;
Sexp **vec;
vec = malloc(len*sizeof(*vec));
for(i = 0; i < len; i++)
vec[i] = init;
return consatom(Vector, len, (uintptr)vec);
}
void
vectorset(Sexp *vec, int i, Sexp *e)
{
((Sexp**)vec->cdr)[i] = e;
}
Sexp*
vectorref(Sexp *vec, int i)
{
return ((Sexp**)vec->cdr)[i];
}
int
vectorlen(Sexp *vec)
{
return vec->cari >> 6;
}
int
isatom(Sexp *e)
{
return e->cari & 0x2;
}
int
ispair(Sexp *e)
{
return !(e->cari & 0x2);
}
int
gettype(Sexp *e)
{
return e->cari>>2 & 0xF;
}
/* TODO: iterate */
int
listlen(Sexp *e)
{
if(e == empty)
return 0;
return 1 + listlen(e->cdr);
}
Sexp*
assq(Sexp *obj, Sexp *alist)
{
tail:
if(alist == empty)
return false;
if(alist->car->car == obj)
return alist->car;
alist = alist->cdr;
goto tail;
}
/* TODO: unused, iterate */
Sexp*
pairlis(Sexp *keys, Sexp *values, Sexp *alist)
{
Sexp *ret;
if(keys == empty || values == empty)
return alist;
pushroot(&keys);
pushroot(&values);
ret = cons(cons(keys->car, cons(values->car, empty)),
pairlis(keys->cdr, values->cdr, alist));
poproot();
poproot();
return ret;
}
/* TODO: check GC, iterate */
Sexp*
pairargs(Sexp *vars, Sexp *values, Sexp *env)
{
Sexp *ret, *a, *b;
if(vars == empty)
return env;
if(isatom(vars))
return cons(cons(vars,
cons(values, empty)),
env);
pushroot(&vars);
pushroot(&values);
a = cons(vars->car, cons(values->car, empty));
pushroot(&a);
b = pairargs(vars->cdr, values->cdr, env);
pushroot(&b);
ret = cons(a, b);
poproot();
poproot();
poproot();
poproot();
return ret;
}
Sexp*
reverse(Sexp *lst)
{
Sexp *rev;
rev = empty;
// TODO: save lst?
tail:
if(lst == empty)
return rev;
rev = cons(lst->car, rev);
lst = lst->cdr;
goto tail;
}
Sexp*
mapcar(Sexp *(*f)(Sexp *), Sexp *lst)
{
Sexp *tmp;
if(lst == empty)
return empty;
tmp = f(lst->car);
pushroot(&tmp);
tmp = cons(tmp, mapcar(f, lst->cdr));
poproot();
return tmp;
}
void
init(void)
{
Binit(&pin, 0, OREAD);
Binit(&pout, 1, OWRITE);
Binit(&perr, 2, OWRITE);
initmem();
empty = consatom(Special, 0, 0);
true = consatom(Special, 0, 0);
false = consatom(Special, 0, 0);
symtab = empty;
pushroot(&empty);
pushroot(&true);
pushroot(&false);
pushroot(&symtab);
λ = getsymbol("λ");
lambda = getsymbol("lambda");
beta = getsymbol("β");
delta = getsymbol("δ");
quote = getsymbol("quote");
quasiquote = getsymbol("quasiquote");
unquote = getsymbol("unquote");
unquotesplicing = getsymbol("unquotesplicing");
initinterp();
}
void
dofile(char *name)
{
Biobuf *f;
Sexp *e, *ret;
f = Bopen(name, OREAD);
if(f == nil){
Bprint(&perr, "couldn't open file %s\n", name);
Bflush(&perr);
return;
}
while(e = readsexp(f))
eval(e, &ret);
Bterm(f);
}
void
printvalues(int n, Sexp *v, Biobuf *f)
{
if(n == 0)
return;
if(v->car->car == beta)
Bprint(f, "β-closure");
else
printsexp(v->car, f);
Bprint(f, "\n");
printvalues(n-1, v->cdr, f);
}
void
main(int argc, char *argv[])
{
Sexp *e, *ret;
int n;
ARGBEGIN{
case 'd':
debug++;
break;
default:
break;
}ARGEND;
if(sizeof(void*) < sizeof(flonum) ||
sizeof(void*) < sizeof(fixnum)){
fprint(2, "error: fixnum/flonum have wrong size\n");
exits("size");
}
init();
// dofile("lib.scm");
gcenable = 1;
while(e = readsexp(&pin)){
if(e == nil)
break;
n = eval(e, &ret);
if(n > 0){
Bprint(&pout, "-> ");
printvalues(n, ret, &pout);
Bflush(&pout);
}
}
exits(nil);
}