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

Languages

FORTH

Gil Filbey


LEARNING FORTH
A miscellany


Concluding the series on the language invented by Charles H. Moore.

  To write in all the elements of a fairly large matrix we get over the tedium of the PUT commands by FILLUP. We type all the elements from last to first and the 'X FILLUP'. As follows.

USE OF 'FILLUP' AND 'DISPLAY

9 8 7 6 5 4 3 2 1 X FILLUP OK

X DISPLAY CR
 1 2 3 4 5 6 7 8 9

X 0 2 SHOW CR
3 OK

X 2 2 SHOW CR
9 OK .

X TRACE CR
15 OK


(NOTE THAT X MATRIX GOES FROM X 0 0
X 22 )

  I have slipped in the word TRACE here which gives the sum of the diagonal elements. It is only meaningful in square matrices and its particular property is that it remains unchanged in certain matrix operations. The TRACE command in the listing gives


X 0 0 + X 1 1 + X 2 2


  Try writing words for giving the sum of any in-line elements as in a magic square.

  You will want to develop your own matrix handling routines and you have to make a choice between speed of operation and ease of programming (or rather the flexibility of programming.) For speed you avoid defining variables as much as possible. Fetching a number from an address to the stack is slow. Constants are faster. The disadvantage of constants is their local character as against the global character of a variable.


For example       6 X !


  Stores 6 at the address X and all programs which get X by means of X@unless this is changed subsequently by say

7 X !

  However 6 CONSTANTX will make X= 6 for any program written subsequently until


7 CONSTANT X


changes the value. But now earlier programs get 6 and later ones get 7.

  So programs for handling at the outset could well use constants for the ROW and COL words using XROW and XCOL, YROW and YCOL etc.

4 BLOCK 12 LIST
  (EXAMPLE)

3 CONSTANT XROW 2 CONSTANT YROW
2 CONSTANT XCOL 3 CONSTANT YCOL

: MATPROD C XROW 0 DO XCOL 0 DO 0

  YROW DO X K I GET Y I J GET *

  + LOOP CR LOOP LOOP ;

  Notice that you don't use @ to fetch a constant. It is not an address. In the MATPROD command I have used loop

It is convenient, but not essential, to

use a disc operating system (OS) with FORTH. The main advantage is that it may be used as virtual memory. The second advantage is that the text file may be stored on disc (and subsequently edited and modified), since the text file is not retained in FORTH once the program has been compiled, i.e. placed into the dictionary. I have referred to the FORTI SCREENS (which are 1 K blocks of memory in my system in a previous article. You can save such screens on disc to be BLOADed into the memory block on another occasion and from there LOADed into the dictionary. In the file name it is wise to include the screen number that it will BLOAD into so you know where to find it. Also, if a number of screens are to be loaded into the dictionary then the order is important so some reference to the order should also be included in the file name. A FORTH word must also be defined to operate DOS e.g.


: DOS 3DO EXEC ;

The procedure is then
1 BOOT DOS
2 BRUN FORTH (The core language stored on disc)
3 DOS
4 BLOAD the required screens
5 CALL 8192 (gets FORTH)
6 DECIMAL (FORTH BOOTS in HEX)
7 LOAD screens by number (e.g. 3 LOAD)
8 UPDATE (Dictionary entries will not be lost by accidental resets)



Here is a CATALOG of one of my discs


DISK VOLUME 254

A 002 HELLO
B 027 FORTH
B 006 FORTH ARRAY HANDLING 4
B 003 FORTH ARITH 4
B 006 FORTH M/C ROUTINES 2
B 004 FORTH A.B DIVIDE 4
B 006 FORTH APPLEDEM M/C 3
B 002 DOS HANDLING
B 006 FORTH DIGITAL FILTERS A 5
B 002 FORTH RANDOM CODE
B 006 FORTH HIRES SETUP 3
B 006 FORTH DIGITAL FILTERS B 4
B 004 FORTH START

  For any program requiring graphics the file FORTH HIRES SETUP 3 must be LOADED before any others. For some work with a digital filter it would go like this


DOS (if the system is already in FORTH
BLOAD FORTH DIGITAL FILTERS A 5
BLOAD FORTH DIGITAL FILTERS B 4
BLOAD FORTH HIRES SETUP 3
BLOAD FORTH M/C ROUTINES 2
CALL 8192


(The order of the above is unimportant)

  DECIMAL
3 LOAD
5 LOAD
4 LOAD
  UPDATE



  Note that M/C routines are not LOADed.

  The system is now ready to go.

  If you are using tape storage then probably the best procedure to save wasting time is to keep everything you define in the dictionary, UPDATE it and put it all on tape when you've finished.

  The equipment of the DOS Procedure takes rather long


Multi Dimensional Arrays


  This is a way to handle multidimensional arrays illustrated by matrices. These are used, for example, for translating, rotating, and distorting shapes on 1 the graphics screen.
  I do no more here than show how to allocate space in the dictionary for matrices, how to address individual elements and how to carry out a simple operation such as matrix multiplication.


         ARRAY HANDLING COMMANDS
         -----------------------


( 0 VARIABLE X R C DIM:X I J BIN: N X I
J PUT: NNN X FILLUP:X DISPLAY :X TRACE)

0 VARIABLE COL 0 VARIABLE ROW
: DIM 2DUP * 2 * ALLOT COL ! ROW ! ;
: BIN SWAP COL @ * + 2 * + ;
: PUT BIN ! ;
: GET BIN @ ;
: SHOW GET . ;
: TRACE 0 COL @ 0 DO SWAP DUP I DUP
  GET ROT + LOOP ;
: J R> R> R> I SHAP >R SWAP
  >R SWAP >R ;
: FILLUP ROW @ 0 DO COL @ 0 DO DUP
  ROT ROT J I PUT LOOP LOOP ;
: DISPLAY ROW @ 0 DO COL @ 0 DO DUP
 J I SHOW LOOP LOOP ;
: K R> R> R> SWAP R> SWAP >R SWAP >R ;

  Here is a screen of matrix commands. The WORDS in brackets at the top are comments to remind the programmer how to use them. The compiler ignores anything in brackets provided a space is left after the leftmost bracket.
  Typing the bracketed words with numbers entered where appropriate will dimension a matrix, fill it up and print it out. The size of the row and column are stored as variables, X I J BIN refers to an address into which the element whose row is I and whose column is J may be put by the command



N X T J PUT
X I J GET fetches the stored value to the stack
X I J SHOW prints it.

counters I J K. These have to be defined and you can see how it is done in the array handling commands list.

We use the two FORTH Words >R and R> The first of these passes a number from the normal stack (called the parameter stack) to the return stack. This second stack which is less-used by the programmer is mainly for loop counters and loop limits. Thus when you type : XXI 10 0 DO-----LOOP ; The limits 10 and I go on the return stack and then the loop counter. I always refers to the top of the return stack even in an illegal use of T' as we can test later. The return stack can also be used as a temporary store for a parameter but care must be exercised or the program will think it is a loop counter or something.


>R means 'to the return stack'
R< means 'from the return stack' Try this
6 >R I . PROTECT
You will find that 6 is printed followed by CANT EXECUTE PROTECT?


(if you don't use protect you will exit to the monitor - you can get back by 2000 G)

  What happened was that 6 was put on the normal stack, R transferred it to the return stack, I took it off and ', printed it. This procedure is illegal - all of this may only properly be done within a colon definition, but PROTECT wards off the evil consequences.


6 >R R R >.

  will, however, print 6.

FORTH

In the MATPROD word our problem is that we need all three loop counters when in the inside loop. In their own loops the counters are all fetched by 'T', but when in the inside loop you have to peel all the limits and counters like the layers of an onion. This is all right provided you reassemble it promptly before the program tries to make use of the missing bits. You can go on to K and L as well if you need them. In summary, I defines the loop counter you are in at the time of writing, J defines the counter for the next outermost loop.


So the next two examples,


: EX1 3 0 DO 2 0 DO I . J . 4 0 DO
  LOOP LOOP LOOP ;
: EX2 3 0 DO 2 0 DO 4 0  DO I . J .
  LOOP LOOP LOOP ;

give very different results. See if you can work out what these will be.


GRAPHICS


  We will now use FORTH with the Apple high resolution graphics. The easiest way is to use the tape version which luckily is located in $ C00 . FFF and exactly fills screen 2 in memory. It is shown on my Disc Catalogue as FORTH M/C ROUTINES 2. It is not to be loaded into the dictionary since it would then be in the wrong area of memory and it is not relocatable. I show here a list of the HIRES SETUP 3.

OK
? BLOCK 212 CLIST
: WHITOPILOT 255 912 C!;
: ERRSE 2 812 C!
: HGR2 3 872 EXEC;
: SETUP -1 190 + 302 C! 0 801 C!
  800 C! :
: PLOT 'SETUP 3780 EXEC ;
: LINE PLOT SETUP 3786 EXEC ;
: AXES 190 0 0 LINE 0 0 255 0 LINE
  25 0 DO I 10 * 1 PLOT LOOP 19 0 DO
  1 I 1 0 * PLOT LOOP ;
: TEXT 3744 EXEC ; : GRAPH 3751 EXEC ;
: CLEAR 3886 EXEC RXES ;
: MARKER 2DUP 2DUP 2 - LINE 2DUP 2DUP
  2 + LINE 2DUP 2DUP SWAP 2 - SWAP LINE
  2DUP SWAP 2 + SWAP LINE ;
: HLINE 0 SWAP 250 OVER LINE ;
: VLINE 0 OVER 190 LINE;
: POINTS 0 DO 7STACK PLOT LOOP ;
: AXES WHITESPOT AXES ;
;S
OK

This is what they do.

WHITEPLOT selects white
ERASE     selects black
HGR2      cleans the screen
SETUP     formats the screen area for
                 plotting
PLOT      uses SETUP and is used by
                 means of X Y PLOT
LINE      needs both end-points to be
                 specified
AXES      sets up left and bottom axes
                 with pips at 10 intervals.
TEXT & GRAPH pass back and forth without
                clearing
MARKER   places a 5 by 5 cross on the
                by means of X Y
MARKER   HLINE & VLINE need only a single
                parameter
POINTS   enables the placing of
                experimental data by means
                of X1 Y1 X2 Y2 POINTS PLOT
                where N is the number
                of points.

  Well, this article is the last of the present series. I hope to be back with a FORTH program from time to time.