Deferred words
Forth has the ability to create a deferred word in the dictionary. This is a pointer that can be remapped to other words, or to think of it another way, a word that can be redefined by the user. Two examples of deferred words in FlashForth are prompt and turnkey (discussed in a later section).
A deferred word pointer is created using the defer word, and can be remapped by the is word. The word ' (tick) is used to lookup an existing word in the dictionary and place its address on the stack. This is stored by the is word to the location of the deferred word pointer in the dictionary.
As a trivial example, to create a deferred word called lights and make it point to the word ledon:
A deferred word pointer is created using the defer word, and can be remapped by the is word. The word ' (tick) is used to lookup an existing word in the dictionary and place its address on the stack. This is stored by the is word to the location of the deferred word pointer in the dictionary.
As a trivial example, to create a deferred word called lights and make it point to the word ledon:
defer lights
' ledon is lights
Switching Between Compile and Interpret
Sometimes, when you are in the middle of defining a new word, you might want to check something, calculate something, or test something, but you’re in compile mode and stuck. Forth has an answer for you. The [ word reverts you back to the interpreter state (also known as immediate mode), where you can type Forth words and get an immediate response. Typing a ] returns you back to the compile state and you can resume writing your word. Anything between [ and ] is not part of the word being defined.
As a trivial example, let’s say you’re writing a simple word called print_d to output the letter "d" to the console. You’ve already started writing your word, but want to confirm that the ASCII code for a "d" is 100. Type [ in the middle of your word definition to enter interpreter state, then get Forth to confirm the code for "d" with 100 emit, then a ] returns you back to the word you are creating:
As a trivial example, let’s say you’re writing a simple word called print_d to output the letter "d" to the console. You’ve already started writing your word, but want to confirm that the ASCII code for a "d" is 100. Type [ in the middle of your word definition to enter interpreter state, then get Forth to confirm the code for "d" with 100 emit, then a ] returns you back to the word you are creating:
: print_d
[ ( enter interpreter state )
100 emit d ok
] ( exit interpreter state )
100 emit ( resume writing your code )
;
As another example, you’re writing a word that converts a number of weeks to hours. You need to know how many hours are in a week and multiply this by the number of weeks from the top of the stack. You realise once you’ve started writing your word, that you forgot to calculate the required constant. So, you can enter interpreter state to calculate it, before returning to compile state:
: weeks ( weeks -- minutes , calculates how many minutes )
[ 24 7 * . 189 ok
]
189 *
;
In the above example, we used the immediate mode in Forth to perform the calculation. That constant was then manually added in the next line of code. Now, we could have just explicitly performed the calculation as part of the Forth word:
: weeks ( weeks -- hours , calculates how many hours )
24 * 7 * *
;
However, every time this word is run, it will perform four multiplications instead of just one. This doesn’t make for efficient code.
The word state will leave a flag on the stack indicating the current state, 0 for interpret and -1 for compile.
The word literal takes the value on top of the stack, and compiles this into your code as a constant. Revisiting the previous example, you can enter interpreter state to calculate a value, then use literal after ] to include that value in your code:
The word state will leave a flag on the stack indicating the current state, 0 for interpret and -1 for compile.
The word literal takes the value on top of the stack, and compiles this into your code as a constant. Revisiting the previous example, you can enter interpreter state to calculate a value, then use literal after ] to include that value in your code:
: weeks
[ 24 7 * ] literal *
;
or:
24 7 *
: weeks
literal *
;
Both of these are the equivalent of:
: weeks
14976 *
;
Immediate and Postpone
Forth gives you the ability to create words that execute during the compilation process, rather than being built into the word that is being created. The word immediate, when used at the end of a colon definition, flags that word for immediate execution during future compilation. immediate must follow on after the semicolon ; .
As an example, let's say we want to create a word memory to show the current memory usage when we're compiling a new word. memory uses the word free and is defined as immediate:
As an example, let's say we want to create a word memory to show the current memory usage when we're compiling a new word. memory uses the word free and is defined as immediate:
: memory
free
; immediate
Now, if we use memory inside another word:
: helloworld
memory ." hi there"
;
This will output (something like)
Flash: 44003 bytes
RAM : 5875 bytes ok
during the compilation of helloworld. But when helloworld is run, the output is simply hi there. memory is only executed during the compilation, and is not included in the compiled code for helloworld.
The word postpone is used to ignore the immediate flag of an immediate word. postpone causes an immediate word to be compiled into a colon definition. For example, to include memory into a word definition:
Flash: 44003 bytes
RAM : 5875 bytes ok
during the compilation of helloworld. But when helloworld is run, the output is simply hi there. memory is only executed during the compilation, and is not included in the compiled code for helloworld.
The word postpone is used to ignore the immediate flag of an immediate word. postpone causes an immediate word to be compiled into a colon definition. For example, to include memory into a word definition:
: myword
." This is how much memory is free:" cr
postpone memory
;
Next, we'll see how to add a word to decompile words from your dictionary.