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.