Loading Makefile +2 −1 Original line number Diff line number Diff line Loading @@ -6,6 +6,7 @@ SOURCES = thinking-forth.tex \ preface.tex \ preface94.tex \ preface2004.tex \ preface-ans.tex \ chapter1.tex \ chapter2.tex \ chapter3.tex \ Loading Loading @@ -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 Loading appendixa.tex +4 −4 Original line number Diff line number Diff line Loading @@ -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. Loading @@ -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}.} Loading Loading @@ -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. Loading appendixb.tex +51 −51 Original line number Diff line number Diff line Loading @@ -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.) Loading @@ -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. Loading @@ -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 Loading Loading @@ -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 Loading @@ -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. Loading @@ -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 Loading Loading @@ -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 ; Loading @@ -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. Loading @@ -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.) Loading @@ -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} Loading @@ -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.) Loading @@ -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." Loading @@ -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 appendixc.tex +17 −17 Original line number Diff line number Diff line Loading @@ -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}} Loading @@ -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{} Loading @@ -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}} Loading @@ -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} appendixd.tex +9 −9 Original line number Diff line number Diff line Loading @@ -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} Loading @@ -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 Loading @@ -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} Loading @@ -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 Loading Loading
Makefile +2 −1 Original line number Diff line number Diff line Loading @@ -6,6 +6,7 @@ SOURCES = thinking-forth.tex \ preface.tex \ preface94.tex \ preface2004.tex \ preface-ans.tex \ chapter1.tex \ chapter2.tex \ chapter3.tex \ Loading Loading @@ -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 Loading
appendixa.tex +4 −4 Original line number Diff line number Diff line Loading @@ -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. Loading @@ -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}.} Loading Loading @@ -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. Loading
appendixb.tex +51 −51 Original line number Diff line number Diff line Loading @@ -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.) Loading @@ -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. Loading @@ -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 Loading Loading @@ -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 Loading @@ -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. Loading @@ -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 Loading Loading @@ -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 ; Loading @@ -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. Loading @@ -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.) Loading @@ -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} Loading @@ -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.) Loading @@ -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." Loading @@ -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
appendixc.tex +17 −17 Original line number Diff line number Diff line Loading @@ -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}} Loading @@ -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{} Loading @@ -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}} Loading @@ -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}
appendixd.tex +9 −9 Original line number Diff line number Diff line Loading @@ -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} Loading @@ -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 Loading @@ -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} Loading @@ -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 Loading