Skip to main content

She said, " Joe Saul knows one trick,
one ingredient. Without that trick  
you'll one day go screaming silently 
in loss. Without it there are no good 
methods or techniques.
John Steinbeck, "Burning Bright"

                         STRENGTH IN FORTH

                            Part Four
                      MAKING A TRUE DECISION 1

I just couldn't decide,  what to do first:  the  returnstack,  the 
colondefinition  or controlstructures and loops.  You've met  them 
all three;  a little bit  of all three,  though. Forth's decisions 
are much simpler to make. FORTH decides on two arguments: FALSE or 
TRUE.  He hasn't to weigh which of THREE (or even more)  arguments 
is most important, as I happened to do. Fairly said, FORTH doesn't 
really decide,  he concludes. I came to a conclusion too: a little 
of this and a little of that. The returnstack had to return to the 
freezer for a while.

THE OUTSIDE

Now,  stay  tuned,  here is some more about  the  colondefinition. 
The  colondefinition is the most commonly used way of  defining  a 
new action in FORTH and has been used without much explanation  in 
some examples in earlier issues of this magazine. The form is like   
: NAME  ..................  ;
First  we  take a look at the outside.  A  colondefinition  always 
starts with the word {:} and ends with the word {;}.  Inside  such 
a definition you can use all words which are in FORTH's dictionary 
at that moment,  the ones you defined yourself too.  And of course 
you can use numbers. After you typed {:} you have to type at least 
one  space.  Then arrives 'le moment suprême'.  As you are  giving 
birth to a new creature,  you could name it as well.   Most FORTHs 
allow  names  up to 31 characters.  All printable  characters  are 
allowed, except a space, because FORTH uses a space to distinguish 
one word from another. By that name the new created word is  known
in FORTH's dictionary.  Then you can type the words,  numbers  and 
parameters  you  thought  were needed to fulfill  the  action  you 
created the new word for.  The definition is finally terminated by 
a  {;}.  Remember to type a space between the words  and  numbers. 

Make it to a habit to type two or three spaces between the name of 
the  new word and the rest of the definition,  for no more  reason 
than clarity.  And speaking of clarity,  if you are going to write 
more  serious definitions for use in  larger  applications,  never 
forget  to write stacknotations and comments,  so you can  retrace 
the action of words and which items they expect on the stack.
Making mistakes is included in making colondefinitions.  What  can 
go  wrong  most  is  forgetting  {;}.   Your  definition  is  then 
incomplete. Incomplete definitions are prevented from being found, 
when  the  dictionary is searched.  To  {FORGET}  such  incomplete 
definitions  you  have  to use {SMUDGE}.  This  word  enables  the 
incomplete definition to be found by {FORGET}.  A FORTH may have a 
{FORGET}, that includes {SMUDGE} in one go. Remember that {FORGET} 
a  word,  starts with that word,  but goes on forgetting  all  the 
words defined after that word.  For example: : PIPO  1 MIN 0 DO ." 
I'm a clown" and at this very moment you unintentionally press the 
RETURN-key.  FORTH doesn't give an OK.  See if the word {PIPO}  is 
placed in the dictionary. If so, then {FORGET} {PIPO} △ . If FORTH 
answers with PIPO ?, then enter {SMUDGE} {FORGET} {PIPO} △ OK.
Once correctly defined a colondefinition can be executed by typing 
the  required  parameters, if any, followed  by  its name. You can 
enter  new words in the dictionary by typing them directly at  the 
keyboard  and  pressing RETURN.  These words are not kept  in  the 
dictionary,  when you turn off your computer.  Simply because  the 
original  dictionary is on a disc and you did not write  your  new 
word  onto that disc.  Another way is to type your words with  the 
help  of an EDITOR into a so called SCREEN.  This screenfile  then 
can  be  written onto a disc.  Later on you can  enter  the  words 
defined  in such a screen in the dictionary.  FORTH  doesn't  care 
where  the  input  comes  from;  directly  from  the  keyboard  or 
indirectly from a screenfile. It's not said, that words entered in 
the  dictionary  by  means  of  a  screenfile,  are  part  of  the 
dictionary  for ever.  You only haven't to retype them,  when  you 
need them.  But every time you need them,  you have to enter  them 
into  the  dictionary.  More about editors and  screenfiles  in  a 
future chapter.  

ON THE INSIDE

There  are  several ways in wich a new word can be placed  in  the 
dictionary.  These use defining  words.  The most  common  are {:}
{CONSTANT}  {VARIABLE}  {USER}  {VOCABULARY} {CREATE}.
The  defining  words thus create a  dictionary  entry.  The  exact 
construction  of an entry (format) is dependent on the  method  of 
implementation  and may well be different in different versions of
FORTH. A general description is given here and although the method
to  describe  is a very common one,  it should not be  assumed  to 
apply  to  all  versions of FORTH.  So 'all' means  'all  in  this 
implementation'.
All entries consists of two parts:  the head and the body. What is 
in a FORTH's head ? Three parts well counted:
a) the name of the entry ( with a variable length );
b) a linkpointer to the name of the previous entry;
c) a codepointer to the machinecode used in the execution of  the 
   entry.
The startingaddresses of these three parts are known as name field 
address,  link  field  address  and compilation  (or  code)  field 
address  respectively.  The  link field addresses allow  FORTH  to 
jump  from one word to another as he does in  a  dictionarysearch. 
The body of an entry contains the information about the action  of 
that  particular  entry.  The nature of this  information  differs 
according to the defining word used in its creation.  The body  is 
also  called  parameter field and the starting  address  parameter 
field address.

An example. Let's define a constant: 56 {CONSTANT} PIPO △ OK. What 
happened  ?  The  defining word {CONSTANT}  creates  a  dictionary 
entry:  a  name field among other things containing the characters
P I P O in ASCII-code.  The linkfield contains the pointer to  the 
previous word,  say MAMALOU. The compilation field helds a pointer 
to machinecode,  used in the execution of the word  {PIPO}.  (When 
you  type PIPO at the keyboard and press  RETURN).  The  parameter 
field  contains no more than the value of the constant  PIPO,  56. 
The  machinecode  to which the pointer in  the  compilation  field 
points  and  which  is executed when the word PIPO  is  typed  and 
RETURN  pressed,  takes  the value 56 in the parameter  field  and 
copies  it  onto  the  top  of  the  stack.   In  the  case  of  a 
colondefinition  the parameter field is a list of the  compilation 
field  addresses  of  the words used to  define  the  action.  The 
Compilation  Field Address (cfa) points to machinecode  to  handle 
those addresses.  The defining word {VARIABLE}, used as {VARIABLE} 
PIPO,  creates a namefield, a linkfield, a compilationfield, and a 
parameterfield.  That last one is some memoryspace,  reserved  for 
later use.  With 256 PIPO {!},  you fill that memoryspace with the 
value 256. On executing PIPO the {VARIABLE}-machinecode places the 
parameter  field address (pfa) of PIPO TOS.  The word {@} is  just 
fine for copying the value from the pfa of PIPO to the top of  the 
stack:  PIPO {@} {.} 256 OK.  Now you should have a rough  idea of 
the  action of three defining words.  Mark the difference  between 
{CONSTANT} and {VARIABLE}.  On execution {CONSTANT} gives you  the 
value, {VARIABLE} the address of that value. 
Each  entry  terminates with the executionaddress of  the  routine 
called  EXIT,  which causes a legitimate exit from the  word.  So, 
instead  of making jokes all the time,  think about that bunch  of 
theory  !!!!  The  diagram  below  shows a  typical  entry  for  a 
colondefinition.

                   |¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯|
Name Field Address |     NAME OF WORD      |
                   |¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯|
Link Field Address |     LINK POINTER      |to previous Namefield
Compilation Field  |¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯|to machinecode for a
    Address        |     CODE POINTER      |colondefinition
Parameter Field    |¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯|
    Address        | COMP. FIELD ADDRESS 1 |
                   |¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯|
                   | COMP. FIELD ADDRESS 2 |
                   |¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯|
                   |           *           |
                   |           *           |
                   |           *           |
                   |¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯|
                   |CMP. FLD. ADDR. OF EXIT|
                    ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
The  whole  complex  of  creating  a  dictionary-entry  is  called 
compilation.  Very  well distinguish compilation  from  execution. 
Compilation  is  the construction of a more  or  less  complicated 
piece of machinery, execution makes the engine run that machine.

HOT WITH A DOT

And  now  practice.  Take for instance the word  {EMIT}.  For  all 
{EMIT} emits. All ASCII-characters {EMIT} sends to the display. So 
7  {EMIT} △ OK.  That woke you up,  didn't it ?  You may  try  all 
numbers from 0 till 256. 46 {EMIT} prints a dot. Let's put it in a 
colondefinition.  :  DOT  46 EMIT ;  △ OK.  Now {DOT} △ . OK. More 
dots {DOT} {DOT} {DOT} △ ...  OK. That's much work and little pay. 
We improve matters by : DOTS  0 DO DOT LOOP ; and then 10 {DOTS} △ 
gives ..........  OK.  You didn't forget to press RETURN after you 
typed the DOTS-word ?  Of course you didn't.  You know by now that 
each input must be terminated with a RETURN.  From now on I  won't 
type  △  anymore.  More improvement of the {DOTS}  with  the  word 
{SPACES}.   Try  10  {DOTS}  10  {SPACES}  10  {DOTS}   ..........
          ..........  OK.  We put it in a definition.   : DOLLY CR  
SPACES DOTS ;.  DOLLY needs two numbers on the stack.  Enter 10 10 
DOLLY           ..........  OK. First 10 spaces, then 10 dots were 
emitted.  Let's add one more improvement.  : DOLLY-DOTS 0 DO DOLLY 
LOOP ;.  Enter 1 10 3 9 5 8 7 7 9 6 11 5 13 4 11 5 9 6 7 7 5 8 3 9 
1  10 13 DOLLY-DOTS (So 13 pairs of dots and spaces) and what  you 
get is a diamond. One day, I promised you, you would play with the 
DOLLY-DOTS. That day is here now. Have fun !!! You may enter other 
pairs  of dots and spaces.  The sequence of those pairs  must  end 
with the number of pairs followed by the word DOLLY-DOTS.  Try  to 
see some logic in the pairs I used for creating a diamond. 

A FEW DAYS LATER........

You did some looping with those DOLLY-DOTS,  didn't you ? You were 
looping all the time with that most creative {DO..LOOP}.  The time 
has come to give you extended looping-lessons. First lesson: never 
loop  outside  the safe institution of  the  colondefinition.  The 
punishment for disobeying this rule is severe. The Holy FORTH will 
send you to the gehenna,  the BASIC-hell. There is a very sensible 
reason why you shouldn't loop outside a colondefinition. It has to 
do  with the calculation of returnaddresses. Let's have  a  closer 
look  at  the {DO...LOOP}.  Second lesson:  the {DO...LOOP}  is  a 
definite loop. You knew on the forehand how much looping was to be
done;  you  defined that in the arguments.  Later we are going  to 
play with indefinite  loops and conditional branches.  
A {DO...LOOP} always needs twee arguments on  the stack; these two
arguments may be inside the colondefinition,  but also could  come 
from outside, it doesn't matter,  if at the  right time  the right 
parameters  are  at the right place.  First  example  with  inside 
parameters: : INSIDE   10 0 DO CR ." Ten times inside" LOOP ; OK . 
If you now type INSIDE, then Ten times inside will  be printed  10 
times  at your display.  The two parameters - 10 and 0 -  do  have 
nicknames.  The  one closest to {DO} - the 0 in this example -  is 
called 'index', the other one - the 10 - is named by 'limit'. {DO} 
removes  the index and limit from the stack and puts them  on  the 
returnstack.  Then the words between {DO} and {LOOP} are executed.  
Once  execution arrives at {LOOP},  the 'index' is increased  with 
one  and  compared  with the 'limit'.  If they are  not  at  least 
equal,{LOOP} branches back to {DO} and the execution of the  words 
between {DO} and {LOOP} is done again. This sequence repeats until 
{LOOP} finds that the increased index is equal or higher than  the 
'limit'.  At  that moment FORTH exits the  loop.  Remember,  FORTH 
always executes the {DO...LOOP} at least once. Even : ONCE  0 1 DO 
."  One  time  through!" LOOP ;  is carried  out  one  time,  thus 
printing One time through!  at the display. The number of times  a 
{DO...LOOP}  is  run  through can  be  calculated  by  subtracting 
'limit' - 'index'.  The parameters being 123 24 {DO},  the loop is 
executed 99 times(123-24=99).  In our DOLLY-DOTS-words we did  not 
incorporate both the limit and the index in the definition of  the 
words.  Look back,  and you will find out,  that only the index is 
placed within the definitions.  That has the advantage of  varying 
the  number of times the DO-loop inside that DOTS-word was  to  be 
executed.  Say, I had to define one word printing 5 dots, one word 
printing  10  dots and one word printing 12534637  dots.  I  could 
write  3  different words to achieve my goal.  But  I  also  could 
restrict myself to write one word,  the DOTS-word given above. Now 
entering  the lacking limit-parameter(5,10 or 12534637) will  give 
the  required result:  10 {DOTS} will print 10 dots.  Now you  may 
even  write  this  word leaving 'limit' and  'index'  outside  the 
definition for later use :  :  DOTS2  DO DOT LOOP ;. Entering 10 0 
DOTS2 will print 10 dots. 

I AND J, YOU AND ME

The  possibility  of entering the 'limit' and 'index' at  a  later 
stage  becomes far  more delicate in using the words {I} and  {J}. 
Enter  the following and see what happens.  :  QUAD   DO  I I *  . 
LOOP ;  OK.  10 0 QUAD 0 1 4 9 16 25 36 49 64 81 OK. It's not hard 
to see that FORTH displayed quadratic numbers. The word {I} copies 
the  actual  value  of the 'index' from  the  returnstack  to  the 
parameterstack.  The first time through the loop the 'index' is 0. 

So  the sequence {I} {I} {*} {.} produces 0 0 {*} (=0),  the  next 
time through the loop the 'index' is increased with one, producing 
1 1 {*} (=1), the third time the outcome is logically 2 2 {*} (=4) 
and  so on.  Watch the 10 10 {*} not being  performed.  There  are 
several tricks to perform a loop which also gives the last 'limit'
value;  you  could for one always make the 'limit' 1  higher.  The 
increment  of the 'index' so far was always one.  There is another 
loop with variable increments, even with negative increments; it's 
the  {DO...  +LOOP}.  There  are  2  things  which  needs  special 
attention.  First: the increment of the index is positive and more 
then  1;  the form of the loop then is :  FORM1    10 0  DO I . 2 
+LOOP  ;  When  you  execute FORM1 10 and  0  are  placed  on  the 
returnstack,  {I} copies the actual value from the returnstack  to 
the  parameterstack,  {.} kicks the TOS to  the  display,  {+LOOP} 
takes  the  2   and increments the  index  with  that  value,  the 
procedure  repeats and {+LOOP} increments the index  with  2,  the 
index now being 4.  It all goes on until the loopindex is equal or 
more  than  the 'limit'.  Second:  the increment of the  index  is 
negative.  :  FORM2  0 10 DO I . -2 +LOOP ;. Because you intend to 
decrement the index, the index has to be higher than the 'limit'.
The  loop ends if the index is less than the limit.  In this  case 
the loop does not  end when index and limit are equal.
Third lesson:  FORTH allows nested loops . Are we glad !! A nested 
loop is a loop inside a loop,  inside a loop, inside a loop...etc. 
The number of 'loop-insiders' is ( in theory ) without limits. But 
there is one,  most effective limit:  YOU.  Well, here is a nested 
{DO...LOOP}. : NESTED   10 0 DO  CR  10 0 DO ." @" LOOP LOOP ; OK.
                             |¯           |¯       ¯¯|¯ ¯¯|¯
                             |             ¯¯¯¯¯1¯¯¯¯     |
                              ¯¯¯¯¯¯¯¯¯¯¯¯¯2¯¯¯¯¯¯¯¯¯¯¯¯¯¯
The  innerloop (1) is enclosed in the outerloop (2).  Pay  special 
attention to the form of the nesting of a loop: the outerloop must 
totally embrace the innerloop. 

NO WORK IS WORTH TO BE DONE HALF

Remember the DOLLY-DOTS-word with that giant queu of parameters  ? 
A more sophisticated version is provided here.  We can use the old 
DOT- and DOTS-word to function in a new word.  That does only half 
the work of the DOLLY-DOTS-word.  : HALFWORK  DO CR 9 I - SPACES I 
2* 1+ DOTS DUP +LOOP DROP ;. The whole work is done by : WHOLEWORK 
0 DO 1 10 0 HALFWORK -1 0 9 HALFWORK LOOP ;. WHOLEWORK is a rather 
complicated word. It is clearly seen that it is a {DO...LOOP}. Not 
directly clear is, that two other loops are nested on equal levels 
within  the  {DO...LOOP}.  HALFWORK is a {DO..+LOOP} and  is  used 
twice  within WHOLEWORK,  but the one HALFWORK is not used  within 
the  other  HALFWORK.  Both HALFWORKs are nested on  equal  levels 
within WHOLEWORK.  The WHOLEWORK is done by entering 3  WHOLEWORK, 
or  with  another parameter.  As you can see  with  WHOLEWORK  and 
DOLLY-DOTS,  I  didn't  cluster  the  whole  action  in  one   big 
definition,  but I defined small ones,  which I put  together.  In 
general  it's  a  FORTH-rule,  that  long  definitions  are  wrong 
definitions. 'Keep them short', my father said and he was a  hair-
cutter.  The definitions I typed here won't win prizes in a FORTH-
beauty-contest.  It's a good FORTH-practice to make an intelligent 
lay-out of your definition.  The outside of a definition must tell 
something  of what's going on inside.  So WHOLEWORK anew  for  the 
beauty-contest. : WHOLEWORK   ( n -- )
                           0 DO 
                               1 10 0 HALFWORK
                              -1  0 9 HALFWORK
                             LOOP
                ;

Now it's more readable. And you know: a beauty for ever is a joy. 

The word {J} has a similar action as {I}. An example will show its 
use and action.  First of all {J} can only be of any use in nested 
{DO...LOOP}s.  It leaves in a inner loop the current index of  the 
outer loop
. Let's nest three loops in an examplestyle:
DO(1) I     DO(2)  I J   DO(3)   I   J   LOOP(3) LOOP(2)  LOOP(1). 
The first I (from the left) leaves on the stack the current  index 
of the DO(1)..LOOP(1)-loop.  The second I leaves the current index 
of the DO(2)..LOOP(2)-loop.  The first J leaves the current  index 
of the DO(1)..LOOP(1)-loop.  The third I leaves the current  index 
of  the DO(3)..LOOP(3)-loop.  The second J at last will leave  the 
current index of the DO(2)..LOOP(2)-loop. Here is some more stuff. 
First define STAR :  STAR  42 EMIT ;, then STARS : STARS 0 DO STAR 
LOOP ;. Then enter : JEE   CR ." J ( outer ) I ( inner )" ( -- )
                           CR 7 3 
                              DO 
                                  3 0 
                                  DO   CR       J STARS                                              
                                       10 SPACES
                                                I DOTS 
                                  LOOP CR 
                              LOOP
                   ; OK
Executing JEE will print a list of stars (outer- J) and a list  of 
dots  (inner-I) according to the incrementing indices of  the  two 
loops.  And study the exact looping:  the outer loop is executed 4 
times  and  each time the inner loop executes 3  times.  Note  the 
difference between JEE and the following HUNDRED. : HUNDRED   10 0 
DO I 10 * 10 0 DO DUP I + .  LOOP DROP CR LOOP ;  OK.  The first I 
acts in his own loop, as does the second I. If you want to use the 
value of the first I in the inner loop, you should use {J}. So {J} 
is  a cook-cook,  laying his eggs in other birds' nests.  In  some 
FORTHs {J} is called {I'}. 
The word {LEAVE} is used within a {DO...LOOP} to leave the loop if 
certain conditions are fulfilled, although the limit and index are 
not  on leaving-the-loop terms.  The exit will occur, if {LOOP} or 
{+LOOP}  is  next encountered and the words  between  {LEAVE}  and 
{LOOP}  will  be  executed  once  before  exiting  the  loop.   To 
illustrate the capability of {LEAVE} is the next example.  :  STAY   
10  0 DO I 5 = IF LEAVE ." Left you " THEN ." for another loop  !" 
CR  LOOP  ;.  One  FORTH  I know of,  leaves  at  the  very  point 
execution encounters {LEAVE}.

SOME HINTS ON SALARYRAISE

There are some hints,  which I won't hold away from you, concerned 
with {DO...LOOP}s.  Don't change the number of items on the  stack 
inside the body of a loop.  :  BIGBANG   1000 0 DO I LOOP  ;  will 
definitely result in an error-message,  or a recoverable crash, or 
a  beautiful hang-up of your system.  If you decide to  alter  the 
number of stackitems, be sure that the stack can hold that number.
Don't  let  your application dilly-dally around.  You  can  use  a 
{DO...LOOP} to create a certain delay.  :  PAUSE   0 DO LOOP ; can 
be  used  as 1500 PAUSE or 15000 PAUSE to give a  variable  length 
delay.  It is akward to remember (o yeah ?) to type the values  in 
reverse order and to have to add one to the last one. So making it 
more frog-friendly you could enter eg. : POPPELEPEE   1+ SWAP DO I 
.  LOOP ;.  Entering 1 3 POPPELEPEE will give 1 2 3 OK.  The  {1+} 
{SWAP}  did it.  You will have to change POPPELEPEE to get a  fine 
rhyme in 1 5 POPPELEPIVE, 1 7 POPPELEHEAVEN etc.  You see FORTH is 
almost  literature.  The  increment  in  a  {DO..+LOOP}  could  be 
calculated within that loop to give a variable value. For example: 
: SALARYRAISE   1+ SWAP DO I DUP . 2* +LOOP ;. 1 10000 SALARYRAISE 
will  give you some happiness every month.  A last remark yet   on
the nested loops and {I} and {J}.  {I} and {J} cannot be used in a 
separate  definition  inside a {DO...LOOP}.  So this has  not  the 
effect you thought it would have:  :  EFFECTLESS   5 0 DO  J . I . 
LOOP ;  ,  :  USELESS   CR 6 2 DO EFFECTLESS CR LOOP ;.  Only  the 
values of {I} are given correctly.
Herewith I definite quit that definite {DO...LOOP},  or in FORTH's 
own  words  I LEAVE DO-LOOP.  Next time I will  serve  conditional 
loops and indefinite loops in paragraph 2 of part 4.

SUMMARY

One   group  of  FORTH-words  are  the  so   called   'operators', 
arithmetic,  stack,  relational and logical. Another group are the 
defining words.  They create a  dictionary-entry:  {:}  {CONSTANT} 
{VARIABLE} {CREATE} {USER} {VOCABULARY} are the most used. Such an 
entry  consists of a head and a body.  A head has three  parts:  a 
namefield, a linkfield, a compilationfield. The body has only one: 
the parameterfield. Each entry is closed with the EXIT-routine.
The  namefield contains the ASCII-code for the  word's  name,  the 
linkfield   a   pointer   to   the   previous    namefield,    the 
compilationfield a pointer to the machinecode used by the type  of 
the  defining word and which is executed when the word whose  name 
is  in  the namefield is executed.  The parameterfield  helds  the 
'information' to be used by the executing machinecode.  Creating a 
dictionary-entry  is  called compilation.  Running  the  entry  is 
called execution.
FORTH-loops are divided in:  definite loops,  indefinite loops and 
conditional  branches.  The definite loop is known as  {DO...LOOP} 
and  its  variation,   the  {DO..+LOOP}.   Both  loops  needs  two 
arguments: the 'limit' and 'index'. The {DO..+LOOP} also needs the 
value  by  which  the index has to be  possitively  or  negatively 
incremented.  {DO...LOOP}s  can be nested.  The outer loop has  to 
enclose totally the inner loop.  {I} copies the current index from 
the  returnstack  to the parameterstack,  {J} copies  the  current 
index of the embracing outer loop to the parameterstack.  {J}  can 
only be used directly in an inner loop.  The word {LEAVE}  enables 
to quit a loop before its 'natural' exit.

REMEMBER

POINTER  -  A  pointer  is  an  address  with  a  special 
            function.  A pointer is located at a  another 
            address, the pointeraddress. A computer knows
            by a programmroutine how to interpret such a
            pointer, when he finds one. That routine will
            turn to the memoryblock indicated by that 
            pointer, to use the information - whatever it
            may be: data, a little programm - in what the
            computer was actually trying to do.
LOOP     -  A loop is a programmingtool without there was 
            no  programming.  As a computer  is  only  a 
            machine,  it can only repeat itself.  As soon 
            as you switch on your computer, it will start
            and perform an endless loop.  Each loop  has 
            its begin. A definite loop has its end after
            a   certain  and   predefined   number   of 
            throughpasses. An indefinite loop mostly ends
            if a certain condition  is  fulfilled.  Each 
            loop has its point of return, from where the
            execution  branches  back  to  the   begin. 
|  WORD    |     STACKNOTATION     |        DESCRIPTION         | 
|----------|-----------------------|----------------------------|
| SMUDGE   |    (  --  )           |Toggles the smudge-bit.     |
|DO...LOOP |  (limit index -- )    |Performs (limit minus index)|
|          |                       |loops, executing what is be-|
|          |                       |tween DO and LOOP.          |
|DO..+LOOP |(limit index DO...incr |identical, except index is  |
|          | +LOOP)                |incremented by incr.        |
| CONSTANT | n CONSTANT name       |Defining word, initialising |
|          |                       |a constant.                 |
| VARIABLE |  VARIABLE name        |Defining word, initialising |
|          |                       |a variable.                 |
|  EMIT    |  ( ascii -- )         |Emits ascii as a character  |
| SPACES   |  ( n   --   )         |Emits n spaces (ascii 32 ). |
|  CR      |  (          )         |Performs a carriage return  |
| LEAVE    |  (    --    )         |Used within a DO...LOOP to  |
|          |                       |exit the loop.              |
|   :      | Used as: : name ... ; |Defining word, creating a   |
|          |                       |new dictionary entry in com-|
|          |                       |bination with ;.            |
|   ;      | See :                 |See :                       |

EXTRAS

FORTH uses the stack very intensively. It is sometimes quite a job 
to  imagine,  what is going on there.  It is always worthwhile  to 
sketch  the  appearance of the stack when defining a new  word  or 
examining an existing word or application. These sketches could be 
the beginning of a documentation of words written by you.  Here is 
an idea to set up a stack coding sheet.

 Date                Word                  Appl.
 ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯  ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯  ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
               STACK                   TOS           WORDS
|¯¯¯¯¯¯¯¯|¯¯¯¯¯¯|¯¯¯¯¯¯|¯¯¯¯¯¯|¯¯¯¯¯¯|¯¯¯¯¯¯| |¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯|
|¯¯¯¯¯¯¯¯|¯¯¯¯¯¯|¯¯¯¯¯¯|¯¯¯¯¯¯|¯¯¯¯¯¯|¯¯¯¯¯¯| |¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯|
|¯¯¯¯¯¯¯¯|¯¯¯¯¯¯|¯¯¯¯¯¯|¯¯¯¯¯¯|¯¯¯¯¯¯|¯¯¯¯¯¯| |¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯|
|¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯| |¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯|
You may extend  this form to make  it as long as you like.   After 
drawing it, you can use a copier for as many copies as you wish.

EXERCISES 

1.   Define a word called LINE.   The stacknotation is (row col -- 
).  The use is row col LINE ." text".  The text will be printed at 
the specified place at the screen.  Remember to 'home' the cursor, 
before  each  new  textprint.  As clearing the  screen  is  not  a 
Standard-word, check your manual on how to do that.
2.   Define a word called ASC. The stacknotation is (limit index -
- ).  The word has to output the ascii-signs, beginning with index 
and ending with limit. 
3.   Define a word called ASC2. The stacknotation is (first last -
- ).  It has to output ascii-signs, but not more than 20. Make the 
word idiot-proof. 
4.    Define a word called POWERLIFT.  The stacknotation is (first 
last -- ). It has to print the powers of two, beginning with first 
and ending with last. Use a {DO..+LOOP}.
5.    Define a word called BACK. The stacknotation is (low high -- 
).  It  has to print the numbers from high to low.  So 0 12  BACK, 
prints 12 11 10 9 8 7 6 5 4 3 2 1 0.

6.   Suppose it would be possible to fold a sheet of ricepaper  25 
times.  The sheet is 0,01 mm  thick. How thick will the package be 
after all that folding ?  Write a word to solve the problem.  Call 
it THICK.  (Tip: 2^25 * 0,01 mm and 'round' to mm.). One stage has 
to  calculate  2^25,  the  other one has to do  the  rounding  and 
printing. Each stage has to define a word !!
7.    Some  simple  arithmetic.  Arrange four 5's and  the  common 
operators,  as + - * / in such a way,  that the results forms  the 
figures  1,2,3,6,7,9 and ( number) 10.  To get 1 for instance  you 
could write 5 5 + 5 5 + /. To get 6, you have to be tricky.
8.   If 8 men can dig 8 holes in 4 days, how long will it take one 
man to dig half a hole ?
9.   Create a word TABLE.  The stacknotation is ( n -- ).  7 TABLE 
has to print out the table of 7.
10. Define a word called SAME.  The stacknotation is (n -- ).  The 
word  has  to check if n is equal to one of the indexvalues  of  a 
ten  times {DO...LOOP}.  If so,  ends the  loop,  printing  'equal 
value' at your display. 

SOLUTIONS OF PART 3

1. Put 4 items on the stack:  12 13 14 15. {OVER} {OVER} gives 12 
   13 14 15 14 15;  {2OVER} gives 12 13 14 15 12 13.
2. {OVER} {OVER} is the same as {2DUP}.
3. You can replace it by {?DUP}.
4. {-ROT} is the same as {ROT} {ROT}.
5. : FIRST  DUP 3 + SWAP / ; : SECOND   DUP DUP / SWAP 6 * 15 - ;
   : THIRD  16 * * SWAP ROT * - ;
6. : NAND  * 1 SWAP - ;
7. : TOTALL_OF  0 ;  (!!!!).  The products: I'll give one example, 
   because  with the other products,  only the price will  differ. 
   : COFFEE  4 * + ;. And if you don't like to enter 4 COFFEE, but 
   are in favour of 4 PACK_OF COFFEE or something alike, you well
   could define PACK_OF as :  PACK_OF ;  or :  LBS_OF ;.  A quite
   simple do-nothing word.  We can define IS as :  IS   .  ;, but 
   you could supply some kind words to please your customers. : IS 
   .  ." Thank you for shopping at this supermarket." ;.
   Thou shall catch flies with sweet treacle.
8. If you define eg. COW as : COW  10 * + ; you can define COWS as 
   : COWS  COW ; (!!!!!). 
9. : *  5 MIN * ; 
10.First define NOT : NOT  DUP NAND ; (See 6 for NAND). AND is of 
   course :  AND   NAND NOT ;. OR is slightly more difficult : OR 
   NOT SWAP NOT NAND ;. Knowing OR then NOR is easy : NOR  OR NOT 
   ;.  Here are XOR :  XOR  2DUP OR -ROT NAND AND ;, : EQUIVALENT  
   XOR NOT ;  and :  IMPLIES  SWAP NOT OR ;.  Study these  words 
   carefully.  I found them in a book some year ago,  wrote  them 
   down.(But I forgot the exact name of the book). 

Disclaimer
The text of the articles is identical to the originals like they appeared in old ST NEWS issues. Please take into consideration that the author(s) was (were) a lot younger and less responsible back then. So bad jokes, bad English, youthful arrogance, insults, bravura, over-crediting and tastelessness should be taken with at least a grain of salt. Any contact and/or payment information, as well as deadlines/release dates of any kind should be regarded as outdated. Due to the fact that these pages are not actually contained in an Atari executable here, references to scroll texts, featured demo screens and hidden articles may also be irrelevant.