2d Array Problem in Gforth

Standard Forth includes the ability to define classes of memory objects, along with an instance behavior for that class. It’s a little like OOP, but without inheritance and with only one class method. Basically, it is a way to add a forth word which can be used to initialize memory and map it to a name, and then use that new name as an interface to the memory. The forth words constant and variable are such words, which define in memory a constant or a variable. Then the name of said constant or variable can be called on to return the value of the constant or the address of the variable’s storage memory.

One problem from Forth Application Techniques is to create a 2D array class. Here is a (non-optimized) solution:

: 2< ( n0 n1 n2 n3 -- b ) rot > -rot < and ;

: 4dup ( n0 n1 n2 n3 -- n0 n1 n2 n3 n0 n1 n2 n3 )
    3 pick 3 pick 3 pick 3 pick ;

: 2array ( n0 n1 -- ) create 2dup , , * cells allot
  does> ( n0 n1 -- a )
    dup >r 2@ 4dup 2< 0= if -24 throw then
    swap 2 pick * nip nip + cells r> + 2 cells + ;

The first two words, 2< and 4dup are some helper words.

The first line of 2array is the defining action, which takes two numbers of the stack and stores them in the memory space to serve as dimensions for the array. Further memory is allotted according to the dimensions given. create associates the memory with the instance word.

The code for 2array after does> is the instance behavior, which takes two index numbers off the stack, and returns the correct memory address. The first line of the instance behavior code serves to confirm that the indices are not larger than the array dimensions. The second line then calculates the appropriate memory address and drops it on the stack.

Here is defining a 3×2 array:

3 2 2array data  ok

In Gforth our cell size is 8 bytes, so our memory address increments by 8 as we move through the array:

0 0 data . 140051427947736  ok
1 0 data . 140051427947744  ok
2 0 data . 140051427947752  ok
0 1 data . 140051427947760  ok
1 1 data . 140051427947768  ok
2 1 data . 140051427947776  ok

If we go too large, we throw an error:

0 2 data . 
:19: Invalid numeric argument
0 2 >>>data<<< .
Backtrace:
$7F60439CF420 throw 
$7F60439CF4C8

Of course, we can store things in our array:

0 0 0 data !  ok
1 1 0 data !  ok
2 2 0 data !  ok
3 0 1 data !  ok
4 1 1 data !  ok
5 2 1 data !  ok
0 0 data 3 2 * cells dump 
7F60439CF4D8: 00 00 00 00  00 00 00 00 - 01 00 00 00  00 00 00 00  ................
7F60439CF4E8: 02 00 00 00  00 00 00 00 - 03 00 00 00  00 00 00 00  ................
7F60439CF4F8: 04 00 00 00  00 00 00 00 - 05 00 00 00  00 00 00 00  ................
 ok

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s