begin comment ALGOL 60 version of program lisp(input,output).
*** version 1, March 28, l988 ***
*** author: F.E.J. Kruseman Aretz ***
*** Philips Research Laboratory Eindhoven ***;
integer maxidf,maxnbr,maxstruct; maxidf ≔ 200; maxnbr ≔ 200; maxstruct ≔ 2000;
begin
integer sym,shift,lastidf,lastnbr,d24,d25,free,indentation,linewidth,dummy,
f,
args,
p,
id,
olp,
t,
nilv,
quote,
cond,
lambda,
define,
car,
cdr,
cons,
equal,
atom,
numberp,
lessp,
greaterp,
add1,
sub1,
add,
minus,
timesv,
divf;
integer array idf[0:maxidf,0:9],alist[0:maxidf];
real array nbr[0:maxnbr];
integer array a,d[1:maxstruct];
boolean array m[1:maxstruct];
comment *** error handling ***;
procedure errorhandler(errorstring); string errorstring;
begin NLCR; NLCR; PRINTTEXT(“+++ error: ”); PRINTTEXT(errorstring);
goto ex;
end errorhandler;
comment *** representation dependent functions ***;
procedure collect garbage;
begin integer i,j;
free ≔ 0;
for i ≔ 1 step 1 until maxstruct do m[i] ≔ true;
NLCR; PRINTTEXT(“garbage collector: ”);
mark(olp);
for i ≔ 0 step 1 until lastidf - 1 do mark(alist[i]);
for i ≔ 1 step 1 until maxstruct do
if m[i] then begin a[i] ≔ free; free ≔ i end;
if free = 0 then errorhandler(“free list exhausted”);
i ≔ 1; j ≔ free;
for j ≔ carf(j) while j ≠ 0 do i ≔ i + 1;
ABSFIXT(4,0,i); NLCR
end collect garbage;
procedure mark(ref); value ref; integer ref;
begin
work: if ref < d24
then begin if m[ref]
then begin m[ref] ≔ false;
mark(a[ref]); ref ≔ d[ref]; goto work
end
end
end mark;
integer procedure createidf;
begin integer i,j;
i ≔ 0;
for dummy ≔ 0 while i < lastidf do
begin for j ≔ 0 step 1 until 9 do
if idf[lastidf,j] ≠ idf[i,j] then goto diff;
goto old;
diff: i ≔ i + 1
end;
new: i ≔ lastidf; alist[i] ≔ nilv; lastidf ≔ lastidf + 1;
if lastidf = maxidf then
begin for i ≔ 0 step 1 until 99 do
begin NLCR; write(d25+i) end;
errorhandler(“too much identifiers”)
end;
old: createidf ≔ d25 + i
end createidf;
integer procedure createnum(x); real x;
begin integer i;
nbr[last nbr] ≔ x; i ≔ 0;
for dummy ≔ 0 while i < last nbr do
begin if nbr[last nbr] = nbr[i] then goto old;
i ≔ i + 1
end;
new: i ≔ last nbr; last nbr ≔ last nbr + 1;
if last nbr = maxnbr then errorhandler(“too much numbers”);
old: createnum ≔ d24 + i
end createnum;
boolean procedure atomf(x); value x; integer x;
begin atomf ≔ x > d24 end atomf;
boolean procedure numberpf(x); value x; integer x;
begin numberpf ≔ x > d24 ∧ x < d25 end numberpf;
procedure getidfval(x,idf); value x; integer x,idf;
begin idf ≔ x - d25 end getidfval;
real procedure numval(x); value x; integer x;
begin numval ≔ br[ x - d24] end numval;
integer procedure carf(x); value x; integer x;
begin if x > d24
then errorhandler(“car undefined for atomic lisp value”);
carf ≔ a[x]
end carf;
integer procedure cdrf(x); value x; integer x;
begin if x > d24
then errorhandler(“cdr undefined for atomic lisp value”);
cdrf ≔ d[x]
end cdrf;
integer procedure consf(x,y);
value x,y; integer x,y;
begin integer n;
if free = 0 then collect garbage;
n ≔ free; free ≔ a[free];
a[n] ≔ x; d[n] ≔ y; consf ≔ n
end consf;
procedure returncell(x); value x; integer x;
begin a[x] ≔ free; free ≔ x end;
procedure returnlist(x); value x; integer x;
begin for dummy ≔ 0 while x ≠ nilv do
begin returncell(x); x ≔ d[x] end
end returnlist;
procedure recycle(x); value x; integer x;
begin for dummy ≔ 0 while ¬ atomf(x) do
begin recycle(a[x]); returncell(x); x ≔ d[x] end
end recycle;
boolean procedure equalf(x,y);
value x,y; integer x,y;
begin switch s ≔ str,num,id;
work:
if x ÷ d24 = y ÷ d24
then begin goto s[x ÷ d24 + 1];
id: num: equalf ≔ x = y; goto ex;
str: if equalf(a[x],a[y])
then begin x ≔ d[x]; y ≔ d[y];
goto work
end
else equalf ≔ false
end
else equalf ≔ false;
ex:
end equalf;
comment *** input procedures ***;
integer procedure RESYM;
begin integer s;
s ≔ read;
if s = 122 ∨ s = 124 then begin shift ≔ s;
RESYM ≔ RESYM
end else
if s = 16 then RESYM ≔ 93 else
if s = 26 then RESYM ≔ 119 else
if s = 8 ∧ shift = 124 then RESYM ≔ 98 else
if s = 25 ∧ shift = 124 then RESYM ≔ 99 else
if s = 107 then RESYM ≔ 88 else
if s = 32 then RESYM ≔ 0 else
begin s ≔ s ÷ 32×32 + s - s ÷ 16×16;
if s = 0 then errorhandler(“eof”);
RESYM ≔ if s < 10 then s else
if s < 64 then s - 6 else
if s < 96 then s - 46 else s - 87
end
end RESYM;
procedure nextsym;
begin sym ≔ RESYM; PRSYM(sym) end nextsym;
procedure skipspaces;
begin for dummy ≔ 0
while sym = 93 ∨ sym = 118 ∨ sym = 119 do nextsym
end skipspaces;
integer procedure number;
begin real x; boolean signed;
x ≔ 0; signed ≔ (sym = 65);
if signed
then begin nextsym;
if sym > 9 then errorhandler(“digit expected in input”)
end;
for dummy ≔ 0 while sym < 10 do
begin x ≔ 10 × x + sym; nextsym end;
number ≔ createnum(if signed then -x else x)
end number;
integer procedure identifier;
begin integer i;
idf[lastidf,0] ≔ sym; nextsym;
for i ≔ 1 step 1 until 9 do idf[lastidf,i] ≔ 93;
i ≔ 0;
for dummy ≔ 0 while sym < 64 ∧ i < 9 do
begin i ≔ i + 1; idf[lastidf,i] ≔ sym; nextsym end;
for dummy ≔ 0 while sym < 64 do nextsym;
identifier ≔ createidf
end identifier;
integer procedure nextitem;
begin integer lv,op;
skipspaces;
if sym < 10 ∨ sym = 65 then nextitem ≔ number
else
if sym < 64 then nextitem ≔ identifier
else
if sym = 98
then begin nextsym; skipspaces;
if sym = 99
then begin nextitem ≔ nilv; nextsym end
else begin op ≔ olp; olp ≔ consf(nilv,op);
lv ≔ a[olp] ≔ consf(nilv,nilv); nextitem ≔ lv;
a[lv] ≔ nextitem; skipspaces;
if sym = 88
then begin nextsym; d[lv] ≔ nextitem;
skipspaces;
if sym ≠ 99
then errorhandler
(“close missing for dotted pair in input”)
end
else for dummy ≔ 0 while sym ≠ 99 do
begin lv ≔ d[lv] ≔ consf(nilv,nilv);
a[lv] ≔ nextitem; skipspaces
end;
nextsym;
olp ≔ op
end;
end
else
if sym = 120
then begin nextsym;
op ≔ olp; olp ≔ consf(nilv,olp);
lv ≔ a[olp] ≔ consf(nilv,nilv); nextitem ≔ lv;
a[lv] ≔ quote; lv ≔ d[lv] ≔ consf(nilv,nilv); a[lv] ≔ nextitem;
olp ≔ op
end
else errorhandler(“illegal symbol in input”)
end nextitem;
comment *** output procedures ***;
procedure PRSYM(sym); value sym; integer sym;
begin switch sw ≔ a0,a1,a2,a3,a4,a5,a6,a7,a8,a9,
a,b,c,d,e,f,g,h,i,j,k,l,m,
n,o,p,q,r,s,t,u,v,w,x,y,z;
if sym = 93 then SPACE(1) else
if sym = 88 then PRINTTEXT(“.”) else
if sym = 98 then PRINTTEXT(“(”) else
if sym = 99 then PRINTTEXT(“)”) else
if sym = 119 then NLCR else
begin if sym > 35
then errorhandler(“illegal output symbol”);
goto sw[sym+1];
a0: PRINTTEXT(“0”); goto ex;
a1: PRINTTEXT(“1”); goto ex;
a2: PRINTTEXT(“2”); goto ex;
a3: PRINTTEXT(“3”); goto ex;
a4: PRINTTEXT(“4”); goto ex;
a5: PRINTTEXT(“5”); goto ex;
a6: PRINTTEXT(“6”); goto ex;
a7: PRINTTEXT(“7”); goto ex;
a8: PRINTTEXT(“8”); goto ex;
a9: PRINTTEXT(“9”); goto ex;
a: PRINTTEXT(“a”); goto ex;
b: PRINTTEXT(“b”); goto ex;
c: PRINTTEXT(“c”); goto ex;
d: PRINTTEXT(“d”); goto ex;
e: PRINTTEXT(“e”); goto ex;
f: PRINTTEXT(“f”); goto ex;
g: PRINTTEXT(“g”); goto ex;
h: PRINTTEXT(“h”); goto ex;
i: PRINTTEXT(“i”); goto ex;
j: PRINTTEXT(“j”); goto ex;
k: PRINTTEXT(“k”); goto ex;
l: PRINTTEXT(“l”); goto ex;
m: PRINTTEXT(“m”); goto ex;
n: PRINTTEXT(“n”); goto ex;
o: PRINTTEXT(“o”); goto ex;
p: PRINTTEXT(“p”); goto ex;
q: PRINTTEXT(“q”); goto ex;
r: PRINTTEXT(“r”); goto ex;
s: PRINTTEXT(“s”); goto ex;
t: PRINTTEXT(“t”); goto ex;
u: PRINTTEXT(“u”); goto ex;
v: PRINTTEXT(“v”); goto ex;
w: PRINTTEXT(“w”); goto ex;
x: PRINTTEXT(“x”); goto ex;
y: PRINTTEXT(“y”); goto ex;
z: PRINTTEXT(“z”)
end;
ex:
end PRSYM;
procedure analyse(x,r); value x; integer x,r;
begin integer n,l; boolean simple;
if numberpf(x)
then begin real dg,v,absv;
v ≔ numval(x);
if v > 0
then begin absv ≔ v; l ≔ 1 end
else begin absv ≔ - v;l ≔ 2 end;
dg ≔ 10;
for dummy ≔ 0 while dg < absv do
begin l ≔ l + 1; dg ≔ 10 × dg end;
r ≔ createnum(l)
end
else
if atomf(x)
then begin getidfval(x,id); n ≔ 10;
for dummy ≔ 0 while idf[id,n-1] = 93 do n ≔ n - 1;
r ≔ createnum(n)
end
else
if islist(x)
then begin indentation ≔ indentation + 1;
analyselist(x,r,l,simple);
indentation ≔ indentation - 1;
if simple ∧ indentation + l < linewidth
then begin recycle(r); r ≔ createnum(l) end
end
else begin indentation ≔ indentation + 1;
olp ≔ consf(nilv,olp);
r ≔ a[olp] ≔ consf(nilv,nilv);
analyse(carf(x),a[r]); analyse(cdrf(x),d[r]);
indentation ≔ indentation - 1;
if atomf(a[r]) ∧ atomf(d[r])
then begin l ≔ numval(carf(r)) + numval(cdrf(r)) + 5;
if indentation + l < linewidth
then begin recycle(r); r ≔ createnum(l) end
end;
returncell(olp); olp ≔ d[olp]
end
end analyse;
procedure analyselist(x,r,l,simple);
value x; integer x,r,l; boolean simple;
begin if x = nilv
then begin r ≔ nilv; l ≔ 1; simple ≔ true end
else begin olp ≔ consf(nilv, olp);
r ≔ a[olp] ≔ consf(nilv,nilv);
analyse(carf(x),a[r]); analyselist(cdrf(x),d[r],l,simple);
if simple ∧ atomf(a[r])
then l ≔ numval(a[r]) + l + 1
else simple ≔ false;
returncell(olp); olp ≔ d[olp]
end
end analyselist;
boolean procedure islist(x); value x; integer x;
begin
work: if atomf(x)
then islist ≔ equalf(x,nilv)
else begin x ≔ cdrf(x); goto work end
end islist;
procedure writenumber(x); value x; integer x;
begin integer n,d,v;
v ≔ numval(x);
if v < 0 then v ≔ - v;
d ≔ 10;
for dummy ≔ 0 while d < v do d ≔ d × 10;
for d ≔ d ÷ 10 while d > 0·5 do
begin n ≔ v ÷ d; PRSYM(n); v ≔ v - d × n end
end writenumber;
procedure writeidentifier(x); value x; integer x;
begin integer i;
getidfval(x,id);
for i ≔ 0 step 1 until 9 do
if idf[id,i] ≠ 93 then PRSYM(idf[id,i])
end writeidentifier;
procedure writelist(x,r); value x,r; integer x,r;
begin integer a,ind; boolean simple,nl;
PRSYM(98);
if atomf(r)
then begin for dummy ≔ 0 while x ≠ nilv do
begin writevalue(carf(x),r); x ≔ cdrf(x);
if x ≠ nilv then PRSYM(93)
end
end
else begin indentation ≔ indentation + 1; ind ≔ indentation;
for dummy ≔ 0 while x ≠ nilv do
begin a ≔ carf(r);
simple ≔ atomf(a);
if simple
then nl ≔ numval(a) + indentation > linewidth
else nl ≔ indentation > ind;
if nl
then begin indentation ≔ ind;
NLCR; SPACE(ind)
end
else if indentation > ind then PRSYM(93);
writevalue(carf(x),a);
if simple
then indentation ≔ indentation + numval(a) + 1
else indentation ≔ linewidth + 1;
x ≔ cdrf(x); r ≔ cdrf(r)
end;
indentation ≔ ind - 1; NLCR; SPACE(indentation)
end;
PRSYM(99)
end writelist;
procedure writepair(x,r); value x,r; integer x,r;
begin PRSYM(98);
if atomf(r)
then begin writevalue(carf(x),r); PRINTTEXT(“ . ”);
writevalue(cdrf(x),r)
end
else begin indentation ≔ indentation + 1;
writevalue(carf(x),carf(r));
NLCR; SPACE(indentation-1); PRINTTEXT(“ . ”);
NLCR; SPACE(indentation); writevalue(cdrf(x),cdrf(r));
NLCR; SPACE(indentation)
end;
PRSYM(99)
end writepair;
procedure writevalue(x,r); value x,r; integer x,r;
begin if numberpf(x) then writenumber(x)
else
if atomf(x) then writeidentifier(x)
else
if islist(x) then writelist(x,r)
else writepair(x,r)
end writevalue;
procedure write(x); value x; integer x;
begin integer r;
indentation ≔ 0;
analyse(x,r); writevalue(x,r); recycle(r)
end write;
comment *** interpreter proper ***;
integer procedure assoc(x); value x; integer x;
begin integer ax;
getidfval(x,id); ax ≔ alist[id];
if ax = nilv then errorhandler(“identifier has no value”);
assoc ≔ carf(ax)
end assoc;
procedure pairlis(x,y); value x,y; integer x,y;
begin for dummy ≔ 0 while ¬ equalf(x,nilv) do
begin getidfval(carf(x),id); alist[id] ≔ consf(carf(y),alist[id]);
x ≔ cdrf(x); y ≔ cdrf(y)
end
end pairlis;
procedure depairlis(x); value x; integer x;
begin for dummy ≔ 0 while ¬ equalf(x,nilv) do
begin getidfval(carf(x),id); alist[id] ≔ cdrf(alist[id]);
x ≔ cdrf(x)
end
end depairlis;
integer procedure eval(e); value e; integer e;
begin integer care;
work: if atomf(e)
then begin if equalf(e,nilv) ∨ equalf(e,t) ∨ numberpf(e)
then eval ≔ e else eval ≔ assoc(e)
end
else begin care ≔ carf(e);
if equalf(care,cond)
then begin e ≔ evcon(cdrf(e)); goto work end
else if equalf(care,quote)
then eval ≔ carf(cdrf(e))
else begin olp ≔ consf(nilv,olp);
a[olp] ≔ evlist(cdrf(e)); eval ≔ apply(care,a[olp]);
returnlist(a[olp]); returncell(olp); olp ≔ cdrf(olp)
end
end
end eval;
integer procedure apply(f,x);
value f,x; integer f,x;
begin
work: if atomf(f)
then begin
if equalf(f,car) then apply ≔ carf(carf(x))
else
if equalf(f,cdr) then apply ≔ cdrf(carf(x))
else
if equalf(f,cons) then apply ≔ consf(carf(x),carf(cdrf(x)))
else
if equalf(f,equal)
then begin if equalf(carf(x),carf(cdrf(x)))
then apply ≔ t
else apply ≔ nilv
end
else
if equalf(f,atom) then begin if atomf(carf(x))
then apply ≔ t
else apply ≔ nilv
end
else
if equalf(f,numberp) then begin if numberpf(carf(x))
then apply ≔ t
else apply ≔ nilv
end
else
if equalf(f,lessp)
then begin if numval(carf(x)) < numval(carf(cdrf(x)))
then apply ≔ t
else apply ≔ nilv
end
else
if equalf(f,greaterp)
then begin if numval(carf(x)) > numval(carf(cdrf(x)))
then apply ≔ t
else apply ≔ nilv
end
else
if equalf(f,add)
then apply ≔ createnum(numval(carf(x)) + 1)
else
if equalf(f,sub1)
then apply ≔ createnum(numval(carf(x)) - 1)
else
if equalf(f,add)
then apply ≔ createnum(numval(carf(x)) + numval(carf(cdrf(x))))
else
if equalf(f,minus)
then apply ≔ createnum(numval(carf(x)) - numval(carf(cdrf(x))))
else
if equalf(f,timesv)
then apply ≔ createnum(numval(carf(x)) × numval(carf(cdrf(x))))
else
if equalf(f,divf)
then apply ≔ createnum(numval(carf(x)) ÷ numval(carf(cdrf(x))))
else begin f ≔ assoc(f); goto work end
end
else begin pairlis(carf(cdrf(f)),x);
apply ≔ eval(carf(cdrf(cdrf(f))));
depairlis(carf(cdrf(f)))
end
end apply;
integer procedure evcon(x); value x; integer x;
begin integer r;
work: r ≔ carf(x);
if equalf(eval(carf(r)),nilv)
then begin x ≔ cdrf(x); goto work end
else evcon ≔ carf(cdrf(r))
end evcon;
integer procedure evlist(x); value x; integer x;
begin integer res;
if equalf(x,nilv)
then evlist ≔ nilv
else begin olp ≔ consf(nilv,olp); a[olp] ≔ res ≔ consf(nilv,nilv);
a[res] ≔ eval(carf(x)); d[res] ≔ evlist(cdrf(x));
evlist ≔ res;
returncell(olp); olp ≔ cdrf(olp)
end
end evlist;
comment *** initialization ***;
procedure create(lv); integer lv;
begin skipspaces;
lv ≔ identifier;
end create;
procedure init;
begin integer i,j;
d24 ≔ 16777216; d25 ≔ 33554432;
last idf ≔ 0; sym ≔ 93; nilv ≔ d25 + 1;
create(t); create(nilv);
create(quote); create(cond);
create(lambda); create(define);
create(car); create(cdr);
create(cons); create(equal);
create(atom); create(numberp);
create(lessp); create(greaterp);
create(add1); create(sub1);
create(add); create(minus);
create(timesv); create(divf);
olp ≔ nilv;
free ≔ 1; last nbr ≔ 0; linewidth ≔ 40;
for i ≔ 1 step 1 until maxstruct - 1 do a[i] ≔ i + 1;
a[maxstruct] ≔ 0
end init;
comment *** main program ***;
procedure function definitions(x,a,r); value x; integer x,a,r;
begin integer carx,lr;
if equalf(x,nilv)
then r ≔ nilv
else begin carx ≔ carf(x);
a ≔ consf(consf(carf(carx),carf(cdrf(carx))),a);
function definitions(cdrf(x),a,lr);
r ≔ consf(carf(carx),lr)
end
end function definitions;
PRINTTEXT(“Lisp interpreter version 1, Oktober 2004”);
NLCR; NLCR;
init;
for dummy ≔ 0 while true do
begin olp ≔ consf(nilv,olp); a[olp] ≔ p ≔ consf(nilv,nilv);
a[p] ≔ f ≔ nextitem; d[p] ≔ args ≔ nextitem;
NLCR;
if equalf(f,define)
then begin args ≔ carf(args); PRSYM(98);
for dummy ≔ 0 while ¬ equalf(args,nilv) do
begin p ≔ carf(args); write(carf(p));
getidfval(carf(p),id);
alist[id] ≔ consf(carf(cdrf(p)),nilv);
args ≔ cdrf(args);
if ¬ equalf(args,nilv) then SPACE(1)
end;
PRSYM(99)
end
else begin p ≔ apply(f,args);
NLCR; write(p)
end;
olp ≔ cdrf(olp)
end;
ex:
end
end