On Aug 25, 2012, at 8:19 AM, openbios-request@openbios.org wrote:
I was wondering if there is a way to implement C's continue statement in Forth. I have this loop, and some times I only want to execute part of it, and then continue on to the next iteration without finishing the current iteration. Is there any way of doing this in OpenBIOS?
It certainly can be done. But it sounds like you are making a word with a very big body; this is not the Forth way. Instead, factor your words into smaller words, for example, pull the loop body (the part between WHILE and REPEAT) into a separate word. It then becomes trivial to do your "continue" (and it will also be much more readable!)
begin \ condition while
\ conditional code if CONTINUE \ skip rest of loop then
\ rest of loop ...
repeat
You don't have anything in here that "increases" the condition (increases some counter, follows a pointer, whatever). Typically you would have that just before the REPEAT, but your example makes it seem you have it between the BEGIN and WHILE. So your code is:
BEGIN cond WHILE smth IF CONTINUE THEN rest REPEAT
which you can write as
BEGIN cond WHILE smth 0= IF rest THEN REPEAT
(and if you do have an "increment" just before the REPEAT, which you want to run on CONTINUE, you can put it between the THEN and REPEAT in the modified example).
But, let's build a CONTINUE like you described, just for fun. Let's look at the structure words you used:
BEGIN ( C: -- dest ) WHILE ( C: dest -- orig dest ) REPEAT ( C: orig dest -- )
You want to use your CONTINUE word between WHILE and REPEAT, and it should jump back to "dest"; at compile time, it should not drop the "dest" from the compilation stack. So its stack diagram is
CONTINUE ( C: orig dest -- orig dest )
or just
CONTINUE ( C: dest -- dest )
For doing an unconditional jump back, there is AGAIN, which is
AGAIN ( C: dest -- )
That eats the dest from the compilation stack though, so we want to duplicate it first, using CS-DUP
CS-DUP ( C: dest -- dest dest )
Not every system has that; just make it from CS-PICK, like so:
: CS-DUP 0 CS-PICK ; IMMEDIATE
And then let's do CONTINUE itself:
: CONTINUE CS-DUP POSTPONE AGAIN ; IMMEDIATE
Or you might want a ?CONTINUE which does the equivalent of IF CONTINUE THEN:
: ?CONTINUE POSTPONE 0= CS-DUP POSTPONE UNTIL ; IMMEDIATE
Hope this helps,
Segher
You are right. My code was a little too long, so refactoring it fixed the problem. I guess I was still programming like a C programmer still. Thanks for the help.