I have been using metacompilation to target compile eForth for Computer Cowboy's MuP21 and F21 chips. I have presented papers for FIG on these simple and straitforward traditional metacompilers that use search order, and a couple of vocabularies to control the metacompilation. (see A Simple Meta Compiler jfox 6/94
The 2.4.2 release of eForth contains the full ANS core, core extension, exception, double, double extension, search- order, search-order extension, facility, and tools word sets. With these tools the metacompiler I have been using to compile MuP21 eForth from DOS would port easily, but instead I use a very simple technique to force the normal Mup21 eForth compiler to produce a new MuP21 eForth system from source.
To do this only a few words need to be changed. Certain immediate words like IF compile a reference to a runtime counterpart. In eForth "IF" compiles the primitive "if" to perform the conditional branch and leaves an address for "ELSE" or "THEN" to resolve later.
After the "if" primitive is compiled in a target metacompile the address of this "if" can be placed in the "IF" in eForth. This will cause "IF" to compile the correct address for the target and make it unusable for normal compilation. There are a few other words in the eForth compiler that need to be modified to that they can compile a reference to a primitive word in the target rather than compiling the address of the primitive word in eForth.
The definition of "IF" starts with " : IF [ ` if ] LITERAL COMPILE, ..." This means that the first cell in the compiled word "IF" will be "DO:" , and the second cell is "lit" and the third cell is the address of the "if" primitive. Thus " ` IF 2 CELLS + " would give the address of the cell containing the "if" primitive in the word "IF".
The word "IF" appears in other words in the eForth source code 57 times before the word "IF" is defined in the eForth source. But as soon as the the primitive "if" is compiled in a new system the word "IF" in the system doing the compiling can be patched to make it into a metacompiling "IF". This is done by " ` if ` IF 2 CELLS + !". This will get the address of "if" in the target system since it is the most recent definintion of "if" and then patch that address into the word "IF" in the system doing the compilation. Thus the word "IF" has been changed into a metacompiling "IF". It will correctly compile references to the target "if" in the target code until a new "IF" is definined in the target.
This can be factored into a single definition and used on each of the immediate words in the eForth compiler as the source code is compiled.
: META ( -- ) ` ` 2 CELLS + ! ; \ as in META if IF"META" needs to be used on certain words in the eForth compiler to transform these words into metacompiling words that compile references to target primitives.
When the new run time words are compiled in the target memory space these addresses are patched into the compiling words of eForth so that words like a target "IF" can be used before "IF" is compiled in the target. It is a way of passing control from one running version of Forth to a new running version with the minimal amount of bridge building. A few commands added to the eForth source transform the normal compiler into a metacompiler on the fly. Then the compiling system is cut loose and the new running eForth is booted.
\ MINIMAL DTC EFORTH METACOMPILER Jeff Fox 10/7/94 \ META ( -
- ) \ get the address of name1 in target \ chang the literal # cell in the host word name2 \ to the execution token in the target word name1 \ place META after the defintion of the TARGET name1 : META ( - - ) ' ' 2 CELLS ! ; \ for DTC eForth META EXIT ; \ ; used 138 times \ before it is defined in target META do: :NONAME \ : used 137 times META lit LITERAL \ LITERAL used 25 times META if IF \ IF used 57 times META if UNTIL \ UNTIL used 10 times META else AGAIN \ AGAIN used 1 time META abort" ABORT" \ ABORT" used 3 times META d" ." \ ." used 3 times \ Jeff Fox 10/14/94