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.