1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
|
~ Now the single most important word...
: funterpret
word
~ If no word was returned, exit.
dup 0 = { drop exit } if
~ The string is on the top of the stack, so to get a pointer to it we get
~ the stack address.
~ (string)
value@ dup emitstring newline find
~ Check whether the word was found in the dictionary.
dup 0 != {
~ If the word is in the dictionary, check what mode we're in, then...
dropstring-with-result
~ (entry pointer)
interpreter-flags @ 0x01 & {
~ ... if we're in compile mode, there's still a chance it's an immediate
~ word, in which case we fall through to interpret mode...
dup entry-flags@ 1 & 0 =
~ ... but it's a regular word, so append it to the heap.
{ entry-to-execution-token , exit } if
} if
~ ... if we're in interpret mode, or the word is immediate, run it.
entry-to-execution-token execute exit
} if
~ If it's not in the dictionary, check whether it's a decimal number.
drop
~ As before, we get the stack address and use it as a string pointer.
~ (string)
value@ read-integer 0 = {
~ It's a number.
interpreter-flags @ 0x01 & {
~ We're in compile mode; append first "lit", then the number, to the
~ heap. The version of "lit" we use is the one that's current when we
~ ourselves are compiled, hardcoded; doing a dynamic lookup would
~ require dealing with what happens if it's not found.
dropstring-with-result
[ ' lit entry-to-execution-token literal ]
, ,
exit
} if
~ We're in interpret mode; push the number to the stack. Or at least, that's
~ what the code we're interpreting will see. Really it's already on the
~ stack, just clean everything else up and leave it there.
dropstring-with-result exit
} if
~ If it's neither in the dictionary nor a number, just print an error.
s" No such word: " emitstring value@ emitstring dropstring exit ;
: funquit { funterpret } forever ;
funquit 4 5 + . bye
|