**this file explains how I implemented the multiple vocabularies with the **copy of L&P Meta.compiler. It was posted on GEnie, I have included it **here for information. How to change Laxen&Perry F83 Metacompiler to use multiple vocabularies when compiling the kernel. First, the version I used this on is the Amiga F83 a derivative of L&P V2.1.0 for CP/M. The Amiga F83 was posted to GEnie by me some time ago. It is a 32 bit model. The differences are obvious, if you have your version at hand and compare the listings. Most are simple substitutions of 4* for 2* and 4+ for 2+, since cell size in my system is 32 bits, the L&P model uses 16 bits. This is not a new Metacompiler. I set out to make changes to the system, instead. This is supposed to be a feature of Forth. Maintainability. And as far as I'm concerned it is. It took very few changes to make multiple vocabularies possible. What that implies is that any word defined to be used interpretively from within Meta is visible at all times. This includes defined VOCABULARIES. Others which will be visible at all times (much as before) are VARIABLES and CONSTANTS. In my opinion that is a small sacrifice. And the major advantage is that the original Kernel.blk and Meta.blk need no changes except for the ones given below. The Metacompiler feels and looks identical to the original from L&P, with the added feature of hiding CODE and COLON definitions. This is a 2 step procedure: 1). Change the kernel, Metacompile 2). Change Meta and some minor changes in the kernel, Metacompile. Some terminology: target-image The data that will be the new kernel, once saved. dictionary A set of vocabularies, with a CONTEXT like array, a variable behaving like CURRENT, and a vocabulary link like VOC-LINK. symbol-dict. A set of vocabularies into which all symbols are entered. It is here that the Metacompiler finds the address to be compiled. In the original version this was the TARGET vocabulary. The symbol-dict will grow as each new target vocabulary is defined. STEP 1 Altering the way the system FINDs words ----------------------------------------------- When Metacompiling, the host system is used to find the word in CONTEXT. Meta controls the search order by using TARGET, the vocabulary where all the symbols are defined. This is only one vocabulary, and what we want is a multiple set of vocabularies, controlled by us in the kernel.blk source file. If the whole idea of FINDing and CONTEXT was designed to be used with multiple dictionaries, that would have been a trivial change. We can still simulate it by altering the way FIND works. If FIND encounters a vocabulary address that we mark as a special vocabulary, it can go and find the word in question in an extra CONTEXT. CONTEXT: .... ..... TARGET ..... 0000 ------------> + + ------> | | +------+ +-------+ | | | | +-> ------------->+ : .... .... .... 0000 In the above diagram TARGET would not receive any words. They are stuck into another current; . This allows Meta to be used, almost unchanged. TARGET is still a vocabulary in Meta, empty, and used as a flag. The actual changes: (in Kernel.blk ) I inserted a blank screen between the screens that define (FIND) and FIND, by moving screens around. In the blank screen I entered: 0 \ Meta multiple voc support. 02Jun88pJa 1 VARIABLE 2 VARIABLE HERE THERE #VOCS 4* DUP ALLOT ERASE 3 VARIABLE -1 !-T 4 : TARGET? (S addr -- fl ) @ = ; 5 : @ ! ; 6 : (S addr -- addr false | cfa flag ) 7 DUP C@ IF PRIOR OFF FALSE #VOCS 0 8 DO DROP I 4* + @ DUP 9 IF DUP PRIOR @ OVER PRIOR ! = 10 IF DROP FALSE 11 ELSE OVER SWAP HASH @ (FIND) DUP ?LEAVE 12 THEN THEN LOOP 13 DUP IF R> DROP LEAVE ELSE DUP THEN 14 ELSE DROP END? ON ['] NOOP 1 THEN ; 15 and are alternate copies of CONTEXT and CURRENT. is a flag, initialized to -1. Here Meta can put the address of the vocabulary, which causes FIND to execute . The word TARGET? returns a flag for that purpose. is the same as DEFINITIONS, for the alternate CONTEXT/CURRENT. is a copy of FIND, with a small difference. It uses and it exists a little different. First of all the C@ will always be true, or execution wouldn't even get to here, since should only be called from FIND. The C@ test is done in FIND, and it will return NOOP and 1 in that case. I'm a little lazy, could have removed that. (You can). If finds a match in it will exit the DO..LOOP via ?LEAVE. It will end up on line 13, test to see if it was a match and exit the caller: FIND. The R> DROP pops the return address and the LEAVE exits the DO..LOOP that was being executed in FIND. If no match it duplicates the flag, to be used in FIND, to indicate no vocabulary in that position of CONTEXT. ( I actually use all lower case, but that's my choice. Watch out for the 4* that should in 16 bit system be 2* ) In the next screen, the original FIND was changed: ..................... DO DROP CONTEXT I 4* + @ DUP TARGET? IF DROP ELSE DUP THEN ( <--inserted ) IF DUP PRIOR @ OVER PRIOR ! = .................. The added line will cause to be used if TARGET? returns true, that is, the vocabulary is e.g. TARGET. In "CREATE, the sequence: CURRENT @ was replaced by: CURRENT @ TARGET? IF @ ELSE CURRENT @ THEN Those are all the changes required for the kernel, next metacompile. The new kernel must be used to Metacompile again, after the next steps have been made. STEP 2. Making the changes in Meta.blk and the last changes in Kernel.blk ------------------------------------------------------------------------- The only changes required in Meta.blk are in the way Meta defines a vocabulary. We want this vocabulary to: 1- Create a header and vocabulary links in the target-image. 2- Save the address of (1) in a symbol, which is kept in the vocabulary, part of the symbol dictionary. 3- Create a word in vocabulary META to save pointers into the symbol dictionary; the vocabulary corresponding to the target-image one. When this word executes, it must set and also CONTEXT-T, which points to a set of links in the target-image. The vocabulary defined in meta is linked into SYMBOL-LINK, not VOC-LINK of the host system. To make life easier a set of words to manipulate and take a look at the symbol table are added. (.SYMBOLS doesn't work) The changes in Meta.blk: After the vocabulary TARGET is defined the variable must be set: VOCABULARY TARGET ' TARGET >BODY ! After that I added a variable: VARIABLE SYMBOL-LINK It links all the symbol vocabularies together, see below. The word VOCABULARY now is: : VOCABULARY (S -- ) RECREATE [FORWARD] HERE-T #THREADS 0 DO 0 ,-T LOOP HERE-T VOC-LINK-T @ ,-T VOC-LINK-T ! [FORTH] CREATE [META] #TRHEADS 0 DO 0 , LOOP HERE SYMBOL-LINK @ , SYMBOL-LINK ! , DOES> DUP ! #THREADS 1+ 4* + @ CONTEXT-T ! ; The first three lines are the same as before. ( In the Amiga version the second ,-T is ,-tr ) On the fourth line, ( forth ) CREATE makes a header in the host system, META vocabulary. It then allocates link pointers which will point into the symbol dict. Links itself into SYMBOL-LINK. Stores the target-image pointer to the target-image version of the defined vocabulary. When the defined vocabulary is used, it will put the saved target-image pointer into CONTEXT-T and set to the link pointers. Next I WIPED the screen defining .SYMBOLS, it will not work with the above vocabulary definition. I used that screen to make some help words: | 0 \ META MANIPULATORS. 03Jun88pJa 1 : (S -- ) \ clears out . 2 (S -- ) \ duplicate 4 DUP 4+ #VOCS 1- 4* CMOVE> ; 5 : (S -- ) \ show what is. 6 CR ." : " #VOCS 0 DO DUP @ ?DUP IF 7 BODY> >NAME .ID THEN 4+ LOOP DROP 8 CR ." : " @ BODY> >NAME .ID ; 9 : (S -- ) \ display symbol vocabularies. 10 SYMBOL-LINK @ BEGIN DUP #THREADS 4* - BODY> >NAME .ID 11 @ DUP 0= UNTIL DROP ; 12 : (S -- ) \ show words (symbols) in . 13 CONTEXT @ @ CONTEXT ! WORDS CONTEXT ! ; 14 15 Again the 4+ and 4* should be 2+ and 2* for 16 bit versions. The words work the same as the standard ONLY/ALSO extension. ONLY is replaced by . Since there is no ROOT vocabulary, it simply empties . Make sure you invoke a vocabulary after . The last change is in the word DEFINITIONS on the last screen of Meta.blk It should be: H: DEFINITIONS DEFINITIONS CONTEXT-T @ CURRENT-T ! ; So much for the changes in Meta.blk. Now for the changes in Kernel.blk.. The problem is with the first word to be defined. FORTH is the first word and is a vocabulary. It must be properly linked into the system. The original version of L&P took care of linking the first word into CURRENT-T. It also initialized that first word to point to it's own link. I will repeat here the way I did it in the Amiga version, and then I will guess at what it would be in a 16 bit version. Amiga: here-t dup 100 + current-t ! dup 116 + there ! vocabulary forth forth definitions dup 108 + -relocate dup 124 + there @ dup last @ name> >body 8+ ! off 0 over 2+ !-t dup 2+ swap 24 + dup relocate !-t in-meta And for 16 bits (guessing) HERE-T DUP 100 + CURRENT-T ! DUP 108 + THERE ! VOCABULARY FORTH FORTH DEFINITIONS DUP 112 + THERE @ DUP LAST @ NAME> >BODY 4 + ! OFF 0 OVER 2+ !-T DUP 2+ SWAP 16 + !-T IN-META The last change to Kernel.blk is not a problem, it is the result of the feature of having multiple vocabularies. When another vocabulary is created and words are to be defined in it, must now be manipulated. For instance: VOCABULARY DOS DOS DEFINITIONS would hide all the FORTH defined symbols, you won't know, but at the end of Metacompiling you will see a bunch of unresolved forward references. You must take care in properly specifying the symbol search order. FORTH DEFINITIONS VOCABULARY DOS DOS DEFINITIONS A final note, when the Metacompiler defines a new colon word, the and are not altered. This is in contrast to the host system, which sets CONTEXT to CURRENT at the start of a colon definition. This way you can do the following: FORTH DEFINITIONS DOS ( = ) : DOS FORTH : FORTH And will stay like that until the next DEFINITIONS. At this point you can Metacompile, using the kernel you compiled in step 1. I hope I didn't forget anything. Peter Appelman.