Commit 1ea6d1f7 authored by paysan's avatar paysan

Changed sources to be more consistent with current ANS Forth style

parent d16e2d99
......@@ -6,6 +6,7 @@ SOURCES = thinking-forth.tex \
preface.tex \
preface94.tex \
preface2004.tex \
preface-ans.tex \
chapter1.tex \
chapter2.tex \
chapter3.tex \
......@@ -76,7 +77,7 @@ LINKCOLOR = blue
# 17x24 for 17cm x 24cm format (one of the standard metric formats)
# splitcover: if you only choose front and back, and the spine is done for you
VERSION = 1.0
VERSION = 2.0-pre1
CP = cp
TAR = tar jcf
MD = mkdir
......
......@@ -49,7 +49,7 @@ portions of an applications, if at all.
Still another defining word is \forthb{CONSTANT},\index{C!CONSTANT} which
is used like this:
\begin{Code}
17 CONSTANT SEVENTEEN
17 Constant SEVENTEEN
\end{Code}
The new word \forth{SEVENTEEN} can now be used in place of the actual
number 17.
......@@ -58,7 +58,7 @@ number 17.
The defining word \forth{VARIABLE}\index{V!VARIABLE} creates a location
for temporary data. \forth{VARIABLE} is used like this:
\begin{Code}
VARIABLE BANANAS
Variable BANANAS
\end{Code}
This reserves a location which is identified by the name \forth{BANANAS}.}
......@@ -96,14 +96,14 @@ For this, \Forth{} employs a much simpler mechanism: the data stack.
When you type a number, it goes on the stack. When you invoke a word
which has numeric input, it will take it from the stack. Thus the phrase
\begin{Code}
17 SPACES
17 spaces
\end{Code}
will display seventeen blanks on the current output device. ``17'' pushes
the binary value 17 onto the stack; the word \forthb{SPACES} consumes it.
A constant also pushes its value onto the stack; thus the phrase:
\begin{Code}
SEVENTEEN SPACES
SEVENTEEN spaces
\end{Code}
has the same effect.
......
......@@ -27,7 +27,7 @@ place it on the return stack. That's all. \Forth{} execution then
continues with this address on the return stack, which will cause the
vectored function to be performed. It's like saying (in '83-Standard)
\begin{Code}
' NOTHING >BODY >R <return>
' NOTHING >body >r <return>
\end{Code}
which executes \forth{NOTHING}. (This trick only works with colon
definitions.)
......@@ -48,7 +48,7 @@ DOER JOE & \\
\noindent Now suppose we define:
\begin{Code}
: TEST MAKE JOE CR ;
: TEST MAKE JOE cr ;
\end{Code}
that is, we define a word that can vector \forth{JOE} to do a carriage
return.
......@@ -68,7 +68,7 @@ TEST & (MAKE) & 0 & JOE & CR & EXIT \\ \hline\noalign{\vspace{2pt}}
\forthb{MAKE} inside a colon definition, \forthb{STATE} will be true, and
we'll execute the phrase:
\begin{Code}
COMPILE (MAKE) HERE MARKER ! 0 ,
COMPILE (MAKE) here marker ! 0 ,
\end{Code}
We can see how \forthb{MAKE} has compiled the address of the run-time
routine, \forthb{(MAKE)}, followed by a zero. (We'll explain what the
......@@ -112,7 +112,7 @@ That's the basic idea. But what about that cell containing zero? That's
for the use of \forthb{;AND}. Suppose we changed \forth{TEST} to read:
\begin{Code}
: TEST MAKE JOE CR ;AND SPACE ;
: TEST MAKE JOE cr ;AND space ;
\end{Code}
That is, when we invoke \forth{TEST} we'll vector \forth{JOE} to do a
\forthb{CR}, and we'll do a \forthb{SPACE} right now. Here's what this
......@@ -130,7 +130,7 @@ TEST & (MAKE) & adr & JOE & CR & EXIT & SPACE & EXIT \\ \hline\noalign{\vspace{2
\end{center}
Here's the definition of \forthb{;AND}:
\begin{Code}
: ;AND COMPILE EXIT HERE MARKER @ ! ; IMMEDIATE
: ;AND COMPILE EXIT here marker @ ! ; immediate
\end{Code}
We can see that \forthb{;AND} has compiled an \forthb{EXIT}\index{E!EXIT},
just as semicolon would.
......@@ -141,7 +141,7 @@ variable called \forthb{MARKER}. Now \forthb{;AND} stores \forthb{HERE}
into the cell previously containing zero. Now \forthb{(MAKE)} has a
pointer to the place to resume execution. The phrase
\begin{Code}
IF >R THEN
IF >r THEN
\end{Code}
will leave on the return stack the address of the code beginning with
\forthb{SPACE}. Thus execution will skip over the code between
......@@ -188,7 +188,7 @@ reason each time).
( DOER/MAKE Shadow screen LPB 12/05/83 )
NOTHING A no-opp
DOER Defines a word whose behavior is vectorable.
MARKER Saves adr for optional continuation pointer.
marker Saves adr for optional continuation pointer.
(MAKE) Stuffs the address of further code into the
parameter field of a doer word.
MAKE Used interpretively: MAKE doer-name forth-code ;
......@@ -206,16 +206,16 @@ UNDO Usage: UNDO doer-name ; makes it safe to execute
\begin{Screen}
\ DOER/MAKE FORTH-83 Laxen/Perry/Harris model LPB 12/05/83
: NOTHING ;
: DOER CREATE ['] NOTHING >BODY , DOES> @ >R ;
VARIABLE MARKER
: (MAKE) R> DUP 2+ DUP 2+ SWAP @ >BODY !
@ ?DUP IF >R THEN ;
: MAKE STATE @ IF ( compiling)
COMPILE (MAKE) HERE MARKER ! 0 ,
ELSE HERE [COMPILE] ' >BODY !
[COMPILE] ] THEN ; IMMEDIATE
: ;AND COMPILE EXIT HERE MARKER @ ! ; IMMEDIATE
: UNDO ['] NOTHING >BODY [COMPILE] ' >BODY ! ;
: DOER Create ['] NOTHING >body , DOES> @ >r ;
Variable marker
: (MAKE) r> dup 2+ dup 2+ swap @ >body !
@ ?dup IF >r THEN ;
: MAKE state @ IF ( compiling)
COMPILE (MAKE) here marker ! 0 ,
ELSE here [compile] ' >body !
[compile] ] THEN ; immediate
: ;AND COMPILE EXIT here marker @ ! ; immediate
: UNDO ['] NOTHING >body [compile] ' >body ! ;
\ The code in this screen is in the public domain.
......@@ -225,16 +225,16 @@ VARIABLE MARKER
\begin{Screen}
( DOER/MAKE FORTH-83 Lab. Micro PC/FORTH 2.0 LPB 12/05/83 )
: NOTHING ;
: DOER CREATE ['] NOTHING >BODY , DOES> @ >R ;
VARIABLE MARKER
: (MAKE) R> DUP 2+ DUP 2+ SWAP @ >BODY !
@ ?DUP IF >R THEN ;
: MAKE STATE @ IF ( compiling)
COMPILE (MAKE) HERE MARKER ! 0 ,
ELSE HERE [COMPILE] ' >BODY !
[COMPILE] ] UNSMUDGE THEN ; IMMEDIATE
: ;AND COMPILE EXIT HERE MARKER @ ! ; IMMEDIATE
: UNDO ['] NOTHING >BODY [COMPILE] ' >BODY ! ;
: DOER Create ['] NOTHING >body , DOES> @ >r ;
Variable marker
: (MAKE) r> dup 2+ dup 2+ swap @ >body !
@ ?dup IF >r THEN ;
: MAKE state @ IF ( compiling)
COMPILE (MAKE) here marker ! 0 ,
ELSE here [compile] ' >body !
[compile] ] UNSMUDGE THEN ; immediate
: ;AND COMPILE EXIT here marker @ ! ; immediate
: UNDO ['] NOTHING >body [compile] ' >body ! ;
( The code in this screen is in the public domain.)
......@@ -245,17 +245,17 @@ VARIABLE MARKER
( DOER/MAKE FIG model LPB 12/05/83 )
: NOTHING ;
: DOES-PFA ( pfa -- pfa of child of <BUILD-DOES> ) 2+ ;
: DOER <BUILDS ' NOTHING , DOES> @ >R ;
0 VARIABLE MARKER
: (MAKE) R> DUP 2+ DUP 2+ SWAP @ 2+ DOES-PFA !
@ -DUP IF >R THEN ;
: MAKE STATE @ IF ( compiling)
COMPILE (MAKE) HERE MARKER ! 0 ,
ELSE HERE [COMPILE] ' DOES-PFA !
SMUDGE [COMPILE] ] THEN ; IMMEDIATE
: ;AND COMPILE ;S HERE MARKER @ ! ; IMMEDIATE
: UNDO ' NOTHING [COMPILE] ' DOES-PFA ! ;
;S
: DOER <BUILDS ' NOTHING , DOES> @ >r ;
0 Variable marker
: (MAKE) r> dup 2+ dup 2+ swap @ 2+ DOES-PFA !
@ -DUP IF >r THEN ;
: MAKE state @ IF ( compiling)
COMPILE (MAKE) here marker ! 0 ,
ELSE here [compile] ' DOES-PFA !
SMUDGE [compile] ] THEN ; immediate
: ;AND COMPILE ;s here marker @ ! ; immediate
: UNDO ' NOTHING [compile] ' DOES-PFA ! ;
;s
The code in this screen is in the public domain.
\end{Screen}
......@@ -263,16 +263,16 @@ The code in this screen is in the public domain.
\begin{Screen}
( DOER/MAKE 79-Standard MVP FORTH LPB 12/05/83 )
: NOTHING ;
: DOER CREATE ' NOTHING , DOES> @ >R ;
VARIABLE MARKER
: (MAKE) R> DUP 2+ DUP 2+ SWAP @ 2+ ( pfa) !
@ ?DUP IF >R THEN ;
: MAKE STATE @ IF ( compiling)
COMPILE (MAKE) HERE MARKER ! 0 ,
ELSE HERE [COMPILE] ' !
[COMPILE] ] THEN ; IMMEDIATE
: ;AND COMPILE EXIT HERE MARKER @ ! ; IMMEDIATE
: UNDO ['] NOTHING [COMPILE] ' ! ;
: DOER Create ' NOTHING , DOES> @ >r ;
Variable marker
: (MAKE) r> dup 2+ dup 2+ swap @ 2+ ( pfa) !
@ ?dup IF >r THEN ;
: MAKE state @ IF ( compiling)
COMPILE (MAKE) here marker ! 0 ,
ELSE here [compile] ' !
[compile] ] THEN ; immediate
: ;AND COMPILE EXIT here marker @ ! ; immediate
: UNDO ['] NOTHING [compile] ' ! ;
( The code in this screen is in the public domain.)
......@@ -283,7 +283,7 @@ VARIABLE MARKER
( TODDLER: Example of DOER/MAKE 12/01/83 )
DOER ANSWER
: RECITAL
CR ." Your daddy is standing on the table. Ask him 'WHY?' "
cr ." Your daddy is standing on the table. Ask him 'WHY?' "
MAKE ANSWER ." To change the light bulb."
BEGIN
MAKE ANSWER ." Because it's burned out."
......@@ -294,8 +294,8 @@ DOER ANSWER
MAKE ANSWER ." Stop saying WHY?"
MAKE ANSWER ." Because it's driving me crazy."
MAKE ANSWER ." Just let me change this light bulb!"
FALSE UNTIL ;
: WHY? CR ANSWER QUIT ;
false UNTIL ;
: WHY? cr ANSWER quit ;
\end{Screen}
\index{D!DOER/MAKE|)}
\vfill
......@@ -17,8 +17,8 @@ Standard is:
\begin{Code}
: ASCII ( -- c) \ Compile: c ( -- )
\ Interpret: c ( -- c)
BL WORD 1+ C@ STATE @
IF [COMPILE] LITERAL THEN ; IMMEDIATE
bl word 1+ c@ state @
IF [compile] Literal THEN ; immediate
\end{Code}
\section{From \Chap{5}}
......@@ -26,44 +26,44 @@ Standard is:
The word \forthb{\bs}\index{S!Skip commands} can be defined as:
\begin{Code}
: \ ( skip rest of line)
>IN @ 64 / 1+ 64 * >IN ! ; IMMEDIATE
>in @ 64 / 1+ 64 * >in ! ; immediate
\end{Code}
If you decide not to use \forthb{EXIT} to terminate a screen, you can
define \forthb{\bs S} as:
\begin{Code}
: \S 1024 >IN ! ;
: \S 1024 >in ! ;
\end{Code}
\index{F!FH|(}%
The word \forthb{FH} can be defined simply as:
\begin{Code}
: FH \ ( offset -- offset-block) "from here"
BLK @ + ;
blk @ + ;
\end{Code}
This factoring allows you to use \forth{FH} in many ways, e.g.:
\begin{Code}
: TEST [ 1 FH ] LITERAL LOAD ;
: TEST [ 1 FH ] Literal load ;
\end{Code}
or
\begin{Code}
: SEE [ 2 FH ] LITERAL LIST ;
: see [ 2 FH ] Literal list ;
\end{Code}
A slightly more complicated version of \forth{FH} also lets you edit or
load a screen with a phrase such as ``\forth{14 FH LIST},'' relative to
the screen that you just listed (\forth{SCR}):
\begin{Code}
: FH \ ( offset -- offset-block) "from here"
BLK @ ?DUP 0= IF SCR @ THEN + ;
blk @ ?dup 0= IF scr @ THEN + ;
\end{Code}
\index{F!FH|)}
\forthb{BL}\index{B!Blank space (BL)} is a simple constant:
\begin{Code}
32 CONSTANT BL
32 Constant bl
\end{Code}
\forthb{TRUE}\index{T!TRUE} and \forthb{FALSE}\index{F!FALSE}
can be defined as:
\begin{Code}
0 CONSTANT FALSE
-1 CONSTANT TRUE
0 Constant false
-1 Constant true
\end{Code}
(\Forth{}'s control words such as \forth{IF} and \forth{UNTIL} interpret
zero as ``false'' and any non-zero value as ``true.'' Before \Forth{}
......@@ -73,13 +73,13 @@ which is the signed number $-1$ (all bits set).
\forthb{WITHIN}\index{W!WITHIN} can be defined in high level like this:
\begin{Code}
: WITHIN ( n lo hi+1 -- ?)
>R 1- OVER < SWAP R> < AND ;
: within ( n lo hi+1 -- ?)
>r 1- over < swap r> < and ;
\end{Code}
or
\begin{Code}
: WITHIN ( n lo hi+1 -- ?)
OVER - >R - R> U< ;
: within ( n lo hi+1 -- ?)
over - >r - r> u< ;
\end{Code}
\section{From \Chap{8}}
......@@ -89,11 +89,11 @@ system implements \forthb{DO} \forthb{LOOP}s. If \forthb{DO} keeps two
items on the return stack (the index and the limit), \forthb{LEAP} must
drop both of them plus one more return-stack item to exit:
\begin{Code}
: LEAP R> R> 2DROP R> DROP ;
: LEAP r> r> 2drop r> drop ;
\end{Code}
If \forthb{DO} keeps \emph{three} items on the return stack, it must be
defined:
\begin{Code}
: LEAP R> R> 2DROP R> R> 2DROP ;
: LEAP r> r> 2drop r> r> 2drop ;
\end{Code}
......@@ -31,12 +31,12 @@ This syntax will remain the same whether we define it to allocate growing
upward:
\begin{Code}
: RAM-ALLOT ( #bytes-to-allot -- starting-adr)
>RAM @ DUP ROT + >RAM ! ;
>RAM @ dup rot + >RAM ! ;
\end{Code}
or to allocate growing downward:
\begin{Code}
: RAM-ALLOT ( #bytes-to-allot -- starting-adr)
>RAM @ SWAP - DUP >RAM ! ;
>RAM @ swap - dup >RAM ! ;
\end{Code}
\end{enumerate}
......@@ -46,15 +46,15 @@ or to allocate growing downward:
\item\fi Our solution is as follows:
\begin{Code}
\ CARDS Shuffle 6-20-83
52 CONSTANT #CARDS
CREATE DECK #CARDS ALLOT \ one card per byte
52 Constant #CARDS
Create DECK #CARDS allot \ one card per byte
: CARD ( i -- adr) DECK + ;
: INIT-DECK #CARDS 0 DO I I CARD C! LOOP ;
: INIT-DECK #CARDS 0 DO i i CARD c! LOOP ;
INIT-DECK
: 'CSWAP ( a1 a2 -- ) \ swap bytes at a1 and a2
2DUP C@ SWAP C@ ROT C! SWAP C! ;
2dup c@ swap c@ rot c! swap c! ;
: SHUFFLE \ shuffle deck of cards
#CARDS 0 DO I CARD #CARDS CHOOSE CARD 'CSWAP
#CARDS 0 DO i CARD #CARDS CHOOSE CARD 'CSWAP
LOOP ;
\end{Code}
\ifeightyfour\end{enumerate}\fi
......@@ -63,7 +63,7 @@ INIT-DECK
\ifeightyfour\begin{enumerate}
\item This will work:
\begin{Code}
20 CHOOSE 2 CHOOSE IF NEGATE THEN
20 CHOOSE 2 CHOOSE IF negate THEN
\end{Code}
But this is simpler:
\begin{Code}
......@@ -71,7 +71,7 @@ But this is simpler:
\end{Code}
\end{enumerate}\else
\begin{Code}
: DIRECTION ( n|-n|0 -- 1|-1|0) DUP IF 0< 1 OR THEN ;
: DIRECTION ( n|-n|0 -- 1|-1|0) dup IF 0< 1 or THEN ;
\end{Code}
\fi
......
......@@ -95,32 +95,32 @@ style\index{C!Commenting style|(}.
\setcounter{screen}{126}
\begin{Screen}
\ Formatter Data Structures -- p.2 06/06/83
6 CONSTANT TMARGIN \ line# where body of text begins
55 CONSTANT BMARGIN \ line# where body of text ends
6 Constant TMARGIN \ line# where body of text begins
55 Constant BMARGIN \ line# where body of text ends
CREATE HEADER 82 ALLOT
Create header 82 allot
\ { 1left-ent | 1right-cnt | 80header }
CREATE FOOTER 82 ALLOT
Create FOOTER 82 allot
\ { 1left-cnt | 1right-ent | 80footer }
VARIABLE ACROSS \ formatter's current horizontal position
VARIABLE DOWNWARD \ formatter's current vertical position
VARIABLE LEFT \ current primary left margin
VARIABLE WALL \ current primary right margin
VARIABLE WALL-WAS \ WALL when curr. line started being formt'd
Variable ACROSS \ formatter's current horizontal position
Variable DOWNWARD \ formatter's current vertical position
Variable LEFT \ current primary left margin
Variable WALL \ current primary right margin
Variable WALL-WAS \ WALL when curr. line started being formt'd
\end{Screen}
\begin{Screen}
\ Formatter positioning -- p.1 06/06/83
: SKIP ( n) ACROSS +! ;
: skip ( n) ACROSS +! ;
: NEWLEFT \ reset left margin
LEFT @ PERMANENT @ + TEMPORARY @ + ACROSS ! ;
: \LINE \ begin new line
DOOR CR' 1 DOWNWARD +! NEWLEFT WALL @ WALL-WAS ! ;
: AT-TOP? ( -- t=at-top) TMARGIN DOWNWARD @ = ;
: >TMARGIN \ move from crease to TMARGIN
O DOWNWARD ! BEGIN \LINE AT-TOP? UNTIL ;
0 DOWNWARD ! BEGIN \LINE AT-TOP? UNTIL ;
\end{Screen}
\index{C!Commenting style|)}
......
......@@ -770,8 +770,8 @@ relate them to what we've seen about traditional methodologies.
Here's an example of \Forth{} code;
\begin{Code}
: BREAKFAST
HURRIED? IF CEREAL ELSE EGGS THEN CLEAN ;
: breakfast
hurried? IF cereal ELSE eggs THEN clean ;
\end{Code}
This is structurally identical to the procedure \forth{MAKE-BREAKFAST} on
page \pageref{fig-fig1-4}. (If you're new to \Forth{}, refer to
......@@ -828,8 +828,8 @@ words \forth{PUSH} and \forth{POP} do not exist in high-level \Forth{}.
Thus we can write:
\begin{Code}
: DOIT
GETC TRANSFORM-TO-D PUT-D ;
: doit
getc transform-to-d put-d ;
\end{Code}
confident that \forth{GETC} will get ``C,'' and leave it on the stack.
\forth{TRANSFORM-TO-D} will pick up ``C'' from the stack, transform
......@@ -858,7 +858,7 @@ words as we need to do that, no matter how simple each of them may be.
A line from a typical \Forth{} application might read:
\begin{Code}
20 ROTATE LEFT TURRET
20 rotate left turret
\end{Code}
Few other languages would encourage you to concoct a subroutine called
\forth{LEFT}, merely as a modifier, or a subroutine called
......@@ -996,12 +996,12 @@ This availability of commands also makes the process of testing and
debugging a whole lot easier. Because \Forth{} is interactive, the
programmer can type and test the primitive commands, such as
\begin{Code}
RIGHT SHOULDER 20 PIVOT
right shoulder 20 pivot
\end{Code}
from the ``outside'' as easily as the more powerful ones like
\begin{Code}
LIFT COFFEE-POT
lift coffee-pot
\end{Code}
At the same time, the programmer can (if he or she wants) deliberately
seal any commands, including \Forth{} itself, from being accessed by the
......@@ -1065,20 +1065,20 @@ access memory.
Suppose we define a variable called \forth{APPLES}, like this:\program{apples1}
\begin{Code}
VARIABLE APPLES
Variable apples
\end{Code}
We can store a number into this variable to indicate how many apples
we currently have:
\begin{Code}
20 APPLES !
20 apples !
\end{Code}
We can display the contents of the variable:
\begin{Code}[commandchars=\&\{\}]
APPLES ? &underline{20 ok}
apples ? &underline{20 ok}
\end{Code}
We can up the count by one:
\begin{Code}
1 APPLES +!
1 apples +!
\end{Code}
(The newcomer can study the mechanics of these phrases in Appendix A.)
......@@ -1105,12 +1105,12 @@ more complicated version of
\forth{APPLES} as follows:
\begin{Code}
VARIABLE COLOR ( pointer to current tally)
VARIABLE REDS ( tally of red apples)
VARIABLE GREENS ( tally of green apples)
: RED ( set apple-type to RED) REDS COLOR ! ;
: GREEN ( set apple-type to GREEN) GREENS COLOR ! ;
: APPLES ( -- adr of current apple tally) COLOR @ ;
Variable color ( pointer to current tally)
Variable reds ( tally of red apples)
Variable greens ( tally of green apples)
: red ( set apple-type to RED) reds color ! ;
: green ( set apple-type to GREEN) greens color ! ;
: apples ( -- adr of current apple tally) color @ ;
\end{Code}
\wepsfiga{fig1-10}{Changing the indirect pointer.}
......@@ -1128,12 +1128,12 @@ We didn't need to change the syntax of any existing code that uses
\forth{APPLES.} We can still say
\begin{Code}
20 APPLES !
20 apples !
\end{Code}
and
\begin{Code}
1 APPLES +!
1 apples +!
\end{Code}
Look again at what we did. We changed the definition of \forth{APPLES}
from that of a variable to a colon definition, without affecting its
......@@ -1163,12 +1163,12 @@ called ``adjectives'' since they modify the function of
\forth{APPLES.} The phrase
\begin{Code}
RED APPLES ?
red apples ?
\end{Code}
is different from
\begin{Code}
GREEN APPLES ?
green apples ?
\end{Code}
\Forth{} words can also serve as adverbs and prepositions. There's little
value in trying to determine what part of speech a particular word is,
......
......@@ -731,11 +731,11 @@ This is because \Forth{}, used properly, approaches a functional language.%
For anyone with a few days' familiarity with \Forth{}, simple definitions
convey at least as much meaning as the diagrams:
\begin{Code}
: REQUEST ( quantity part# -- )
ON-HAND? IF TRANSFER ELSE REORDER THEN ;
: REORDER AUTHORIZATION? IF P.O. THEN ;
: P.O. BOOKKEEPING COPY RECEIVING COPY
VENDOR MAIL-COPY ;
: request ( quantity part# -- )
on-hand? IF transfer ELSE reorder THEN ;
: reorder authorization? IF p.o. THEN ;
: p.o. bookkeeping copy receiving copy
vendor mail-copy ;
\end{Code}
This is \Forth{} pseudocode. No effort has been made to determine what
values are actually passed on the stack, because that is an
......@@ -746,7 +746,7 @@ only to indicate the two items of data needed to initiate the process.
interface be a word called \forth{NEED}, which has this syntax:
\begin{Code}
NEED 50 AXLES
need 50 axles
\end{Code}
\noindent \forth{NEED} converts the quantity into a numeric value on
......@@ -897,7 +897,7 @@ ELSE ( not-full-rate)
.22 + .10/100miles
ELSE ( add'l- minute)
.15 + .10/100miles
END IF
ENDIF
ELSE ( operator)
IF first-minute
1.12 + .10/100miles
......@@ -1042,8 +1042,8 @@ and calculation. The formula for the per-minute charge can be
expressed as a pseudo\Forth{} definition:
\begin{Code}
: PER-MINUTE-CHARGE ( -- per-minute-charge)
CONNECT-CHARGE MILEAGE-CHARGE + ;
: per-minute-charge ( -- per-minute-charge )
connect-charge mileage-charge + ;
\end{Code}
The ``\forth{+}'' now appears once in the definition,
not nine times in the table.
......@@ -1058,9 +1058,8 @@ appropriately expressed as a ``logical calculation''; that is, a
function that combines logic with arithmetic:
\begin{Code}
: ?ASSISTANCE
( direct-dial-charge -- total-charge)
OPERATOR? IF .90 + THEN ;
: ?assistance ( direct-dial-charge -- total-charge )
operator? IF .90 + THEN ;
\end{Code}
(But remember, this charge applies only to the first minute.)
......@@ -1072,8 +1071,8 @@ somewhere.
Let's go back to our definition of \forth{PER-MINUTE-CHARGE}:
\begin{Code}
: PER-MINUTE-CHARGE ( -- per-minute-charge)
CONNECT-CHARGE MILEAGE-CHARGE + ;
: per-minute-charge ( -- per-minute-charge )
connect-charge mileage-charge + ;
\end{Code}
Let's get more specific about the rules for the connection charge and for
the mileage charge.
......@@ -1094,10 +1093,10 @@ Now we can define the pair of words to replace \forth{PER-MINUTE-CHARGE}:
%Page 059 in first edition
\begin{Code}
: FIRST ( -- charge)
1MINUTE ?ASSISTANCE MILEAGE-CHARGE + ;
: PER-ADDITIONAL ( -- charge)
+MINUTES MILEAGE-CHARGE + ;
: first ( -- charge )
1minute ?assistance mileage-charge + ;
: per-additional ( -- charge )
+minutes mileage-charge + ;
\end{Code}
What is the rule for the mileage charge? Very simple. It is the rate
(per hundred miles) times the number of miles (in hundreds). Let's
......@@ -1105,18 +1104,18 @@ assume we can define the word \forth{MILEAGE-RATE}, which will fetch
the mileage rate from the table:
\begin{Code}
: MILEAGE-CHARGE ( -- charge)
#MILES @ MILEAGE-RATE * ;
: mileage-charge ( -- charge )
#miles @ mileage-rate * ;
\end{Code}
Finally, if we know the total number of minutes for a call, we can now
calculate the total direct-dial charge:
\begin{Code}
: TOTAL ( -- total-charge)
FIRST ( first minute rate)
( #minutes) 1- ( additional minutes)
PER-ADDITIONAL * ( times the rate)
+ ; ( added together)
: total ( -- total-charge )
first \ first minute rate
( #minutes) 1- \ additional minutes
per-additional * \ times the rate
+ ; \ added together
\end{Code}
We've expressed the rules to this particular problem through a
combination of simple tables and logical calculations.
......@@ -1499,7 +1498,7 @@ This puts you in the position of either accepting or going without a job.
But if you say, ``You have a choice: for \$4,000 I'll make it
\emph{walk} through the hoop; for \$6,000 I'll make it \emph{jump}
through the hoop. For \$8,000 I'll make it \emph{dance} through the
hoop waving flags, tossing confetti and singing ``Roll Out the Barrel.''
hoop waving flags, tossing confetti and singing `Roll Out the Barrel.'\,''
Most customers opt for jumping through the hoop.
\end{enumerate}
......
......@@ -129,19 +129,19 @@ won't be used elsewhere, you don't need to define it as constant. Just use
the number 14 in both definitions:
\begin{Code}
: +RECORD 14 RECORD# +! ;
: -RECORD -14 RECORD# +! ;
: +record 14 record# +! ;
: -record -14 record# +! ;
\end{Code}
On the other hand, if the value will be needed outside of the component,
or if it's used several times within the component and there's a good
chance that it will change, you're better off hiding it behind a name:
\begin{Code}
14 CONSTANT /RECORD
: +RECORD /RECORD RECORD# +! ;
: -RECORD /RECORD NEGATE RECORD# +! ;
14 Constant /record
: +record /record record# +! ;
: -record /record negate record# +! ;
\end{Code}
(The name \forth{/RECORD}, by convention, means ``bytes per record.'')
(The name \forth{/RECORD}, by convention, means ``\/bytes per record.'')
\section{Example: A Tiny Editor}\program{editor1}
......@@ -211,7 +211,7 @@ screen. For the sake of simplicity, let's plan on creating one word only,
\forth{REDISPLAY}, to redisplay the entire field after each key is pressed.
\begin{Code}
: EDITOR BEGIN KEY REVISE REDISPLAY ... UNTIL ;
: editor BEGIN key revise redisplay ... UNTIL ;
\end{Code}
This approach separates revising the buffer from updating the display.
For now, we'll only concentrate on revising the buffer.
......@@ -304,13 +304,13 @@ hidden within this component.
Let's attempt to rewrite these algorithms in code:
\begin{Code}
: KEY# ( returns value of key last pressed ) ... ;
: POSITION ( returns address of character pointed-to) ;
: FORWARD ( advance pointer, stopping at last position) ;
: BACKWARD ( decrement pointer, stopping at first position) ;
: OVERWRITE KEY# POSITION C! FORWARD ;
: INSERT SLIDE> OVERWRITE ;
: DELETE SLIDE< BLANK-END ;
: key# ( returns value of key last pressed ) ... ;
: position ( returns address of character pointed-to) ;
: forward ( advance pointer, stopping at last position) ;
: backward ( decrement pointer, stopping at first position) ;
: overwrite key# position c! forward ;
: insert slide> overwrite ;
: delete slide< blank-end ;
\end{Code}
To copy the text leftwards and rightwards, we had to invent two new
names as we went along, \forth{SLIDE<} and \forth{SLIDE>} (pronounced
......@@ -365,7 +365,7 @@ To implement what happens when ``backspace'' is pressed while in
Insert Mode, we add a new procedure:
\begin{Code}
: INSERT< BACKWARD SLIDE< ;
: insert< backward slide< ;
\end{Code}
(move the cursor backwards on top of the last character typed, then slide
everything to the right leftward, covering the mistake).
......@@ -425,11 +425,11 @@ are in boldface:
%!! "KEY# EMIT" and "RETYPE" in boldface
\begin{Code}[commandchars=\&\{\}]
: OVERWRITE KEY# POSITION C! &poorbf{KEY# EMIT} FORWARD ;
: &poorbf{RETYPE ( type from current position to}
: overwrite key# position c! &poorbf{key# emit} forward ;
: &poorbf{retype ( type from current position to}
&poorbf{end of field and reset cursor) ;}
: INSERT SLIDE> &poorbf{RETYPE} OVERWRITE ;
: DELETE SLIDE< BLANK-END &poorbf{RETYPE} ;
: insert slide> &poorbf{retype} overwrite ;
: delete slide< blank-end &poorbf{retype} ;
\end{Code}
Since these are the only three functions that change memory, they are
the only three functions that need to refresh the screen. This idea is
......@@ -647,8 +647,8 @@ buffers are defined with \forthb{CREATE}, the count is an ordinary
\forthb{VARIABLE}, and the attribute patterns are defined as
\forthb{CONSTANT}s, such as:
\begin{Code}
1 CONSTANT UNDERNESS ( bit mask for underlining)
2 CONSTANT BOLDNESS ( bit mask for boldface)
1 Constant underness ( bit mask for underlining)
2 Constant boldness ( bit mask for boldface)
\end{Code}
The formatting component uses phrases like \forth{UNDERNESS SET-FLAG}
to set bits in the attribute buffer. The output component uses phrases
......@@ -771,8 +771,8 @@ next executed, it will format the deferred figure at the top of the
new page:
\begin{Code}
: NEWPAGE ... ( terminate page with footer)
( start new page with header) ... ?HOLDOVER ... ;
: newpage ... ( terminate page with footer)
( start new page with header) ... ?holdover ... ;
\end{Code}
How can \forth{NEWPAGE} invoke \forth{?HOLDOVER}, if \forth{?HOLDOVER} is
not defined until much later?
......@@ -1071,35 +1071,35 @@ interpreter. Which would you prefer? Why?
\begin{enumerate}
\item \begin{Code}
( Define editor keys )
HEX
72 CONSTANT UPCURSOR
80 CONSTANT DOWNCURSOR
77 CONSTANT RIGHTCURSOR
75 CONSTANT LEFTCURSOR
82 CONSTANT INSERTKEY
83 CONSTANT DELETEKEY
DECIMAL
hex
72 Constant upcursor
80 Constant downcursor
77 Constant rightcursor
75 Constant leftcursor
82 Constant insertkey
83 Constant deletekey
decimal
( Keystroke interpreter)
: EDITOR
BEGIN MORE WHILE KEY CASE
UPCURSOR OF CURSOR-UP ENDOF
DOWNCURSOR OF CURSOR-DOWN ENDOF
RIGHTCURSOR OF CURSOR> ENDOF