27.8 Extending the compiler. 4tH 4tH Forth compiler
Reklaam
Reklaam
CHAPTER 27. MODIFYING 4TH
27.8
Extending the compiler
521
So far we’ve only added words that are directly compiled into a token/argument pair. If that was the way all 4tH words worked, we would never have branches, variables or other things that make up a language. In fact, you would never construct this complex architecture, since there are easier ways to achieve the same functionality.
The secret lies in the last major function of comp_4th() we have discussed, which is called GetImmediate(). When you look at it for the first time, it looks quite like
GetConstant() and GetWord(). The associated table ImmedList[] has a lengthbyte and a name but instead of a token or a value the last field is a pointer to a function.
You’ll find these functions above GetImmediate() and they all start with Do..(). In fact, they are the icing on the cake. They make 4tH a compiler, since they allow non-linear compiling. That includes:
• Branching
• Comments
• Allocation of variables
• String handling
• Assertions
• Constants
If there is something you want to do that you cannot define in a single token/argument, this is the place where you have to be. But before you are starting to make new functions, note there are many functions that you can use.
E.g. when you want to compile a word, you don’t have to bother yourself with errorchecking or other 4tH-internals. Just make a call to CompileWord():
CompileWord (NIP, 0);
Extending the compiler is quite easy. We will illustrate that by using a very simple example.
We have some compiler-words that handle the radix at compile time. They are:
[BINARY]
[OCTAL]
[DECIMAL]
[HEX]
Now we want to add a new one called "[SEXTAL]", which sets the radix to six. The radix at compile-time is handled by a single variable called "Base". First we have to make a function, which sets "Base". We call it DoSextal(). Note that this function cannot receive or return any values, like all Do..() functions:
#ifndef ARCHAIC static void DoSextal (void)
#else
#endif static void DoSextal ()
{
Base = 6;
}
CHAPTER 27. MODIFYING 4TH
MarkLink()
MakeLink()
PairLink()
CompileMark()
B
RANCHING
Adds a link to the controlstack
Makes a back-link
Retrieves a link from the controlstack
Compiles a token and adds a link to the controlstack
S
YMBOLTABLE
AddSymbol()
MakeSymbol()
GetSymbol()
Adds a symbol to the symboltable
Adds the current word as a symbol to the symboltable
Retrieves an entry from the symboltable
GetNextWord()
P
ARSING
Gets next word in the source
DecodeSymbol() Decodes a symbol from source
DecodeLiteral() Gets a compiled literal expression
DecodeOperand() Gets a compiled expression
DecodeWord() Gets a name from source
DecodeName()
SkipSource()
Gets a previously delared name from source
Discards all source between two labels
CompileWord()
InlineWords()
MoveString()
CompileString()
C
OMPILING
Compiles a token and its argument
Compiles a sequence of tokens without arguments
S
TRINGS
Moves a string inside the String Segment
Compiles a token and its associated string
Table 27.3: comp_4th() basic API
522
Just place it anywhere before ImmedList[] and you’re safe. Now we have to make it work. Like the other Get..() functions, there is a table called ImmedList[] which drives this behaviour, so let’s get started:
1. Length byte = 8
2. Symboltable entries = 0
3
3. Additional tokens = -1
4
4. Delimiter = ""
5
5. Name = "[SEXTAL]"
6. Function = DoSextal
Now let’s update that table:
{ 7, 0, -1, "ALIGNED",
{ 7, 0, 0, "RECURSE",
{ 8, 0, -1, "[SEXTAL]",
{ 8, 1, -3, "CONSTANT",
{ 8, 1, -2, "VARIABLE",
"",
"",
"",
"",
"",
DoDummy },
DoRecurse },
DoSextal },
DoConstant },
DoVariable },
You’re done now! Recompile the program and "[SEXTAL]" has become a part of 4tH.
Note that not all words within ImmedList[] can be defined that easily. If special tokens are required, you might have to edit other files as well.
3
See section 27.22
4
See section 27.15
5
See section 27.17
Laadi alla
Reklaam