I need to implement an idefinite loop with multiple exit points. Unfortunately the most obvious solution - REPEAT - UNTIL with multiple WHILE doesn't work neither in Gforth nor in swapforth (Of course the loop in the example below may be implemented with DO - LOOP. However, that code is just a demonstration. The real problem is related to hardware control in an embedded system, so the loop indeed must be indefinite):
: test1 ( step -- step count )
0
begin
over +
dup .
dup 20 < while
dup 13 = while
repeat
;
3 test1
In "Thinking Forth" there is Moore's statement quoted:
Many times conditionals are used to get out of loops. That particular use can be avoided by having loops with multiple exit points. This is a live topic, because of the multiple WHILE construct which is in poly- Forth but hasn’t percolated up to Forth ’83. It’s a simple way of defining multiple WHILEs in the same REPEAT. Also Dean Sanderson [of Forth, Inc.] has invented a new construct that introduces two exit points to a DO LOOP. Given that construction you’ll have fewer tests.
Unfortunately I failed to find the Dean's solution. Is there any portable way to implement multiple exit points in the indefinite loop in Forth?
After some experiments, I have created a solution based on a DO +LOOP. I don't know if it is the same as the one proposed by Dean Sanderson.
I have successfully tested it in Gforth and in swapforth. It seems that it is possible to create the arbitrary number of exit points. The indefinite loop is created via: 0 1 DO loop content here 0 +LOOP. The exit points are created by LEAVE placed in IF THEN.
Example code:
: test1 ( start step -- count step )
swap
1 0 do
over +
dup .
dup 20 > if
." >20 "
leave
then
dup 13 = if
." =13 "
leave
then
dup 17 = if
." =17 "
leave
then
0 +loop
;
Test results:
> 1 3 test1
4 7 10 13 =13 ok
> 2 3 test1
5 8 11 14 17 =17 ok
> 0 3 test1
3 6 9 12 15 18 21 >20 ok