27.18Adding words with arguments. 4tH 4tH Forth compiler
Iklan
Iklan
CHAPTER 27. MODIFYING 4TH
• The string can be parsed
• We can move it to the String Segment
• We can compile a token and an argument
This is the code for DoDotQuote():
#ifndef ARCHAIC static void DoDotQuote (void)
#else static void DoDotQuote ()
#endif
{
CompileString (PRINT);
}
535
We aren’t done yet. We still have to link the string ’."’ to this routine by adding an entry to
ImmedList[] :
{ 2, 0, -1, ",\"",
{ 2, 0, -1, ",|",
{ 2, 0, -1, ".\"",
{ 2, 0, -1, ".(",
"\"", DoCommaQuote },
"|", DoCommaQuote },
"\"", DoDotQuote },
")", DoDotQuote },
Now we can save comp_4th() and get on with the next file. Remember, we still got to add a token. As you will probably know, we do that in cmds_4th.h:
#define NOOP
#define CELLD
#define EXECUTE
#define CR
#define SPACES
#define EMIT
#define PRINT
#define DOT
#define FETCH
3
4
5
6
7
0
0
1
2
And of course, we have to add a name to name_4th.c, so it can be decompiled properly: char *name_4th [] = {
",", "execute", "cr", "spaces", "emit", ".\"",
Are we done yet? Not by a long shot. We have created a word with an argument, which is the offset of the string in the String Segment. That requires some special techniques. But we’ll go into that in the next section.
27.18
Adding words with arguments
The very first thing you have to do is to make sure that your code can be saved and loaded again. Words that only consist of a token are saved without the argument. That reduces the size of the HX file. If you want to save the argument you have to add a line to both load_4th() and save_4th():
CHAPTER 27. MODIFYING 4TH 536 case (LITERAL): case (PRINT): case (BRANCH): case (BRANCH0):
Now we have to add code to exec_4th() in order to execute ’."’. The first problem we encounter is: how do we access the argument? Accessing an argument is quite an expression:
Object->CodeSeg [Object->ErrLine].Value
In which:
O
BJECT
= Hcode pointer
C
ODE
S
EG
= Member of Hcode, pointing to the Code Segment
E
RR
L
INE
= Member of Hcode, pointing to the current word
V
ALUE
= Member of word, holding the argument
In plain English it means: give me the argument of the currently executed word in the Code
Segment. But we can also make our lives a lot easier by using this macro:
OPERAND
But this is only half the problem. How can we access the String Segment where the stringconstant is stored? We made a pretty table on that subject.
D
ATATYPE
E
XPRESSION
String
String
Character
Character
Variable
Code
Object->StringSeg [{cell}]
Object->StringSeg + {cell}
Object->UnitSeg [{cell}]
Object->UnitSeg + {cell}
T
YPE char char* char char*
Vars [Object->Offset + {cell}] cell
Object->CodeSeg [{cell}] dict
Table 27.7: Accessing 4tH data from C
Most of the time it is more convenient to use functions to access those segments instead of addressing them directly:
A
REA
F
ETCH
S
TORE
Data Stack DPOP DPUSH (value)
Return Stack RPOP RPUSH (value)
Character Segment fetch (location) store (location, char)
Table 27.8: exec_4th() data access API
You might consider using other functions too if certain datatypes are accessed more frequently.
Back to ’."’. We have to access the String Segment for this one. Since all output is channelled through emit(), we have to convert the string to "units", which are unsigned characters. We could use the expression "Object->StringSeg [{arg}]", but that would be slower than pointer access on most systems. We decide to use "p", which is a temporary stringpointer:
Unduh
Iklan