11.6 Enumerations. 4tH 4tH Forth compiler
विज्ञापन
विज्ञापन
CHAPTER 11. ADVANCED PROGRAMMING 141
Another ’DROP’? But wouldn’t that trigger an "Stack empty" error? Yeah, it does. But instead of exiting, the program will react as if we wrote "-4 THROW" instead of "DROP
DROP". The program will correctly report an exception when we enter "0" and act accordingly.
This will work with virtually every runtime error. Which means we won’t have to protect our program against every possible user-error, but let 4tH do the checking.
We won’t even have to set flags in every possible colon-definition, since 4tH will automatically skip every level between ’THROW’ and ’CATCH’. Even better, the stacks will be restored to the same depth as they were before ’CATCH’ was called.
You can handle the error in any way you want. You can display an error message, call some kind of error-handler, or just ignore the error. Is that enough flexibility for you?
11.6
Enumerations
Sometimes you need a lot of constants:
0 constant Monday
1 constant Tuesday
2 constant Wednesday
3 constant Thursday
4 constant Friday
5 constant Saturday
6 constant Sunday
A little error here may ruin your program. This does the very same thing, except it is easier to maintain:
0 enum Monday enum Tuesday enum Wednesday enum Thursday enum Friday enum Saturday enum Sunday drop
’ENUM’ is much like a ’CONSTANT’, but increments and leaves a value after the constant has been created. That is why we need to add ’DROP’ after the final enumeration. To show you that ’ENUM’ and ’CONSTANT’ are much alike, you could also write the declaration above as:
0 enum Monday enum Tuesday enum Wednesday enum Thursday enum Friday enum Saturday constant Sunday
Since ’CONSTANT’ just consumes the value, you don’t need the final ’DROP’.
11.7
Forward declarations
It doesn’t happen very often, but sometimes you have a program where two colon-definitions call each other. When you look at 4tHs source you find several examples. The throw() function calls the rpop() function, because ’THROW’ takes items from the Return Stack. On the other hand, when the Return Stack underflows, it has to call ’THROW’.
There is a special instruction in 4tH to do this, called ’DEFER’. ’DEFER’ doesn’t create an executable word, but a vector containing an execution token
1
, which is executed when called. You might want to consult section 10.3 first to see how this works. But for all purposes you might consider it to be an executable word, because it behaves the same way.
1
See section 10.4.
CHAPTER 11. ADVANCED PROGRAMMING 142 defer Step2
Now we can create "STEP1" without a problem:
: Step1 1+ dup . cr Step2 ;
But "STEP2" does not have a body yet. Of course, you could create a new colon-definition, tick it and assign the execution token to "STEP2" manually, but it is much neater to use
’:NONAME’. ’:NONAME’ can be used like a normal ’:’, but it doesn’t require a name.
Instead, it pushes the execution token of the colon-definition it created on the stack. No,
’:NONAME’ does not create a literal expression, but it is just what we need:
:noname 1+ dup . cr Step1 ; is Step2
Now we are ready! We can simply execute the program by calling "STEP1":
1 Step1
Note that if you run this program, you’ll get stack errors! Sorry, but the example has been taken from a Turbo Pascal manual ;-). If you have forgotten what a deferred word actually executes, you can retrieve the execution token by using ’DEFER@’: defer thisword
: plus + ;
’ plus is thisword
’ thisword defer@
2 3 rot execute
. cr
\ create a vector
\ define a word
\ assign the word to the vector
\ retrieve the execution token
\ execute the deferred word
\ display the result
As a matter of fact, this expression:
’ thisword defer@ execute
Is equivalent to this one: thisword
You can also reassign a vector without using ’IS’. ’IS’ is a parsing version. That means the actual vector to which a certain behaviour is assigned is determined at compiletime. ’DE-
FER!’ can be used to assign a certain behaviour at runtime. ’DEFER!’ takes two execution tokens: defer thisword
: plus + ;
’ plus ’ thisword defer!
\ create a vector
\ define a word
\ assign it to a vector
This is equivalent to this: defer thisword
: plus + ;
’ plus is thisword
\ create a vector
\ define a word
\ assign it to a vector
I guess you’ll agree with me that this creates countless possibilities.
डाउनलोड
विज्ञापन