Part six of the implementation is very similar to part5, the difference is that we've added support for if/then instructions.
NOTE We didn't add support for else.
In FORTH if looks like this:
: one? 1 = if 42 emit 10 emit then ;
if will execute if the top-most word on the stack is 1, otherwise it will skip to the word after the then.
(Of course if there were else support then that would be jumped to instead!)
To build and run this version:
go build .
./part6
> : one? 1 = if 42 emit 10 emit then ;
> 1 one?
*
> 0 one?
> 3 one?
> 1 one?
*
> ^D
Here we've defined a word which takes a number from the stack, compares it with 1 and if equal outputs a star (and newline).
You'll see that we've implemented a whole bunch of new primitives, specifically to allow new conditional things:
=is an equality test. It pops two values off the stack.- If equal it pushes
1. - Otherwise it pushes
0.
- If equal it pushes
<is a less-than test. It pops two values off the stack.- If the test passes it pushes
1. - Otherwise it pushes
0.
- If the test passes it pushes
- etc.
The implementation here is pretty simple again, as suits a tutorial-code.
When we see an if we need to add a conditional-jump opcode, which will skip over the loop body at run-time if the topmost stack value is not 0.
In C we might write something like this:
if ( a < b ) {
do stuff
}
When we implement that we have to have this in our definition:
a
b
<
if
-3 \ -3 is a JUMP opcode, which conditionally
XXX \ jumps to the specified offset.
do
stuff
XXX:
Here we're using -3 as the magic opcode to mean "pop a value from the stack, and if the value is zero we jump to the specified offset in our word-list.
Hopefully that is clear!