<< . .

. 7
( : 45)

. . >>

tells to delete the next token (the unwanted ˜:™); then type ˜I;™,
which inserts a semicolon. This semicolon protects the rest of line 2 from being
¬‚ushed away, so all will go well until reaches another garbled line.
The next error message is more elaborate, because it is detected while
is trying to carry out a penpos command; penpos is not a primitive
operation (it is de¬ned in plain ), hence a lot more context is given:
>> l0
! Improper transformation argument.
<to be read again>
l.10 penpos1(thick,l0)
; penpos2(.1[thin,thick],90-10);
At ¬rst, such error messages will appear to be complete nonsense to you, because
much of what you see is low-level code that you never wrote. But you
can overcome this hangup by getting a feeling for the way operates.
The bottom line shows how much progress has made so far
in the badio ¬le: It has read ˜penpos1(thick,l0)™ but not yet the semicolon,
on line 10. The penpos routine expands into a long list of tokens; indeed, this
list is so long that it can™t all be shown on two lines, and the appearances of
˜...™ indicate that the de¬nition of penpos has been truncated here. Parameter
values are often inserted into the expansion of a high-level routine; in this case,
for example, ˜(EXPR3)™ and ˜(EXPR4)™ correspond to the respective parameters
˜thick™ and ˜l0™, and ˜(SUFFIX2)™ corresponds to ˜1™. detected an
error just after encountering the phrase ˜rotated(EXPR4)™; the value of (EXPR4)
was an unde¬ned quantity (namely ˜l0™, which treats as the sub-
scripted variable ˜l0 ™ ), and rotation is permitted only when a known numeric
value has been supplied. Rotations are particular instances of what
calls transformations; hence describes this particular error by saying
that an “improper transformation argument” was present.
Chapter 5: Running 45

When you get a multiline error message like this, the best clues about
the source of the trouble are usually on the bottom line (since that is what
you typed) and on the top line (since that is what triggered the error message).
Somewhere in there you can usually spot the problem.
If you type ˜H™ now, you™ll ¬nd that has simply decided to
continue without doing the requested rotation. Thus, if you respond by typing
return , will go on as if the program had said ˜penpos1(thick,0)™.
Comparatively little harm has been done; but there™s actually a way to ¬x the
error perfectly before proceeding: Insert the correct rotation by typing
I rotated 10
and will rotate by 10 degrees as if ˜l0™ had been ˜10™.
What happens next in Experiment 5? will hiccup on the
remaining bug that we planted in the ¬le. This time, however, the typo will
not be discovered until much later, because there™s nothing wrong with line 11
as it stands. (The variable thinn is not de¬ned, but unde¬ned quantities are
no problem unless you™re doing something complicated like rotation. Indeed,
programs typically consist of equations in which there are lots of
unknowns; variables get more and more de¬ned as time goes on. Hence spelling
errors cannot possibly be detected until the last minute.) Finally comes the
moment of truth, when badio tries to draw a path through an unknown point;
and you will get an error message that™s even scarier than the previous one:
>> 0.08682thinn+144
! Undefined x coordinate has been replaced by 0.
<to be read again>
<for(l)> ...FFIX0){up}..z4(SUFFIX0){
left}..cycle; ENDFOR
<to be read again>
l.15 ... ..z3e{up}..z4e{left}..cycle;

Wow; what™s this? The expansion of penstroke involves a “for loop,” and the
error was detected in the midst of it. The expression ˜0.08682thinn+144™ just
above the error message implies that the culprit in this case was a misspelled
˜thin™. If that hadn™t been enough information, you could have gleaned another
clue from the fact that ˜z4(SUFFIX0)™ has just been read; (SUFFIX0) is the
current loop value and ˜<for(l)>™ indicates that the value in question is ˜l™,
hence z4l is under suspicion. (Sure enough, the unde¬ned x coordinate that
provoked this error can be shown to be x4l = 0.08682thinn + 144.)
46 Chapter 5: Running

In any event the mistake on line 11 has propagated too far to be ¬xable, editing
so you™re justi¬ed in typing ˜X™ or ˜E™ at this point. But type ˜S™ instead, just
for fun: This tells to plunge ahead, correcting all remaining errors
as best it can. (There will be a few more problems, since several variables still
depend on ˜thinn™.) will draw a very strange letter O before it gets
to the end of the ¬le. Then you should type ˜end™ to terminate the run.
If you try to edit badio.mf again, you™ll notice that line 2 still contains
a colon instead of a semicolon. The fact that you told to delete the
colon and to insert additional material doesn™t mean that your ¬le has changed
in any way. However, the transcript ¬le badio.log has a record of all the errors,
so it™s a handy reference when you want to correct mistakes. (Why not look at
badio.log now, and io.log too, in order to get familiar with log ¬les?)
Suppose you were doing Experiment 3 with badio instead of io, so you be-
gan by saying ˜\mode=smoke; input badio™. Then you would want to recover from the
error on line 1 by inserting a correct mode setup command, instead of by simply
return ing, because mode setup is what really establishes smoke mode. Unfortu-
nately if you try typing ˜I mode_setup™ in response to the “isolated expression” error,
it doesn™t work. What should you type instead?
By doing the ¬ve experiments in this chapter you have learned at ¬rst
hand (1) how to produce proofsheets of various kinds, including “smoke proofs”;
(2) how to make a new font and test it; (3) how to keep calm when
issues stern warnings. Congratulations! You™re on the threshold of being able to
do lots more. As you read the following chapters, the best strategy will be for
you to continue making trial runs, using experiments of your own design.
However, this has been an extremely long chapter, so you should go outside now
and get some real exercise.
Chapter 5: Running 47


Let us learn how Io™s frenzy came”
She telling her disasters manifold.
” ÆSCHYLUS, Prometheus Bound (c. 470 B.C.)

To the student who wishes to use graphical methods as a tool,
it can not be emphasized too strongly that practice in the use of that tool
is as essential as a knowledge of how to use it.
The oft-repeated pedagogical phrase, “we learn by doing,” is applicable here.
” THEODORE RUNNING, Graphical Mathematics (1927)
(page 48)

Reads What You
Chapter 6: How Reads What You Type 49

So far in this book we™ve seen lots of things that can do, but we ASCII
haven™t discussed what can™t do. We have looked at many examples string tokens
of commands that can understand, but we haven™t dwelt on the numeric tokens
symbolic tokens
fact that the computer will ¬nd many phrases unintelligible. It™s time now to underline
adopt a more systematic approach and to study the exact rules of ™s grammatical rules
language. Then we™ll know what makes sense to the machine, and we™ll also Naur
know how to avoid ungrammatical utterances. angle brackets
syntax rules
A program consists of one or more lines of text, where each
line is made up of letters, numbers, punctuation marks, and other symbols that
appear on a standard computer keyboard. A total of 95 di¬erent characters
can be employed, namely a blank space plus the 94 visible symbols of stan-
dard ASCII. (Appendix C describes the American Standard Code for Informa-
tion Interchange, popularly known as “ASCII,” under which code numbers 33
through 126 have been assigned to 94 speci¬c symbols. This particular coding
scheme is not important to a programmer; the only relevant thing
is that 94 di¬erent nonblank symbols can be used.)
converts each line of text into a series of tokens, and a
programmer should understand exactly how this conversion takes place. Tokens
are the individual lexical units that govern the computer™s activities. They are
the basic building blocks from which meaningful sequences of instructions can
be constructed. We discussed tokens brie¬‚y at the end of the previous chapter;
now we shall consider them in detail. Line 9 of the ¬le io.mf in that chapter is
a typical example of what the machine might encounter:
beginchar("O",0.8em#,cap#,0); "The letter O";
When reads these ASCII characters it ¬nds sixteen tokens:
beginchar ( "O" , 0.8 em # ,
cap # , 0 ) ; "The letter O" ;
Two of these, "O" and "The letter O", are called string tokens because they
represent strings of characters. Two of them, ˜0.8™ and ˜0™, are called numeric
tokens because they represent numbers. The other twelve”˜beginchar™, ˜(™,
etc.”are called symbolic tokens; such tokens can change their meaning while a
program runs, but string tokens and numeric tokens always have a
predetermined signi¬cance. Notice that clusters of letters like ˜beginchar™ are
treated as a unit; the same holds with respect to letters mixed with underline
characters, as in ˜mode_setup™. Indeed, the rules we are about to study will
explain that clusters of other characters like ˜0.8™ and ˜:=™ are also considered
to be indecomposable tokens. has a de¬nite way of deciding where
one token stops and another one begins.
It™s often convenient to discuss grammatical rules by formulating them
in a special notation that was introduced about 1960 by John Backus and Peter
Naur. Parts of speech are represented by named quantities in angle brackets,
and syntax rules are used to express the ways in which those quantities can
50 Chapter 6: How Reads What You Type

be built up from simpler units. For example, here are three syntax rules that decimal digit
digit string
completely describe the possible forms of numeric tokens: numeric token
decimal digit ’’ 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 semantics
digit string ’’ decimal digit | digit string decimal digit numeric tokens, rounded values
numeric tokens, maximum value
numeric token ’’ digit string | . digit string space
| digit string . digit string period
decimal point
percent sign
The ¬rst rule says that a decimal digit is either ˜0™ or ˜1™ or · · · or ˜9™; thus comments
it must be one of the ten numerals. The next rule says that a digit string is decimal digit
double-quote mark
either a decimal digit or a digit string followed by a decimal digit ; thus it
must be a sequence of one or more digits. Finally, a numeric token has one of
three forms, exempli¬ed respectively by ˜15™, ˜.05™, and ˜3.14159™.
Syntax rules explain only the surface structure of a language, not the
underlying meanings of things. For example, the rules above tell us that ˜15™
is a numeric token , but they don™t imply that ˜15™ has any connection with
the number ¬fteen. Therefore syntax rules are generally accompanied by rules
of semantics, which ascribe meanings to the strings of symbols that meet the
conditions of the syntax. In the case of numeric tokens, the principles of ordinary
decimal notation de¬ne the semantics, except that deals only with
numbers in a limited range: A numeric token must be less than 4096, and its
value is always rounded to the nearest multiple of 65536 . Thus, for example,
1 6554 1
˜.1™ does not mean 10 , it means 65536 (which is slightly greater than 10 ). It
turns out that the tokens ˜.099999™ and ˜0.10001™ both have exactly the same
meaning as ˜.1™, because all three tokens represent the value 65536 .
Are the following pairs of numeric tokens equivalent to each other, when they
appear in programs? (a) 0 and 0.00001; (b) 0.00001 and 0.00002;
(c) 0.00002 and 0.00003; (d) 04095.999999 and 10000?

converts each line of text into a sequence of tokens by re-
peating the following rules until no more characters remain on the line:
1) If the next character is a space, or if it™s a period ( ˜.™ ) that isn™t followed
by a decimal digit or a period, ignore it and move on.
2) If the next character is a percent sign ( ˜%™ ), ignore it and also ignore
everything else that remains on the current line. (Percent signs therefore
allow you to write comments that are unseen by .)
3) If the next character is a decimal digit or a period that™s followed by
a decimal digit, the next token is a numeric token, consisting of the
longest sequence of contiguous characters starting at the current place
that satis¬es the syntax for numeric token above.
4) If the next character is a double-quote mark ( ˜"™ ), the next token is a
string token, consisting of all characters from the current place to the
next double-quote, inclusive. (There must be at least one more double-
quote remaining on the line, otherwise will complain about
Chapter 6: How Reads What You Type 51

an “incomplete string.”) A string token represents the sequence of incomplete string
characters between the double-quotes. table of character classes
5) If the next character is a parenthesis ( ˜(™ or ˜)™ ), a comma ( ˜,™ ), or a HOLLAND
semicolon ( ˜;™ ), the next token is a symbolic token consisting of that COWPER
single character. Homer
6) Otherwise the next token is a symbolic token consisting of the next
character together with all immediately following characters that appear
in the same row of the following table:

(see rules 1, 3, 6)
(see rule 5; these characters are “loners”)
(see rule 4 for details about string tokens)
(see rule 3 for details about numeric tokens)
(see rule 2 for details about comments)
The best way to learn the six rules about tokens is to work the following exercise,
after which you™ll be able to read any input ¬le just as the computer does.
What tokens does ¬nd in the (ridiculous) line
xx3.1.6..[[a+-bc_d.e] ]"a %" <|>(($1. 5"+-""" % weird?
Criticize the following statement: ignores all spaces in the input.
True or false: If the syntax for numeric token were changed to include a
fourth alternative, ˜ digit string .™, the meaning of programs would not
change in any way.

Yet wee with all our seeking could see no tokens.
” PHILEMON HOLLAND, Camden™s Brittania (1610)

Unpropitious tokens interfered.
” WILLIAM COWPER, Homer™s Iliad (1791)
(page 52)

Chapter 7: Variables 53

One of ™s most important concepts is the notion of a variable” variable
data structure
something that can take on a variety of di¬erent values. Indeed, this is one of primitive
the most important concepts in all of mathematics, and variables play a promi- macro
nent rˆle in almost all computer languages. The basic idea is that a program
o tag
manipulates data, and the data values are stored in little compartments of a
computer™s memory. Each little compartment is a variable, and we refer to an
item of data by giving its compartment a name.
For example, the io.mf program for the letter in Chapter 5 contains
lots of variables. Some of these, like ˜x1l™ and ˜y1™, represent coordinates. Others,
like ˜up™, represent directions. The variables ˜em#™ and ˜thin#™ stand for physical,
machine-independent distances; the analogous variables ˜em™ and ˜thin™ stand for
the corresponding machine-dependent distances in units of pixels.
These examples indicate that di¬erent variables are often related to each
other. There™s an implicit connection between ˜em#™ and ˜em™, between ˜x1™ and
˜y1™; the ˜penpos ™ convention sets up relationships between ˜x1l™, ˜x1™, and ˜x1r™.
By choosing the names of variables carefully, programmers can make their pro-
grams much easier to understand, because the relationships between variables
can be made to correspond to the structure of their names.
In the previous chapter we discussed tokens, the atomic elements from
which all programs are made. We learned that there are three kinds
of tokens: numeric (representing numbers), string (representing text), and sym-
bolic (representing everything else). Symbolic tokens have no intrinsic meaning;
any symbolic token can stand for whatever a programmer wants it to represent.
Some symbolic tokens do, however, have prede¬ned primitive meanings,
when begins its operations. For example, ˜+™ stands initially for
“plus,” and ˜;™ stands for “¬nish the current statement and move on to the next
part of the program.” It is customary to let such tokens retain their primitive
meanings, but any symbolic token can actually be assigned a new meaning as a
program is performed. For example, the de¬nition of ˜test_I™ in io.mf makes
that token stand for a macro, i.e., a subroutine. We™ll see later that you can
instruct to ˜let plus=+™, after which ˜plus™ will act just like ˜+™ did.
divides symbolic tokens into two categories, depending on
their current meaning. If the symbolic token currently stands for one of -
™s primitive operations, or if it has been de¬ned to be a macro, it is called a
spark; otherwise it is called a tag. Almost all symbolic tokens are tags, because
only a few are de¬ned to be sparks; however, programs typically in-
volve lots of sparks, because sparks are what make things happen. The symbolic
tokens on the ¬rst ¬ve lines of io.mf include the following sparks:

mode_setup ; := / define_pixels ( , )

and the following tags:

em # pt cap thin thick o
54 Chapter 7: Variables

(some of which appear several times). Tags are used to designate variables, but Pascal
sparks cannot be used within a variable™s name. su¬x
Some variables, like ˜em#™, have names that are made from more than subscript
one token; in fact, the variable ˜x1l™ is named by three tokens, one of which is subscript
numeric. has been designed so that it is easy to make compound arrays
names that correspond to the relations between variables. Conventional pro- [
gramming languages like Pascal would refer to ˜x1l™ by the more cumbersome ]
notation ˜x[1].l™; it turns out that ˜x[1].l™ is an acceptable way to designate internal quantities
the variable x1l in a program, but the shorthand form ˜x1l™ is a fontmaking
great convenience because such variables are used frequently.
Here are the formal rules of syntax by which understands
the names of variables:
variable ’’ tag su¬x
su¬x ’’ empty | su¬x subscript | su¬x tag
subscript ’’ numeric token | [ numeric expression ]
First comes a tag, like ˜x™; then comes a su¬x to the tag, like ˜1l™. The su¬x
might be empty, or it might consist of one or more subscripts or tags that are
tacked on to the original tag. A subscript is a numeric index that permits you
to construct arrays of related variables. The subscript is either a single numeric
token, or it is a formula enclosed in square brackets; in the latter case the formula
should produce a numeric value. For example, ˜x[1]™ and ˜x[k]™ and ˜x[3-2k]™
all mean the same thing as ˜x1™, if k is a variable whose value is 1. But ˜x.k™ is
not the same; it is the tag ˜x™ su¬xed by the tag ˜k™, not the tag ˜x™ subscripted
by the value of variable k.
The variables ˜x1™ and ˜x01™ and ˜x1.00™ are identical. Since any numeric token
can be used as a subscript, fractional indices are possible; for example, ˜x1.5™
is the same as ˜x[3/2]™. Notice, however, that ˜B007™ and ˜B.007™ are not the same
variable, because the latter has a fractional subscript.
makes each su¬x as long as possible. In other words, a su¬x
is always extended if it is followed by a subscript or a tag .
Explain how to type a reference to the doubly subscripted variable ˜a[1][5]™
without using square brackets.
Is it possible to refer to any variable without using square brackets?
Jonathan H. Quick (a student) used ˜a.plus1™ as the name of a variable at
the beginning of his program; later he said ˜let plus=+™. How could he refer to the
variable ˜a.plus1™ after that?
has several special variables called internal quantities that are
intimately wired-in to the computer™s behavior. For example, there™s an in-
ternal quantity called ˜fontmaking™ that controls whether or not a tfm ¬le is produced;
Chapter 7: Variables 55

another one called ˜tracingtitles™ governs whether or not titles like "The letter O" tracingtitles
appear on your terminal; still another one called ˜smoothing™ a¬ects the digitization of
curves. (A complete list of ™s internal quantities appears in Chapter 25.) tag
The name of an internal quantity acts like a tag, but internal quantities cannot be italic type
su¬xed. Thus, the syntax rule for variable should actually be replaced by a slightly types
more complicated pair of rules: boolean

<< . .

. 7
( : 45)

. . >>