Search code examples
forth

How do I create an array in Forth?


I know, the question was often asked in the past and perhaps the information are given in previous Stack Overflow postings. But learning Forth is a very complicated task and repetition helps to understand the advantages of a concatenative programming language over alternative languages like C.

What I have learned from Forth tutorials is that Forth doesn't provide commands for creating a 2D array, but the user has to realize everything from scratch in the program. I've found two options in occupying memory in Forth. At first by creating a new word:

: namelist s” hello” s” world” ;

or secondly by the CREATE statement:

create temperature 10 allot
temperature 10 cells dump

So far so good; we have created an array of 10 cells in which integer variables can be stored. But what is, if I need to save float numbers? Do I have to convert float always to int or can they saved into the normal cells?

Another open problem is how to store string values in the array. As far as I know, a string contains a pointer plus a size. So in theory I can store only 5 strings in a 10 cell array and additionally I need memory somewhere else which holds the string itself. That doesn't make much sense.

Is there some kind of higher abstraction available to store values in arrays which can be used to write easy to read programs? I mean, if every programmer is using his own Forth method to store something in the memory, other programmers will find it hard to read the code.


Solution

  • A generalised 2darray of elements. Takes the element size as a parameter

    \ size is the per element multiplier
    \ n size * is the per_row factor
    \ m n size * * is the total space required
    
    : 2darray  \ create>  m n size -- ; does> mix nix -- a
    \  size is the number of bytes for one element
    \  
      create  2dup * ,      \ multiplier to apply to m index 
              dup ,         \ multiplier to apply to n index
              * * allot     \ calculate total bytes and allot them
      does>  \ mix nix -- a 
        >r r@ cell+ @ *     \ offset from n index  
           swap r@ @ * +    \ offset with m index
       r> + 2 cells+        \ 2 cells offset for the 'admin' cells
    ;
    

    Examples

    50 40 /float 2darray 50x40floats
    50 40 2 cells 2darray 50x40stringpairs
    

    even

    20 constant /record
    10 200 /record 2darray 2000records