[comp.lang.forth] +FOR...NEXT

gamber@cosmo.UUCP (Johannes Teich) (05/08/90)

Forthers,
I'm glad to have them both running:
 
              +--------+                     +--------+
       FOR    |  For   |              ?DO    |  ?Do   |
              +--------+                     +--------+
              |  offs  |--.                  |  offs  |--.
              +--------+  |                  +--------+  |
              |        |<-|-.                |        |<-|-.
              |        |  | |                |        |  | |
       LEAVE  | Leave  ---|-|-.       LEAVE  | Leave  ---|-|-.
              |        |  | | |              |        |  | | |
       LEAVE  | Leave  ---|-|-.       LEAVE  | Leave  ---|-|-.
              |        |  | | |              |        |  | | |
              +--------+  | | |              +--------+  | | |
       NEXT   |  Next  |<-' | |       LOOP   |  Loop  |  | | |
              +--------+    | |              +--------+  | | |
              |  offs  |----' |              |  offs  |--|-' |
              +--------+      |              +--------+  |   |
              |        |<-----'              |        |<-' <-'
 
 
        FOR ... I ... LEAVE ... LEAVE ... NEXT
        ?DO ... I ... LEAVE ... LEAVE ... LOOP   ( or DO and/or +LOOP )
 
There are 3 values on the return stack: jump-addr reference loop-index.
The jump-addr is for LEAVE . The reference is for FORTH-83 & speed.
The word  I  does a subtraction:  R> DUP R@ - SWAP >R  (it could be an
addition like in Zen as well).
 
The reference is always zero for FOR...NEXT , but must be present because
of LEAVE , I and J .  R@ is the same as  I , then, but quicker.
 
Now I think of something like  n +FOR  which sets the reference to n.
 
                       10 4 +FOR ... NEXT         -->   9 8 7 6 5 4
doing the same as:     4 9 DO ... -1 +LOOP ( FORTH-83 )
 
The reference value would no longer be waisted.
What do others think about +FOR or whatever it should be called?
 
I prefer offsets over absolut addresses (as used in Pygmy), for I plan to
shift the code in memory, and metacompiling becomes a little simpler, too.
Btw, my 0 FOR...NEXT loops zero times. (In addition, cmFOR is available.)
 
   cheers,  --Hannes                               | gamber@cosmo.uucp |
                                                   | fido 2:507/414.20 |
 

gamber@cosmo.UUCP (Johannes Teich) (05/09/90)

In article <5628@balu.UUCP>, gamber@cosmo.UUCP (Johannes Teich) writes:
 
 > Now I think of something like  n +FOR  which sets the reference to n.
 >
 >                       10 4 +FOR ... NEXT         -->   9 8 7 6 5 4
 > doing the same as:     4 9 DO ... -1 +LOOP ( FORTH-83 )
 
Maybe there is little need for that type of a loop. It's just simple to
implement. It would be more useful if the index went forward... but why
not take the DO ... LOOP construct, then?
 
The FORTH-83 Standard says: "If the new index was incremented across
the boundary between limit-1 and limit then the loop is terminated".
That is,
                 3  0  DO  I .      LOOP   -->    0  1  2
                 0 -3  DO  I .      LOOP   -->   -2 -1  0
                 0  3  DO  I .  -1 +LOOP   -->    3  2  1  0
                -3  0  DO  I .  -1 +LOOP   -->    0 -1 -2 -3
 
This leads to the solution with the CPU overflow flag in several Forths:
 
    3 0 DO ... R@ . ... LOOP        32765  32766  32767  (overflow)
    reference (2nd on Rstack)       32765  32765  32765
    3 0 DO ... I . ... LOOP             0      1      2
 
    0 3 DO ... R@ . ... -1 +LOOP   -32775 -32776 -32767 -32768  (overflow)
    reference (2nd on Rstack)      -32768 -32768 -32768 -32768
    0 3 DO ... I . ... -1 +LOOP         3      2      1      0
 
This unsymmetric behavior looks less plausible than floored division.
(In fact, I dislike it.) On the other hand, I do not intend to use standard
words or controlled words other than described in the standard paper.
(I even hesitate to use FOR and cmFOR instead of ?FOR and FOR . But CM
doesn't care of any standards, does he?)
 
When Rstack holds only one value, how can the loop index increment?
 
    3 FOR ... R@ . ... NEXT                   2     1     0
    3 DUP 1- SWAP FOR ... R@ - . ... NEXT     0     1     2
 
    3 cmFOR ... R@ . ... NEXT                 3     2     1     0
    3 DUP cmFOR ... R@ - . ... NEXT           0     1     2     3
 
Now I see why CM choose his version... :-)
 
Alternatively, we may have the loop index on Dstack:
 
    0 3 FOR ... DUP . 1+ ... NEXT DROP        0     1     2
    0 3 cmFOR ... DUP . 1+ ... NEXT DROP      0     1     2     3
 
Heretical question: why not have an incrementing negative index?
 
    3 -FOR ... R@ . ... NEXT                 -2    -1     0
    3 -FOR ... R@ ABS . ... NEXT              2     1     0
    3 DUP -FOR ... R@ + . ... NEXT            0     1     2
    3 DUP 5 + SWAP -FOR ... R@ + . ... NEXT   5     6     7
 
This could be considered a special case of >FOR .  :-)
(Now we have to have more than one value on Rstack.)
 
    0 3 >FOR ... R@ . ... NEXT               -2    -1     0
    reference (2nd on Rstack)                -2    -2    -2
    0 3 >FOR ... I . ... NEXT                 0     1     2
 
    5 8 >FOR ... R@ . ... NEXT               -2    -1     0
    reference (2nd on Rstack)                -7    -7    -7
    5 8 >FOR ... I . ... NEXT                 5     6     7
 
    5 8 <FOR ... R@ . ... NEXT                2     1     0
    reference (2nd on Rstack)                -5    -5    -5
    5 8 <FOR ... I . ... NEXT                 7     6     5
 
To conclude this brainstorming, just a look on TYPE :
 
  : TYPE  ( a n -)  ?DUP IF OVER + SWAP DO I C@ EMIT LOOP ELSE DROP THEN ;
  : TYPE  ( a n -)  ?DUP IF 1- cmFOR DUP C@ EMIT 1+ NEXT THEN DROP ;
  : TYPE  ( a n -)  ?DUP IF FOR DUP C@ EMIT 1+ NEXT THEN DROP ;
  : TYPE  ( a n -)  ?DUP IF -FOR DUP I + C@ EMIT NEXT THEN DROP ;
  : TYPE  ( a n -)  ?DUP IF OVER + >FOR I C@ EMIT NEXT ELSE DROP THEN ;
 
Maybe FOR ... NEXT is all we need.  :-)
 
   cheers,  --Hannes                               | gamber@cosmo.uucp |
                                                   | fido 2:507/414.20 |