Standard Forth permits and supports using control structures in a non-nested way. Information about incomplete control structures is stored on the control-flow stack. This stack may be implemented on the Forth data stack, and this is what we have done in Gforth.
An orig entry represents an unresolved forward branch, a dest entry represents a backward branch target. A few words are the basis for building any control structure possible (except control structures that need storage, like calls, coroutines, and backtracking).
At run-time, if f=0, execution continues after the
THEN (or ELSE) that consumes the orig,
otherwise right after the IF (see Selection).
At run-time, execution continues after the THEN that
consumes the orig.
The IF, AHEAD, ELSE or WHILE that
pushed orig jumps right after the THEN
(see Selection).
The UNTIL, AGAIN or REPEAT that consumes
the dest jumps right behind the BEGIN
(see General Loops).
At run-time, if f=0, execution continues after the
BEGIN that produced dest, otherwise right after
the UNTIL (see General Loops).
At run-time, execution continues after the BEGIN that
produced the dest (see General Loops).
The Standard words cs-pick and cs-roll allow you to
manipulate the control-flow stack in a portable way. Without them, you
would need to know how many stack items are occupied by a control-flow
entry (Many systems use one cell. In Gforth they currently take four
cells, but this may change in the future).
When using cs-pick and cs-drop on an orig, you need to
use one cs-drop for every cs-pick (and vice versa) of a
given orig, because the orig must be resolved by then exactly
once.
Some standard control structure words are built from these words:
At run-time, execution continues after the THEN that
consumes the orig; the IF, AHEAD, ELSE
or WHILE that pushed orig1 jumps right after the
ELSE. (see Selection).
At run-time, if f=0, execution continues after the
REPEAT (or THEN or ELSE) that consumes the
orig, otherwise right after the WHILE
(see General Loops).
At run-time, execution continues after the BEGIN that
produced the dest; the WHILE, IF,
AHEAD or ELSE that pushed orig jumps right
after the REPEAT. (see General Loops).
Gforth adds some more control-structure words:
Same as THEN.
This is the preferred alternative to the idiom "?DUP
IF", since it can be better handled by tools like stack
checkers. Besides, it’s faster.