Home > Previous Page >  Gil Filbey - Forth Series part 3
Archive Search  

Languages

FORTH

Gil Filbey


The third article in the series on a language for micros.


Variables


F

orth is a high-level programming language designed for small computers. It has been in existence for some years and has a following in America, but is only just beginning to appear in Britain. The main advantages of FORTH are:

  • It requires only a small amount of
         memory
  • It is fast
  • It lends itself naturally to structured
         programming
  • It is virtually machine independent

  I propose to illustrate the use of FORTH by showing a program and what it does; then discussing how it does it. The implementation I am using is APPLEFORTH V1.5 on cassette. I also have APPLEFORTH V1.2 by Programma International, though I have not made much use of this version yet. Both these versions are also available on disc.

We now show how to assign addresses in the dictionary at which the val ues of variables may be stored and accessed.

  The form is,

0 VARIABLE X


  When this is entered from the keyboard an address labelled X is created and value is stored there. (Two consecutive addresses are used in fact, so that a sixteen bit number may be stored). To change the value to 6 say, during the course of a definition, or immediately, we write


6 X !        (! is FORTH for "store")

The value 6 has now been stored at the address X, replacing the value 0. In FORTH, clear distinction is maintained between the address of a variable and the value stored there. Thus, if you type,

         X .

the address is printed and not the value.

To see the value of the variable X you type

         X @ .

The FORTH word @ (pronounced 'at') is used to fetch the value to the top of the stack. 6 would be printed in the present case.

You may add a number to the contents of X without fetching the value by means of the FORTH word +!e.g.

         10 X +!

adds 10 to the quantity stored at X. This statement is equivalent to the BASIC statement

         X = X + 10


This latter form, I am sure, must create difficulties with school children who are learning at the same time to handle algebraic equations. They may get to know

what it means but they will take some time to feel what it means. Luckily, in BASIC you are not allowed to use numbers as the names of variables, for then the form

         6 = 6 + 10

would be allowed, although it is no more ridiculous than

         X = X + 10

In FORTH you could write

         6 VARIABLE 5

which simply means that, at the address labelled 5 the number 6 is siored. To save confusion in reading, however, this is best avoided, although the machine would not be confused!

Suppose variables X and Y have been assigned then we might write,

         X @ Y +!

for adding the contents of X to that of Y. This can be written, as above, for immediate execution or compiled into a definition

         : XINTOY X @ Y +! ;

         : YINTOX Y @ X +! ;

(The contents of X in the first definition and the contents of Yin the second are left unaltered)



Here is a time-comparison with BASIC (Applesoft) see fig. 1.

What is the result of,

          XSHOW X @ . ;

         : YSHOW Y @ . ;

: SEQUENCE OX! 1 Y ! 10 0 DO
XINTOY YSHOW YINTOX XSHOW LOOP ;


You guessed it! Twenty terms of a Fibonacci sequence. In BASIC the equivalent is,


         10 X=0: Y = 1
         20 FOR I = 1 to 10

FORTH

: TEST 10000 0 DO XINTOY LOOP ;

RUN TIME = 6.2 Sec

Basic

10 FOR I = 0 TO 10000
20 Y = y + x
30 NEXT
RUN TIME = 31 Sec.

         30 X = X + Y : PRINT X
         40 Y= Y + X : PRINT Y
         50 NEXT


Constants


To define a Constant such as the acceleration due to gravity we may use

             981 CONSTANT G

G here stands for the value 981 so that,

             G .

prints 981 and not an address. The rules for naming variable addresses and for constants are the same as for defined words. The first three letters (symbols) and the length of the name are recognised.


Arrays


  There is no real distinction between arrays and variables but obviously, for convenience, a method is needed for setting aside enough space in the dictionary for the number of elements you require. This is done by means of the FORTH word ALLOT. If, for any purpose, you wish to reserve an area of memory in the dictionary, which will not be written into unless you specify it, you may write for example:

             200 ALLOT

and the next 200 1-byte locations (room for 100 2-byte numbers) are reserved. This word is not used only for arrays but also for, say, protecting the high resolution graphics page from being written into. To get at the reserved area for assigning array elements we first specify the base address by:


             20 VARIABLE X

and then,

             200 ALLOT

Now:

             X @

fetches the contents of the base address, and:

             X 2 + @

fetches the next.

To systematise this we now define array-handling words:


             : BIN DUP + + ;

             : GET BIN @ :

             : SHOW GET . ;

             : PUT BIN ! ;


  X 3 BIN is the address of the third array element.

  X 3 GET fetches the value from the third address.

  X 3 SHOW prints it.

25 X 3 PUT says, in English, "put 25 in the third address of the array X".

        X 6 GET X 7 GET + X 8 PUT

adds the contents of X 6 and X 7, and stores the result in X 8.

  With the words as we have defined them:

  X 6 corresponds to X(6) in BASIC.

  If we want to store the natural numbers in consecutive array "bins" we may write:

         1 X 1 PUT 2 X 2 PUT (etc)

or, better

      : NATNUM 0 do 1 X 1 PUT LOOP ;

Now 100 NATNUM fills all bins from 0 to 199 with integers from 0 to 199.

  If you want to put numbers from a table into consecutive bins, then define first a

FORTH

variable which assigns a length to the list (useful for later reference):

             0 VARIABLE N

Then:

       : XSTORE DUP N ! 0 D X N @ l - PUT
      LOOP ;

and enter the list:

1 3 7 2 6 9 4 5 2 1 10 XSTORE
X 5 SHOW returns 6


  The following program sorts a set of numbers into ascending order by means of a bubble sort (The storing of the numbers has initialised N.)

  We shall now need to compare the first of these with the second and swap them over if they are in the wrong order. Doing this N-1 times will float the largest to the top. So we define:


: FLOAT O DO X I GET X I 1+ GET
2DUP
>IF X I PUT X > l 1+ PUT ELSE DROP
DROP
THEN LOOP ;


  What does 1 FLOAT do? It gets the contents of X 0 and X 1, duplicates them since comparison will remove them from the stack, and swap-stores them if they are in the wrong order. (i.e. if (X 0) is bigger than (X 1)). If we do this N-1 times we'll have the biggest on top. So we define

    : COUNT N @ 1 - ;


  However, each successive run we shall need one less comparison; so we define:


     : SORT COUNT 0 DO COUNT I - FLOAT LOOP ;


  This last definition repays thinking about since it involves nested loops, and contains my recipe for painless programming of such loops. The inner loop is defined and replaced by a single word. The next loop contains the count limit for the inner loop. This way we can fetch the loop counter I in as many of the loops as we want, and in any way we want, and no defined loop will explicitly contain the loop counter for a further-in loop.

  I'll repeat this technique. Define the innermost loop so that the only thing necessary to make it run is the count limit. For safety's sake test it by, for example


      1 FLOAT


If it works - carry on out.

  So the word SORT will set a count limit for FLOAT which decreases by one count on each run.

  Note that the I which appears explicitly in FLOAT is not the same as that which appears explicitly in SORT. The program will take care of this.

  As a matter of interest here the FORTH program sorted forty numbers, initially in the reverse order, in 2.6 secs. whilst BASIC took 20 seconds. Bubblesort is useless for large N, but will here serve as a speed comparison.


  Gil Filbey is a lecturer in physics at the Polytechnic of the South Bank, London.

Magazine Adverts