In which I learn how to regain control.
In Forth
http://beza1e1.tuxen.de/articles/forth.htmlif,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:
cond IF conditional-words THEN trailing-words
becomes
cond 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.
cond IF conditional-words ELSE else-words THEN trailing-words
becomes
cond 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 ELSE or 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 THEN.
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 (THEN and ELSE).
The code for IF … ELSE … 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.
