PDA

View Full Version : Creating Word Arrays


g_jilek
10-28-03, 04:07 PM
What is the best way to develop Word Arrays?
The way I'm looking at this is to use something like the following:

Previously defined Words:
WORD1
WORD2 WORD3 WORD4

CREATE WORD_ARRAY ' WORD1 , ' WORD2 , ' WORD3 , ' WORD4 ,

Does the Maxforth / IsoMax version of ' (tick) return the pfa or the cfa? i.e. will ' WORD3 store the word's pfa so that WORD_ARRAY 2 2* + @ EXECUTE will compile and run WORD3 ? Is EXECUTE looking for the pfa or the cfa?

Thanks,
Gerard

rob
10-28-03, 08:32 PM
Perhaps you are looking for a tool that already exists which is called :CASE. For example:
: ENGLISH ." HELLO " ; OK
: FRENCH ." BONJOUR " ; OK
: ITALIAN ." BONJOURNO " ; OK
: JAPANESE ." COMBONWA " ; OK
:CASE GREET ENGLISH FRENCH ITALIAN JAPANESE ; OK
0 GREET HELLO OK
1 GREET BONJOUR OK
2 GREET BONJOURNO OK
3 GREET COMBONWA OK

' returns the pfa pointer since MaxForth supports a separated head system. Execute expects a CFA. So to execute a word using ' you would do:
1 ' GREET CFA EXECUTE BONJOUR OK
If you store the ' or the pfaptr, you will be storing an address to the header. This is ok if you keep the headers around and you can also use it to get at the name of the word:' GREET NFA ID.
GREET OK
Hope this is clear now.

Rob

g_jilek
10-29-03, 02:43 PM
To make sure that I understand what is going on, will the following code work?

: WORD1 {code} ;
: WORD2 {code} ;
: WORD3 {code} ;
: WORD4 {code} ;
VARIABLE :CASE_INDEX {value} :CASE_INDEX !

: LOAD_ARRAY :CASE WORD_ARRAY
WORD1 WORD2 WORD3 WORD4 ;

: STEP_WORD_ARRAY
:CASE_INDEX @ DUP 3 <
IF 1 + DUP :CASE_INDEX !
ELSE DROP 0 0 :CASE_INDEX !
THEN WORD_ARRAY ;

Also in an effort to understand what is going on at a deeper level, is the following code equivalent to the above?

: WORD1 {code} ;
: WORD2 {code} ;
: WORD3 {code} ;
: WORD4 {code} ;
VARIABLE ARRAY_INDEX {value} ARRAY_INDEX !

: LOAD_ARRAY CREATE WORD_ARRAY
‘ WORD1 CFA , ‘ WORD2 CFA , ‘ WORD3 CFA , ‘ WORD4 CFA , ;

: STEP_WORD_ARRAY
ARRAY_INDEX @ DUP 3 <
IF 1 + DUP ARRAY_INDEX ! 2*
ELSE DROP 0 0 ARRAY_INDEX !
THEN WORD_ARRAY + @ EXECUTE ;

Thanks for the InPut,
Gerard

RMDumse
10-29-03, 07:05 PM
Originally posted by g_jilek
To make sure that I understand what is going on, will the following code work?
...
: LOAD_ARRAY :CASE WORD_ARRAY
WORD1 WORD2 WORD3 WORD4 ;


There is a problem in this line. I probably have to go back to basic principles to explain this. So leaving the rest of your proposed code aside...

The ":" word is a defining word. Likewise, :CASE is a defining word. You don't use one defining word in the middle of another defining word. You'll get an error. The ": LOAD_ARRAY " part in this line above is at least redundant, or more so unnecessary, and at worse an error for the compiler.

When you say : <name> what happens is the name is parsed, tacked on the end of the dictionary, and the interpreter is switched to the compiling mode. When new words come in (and they are ordinary words, not IMMEDIATE words) in compiling mode, they are compiled. In essence they are ticked, CFA's and the result comma'd into memory.

Usually the interpreter stays in compile mode until a ; is encountered, which checks compiler security, and if all is okay, finishes off the definition under construction, makes if available in the dictionary, and switches out of compiling mode, back into interpreting mode.

So in your opening post where you said,

Originally posted by g_jilek
Previously defined Words:
WORD1
WORD2 WORD3 WORD4

CREATE WORD_ARRAY ' WORD1 , ' WORD2 , ' WORD3 , ' WORD4 ,


You almost described what Forth actually does when compiling.

In fact, as an exercise you should try this, almost the same:

COLD

HEX
: WORD1 1 . ;
: WORD2 2 . ;
: WORD3 3 . ;
: WORD4 4 . ;

CREATE WORD_ARRAY1 ' WORD1 CFA P, ' WORD2 CFA P, ' WORD3 CFA P, ' WORD4 CFA P,

: WORD_ARRAY2 WORD1 WORD2 WORD3 WORD4 ;

:CASE WORD_ARRAY3 WORD1 WORD2 WORD3 WORD4 ;

Then go back and tick each name, go to the very beginning of the definition NFA, and dump the program memory, and compare.

' WORD_ARRAY1 NFA 20 PDUMP




' WORD_ARRAY2 NFA 20 PDUMP




' WORD_ARRAY3 NFA 20 PDUMP





which will give results like this:


' WORD_ARRAY1 NFA 20 PDUMP
7E34 8B 57 4F 52 44 5F 41 52
7E3C 52 41 59 B1 7E27 7E43 C8 7E08
7E44 7E15 7E22 7E2F 8B 57 4F 52 44
7E4C 5F 41 52 52 41 59 B2 7E34 OK
OK
' WORD_ARRAY2 NFA 20 PDUMP
7E47 8B 57 4F 52 44 5F 41 52
7E4F 52 41 59 B2 7E34 7E56 9B 7E08
7E57 7E15 7E22 7E2F 1073 8B 57 4F 52
7E5F 44 5F 41 52 52 41 59 B3 OK
OK
' WORD_ARRAY3 NFA 20 PDUMP
7E5B 8B 57 4F 52 44 5F 41 52
7E63 52 41 59 B3 7E47 7E6A DB 5723
7E6B 7E08 7E15 7E22 7E2F 1073 6318 62C1 D2E
7E73 10 1530 6318 6271 1530 6318 6281 1530 OK

Let's have a look at the memory signatures side by side. Let me rearrange the dump a bit.

WORD_ARRAY1
8B 57 4F 52 44 5F 41 52 52 41 59 B1 7E27 7E43 C8 7E08 7E15 7E22 7E2F
OK
WORD_ARRAY2
8B 57 4F 52 44 5F 41 52 52 41 59 B2 7E34 7E56 9B 7E08 7E15 7E22 7E2F 1073
OK
' WORD_ARRAY3 NFA 20 PDUMP
8B 57 4F 52 44 5F 41 52 52 41 59 B3 7E47 7E6A DB 5723 7E08 7E15 7E22 7E2F 1073

The 8B 57 4F 52 44 5F 41 52 52 41 59 B1 is the name field of WORD_ARRAY1. The 8B 57 4F 52 44 5F 41 52 52 41 59 B2 is the name field of WORD_ARRAY2. The 8B 57 4F 52 44 5F 41 52 52 41 59 B3 is the name field of WORD_ARRAY3. All three are counted ascii strings with MSB of first byte set. Next is a link field, where each points to the previous. (7E27, 7E34, 7E47.) This is just a dictionary linkage. Next is a PFAPTR, pointing to the actual parameter field. (7E43, 7E56, 7E6A.) Next field is the CFA, and this is different in each, each definiting word leaving a different address to interpret what is found in the parameter field. In the first example, C8 is left, which is probably the interpreter for CONSTANT (called DOCON) . In the second example 9B is the interpreter for COLON (called DOCOL) . In the third example is DB the interpreter for high level definition interpreters and 5723 to interpret :CASE (called DOCASE) .

Now, notice, in all three example the word's CFA's follow:

7E08 7E15 7E22 7E2F

The : and :CASE examples follow with a 1073 which should be the end-of-a-word interpreter for ";" called SEMIS. The CREATE example doesn't have anything here.

So all three ways are ways to make arrays of words. ":" and ":CASE" work on their different ways. ":" runs through its list sequentially. ":CASE" indexes into its list and executes one of them. CREATE returns the address of the list and nothing else.

Hope that helps.

g_jilek
10-30-03, 03:02 PM
Thanks for the in-depth response Randy. It has helped me correlate my study of FORTH with MaxForth / IsoMax. Seeing that “:” was actually a word array was insightful.

Reworking the code from my last post I have the following:

: WORD1 1 ; EEWORD
: WORD2 2 ; EEWORD
: WORD3 3 ; EEWORD
: WORD4 4 ; EEWORD
VARIABLE :CASE_INDEX 0 :CASE_INDEX ! EEWORD

:CASE WORD_ARRAY WORD1 WORD2 WORD3 WORD4 ; EEWORD

: STEP_WORD_ARRAY
:CASE_INDEX @ DUP 3 <
IF 1 + DUP :CASE_INDEX !
ELSE DROP 0 0 :CASE_INDEX !
THEN WORD_ARRAY ; EEWORD

Is the following code equivalent to the above?

: WORD1 1 ; EEWORD
: WORD2 2 ; EEWORD
: WORD3 3 ; EEWORD
: WORD4 4 ; EEWORD
VARIABLE ARRAY_INDEX 0 ARRAY_INDEX ! EEWORD

CREATE WORD_ARRAY ‘ WORD1 CFA P, ‘ WORD2 CFA P, ‘ WORD3 CFA P, ‘ WORD4 CFA P, EEWORD

: STEP_WORD_ARRAY
ARRAY_INDEX @ DUP 3 <
IF 1 + DUP ARRAY_INDEX ! 2*
ELSE DROP 0 0 ARRAY_INDEX !
THEN WORD_ARRAY + @ EXECUTE ; EEWORD

There are a few questions that this raises. Is “:CASE” unique to MaxForth? Which of the two above examples will execute “STEP_WORD_ARRAY” faster?
Why use “P,” instead of “,”? Is dictionary space at a premium, or is the program space more efficient, and how does “:CASE” handle this?

Thank you for your consideration,
Gerard

RMDumse
10-30-03, 08:33 PM
Originally posted by g_jilek
Is the following code equivalent to the above?


Pretty close. I'm troubled by the 2* in the second example. Don't think that step is necessary. There are more efficient ways to write the index handling. But they are close in composition.


There are a few questions that this raises. Is “:CASE” unique to MaxForth?


No, many other Forth's have a :CASE or CASE: or structure CASE OF ENDCASE set.

The equivalent in C is a switch with break statements.


Which of the two above examples will execute “STEP_WORD_ARRAY” faster?


Don't know, but I'd sure suspect the :CASE


Why use “P,” instead of “,”?


"P," is program space. While just "," is data space.


Is dictionary space at a premium, or is the program space more efficient, and how does “:CASE” handle this?


The big available memory is Program Flash. There's 32K x 16 of program space flash, and only a 4K x 16 of data flash. Plus all the other program structures are in program space, so it seems the natural place to put them in the particular CPU's split architecture.

g_jilek
10-30-03, 10:13 PM
I had included the “2*” to multiply the index by two because I was under the impression that “CREATE” in conjunction “ALLOT” or “,” and “P,” assigned memory space in bytes. Hence the index had to be multiplied by 2 before it could be added to the address established by “CREATE” providing the proper offset. Please let me know on this.

My planned use of the word array was to step through the array based on a timer interrupt.

Thanks again,
Gerard

RMDumse
10-31-03, 08:20 AM
In the DSP version, ALLOT works on cells. There is no byte addressing. That's why you should use :CASE as it takes care of the indexing for you.