In which I learn how to regain control.
while, and similar control flow constructs are not builtin but implemented. Implement them in your Forth.
Let’s start with
IF ... ELSE ... THEN. This construct doesn’t have a run time primitive word (or words). Instead it compiles as follows:
0 = BRANCH? conditional-words trailing-words
In the above
<trailing-words> is the relative offset of *trailing-words*. The
0 = logically inverts the original condition.
0 = BRANCH? conditional-words
BRANCH else-words trailing-words
The problem is that we can’t put in the offset for the branch at the point where we encounter the
IF because we don’t know how far along the
THEN will be. Instead we’ll put in a placeholder to be filled in with the offset later. When we get to the
THEN or the
ELSE we need to know where the placeholder was so we can go back and put it in. For an
ELSE we then have to repeat the process for the
It as to be possible to nest control structures, so the natural way to implement this is through a stack called the control-flow stack. You can fold the control flow stack into the data stack as gforth does, but I am going to keep it separate for now on the grounds that my data stack only holds integers and we will need two types of value: dest for backward jumps (e.g. a loop) and orig for forward jumps (
The code for
THEN is tagged blog-1070-1
It has not escaped my notice that I now have a failing unit test. Because I tightened up the conditions for executing in interpreting mode and executing in compile mode, comments no longer work in interpreting mode. I was going to continue this blog by discussing loops, but that is going to have to go by the wayside while I refactor compilation and interpreting semantics.