13.8 Interpreters. 4tH 4tH Forth compiler
Annonce
Annonce
CHAPTER 13. SPECIAL LIBRARIES
W
ORD palette>color to_palette color>n n>color
S
–
TACK n - rgb rgb – n n – rgb
E
FFECT
C
OMMENT
Convert palette code to color
Set library primitives so that pixel and color data will use 1 byte palette code.
Convert color to palette (or grayscale) format
Convert palette (or grayscale) to color format
211
13.8
Interpreters
Those of you who know Forth will be very surprised to see that 4tH doesn’t have a Forth prompt. Some will be even more surprised to see that 4tH does have an interpreter. It is a library routine, written in 4tH, that can easily be adapted and expanded. If you can write
4tH and maintain a table, you can use it. The next question you have to ask yourself, is do you want your interpreter to be case sensitive or not? If it is, "id" will work, but "Id" or "ID" will not. If you want it to be case sensitive, add the pragma casesensitive.
Example:
\ don’t ignore case [pragma] casesensitive
[needs lib/interpret.4th]
: _+ + ;
: _. . ;
: id ." This is 4tH" cr ;
Well, that isn’t very hard, is it. Now we add a table to all that: create wordlist
," +" ’ _+ ,
," ." ’ _. ,
," id" ’ id ,
NULL ,
Remember to terminate your table with "NULL"! Every entry consists of a string and an address to your routine. What will happen is that your user enters the string and the appropriate routine will be called. In this case, your interpreter has three commands: "+",
"." and "id". We’re a hair away from a real interpreter. We just have to assign our table to the dictionary. These lines do the job: wordlist to dictionary refill drop interpret
Now you can compile your application and run it. Enter:
45 12 + .
And it will print:
57
CHAPTER 13. SPECIAL LIBRARIES 212
Yes, it’s just as easy as that! If you enter something the interpreter doesn’t recognize it will try to convert it to a number and throw it on the stack. But you will also see that it exits after you’ve entered that single line. That is because the interpreter is called just once. If you change that to: begin refill drop interpret again
It will return with an new prompt. In that case it is wise to add a routine like:
: _quit quit ;
And add it to your interpreter, because otherwise your user will not be able to leave the application. Note that you have to do all the error-checking. E.g., if your user calls "_+" without putting sufficient items on the stack, 4tH will exit with an error. Of course, you can catch any exceptions. ”INTERPRET” has a builtin word, ”NotFound”, that deals with any unrecognized strings. You can define your own if you want to. The only thing you have to do is to write a word which takes an address/count string and returns nothing, e.g.:
:noname 2drop ." I don’t understand this!" cr ; is NotFound
Or more elaborate:
:noname ." I don’t what ’" type ." ’ means!" cr ; is NotFound
You could even integrate it with the exception trapping, if you defined one:
1 constant #UndefName
:noname #UndefName throw ; is NotFound
When a word is not found, a user exception is thrown. This example is taken from dc.4th:
: dc begin
." OK" cr refill drop
[’] interpret catch dup if
ShowMessage else drop then again
;
\ main interpretation loop
\ print prompt
\ get input from use
\ interpret it
\ catch any errors
\ if one occurred
\ show a message
\ otherwise
\ drop the throw code
\ loop back
You can still see the basic structure, but this one is much more advanced. You can also remove the code from the interpreter that decodes numbers. In that case, if a word is not found in the "dictionary" table it will exit immediately and report an error. Simply define this pragma before including the library:
[pragma] ignorenumbers include lib/interprt.4th
Download
Annonce