environment). Before condemning
Pascal for excessive verbosity, you
may wish to recall the Swiss keyboard
has keycaps for the five English vowels, as well as the French accented
vowels and German umlauted vowels, and hence does not offer so much
punctuation. Before condemning Python and Haskell for whitespace sensitivity, recall that Peter Landin came
up with the “offside rule” in 1966, 7
which “is based on vertical alignment, not character width, and hence
is equally appropriate in handwritten,
typeset, or typed texts.” This was not
only prescient with regard to the presentation of code in variable-width
fonts, but presumably also catered
to the then-common case of one person keypunching code that had been
handwritten on a coding sheet by a
different person.
As Schorre himself notes, because
of the fixpoint nature of this process,
it can, if one is fortunate, be forgiving
of human error: “Someone always asks
if the compiler really produced exactly
the program I had written by hand and
I have to say that it was ‘almost’ the
same program. I followed the syntax
equations and tried to write just what
the compiler was going to produce. Un-
fortunately I forgot one of the redun-
dant instructions, so the results were
not quite the same. Of course, when
the first machine-produced compiler
compiled itself the second time, it re-
produced itself exactly.”
Being lazy, however, I chose to take
a switchback on the ascent, bootstrap-
ping via Python. Much as the Jungfrau-
joch or the Klein Matterhorn can now
be approached via funicular and gon-
dola instead of on foot, we can take
advantage of string and named tuple
library facilities to approach the same
viewpoint with little danger of arriving
out of breath. The pipeline I first set up
was structured as follows:
0. Lexical analysis (unfolding the
character-by-character input string
into a sequence of tokens and literal
strings).
1. Syntax analysis (unfolding the linear lexical list into a syntax tree).
2. Code generation (in a traditional
syntax-directed style).
Depending on your programming
subculture, you may prefer to call this
syntax-directed translation, a visitor
pattern, or even an algebraic homomorphism. No matter what it is called, the
essence of the matter is the mapping
of a composition can be expressed as
the composition of mappings, and we
use this distributive property to divide
and conquer (advice which was probably passed on to Alexander by Aristotle—showing that in certain things the
ancients anticipated Hoare and Blel-loch by at least a few millennia), pushing the problem of translation out to
the leaves of our syntax tree and concatenating the results, thereby folding
the tree back down to a sequence of
output characters.
Each stage is motivated by a structural transformation: the first two
steps take structure that was implicit
in the input and make it explicit, while
the final step uses this explicit structure to guide the translation but then
(using the output from step 1).
Note that Schorre’s character set
does not include “;” hence his quasi-BNF (Backus-Naur Form) is written
within the sequence “.,”. Those in
search of verisimilitude may wish to
use a keypunch simulator to create a
“deck” from Figure 1. Type-ahead is
anachronistic, however, so if you are
going to wear the hairshirt, it may be
better to try talking someone else into
being your keypunch operator.
Before condemning APL for excessive terseness, you may want to
remember both that it was formed
before standard character sets, and
that at 110 baud, you have much more
time to think about each character
typed than you do with an autocom-pleting IDE (integrated development
Figure 4. This is Figure 6. 3 from Schorre’s original paper.
Constant and Control Codes
ADR IDEN T ADDRESS Produces the address that is assigned to the given identifier as a
constant.
END END Denotes the end of the program.
Figure 3. This is Figure 6. 2 in Schorre’s original paper.
R RETURN Return to the exit address, popping up the stack by one or three
cells according to the flag. If the stack is popped by only one cell,
then clear the top two cells to blanks, because they were blank
when the subroutine was entered.
SET SET Set branch switch on.
B AAA BRANCH Branch unconditionally to location AAA.
BT AAA BRANCH IF TRUE Branch to location AAA if switch is on. Otherwise, continue in
sequence.
BF AAA BRANCH IF FALSE Branch to location AAA if switch is off. Otherwise, continue in
sequence.
BE BRANCH TO ERROR
IF FALSE
Halt if switch is off, other wise, continue in sequence.
CL STRING COPY LITERAL Output the variable length string given as the argument. A blank
character will be inserted in the output following the string.
CI COPY INPUT Output the last sequence of characters deleted from the input
string. This command may not function properly if the last
command which could cause deletion failed to do so.
GN1 GENERATE 1 This concerns the current label 1 cell; that is, the next to top cell
in the stack, which is either clear or contains a generated label. If
clear, generate a label and put it into that cell. Whether the label
has just been put into the cell or was already there, output it.
Finally, insert a blank character in the output following the label.
GN2 GENERATE 2 Same as GN1, except that it concerns the current label 2 cell; that
is, the top cell in the stack.
LB LABEL Set the output counter to card column 1.
OUT OUTPUT Punch card and reset output counter to card column 8.