I'm still working on the documentation for Fleet Forth, but in the meantime I've made some improvements. One of the improvements was to the metacompiler. Previously, I handled the metacompiler version of control flow in the target by defining VALUE like words to hold the addresses of the primitives to be metacompiled. Any words which had to compile another word ( control flow, ." , ABORT" , etc. ) looked something like this, for example:
Code:
: ." ( -- )
'(.") ,-T
,"-T ; IMMEDIATE
: IF ( -- ADR CS )
'?BRANCH ,-T
>MARK ; IMMEDIATE
: AHEAD ( -- ADR CS )
'BRANCH ,-T
>MARK ; IMMEDIATE
Which meant I had something like the following for each word compiled by an immediate word (such as the control flow primitives) in the kernel source:
Code:
: (.") ( -- )
R> COUNT 2DUP + >R TYPE ;
' (.") TIS '(.")
Even worse, when trying to do something clever, such as having the code field of a primitive point somewhere other than its body ( a 'code word' without a body):
Code:
CODE BRANCH ( -- )
-2 ALLOT XBRANCH 2+ , END-CODE
' BRANCH TIS 'BRANCH
CODE ?BRANCH
-2 ALLOT ?BRANCH.BODY , END-CODE
' ?BRANCH TIS '?BRANCH
the following lines
Code:
' BRANCH TIS 'BRANCH
' ?BRANCH TIS '?BRANCH
tend to be a little distracting, as well as making it a little harder to test a new version of such a primitive on the host system before committing to a new kernel build.
My solution was
MCOMPILE , so that the control flow words ( and others) now looked like this:
Code:
: ." ( -- )
MCOMPILE (.")
,"-T ; IMMEDIATE
: IF ( -- ADR CS )
MCOMPILE ?BRANCH
>MARK ; IMMEDIATE
: AHEAD ( -- ADR CS )
MCOMPILE BRANCH
>MARK ; IMMEDIATE
Now the definitions for the primitives used by the control flow words ( and others) no longer need that annoying line:
Code:
' SOME.PRIMITIVE TIS 'SOME.PRIMITIVE
When the metacompiler is built, the versions of the primitives found in the host Forth vocabulary are compiled into the definition of the control flow words.
Code:
SEE AHEAD
AHEAD IMMEDIATE
6D17 6072 MCOMPILE
6D19 C4C BRANCH \ host BRANCH
6D1B 6CA8 >MARK \ metacompiler version of >MARK
6D1D 966 EXIT
8
OK
SEE IF
IF IMMEDIATE
6D05 6072 MCOMPILE
6D07 C58 ?BRANCH \ host ?BRANCH
6D09 6CA8 >MARK \ metacompiler version of >MARK
6D0B 966 EXIT
8
OK
Which is not a problem because
MCOMPILE copies the name to
HERE and uses it as the search string to find the address of the primitive in the target FORTH vocabulary.
M, ( meta comma) then compiles the correct address in virtual memory.
Here is the source for
M, and
MCOMPILE :
Code:
: M, ( CFA -- )
DUP ?TW \ Is it a target word?
>BODY
1 OVER 2+ 2+ +! \ Record some statistics
@ \ fetch virtual address
,-T ; \ and compile to virtual HERE
: MCOMPILE ( -- )
?COMP
R> DUP 2+ >R @ \ Get the code field
>NAME COUNT 1F AND >HERE \ Back up to name and copy to HERE
DUP COUNT >LOWER \ clear high bit of each byte
FIND 0= ?HUH M, ; \ Search and metacompile
I've used the backslash for comments because the comments were added after the fact.