<< Home | About Forth | About TurboForth | Download | Language Reference | Resources | Tutorials | YouTube >>
TurboForth is based on the Forth-83 standard. Compiling words into definitions in Forth-83 is done by two words:
This can be a minor inconvenience, because it requires you to know in advance if a word is immediate or not before you can compile it with COMPILE or [COMPILE]. Also, there is no convenient, standardised way to compile literals (numbers) in Forth-83. It would be specific to the system you are writing code for. In TurboForth, literals could be compiled like this:
: ninety-nine ( -- 99 )
[ [compile] lit 99 , ] ;
or
: ninety-nine ( -- 99 )
[ ' lit , 99 , ] ;
Both of the above being the equivalent of:
: ninety-nine ( -- 99 )
99 ;
ANS Forth, the Forth standard formally approved by the American National Standards Committe introduced a nice new word, POSTPONE which solves these problems rather nicely. It is used like this:
POSTPONE SWAP ( swap is a non-immediate word)
or
POSTPONE IF ( IF is an immediate word)
In other words, the usage is the same regardless of the word being immediate or not. Additionally, can you use it to compile numbers into definitions:
: ninety-99 ( -- 99 )
postpone 99 ;
POSTPONE is really only useful in compiling words - words that compile code into other words. Compiling words are nearly always immediate. So, expanding on the ninety-nine example just given above:
: ninety-nine ( -- )
postpone 99 ; immediate
Notice two things have changed:
Let's look at how it might be used:
: nn ( -- 99 ) ninety-nine ;
nn .
99 ok:0
As we can see the word ninety-nine was called during the definition of nn. Since the word ninety-nine is immediate it was executed rather than compiled. As shown above, ninety-nine is defined such that it postpones the compilation of the literal ninety-nine, hence the definition nn has code compiled into it such that, when nn is executed, 99 shall be pushed to the stack.
Executable code is compiled in exactly the same way. Here is an example of how one would replace the word THEN with the word ENDIF. ENDIF is found in some flavours of forth and is preferred by some forth programmers.
: ENDIF ( -- )
POSTPONE THEN ; IMMEDIATE
we can now use ENDIF anywhere that we would use the word THEN:
: TEST ( -- ) 1 2 < if ." true" else ." false" endif ;
Postponing (compiling) immediate and non-immediate words is sometimes confusing, because they do their work at different times depending on whether or not the word being postponed is immediate or not.
Consider the following:
: 2DUP ( int: -- runtime: a b -- a b a b )
\ compile code into a definition such that a and b are duplicated
postpone over postpone over
; immediate
: test 1 2 2dup ;
test .
1 2 1 2 ok:4
In above example the word OVER is compiled twice into the word test to effect a 2DUP (which duplicates the top two values on the stack). Note that the word OVER is a non-immediate word. When postponing an immediate word things are different:
: my-if ( -- )
postpone if
; immediate
You might think that the compilation of IF will be postponed until my-if is executed in a definition, however this is not the case. If is an immediate word. Recall that immediate words are executed whenever they are encountered by the compiler. Therefore in the above example, if the word postpone were missing, if, being immediate, would execute immediately and compile some code into the definition of my-if. Postponing it causes a reference to IF to be compiled into the definition of my-if itself, such that when my-if is subsequently executed, if will be executed; and of course IF will compile some code into the definition currently being built. Confused yet?!
It is critical to clearly understand this distinction, otherwise huge confusion can result!
Here's the code that constitutes postpone. It occupies 330 bytes. You can also find this code on the TurboForth tools disk in the downloads page. Note: the version of the code posted below includes full error-checking (if you try to postpone a word that does not exist, or that is not a legal number, it will tell you). In addition, double numbers can be postponed into definitions, as long as they include a period somewhere in the number (which is the Forth standard way to indicate a double length number).
Article uploaded 15 July 2015
<< Home | About Forth | About TurboForth | Download | Language Reference | Resources | Tutorials | YouTube >>