http://www.cs.otago.ac.nz/staffpriv/ok/pop2.htm
is mine. I have in fact typed a lot of that code in,
have begun retyping RMYCIN, and have written but not
yet debugged other stuff.
I am not yet ready to put that stuff on line, but
would be happy to send it by e-mail to the original
poster.
As the Silver Book says, "FOURS is a game of three-dimensional noughts
and crosses, played on a 4x4x4 board."
My "stash" includes over 400 solutions to RosettaCode problems,
which I have not yet tested (because my compiler is not yet finished).
I would be thrilled to the very socks to be given a copy of the
POPLAN interpreter materials in exchange.
A word of warning: the primary reference for Pop-2 is the Silver Book,
but the language kept on developing until the mid to late 1980s. For
example, the Pop-2 system I used at Edinburgh included "properties"
(hash tables), which are not in the Silver Book. By the time anyone
thought about revising that, Pop-11 had replaced Pop-2. As an
example of Pop-2 development, the language described in the Silver
Book includes loopif Cond then Stmts close, which is a cross between
a 'while' loop and a Dijkstra 'do' loop (in that it can have more than
one alternative), but the library hadn't been updated to use that
feature.
The AI department at Edinburgh used an Emacs-like editor called
DOPE (the Display-Oriented Pop Editor) in the 1980s, a lineal
descendant of the "77 editor", using the "piece table" approach.
I might have that on a tape somewhere, but have no tape drive to
read it, sorry.
DAI Edinburgh lost a lot of stuff in a fire, sadly, including Pop-2
materials.
Oh yes, this should be Man or Boy. UNTESTED!
"""
function A k x1 x2 x3 x4 x5;
function B kref;
vars k;
kref.cont -> k;
k-1 -> k;
k -> kref.cont;
A(k, B, x1, x2, x3, x4)
end;
if k <= 0 then
x4() + x5()
else
apply(B(% consref(k) %))
close
end;
A(10, lambda; 1 end, lambda; -1 end,
lambda; -1 end, lambda; 1 end,
lambda; 0 end) =>
"""
The Algol 60 function A has an integer parameter k passed by
value and five other parameters passed by name. Pass by name was meant
to be like pass by reference, but what Algol 60 actually specified was
basically a pair of procedures (L,R), the L procedure being called when
you wanted an address to store into and the R procedure being called
when you wanted a value (the modern word for R is "thunk"). That's
why the Algol code has x4 + x5 and the Pop-2 code has x4() + x5(),
and it's always why the Pop-2 code has anonymous functions
(lambda ; end) in the top level call to A where Algol
had constants.
The thing that makes this example a bit of a pain in Pop-2, and more
of a pain than in Pop-11, is the scope rules. A funny thing happened
in the early days of Lisp. McCarthy et all meant to specify the
same kind of static scope rules that Lisp and Scheme now enjoy, but
by mistake implemented 'dynamic scope'. One way to think of it is
that all references to an identifier always go to the same static
location; when you enter a scope where a variable is (re)declared
its old value is saved on a stack, and restored when you leave that
scope. (Common Lisp now calls this "fluid binding".) Pop-2 went
with Lisp. By the mid-1980s 'vars' had been replaced by 'lvars'
("Lexically scoped VARiableS"). The language described in the
Silver Book didn't have lvars. Nor did functions capture their
non-local variables in "closures". Closures had to be made by hand.
B(% ... %) says "make a closure where the code part is B and the
values of ... will be passed as extra arguments at the end." Now
B needs to change k, so we stuff the value of k into a one-word
record called a "reference".
Finally, => is called the "print arrow". Inside a function, it
prints and removes the top item on the stack. At top level, it
prints and removes everything on the stack.