Apr 272020
 

Dr.CH.Ting:

“n FOR-NEXT runs n+1 loops by design”

Why and how to cope with:

https://github.com/TG9541/stm8ef/wiki/eForth-FOR-..-NEXT

eForth FOR .. NEXT

Thomas edited this page on Dec 26, 2018 · 1 revision

Discussion of eForth FOR .. NEXT

While it’s advisable to use the STM8 eForth DO .. LEAVE .. LOOP/+LOOP structure instead of FOR .. NEXT and its variants, the following discussion deals with the most main properties, idioms and limitations of the this “eForth-ism”.

Basic properties of eForth FOR .. NEXT

Among “small Forth implemenations” the eForth FOR .. NEXT construct is idiosyncratic, and some of its properties and idioms are rather difficult to understand.

Here is a the basic FOR .. NEXT loop:

: test-for
   FOR I . NEXT ;

NEXT decrements the loop counter on the return stack (accessible with I or R@) and loops while the counter is positive. 4 test-for prints 4 3 2 1 00 test-for prints 0, and -1 test-for prints -1.

The following FOR .. NEXT properties are noteworthy:

  • at least one iteration, with the loop counter equal to the input to FOR will be performed
  • the nuber of iterations is limited to 32768, and
  • the loop count will be “one-too-many” compared to standard loop structures (e.g. DO .. LOOP)

eForth FOR .. AFT .. THEN .. NEXT

The most unusual feature eForth provides is the word AFT:

: test-aft1 ( n -- )
   FOR
      \ first loop
      ."  for"
      AFT
         \ following iterations
         ."  aft"
      THEN
      \ all iterations
      I .
   NEXT ;

2 test-aft1 prints for 2 aft 1 aft 0. Why one would need such a control structure is all but obvious. The eForth core implementation use of AFT, however, shows that it not only works around the “one-too-many” iterations in FOR .. NEXT, but it also provides loop count testing if the actual “loop clause code” is in the AFT .. THEN block:

: test-aft2 ( n -- )
    FOR AFT
       I .
    THEN NEXT ;

Running 3 test-aft2 prints 2 1 0, and 0 test-aft2 or -1 test-aft2 print nothing at all. This structure is widely used in the eForth core, e.g. in CMOVESAME? and TYPE. The effect is that input testing around FOR .. NEXT, especially for 0 counts, isn’t needed.

eForth FOR .. WHILE .. NEXT .. ELSE .. THEN

A loop structure similar to DO .. LEAVE .. LOOP can be implemented in “pure eForth” with an idiomatic combination of FOR .. NEXTWHILE, and ELSE .. THEN:

: test-for-while ( n1 n2 -- )
   FOR
      DUP I = NOT WHILE
      I . \ limit not reached
   NEXT
      ."  end"
   ELSE
      ."  limit"
      R> DROP \ remove the FOR loop counter
   THEN
   DROP ;   \ drop limit

In this example, 5 10 test-for-while prints 10 9 8 5 6 limit, and 5 4 test-for-while prints 4 3 2 1 0 end.

WHILE puts a the address of its conditional branch target on the stack above the start address of FOR the for loop (which is used when compiling NEXT). During compilation, ELSE then uses this address to make WHILE exit to the code block delimited by THEN. Note that the ELSE clause is responsible of removing the loop counter from the return stack.

Note that the FOR .. WHILE .. NEXT .. ELSE .. THEN idiom can’t be mixed with the FOR .. AFT .. THEN .. NEXT idiom!

 Posted by at 7:22 am

 Leave a Reply

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

(required)

(required)