CASE
The Robot World Repo on GitHub
The Forth Repo on GitHub
Let’s start thinking about CASE-ENDCASE. Thinking seems important right about now.
Let’s see if we can come up with some kind of notation to describe the CASE-OF-ENDOF-ENDCASE phrase and how we’ll compile it. We might have something like this, with value v on the stack and test values t1, t2:
v CASE
t1 OF
...
ENDOF
t2 OF
...
ENDOF
... (default)
ENDCASE
If v = t1 we do what’s inside the first OF-ENDOF, if v == t2 we do the second, and if none of the OFs match we do the default code.
I think we’ll compile something like what’s below, where 0BR is a conditional branch if the top of the stack is zero, and BR is an unconditional branch. 0BR consumes stack top.
LABEL | FORTH | COMPILED |
---|---|---|
v CASE | ||
t1 OF | t1 OVER = 0BR a | |
DROP | ||
… | … | |
ENDOF | BR x | |
a | ||
t2 OF | t2 OVER = 0BR b | |
DROP | ||
… | … | |
ENDOF | BR x | |
b | ||
… (default) | … | |
x | ||
ENDCASE |
So I expect that we’ll have two items on the compile stack during compilation of CASE. We’ll put a case-item on, which will have a list of the places that need x plugged in, and then each OF will put an of-item on the stack saying where the local skip, a or b, or whatever needs to be plugged in.
I’m not absolutely sure yet about the data stack management. We have to retain v to be checked in each OF, which the t1 OVER sequence manages. Then if the branch is not taken, that is, we’re doing this case, we drop v. The standard puts it this way:
If the two values on the stack are not equal, discard the top value and continue execution at the location … following the next ENDOF. Otherwise, discard both values and continue execution in line.
It follows that if we drop into the default, the test value v will be on stack top, so presumably the convention in a default will be that you have to drop it. I haven’t been able to think of a way to check that. Caveat Emptor, I guess. Assuming that, then when we hit ENDCASE, v is off the stack and whatever the selected OF or default has done is on the stack.
It seems almost easy, doesn’t it?
Summary
I mentioned “technical debt” this morning. the branch patching so far is kind of ad hoc, with strange offsets of 1 and -1, and special words like *IF that include the skipping and branching logic. It seems likely that we can do most everything with 0BR and BR, so we’ll see if we can get some improvement for the other words that do branching.
I feel that the above analysis is close to right. We’ll learn more when we start to do it. See you next time!