# 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``````