Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.forth > #41835 > unrolled thread

old `leave` renamed to `exhaust`

Started byMarcos Cruz <null_email_so_use_my_contact_page@programandala.net>
First post2015-09-07 20:29 +0000
Last post2015-09-11 14:16 +0200
Articles 18 on this page of 38 — 9 participants

Back to article view | Back to comp.lang.forth


Contents

  old `leave` renamed to `exhaust` Marcos Cruz <null_email_so_use_my_contact_page@programandala.net> - 2015-09-07 20:29 +0000
    Re: old `leave` renamed to `exhaust` "HAA" <someone@microsoft.com> - 2015-09-08 14:52 +1000
      Re: old `leave` renamed to `exhaust` Mark Wills <markwills1970@gmail.com> - 2015-09-08 00:57 -0700
        Re: old `leave` renamed to `exhaust` Bernd Paysan <bernd.paysan@gmx.de> - 2015-09-08 15:19 +0200
      Re: old `leave` renamed to `exhaust` Marcos Cruz <null_email_so_use_my_contact_page@programandala.net> - 2015-09-08 16:25 +0000
        Re: old `leave` renamed to `exhaust` "HAA" <someone@microsoft.com> - 2015-09-09 11:39 +1000
          Re: old `leave` renamed to `exhaust` Marcos Cruz <null_email_so_use_my_contact_page@programandala.net> - 2015-09-09 10:42 +0000
            Re: old `leave` renamed to `exhaust` "HAA" <someone@microsoft.com> - 2015-09-10 14:05 +1000
              Re: old `leave` renamed to `exhaust` Marcos Cruz <null_email_so_use_my_contact_page@programandala.net> - 2015-09-10 13:33 +0000
                Re: old `leave` renamed to `exhaust` Coos Haak <chforth@hccnet.nl> - 2015-09-10 22:04 +0200
                  Re: old `leave` renamed to `exhaust` Coos Haak <chforth@hccnet.nl> - 2015-09-10 22:13 +0200
                  Re: old `leave` renamed to `exhaust` "HAA" <someone@microsoft.com> - 2015-09-11 13:14 +1000
                    Re: old `leave` renamed to `exhaust` Coos Haak <chforth@hccnet.nl> - 2015-09-11 12:30 +0200
                      Re: old `leave` renamed to `exhaust` "HAA" <someone@microsoft.com> - 2015-09-11 21:47 +1000
                        Re: old `leave` renamed to `exhaust` Bernd Paysan <bernd.paysan@gmx.de> - 2015-09-11 14:09 +0200
                          Re: old `leave` renamed to `exhaust` "HAA" <someone@microsoft.com> - 2015-09-12 11:29 +1000
                            Re: old `leave` renamed to `exhaust` "Elizabeth D. Rather" <erather@forth.com> - 2015-09-11 16:05 -1000
                              Re: old `leave` renamed to `exhaust` "HAA" <someone@microsoft.com> - 2015-09-14 12:25 +1000
                                Re: old `leave` renamed to `exhaust` "Elizabeth D. Rather" <erather@forth.com> - 2015-09-13 17:53 -1000
                                Re: old `leave` renamed to `exhaust` anton@mips.complang.tuwien.ac.at (Anton Ertl) - 2015-09-14 08:33 +0000
                                  Re: old `leave` renamed to `exhaust` "HAA" <someone@microsoft.com> - 2015-09-15 16:55 +1000
                                    Re: old `leave` renamed to `exhaust` hughaguilar96@gmail.com - 2015-09-15 01:46 -0700
                                    Re: old `leave` renamed to `exhaust` Coos Haak <chforth@hccnet.nl> - 2015-09-15 15:14 +0200
                                      Re: old `leave` renamed to `exhaust` anton@mips.complang.tuwien.ac.at (Anton Ertl) - 2015-09-15 15:13 +0000
                                        Re: old `leave` renamed to `exhaust` hughaguilar96@gmail.com - 2015-09-15 16:13 -0700
                                          Re: old `leave` renamed to `exhaust` jim.brakefield@ieee.org - 2015-09-15 17:05 -0700
                                            Re: old `leave` renamed to `exhaust` hughaguilar96@gmail.com - 2015-09-15 18:35 -0700
                                        Re: old `leave` renamed to `exhaust` "HAA" <someone@microsoft.com> - 2015-09-19 11:42 +1000
                                          Re: old `leave` renamed to `exhaust` anton@mips.complang.tuwien.ac.at (Anton Ertl) - 2015-09-19 10:48 +0000
                                            Re: old `leave` renamed to `exhaust` "HAA" <someone@microsoft.com> - 2015-09-20 00:01 +1000
                                              Re: old `leave` renamed to `exhaust` anton@mips.complang.tuwien.ac.at (Anton Ertl) - 2015-09-19 15:02 +0000
                                                Re: old `leave` renamed to `exhaust` "HAA" <someone@microsoft.com> - 2015-09-21 15:51 +1000
                                      Re: old `leave` renamed to `exhaust` "Elizabeth D. Rather" <erather@forth.com> - 2015-09-15 08:45 -1000
                                      Re: old `leave` renamed to `exhaust` "HAA" <someone@microsoft.com> - 2015-09-16 11:18 +1000
                                        Re: old `leave` renamed to `exhaust` anton@mips.complang.tuwien.ac.at (Anton Ertl) - 2015-09-16 06:10 +0000
                                          Re: old `leave` renamed to `exhaust` "HAA" <someone@microsoft.com> - 2015-09-17 15:15 +1000
                                            Re: old `leave` renamed to `exhaust` anton@mips.complang.tuwien.ac.at (Anton Ertl) - 2015-09-17 06:04 +0000
                        Re: old `leave` renamed to `exhaust` Coos Haak <chforth@hccnet.nl> - 2015-09-11 14:16 +0200

Page 2 of 2 — ← Prev page 1 [2]


#42010

From"HAA" <someone@microsoft.com>
Date2015-09-15 16:55 +1000
Message-ID<mt8f9i$qm3$1@speranza.aioe.org>
In reply to#41995
Anton Ertl wrote:
> "HAA" <someone@microsoft.com> writes:
> >I think 83 loop was a positive change.  It worked over the full range, eliminated
> >the need for /LOOP
>
> But Forth-83's +LOOP does not eliminate the need for \LOOP, so you can
> just as well have /LOOP instead of +LOOP.
>
> And if the start value is at the wrong side of the limit value, DO and
> even ?DO are not so great, so overall, I feel that the Forth-83
> counted loops leave a lot to be desired (not that the Forth-79 ones
> were better).  But the 83-LEAVE is indeed better than the 79-LEAVE.
>
> - anton

I have no complaints with +LOOP.  Considering its simplicity and
what it can do, the asymmetry is a small price to pay IMHO.




[toc] | [prev] | [next] | [standalone]


#42011

Fromhughaguilar96@gmail.com
Date2015-09-15 01:46 -0700
Message-ID<ed520268-1736-4b9d-98a3-7c8785fe54f2@googlegroups.com>
In reply to#42010
On Monday, September 14, 2015 at 11:53:43 PM UTC-7, HAA wrote:
> Anton Ertl wrote:
> > "HAA" <someone@microsoft.com> writes:
> > >I think 83 loop was a positive change.  It worked over the full range, eliminated
> > >the need for /LOOP
> >
> > But Forth-83's +LOOP does not eliminate the need for \LOOP, so you can
> > just as well have /LOOP instead of +LOOP.
> >
> > And if the start value is at the wrong side of the limit value, DO and
> > even ?DO are not so great, so overall, I feel that the Forth-83
> > counted loops leave a lot to be desired (not that the Forth-79 ones
> > were better).  But the 83-LEAVE is indeed better than the 79-LEAVE.
> >
> > - anton
> 
> I have no complaints with +LOOP.  Considering its simplicity and
> what it can do, the asymmetry is a small price to pay IMHO.

I don't have DO loops at all in my language. See http://www.forth.org/FMITE.txt for how I do iteration.

DO loops are just horrible cruft from the 1970s. The problem with asymmetry going up or down is complicated and non-intuitive. The problem with DO loops clashing with >R data is horrible. The I and J pseudo-locals are a throwback to a time when Forth lacked locals; they aren't needed any more. All in all, DO loops make ANS-Forth look like a hold-out from the 1970s (which, of course, is exactly what ANS-Forth is).

Here is an excerpt from the FMITE.TXT file:


|ITERATE is the idiomatic way to do iteration in LOTD. For example, in ANS-Forth we might have this for printing a string:

: type  \ adr cnt --                            \ the CNT is unsigned
    over + swap ?do  I c@ emit  loop ;

In LOTD, this would be:

: type  \ adr:cnt --                            \ the CNT is unsigned       
    { dup c@ emit  1+ }  |iterate drop ;

Here is an ANS-Forth function for printing numbers upwards:

: up.  \ limit base --                          \ assumes LIMIT is above BASE
    ?do  I .  loop ;

In LOTD, use this:

: up.  \ limit base --                          \ assumes LIMIT is above BASE
    tuck -  { dup .  1+ }  |iterate drop ;

Here is an ANS-Forth function that is like UP. but goes downwards (using ?DO with a negative step is very non-intuitive):

: down.  \ limit base --                        \ assumes LIMIT is below BASE
    swap 1+  swap ?do  I .  -1 +loop ;

In LOTD, DOWN. would be similar to UP. except that our count is negated and our increment is negative (hopefully this will seem intuitive to the reader):

: down.  \ limit base --                        \ assumes LIMIT is below BASE
    tuck - negate  { dup .  1- }  |iterate drop ;

We could have a function THROUGH. ( limit base -- ) that goes either up or down:

: design  \ val -- |val| sign                   
\ converts VAL into an absolute value
\ provides SIGN as either -1 or 1 representing sign of original VAL
    dup 0< if  negate  -1  exit then
    1 ;

: through.  \ limit base --                     
\ if LIMIT is above BASE iterate up, otherwise iterate down
    tuck -              \ -- base count       \ COUNT is signed
    design -rot         \ -- step base count  \ COUNT is positive, STEP is the sign
    { dup .  over + }  |iterate 2drop ;

The reader may be wondering what happens if LIMIT equals BASE (causing VAL to be zero). It may seem that DESIGN should return zero when VAL is zero, rather than one. This isn't necessary. |ITERATE and ITERATE are similar to ?DO in ANS-Forth in that they exit prior to its loop if LIMIT equals BASE, so the step value (provided by DESIGN) for use in the quotation is never used because the quotation is never executed. |EACH and EACH are similar to ITERATE and |ITERATE in that they exit prior to its loop if HEAD (the node-pointer for the head of the list) is zero, and they never execute the quotation in this case.

The advantage of the FMITE idiom is that all of the complicated iteration code gets hidden away inside of the higher-order function. The application programmer doesn't have to deal with this stuff, which is a good thing because iteration is a common source of bugs. The application programmer's job is much easier if he just has to write the quotation and give it to a higher-order function. Another advantage is that the application program is more compact. Higher-order functions such as |EACH or |ITERATE may get used dozens of times in an application program. If every loop were written with BEGIN WHILE REPEAT, this would result in quite bloated code. If every loop is written with a quotation and a call to a higher-order function, this results in pretty compact code. The FMITE only has 16KB of program-memory, so the instruction set is designed to make it easy to write compact code.

[toc] | [prev] | [next] | [standalone]


#42012

FromCoos Haak <chforth@hccnet.nl>
Date2015-09-15 15:14 +0200
Message-ID<y7pior0acvxj.ch2dlom72stl$.dlg@40tude.net>
In reply to#42010
Op Tue, 15 Sep 2015 16:55:44 +1000 schreef HAA:

> Anton Ertl wrote:
>> "HAA" <someone@microsoft.com> writes:
>>>I think 83 loop was a positive change.  It worked over the full range, eliminated
>>>the need for /LOOP
>>
>> But Forth-83's +LOOP does not eliminate the need for \LOOP, so you can
>> just as well have /LOOP instead of +LOOP.
>>
>> And if the start value is at the wrong side of the limit value, DO and
>> even ?DO are not so great, so overall, I feel that the Forth-83
>> counted loops leave a lot to be desired (not that the Forth-79 ones
>> were better).  But the 83-LEAVE is indeed better than the 79-LEAVE.
>>
>> - anton
> 
> I have no complaints with +LOOP.  Considering its simplicity and
> what it can do, the asymmetry is a small price to pay IMHO.

Same experience here.
Is there any description of what /LOOP and \LOOP are supposed to do?
I've never found an implementation of them, even several versions
of Gforth don't have them.

groet Coos

[toc] | [prev] | [next] | [standalone]


#42013

Fromanton@mips.complang.tuwien.ac.at (Anton Ertl)
Date2015-09-15 15:13 +0000
Message-ID<2015Sep15.171318@mips.complang.tuwien.ac.at>
In reply to#42012
Coos Haak <chforth@hccnet.nl> writes:
>Is there any description of what /LOOP and \LOOP are supposed to do?
>I've never found an implementation of them, even several versions
>of Gforth don't have them.

We introduced -LOOP a long time ago, and I learned about \LOOP only a
few months ago (and nobody answered my question about the exact
behavior); with the existence of \LOOP the name /LOOP also makes more
sense.

Anyway, my impression until now is that /LOOP is for counting upwards
with a step size >1, and \LOOP is for counting downwards.

Here is how Gforth's -LOOP behaves:

   `-2 0 ?DO  i .  1 -LOOP'  prints `0 -1'
   `-1 0 ?DO  i .  1 -LOOP'  prints `0'
   ` 0 0 ?DO  i .  1 -LOOP'  prints nothing

The current looping constructs for negative stride in Gforth still
have one weakness, though:

When walking backwards over an array addr u of cells, we would like to
start with addr u 1- cells + and end with addr, but that's relatively
cumbersome to express, e.g.:

addr 1 cells - addr u 1- cells + ?do ... i ... 1 cells -loop

or (less run-time efficiency)

addr addr u cells + ?do ... i 1 cells - ... 1 cells -loop

- anton
-- 
M. Anton Ertl  http://www.complang.tuwien.ac.at/anton/home.html
comp.lang.forth FAQs: http://www.complang.tuwien.ac.at/forth/faq/toc.html
     New standard: http://www.forth200x.org/forth200x.html
   EuroForth 2015: http://www.rigwit.co.uk/EuroForth2015/

[toc] | [prev] | [next] | [standalone]


#42020

Fromhughaguilar96@gmail.com
Date2015-09-15 16:13 -0700
Message-ID<b020e43e-e285-4323-a0e3-e8bb2a9c2bed@googlegroups.com>
In reply to#42013
On Tuesday, September 15, 2015 at 8:52:48 AM UTC-7, Anton Ertl wrote:
> Coos Haak <chforth@hccnet.nl> writes:
> >Is there any description of what /LOOP and \LOOP are supposed to do?
> >I've never found an implementation of them, even several versions
> >of Gforth don't have them.
> 
> We introduced -LOOP a long time ago, and I learned about \LOOP only a
> few months ago (and nobody answered my question about the exact
> behavior); with the existence of \LOOP the name /LOOP also makes more
> sense.
> 
> Anyway, my impression until now is that /LOOP is for counting upwards
> with a step size >1, and \LOOP is for counting downwards.
> 
> Here is how Gforth's -LOOP behaves:
> 
>    `-2 0 ?DO  i .  1 -LOOP'  prints `0 -1'
>    `-1 0 ?DO  i .  1 -LOOP'  prints `0'
>    ` 0 0 ?DO  i .  1 -LOOP'  prints nothing
> 
> The current looping constructs for negative stride in Gforth still
> have one weakness, though:
> 
> When walking backwards over an array addr u of cells, we would like to
> start with addr u 1- cells + and end with addr, but that's relatively
> cumbersome to express, e.g.:
> 
> addr 1 cells - addr u 1- cells + ?do ... i ... 1 cells -loop
> 
> or (less run-time efficiency)
> 
> addr addr u cells + ?do ... i 1 cells - ... 1 cells -loop
> 
> - anton

Forth-200x is hamstrung by the mandate that it be 100% compatible with ANS-Forth. You just add more complexity and more words to the vocabulary, but you aren't addressing the serious problems of DO loops:

1.) DO loops use the return-stack, but >R also uses the return-stack, so they clash. Any >R data from outside of the loop is not available inside of the loop, and any >R data inside of the loop has to be removed with R> before the loop iterates again.

2.) DO loops use the pseudo-variables I and J. In nested loops, I is the index of the outer loop in the outer loop, but the name changes to J inside of the inner loop, at which time the I is the index of the inner loop. 

3.) DO loops are asymmetric going up or down, which is very non-intuitive.

These three aspects of DO loops are extremely difficult to explain to novices. The more you try to explain, the more foolish you appear to be. This is true even if the novice has never programmed at all before, but if the novice has any experience in any other language (even line-number BASIC), the novice is going to consider this to be utter foolishness.

DO loops were badly designed. Over time, more and more words were added to DO loops to provide more and more capability. We now have:
DO ?DO LOOP +LOOP /LOOP \LOOP LEAVE UNLOOP
This is a lot of words, just to accomplish iteration. In my language I have |ITERATE that does iteration. I also have |EACH and some others that are specifically for iterating through linked lists. Iteration is not all that complicated --- you start with a bad design though, and you pile complexity on top of complexity, and you end up with a big mess.

[toc] | [prev] | [next] | [standalone]


#42021

Fromjim.brakefield@ieee.org
Date2015-09-15 17:05 -0700
Message-ID<fc4ce412-b53a-42e8-80c5-6858fb25ec0a@googlegroups.com>
In reply to#42020
On Tuesday, September 15, 2015 at 6:13:07 PM UTC-5, hughag...@gmail.com wrote:
> On Tuesday, September 15, 2015 at 8:52:48 AM UTC-7, Anton Ertl wrote:
> > Coos Haak <chfo...@hccnet.nl> writes:
> > >Is there any description of what /LOOP and \LOOP are supposed to do?
> > >I've never found an implementation of them, even several versions
> > >of Gforth don't have them.
> > 
> > We introduced -LOOP a long time ago, and I learned about \LOOP only a
> > few months ago (and nobody answered my question about the exact
> > behavior); with the existence of \LOOP the name /LOOP also makes more
> > sense.
> > 
> > Anyway, my impression until now is that /LOOP is for counting upwards
> > with a step size >1, and \LOOP is for counting downwards.
> > 
> > Here is how Gforth's -LOOP behaves:
> > 
> >    `-2 0 ?DO  i .  1 -LOOP'  prints `0 -1'
> >    `-1 0 ?DO  i .  1 -LOOP'  prints `0'
> >    ` 0 0 ?DO  i .  1 -LOOP'  prints nothing
> > 
> > The current looping constructs for negative stride in Gforth still
> > have one weakness, though:
> > 
> > When walking backwards over an array addr u of cells, we would like to
> > start with addr u 1- cells + and end with addr, but that's relatively
> > cumbersome to express, e.g.:
> > 
> > addr 1 cells - addr u 1- cells + ?do ... i ... 1 cells -loop
> > 
> > or (less run-time efficiency)
> > 
> > addr addr u cells + ?do ... i 1 cells - ... 1 cells -loop
> > 
> > - anton
> 
> Forth-200x is hamstrung by the mandate that it be 100% compatible with ANS-Forth. You just add more complexity and more words to the vocabulary, but you aren't addressing the serious problems of DO loops:
> 
> 1.) DO loops use the return-stack, but >R also uses the return-stack, so they clash. Any >R data from outside of the loop is not available inside of the loop, and any >R data inside of the loop has to be removed with R> before the loop iterates again.
> 
> 2.) DO loops use the pseudo-variables I and J. In nested loops, I is the index of the outer loop in the outer loop, but the name changes to J inside of the inner loop, at which time the I is the index of the inner loop. 
> 
> 3.) DO loops are asymmetric going up or down, which is very non-intuitive.
> 
> These three aspects of DO loops are extremely difficult to explain to novices. The more you try to explain, the more foolish you appear to be. This is true even if the novice has never programmed at all before, but if the novice has any experience in any other language (even line-number BASIC), the novice is going to consider this to be utter foolishness.
> 
> DO loops were badly designed. Over time, more and more words were added to DO loops to provide more and more capability. We now have:
> DO ?DO LOOP +LOOP /LOOP \LOOP LEAVE UNLOOP
> This is a lot of words, just to accomplish iteration. In my language I have |ITERATE that does iteration. I also have |EACH and some others that are specifically for iterating through linked lists. Iteration is not all that complicated --- you start with a bad design though, and you pile complexity on top of complexity, and you end up with a big mess.

At the risk of stating something that has been said before, or it otherwise dumb:

Why not make loop stack items into locals?
E.g. I & J would be locals along with ancillary values (limit?, top of loop pointer, etc.).
If the compiler can figure out how to do it without locals, then that is optimization.

[toc] | [prev] | [next] | [standalone]


#42025

Fromhughaguilar96@gmail.com
Date2015-09-15 18:35 -0700
Message-ID<83171137-c0c3-4685-92b4-e2790c120f12@googlegroups.com>
In reply to#42021
On Tuesday, September 15, 2015 at 5:05:06 PM UTC-7, jim.bra...@ieee.org wrote:
> At the risk of stating something that has been said before, or it otherwise dumb:
> 
> Why not make loop stack items into locals?
> E.g. I & J would be locals along with ancillary values (limit?, top of loop pointer, etc.).
> If the compiler can figure out how to do it without locals, then that is optimization.

I provided some examples using |ITERATE earlier in which I kept the index on the stack. The index can also be kept in a local variable --- my quotations have access to the parent function's local variables when the execute inside of the higher-order function (in this case, |ITERATE is the higher-order function).

Using locals rather than the stack helps with nested loops or when there is a lot of data on the stack. 

Here is an earlier example:

: down.  \ limit base --                        \ assumes LIMIT is below BASE
    tuck - negate  { dup .  1- }  |iterate drop ;

We could rewrite DOWN. to use locals like this:

: down.  local{ limit base -- }
    limit @ base @ - negate  { base @ .  -1 base +! }  |iterate ;

In this case, the use of locals just adds clutter. As I said though, given more complicated code the use of locals can get rid of stack juggling to make the code more clear.

I don't think that it is a good idea to require iteration to use locals (I actually experimented with this) because the use of locals can clutter up the source-code in simple functions --- and given good factoring, most functions should be pretty simple --- sometimes you can't really dodge the complexity though, in which case locals can help. The good thing about |ITERATION is that it is flexible --- it either works with an index on the stack, or in a local.

A lot of ANS-Forth is just very rigid:
1.) You always have the pseudo-locals I and J (what if you wanted to call them Bill and Ted so they could have an excellent adventure?). 
2.) You always clash with >R data, because it is non-standard to use a different stack for DO loops (nowadays we have plenty of registers, so there is no need to use use the return-stack for both >R data and DO loops)
3.) You always quit when crossing the bottom edge of the limit, whether going up or down.

With |ITERATE you have flexibility --- it is not a Procrustean Bed like ANS-Forth's DO loop.

[toc] | [prev] | [next] | [standalone]


#42083

From"HAA" <someone@microsoft.com>
Date2015-09-19 11:42 +1000
Message-ID<mtieeo$h7v$1@speranza.aioe.org>
In reply to#42013
Anton Ertl wrote:
>
> The current looping constructs for negative stride in Gforth still
> have one weakness, though:
>
> When walking backwards over an array addr u of cells, we would like to
> start with addr u 1- cells + and end with addr, but that's relatively
> cumbersome to express, e.g.:
>
> addr 1 cells - addr u 1- cells + ?do ... i ... 1 cells -loop
>
> or (less run-time efficiency)
>
> addr addr u cells + ?do ... i 1 cells - ... 1 cells -loop
>
> - anton

Typically addr u will be constants and u > 1 which your program can exploit:

  0 u 1- do ... i cells addr + ... -1 +loop


[toc] | [prev] | [next] | [standalone]


#42084

Fromanton@mips.complang.tuwien.ac.at (Anton Ertl)
Date2015-09-19 10:48 +0000
Message-ID<2015Sep19.124814@mips.complang.tuwien.ac.at>
In reply to#42083
"HAA" <someone@microsoft.com> writes:
>Anton Ertl wrote:
>>
>> The current looping constructs for negative stride in Gforth still
>> have one weakness, though:
>>
>> When walking backwards over an array addr u of cells, we would like to
>> start with addr u 1- cells + and end with addr, but that's relatively
>> cumbersome to express, e.g.:
>>
>> addr 1 cells - addr u 1- cells + ?do ... i ... 1 cells -loop
>>
>> or (less run-time efficiency)
>>
>> addr addr u cells + ?do ... i 1 cells - ... 1 cells -loop
>>
>> - anton
>
>Typically addr u will be constants and u > 1 which your program can exploit:
>
>  0 u 1- do ... i cells addr + ... -1 +loop

You need to replace 0 with -1 in order to be equivalent to the
variants above.  Depending on the implementation and CPU, this may be
slower at run-time than the variants above.

- anton
-- 
M. Anton Ertl  http://www.complang.tuwien.ac.at/anton/home.html
comp.lang.forth FAQs: http://www.complang.tuwien.ac.at/forth/faq/toc.html
     New standard: http://www.forth200x.org/forth200x.html
   EuroForth 2015: http://www.rigwit.co.uk/EuroForth2015/

[toc] | [prev] | [next] | [standalone]


#42086

From"HAA" <someone@microsoft.com>
Date2015-09-20 00:01 +1000
Message-ID<mtjpq7$3rd$1@speranza.aioe.org>
In reply to#42084
Anton Ertl wrote:
> "HAA" <someone@microsoft.com> writes:
> >Anton Ertl wrote:
> >>
> >> The current looping constructs for negative stride in Gforth still
> >> have one weakness, though:
> >>
> >> When walking backwards over an array addr u of cells, we would like to
> >> start with addr u 1- cells + and end with addr, but that's relatively
> >> cumbersome to express, e.g.:
> >>
> >> addr 1 cells - addr u 1- cells + ?do ... i ... 1 cells -loop
> >>
> >> or (less run-time efficiency)
> >>
> >> addr addr u cells + ?do ... i 1 cells - ... 1 cells -loop
> >>
> >> - anton
> >
> >Typically addr u will be constants and u > 1 which your program can exploit:
> >
> >  0 u 1- do ... i cells addr + ... -1 +loop
>
> You need to replace 0 with -1 in order to be equivalent to the
> variants above.

Such a change would result in u+1 iterations

> Depending on the implementation and CPU, this may be
> slower at run-time than the variants above.

On VFX  -1 +LOOP is 3 machine instructions and CELLS ADDR +
is 2 instructions.  I don't see the runtime for -LOOP being less.


[toc] | [prev] | [next] | [standalone]


#42087

Fromanton@mips.complang.tuwien.ac.at (Anton Ertl)
Date2015-09-19 15:02 +0000
Message-ID<2015Sep19.170230@mips.complang.tuwien.ac.at>
In reply to#42086
"HAA" <someone@microsoft.com> writes:
>Anton Ertl wrote:
>> "HAA" <someone@microsoft.com> writes:
>> >Anton Ertl wrote:
>> >>
>> >> The current looping constructs for negative stride in Gforth still
>> >> have one weakness, though:
>> >>
>> >> When walking backwards over an array addr u of cells, we would like to
>> >> start with addr u 1- cells + and end with addr, but that's relatively
>> >> cumbersome to express, e.g.:
>> >>
>> >> addr 1 cells - addr u 1- cells + ?do ... i ... 1 cells -loop
>> >>
>> >> or (less run-time efficiency)
>> >>
>> >> addr addr u cells + ?do ... i 1 cells - ... 1 cells -loop
>> >>
>> >> - anton
>> >
>> >Typically addr u will be constants and u > 1 which your program can exploit:
>> >
>> >  0 u 1- do ... i cells addr + ... -1 +loop
>>
>> You need to replace 0 with -1 in order to be equivalent to the
>> variants above.
>
>Such a change would result in u+1 iterations

Yes, sorry, I had not noticed that you use the broken "-1 +loop".

As a simple task (with the proper counted loop), implement a word:

rev-type ( c-addr u -- )

that prints an ASCII string in reverse.  E.g.

s" dog" cr char " emit rev-type char " emit \ prints "god"
s" x"   cr char " emit rev-type char " emit \ prints "x"
s" "    cr char " emit rev-type char " emit \ prints ""

>> Depending on the implementation and CPU, this may be
>> slower at run-time than the variants above.
>
>On VFX  -1 +LOOP is 3 machine instructions and CELLS ADDR +
>is 2 instructions.

On VFX no words (as in the first variant) is 0 instructions.

>I don't see the runtime for -LOOP being less.

Let's just use Gforth's compat/loops.fs with VFX, and for

: foo u-do i @ + 1 cells -loop ;

(loop setup elided, because it does not affect the inner loop)

we get the following inner loop:

( 080BF5F8    8B1424 )                MOV       EDX, [ESP]
( 080BF5FB    031A )                  ADD       EBX, 0 [EDX]
( 080BF5FD    830424FC )              ADD       [ESP], -04
( 080BF601    83442404FC )            ADD       [ESP+04], -04
( 080BF606    71F0 )                  JNO       080BF5F8

Let's do the equivalent with your code:

: bar do over i cells + @ + -1 +loop ;

The inner loop is:

( 080BF5F0    8B1424 )                MOV       EDX, [ESP]
( 080BF5F3    C1E202 )                SHL       EDX, 02
( 080BF5F6    035500 )                ADD       EDX, [EBP]
( 080BF5F9    031A )                  ADD       EBX, 0 [EDX]
( 080BF5FB    830424FF )              ADD       [ESP], -01
( 080BF5FF    83442404FF )            ADD       [ESP+04], -01
( 080BF604    71EA )                  JNO       080BF5F0

Two instructions more; the -LOOP implementation in compat/loops.fs
implementation has some limitations, in particular, it's based on
+LOOP, so it cannot be more efficient than +LOOP; but the overhead of
computing addresses in the inner loop is still there in your code.

- anton
-- 
M. Anton Ertl  http://www.complang.tuwien.ac.at/anton/home.html
comp.lang.forth FAQs: http://www.complang.tuwien.ac.at/forth/faq/toc.html
     New standard: http://www.forth200x.org/forth200x.html
   EuroForth 2015: http://www.rigwit.co.uk/EuroForth2015/

[toc] | [prev] | [next] | [standalone]


#42097

From"HAA" <someone@microsoft.com>
Date2015-09-21 15:51 +1000
Message-ID<mto5oa$u43$1@speranza.aioe.org>
In reply to#42087
Anton Ertl wrote:
>
> Yes, sorry, I had not noticed that you use the broken "-1 +loop".
>
> As a simple task (with the proper counted loop), implement a word:
>
> rev-type ( c-addr u -- )
>
> that prints an ASCII string in reverse.  E.g.
>
> s" dog" cr char " emit rev-type char " emit \ prints "god"
> s" x"   cr char " emit rev-type char " emit \ prints "x"
> s" "    cr char " emit rev-type char " emit \ prints ""

In Forth the programmer gets to choose which loop to use:

: rev-type ( a u )  begin dup while 1- 2dup + c@ emit repeat 2drop ;

 (13 instructions using VFX)

 You don't need -LOOP

> >> Depending on the implementation and CPU, this may be
> >> slower at run-time than the variants above.
> >
> >On VFX  -1 +LOOP is 3 machine instructions and CELLS ADDR +
> >is 2 instructions.
>
> On VFX no words (as in the first variant) is 0 instructions.
>
> >I don't see the runtime for -LOOP being less.
>
> Let's just use Gforth's compat/loops.fs with VFX, and for
>
> [snipped]
>
> Two instructions more; the -LOOP implementation in compat/loops.fs
> implementation has some limitations, in particular, it's based on
> +LOOP, so it cannot be more efficient than +LOOP; but the overhead of
> computing addresses in the inner loop is still there in your code.

You can't have it both ways.  Either +LOOP is "broken" as you said and
deserves no part in the implementation of -LOOP.  Or +LOOP is very
efficient (which your disassembly shows) and Forth-83 gave users the
best loop possible.

: foo u-do i @ + 1 cells -loop ;
: bar do over i cells + @ + -1 +loop ;

foo = 23 instructions
bar = 18 instructions

Your original two examples followed by mine:

1000 constant addr
5 constant u

: t1 addr 1 cells - addr u 1- cells + u-do i 1 cells -loop ;
: t2 addr addr u cells + u-do i 1 cells - 1 cells -loop ;
: t3 0 u 1- do i cells addr + -1 +loop ;

t1 = 30 instructions
t2 = 31 instructions
t3 = 14 instructions





[toc] | [prev] | [next] | [standalone]


#42014

From"Elizabeth D. Rather" <erather@forth.com>
Date2015-09-15 08:45 -1000
Message-ID<w9ydnXLuQvXY-mXInZ2dnUU7-SWdnZ2d@supernews.com>
In reply to#42012
On 9/15/15 3:14 AM, Coos Haak wrote:
> Op Tue, 15 Sep 2015 16:55:44 +1000 schreef HAA:
>
>> Anton Ertl wrote:
>>> "HAA" <someone@microsoft.com> writes:
>>>> I think 83 loop was a positive change.  It worked over the full range, eliminated
>>>> the need for /LOOP
>>>
>>> But Forth-83's +LOOP does not eliminate the need for \LOOP, so you can
>>> just as well have /LOOP instead of +LOOP.
>>>
>>> And if the start value is at the wrong side of the limit value, DO and
>>> even ?DO are not so great, so overall, I feel that the Forth-83
>>> counted loops leave a lot to be desired (not that the Forth-79 ones
>>> were better).  But the 83-LEAVE is indeed better than the 79-LEAVE.
>>>
>>> - anton
>>
>> I have no complaints with +LOOP.  Considering its simplicity and
>> what it can do, the asymmetry is a small price to pay IMHO.
>
> Same experience here.
> Is there any description of what /LOOP and \LOOP are supposed to do?
> I've never found an implementation of them, even several versions
> of Gforth don't have them.

We used them at FORTH, Inc. a lot in the 70's and 80's, and occasionally 
since, for stepper motors etc. They're called "ramp up" and "ramp down" 
respectively. They take an unsigned argument and either add it to or 
subtract it from the current index. The code is significantly faster 
than +LOOP, which is why it was particularly attractive in the days of 
slow, under-powered processors.

Cheers,
Elizabeth

-- 
==================================================
Elizabeth D. Rather   (US & Canada)   800-55-FORTH
FORTH Inc.                         +1 310.999.6784
5959 West Century Blvd. Suite 700
Los Angeles, CA 90045
http://www.forth.com

"Forth-based products and Services for real-time
applications since 1973."
==================================================

[toc] | [prev] | [next] | [standalone]


#42023

From"HAA" <someone@microsoft.com>
Date2015-09-16 11:18 +1000
Message-ID<mtafsr$j8m$1@speranza.aioe.org>
In reply to#42012
Coos Haak wrote:
>
> Is there any description of what /LOOP and \LOOP are supposed to do?
> I've never found an implementation of them, even several versions
> of Gforth don't have them.

/LOOP \LOOP use unsigned limit/index and are defined in the Forth-79
Reference Word Set.  (79 +LOOP only worked over the signed range.)
/LOOP appears in Micromotion and Polyforth.  \LOOP is much more
scarce.  83 +LOOP effectively replaced them all.


[toc] | [prev] | [next] | [standalone]


#42031

Fromanton@mips.complang.tuwien.ac.at (Anton Ertl)
Date2015-09-16 06:10 +0000
Message-ID<2015Sep16.081024@mips.complang.tuwien.ac.at>
In reply to#42023
"HAA" <someone@microsoft.com> writes:
>Coos Haak wrote:
>>
>> Is there any description of what /LOOP and \LOOP are supposed to do?
>> I've never found an implementation of them, even several versions
>> of Gforth don't have them.
>
>/LOOP \LOOP use unsigned limit/index and are defined in the Forth-79
>Reference Word Set.

Thanks.  This says:

/LOOP          n --                                       "up-loop"
     A DO-LOOP terminating word.   The loop index is incremented by
     the  unsigned  magnitude  of n.   Until  the  resultant  index
     exceeds  the  limit,  execution  returns  to  just  after  the
     corresponding   DO:   otherwise,   the  index  and  limit  are
     discarded.  Magnitude logic is used.

\LOOP          n --                          I,C        "down-loop"
     A DO-LOOP terminating word.   The loop index is decremented by
     n  and  the loop terminated when the resultant  index  becomes
     equal to or less than the limit.  Magnitude logic is used, and
     n must be positive.

Not sure what they meant by "magnitude logic"; "magnitude" occurs only
in U< /LOOP and \LOOP in the Forth-79 document, with no definition.

\LOOP works like Gforth's -LOOP, except that -LOOP also works for
unsigned operands exceeding the +n range.  The "exceeds the limit" in
/LOOP is curious, as it does not match \LOOP and LOOP either in
wording, or in meaning.

+LOOP in Forth-79 already was assymetric:

+LOOP          n --                          I,C,141    "plus-loop"
     Add  the  signed  increment  n to the  loop  index  using  the
     convention for +,  and compare the total to the limit.  Return
     execution to the corresponding DO until the new index is equal
     to or greater than the limit (n>0),  or until the new index is
     less  than the limit (n<0).   Upon the exiting from the  loop,
     discard  the  loop control  parameters,  continuing  execution
     ahead.   Index and  limit are  signed  integers in  the  range
     {-32,768..32,767}.

     (Comment:  It is a historical precedent that the limit for n<0
     is irregular.   Further consideration of the characteristic is
     unlikely.)

- anton
-- 
M. Anton Ertl  http://www.complang.tuwien.ac.at/anton/home.html
comp.lang.forth FAQs: http://www.complang.tuwien.ac.at/forth/faq/toc.html
     New standard: http://www.forth200x.org/forth200x.html
   EuroForth 2015: http://www.rigwit.co.uk/EuroForth2015/

[toc] | [prev] | [next] | [standalone]


#42045

From"HAA" <someone@microsoft.com>
Date2015-09-17 15:15 +1000
Message-ID<mtdi68$5nh$1@speranza.aioe.org>
In reply to#42031
Anton Ertl wrote:
> "HAA" <someone@microsoft.com> writes:
> >Coos Haak wrote:
> >>
> >> Is there any description of what /LOOP and \LOOP are supposed to do?
> >> I've never found an implementation of them, even several versions
> >> of Gforth don't have them.
> >
> >/LOOP \LOOP use unsigned limit/index and are defined in the Forth-79
> >Reference Word Set.
>
> Thanks.  This says:
>
> /LOOP          n --                                       "up-loop"
>      A DO-LOOP terminating word.   The loop index is incremented by
>      the  unsigned  magnitude  of n.   Until  the  resultant  index
>      exceeds  the  limit,  execution  returns  to  just  after  the
>      corresponding   DO:   otherwise,   the  index  and  limit  are
>      discarded.  Magnitude logic is used.
>
> \LOOP          n --                          I,C        "down-loop"
>      A DO-LOOP terminating word.   The loop index is decremented by
>      n  and  the loop terminated when the resultant  index  becomes
>      equal to or less than the limit.  Magnitude logic is used, and
>      n must be positive.
>
> Not sure what they meant by "magnitude logic"; "magnitude" occurs only
> in U< /LOOP and \LOOP in the Forth-79 document, with no definition.

Forth-83 document has this:

      /LOOP        +n --                         C,I          "up-loop"
                   sys --   (compiling)
           A do-loop terminating word.  The loop index is incremented
           by the positive value +n.  If the unsigned magnitude of the
           resultant index is greater than the limit, then the loop is
           terminated, otherwise execution returns to the corresponding
           DO .  The comparison is unsigned magnitude.  sys is balanced
           with its corresponding DO .  See:  DO

      \LOOP        +n --                         C,I        "down-loop"
                   sys --   (compiling)
           A do-loop terminating word.  The loop index is decremented
           by the positive value +n.  If the unsigned magnitude of the
           resultant index is less than or equal to the limit, then the
           loop is terminated, otherwise execution returns to the
           corresponding DO .  The comparison is unsigned.  sys is
           balanced with its corresponding DO .  See:  DO

"Reference Words" were intended to describe existing practice.  Output
below is from 8086 PolyForth /LOOP.  I was unable to test \LOOP as
there was none in the implementation I had.

: TEST DO I U. 1 /LOOP ; ok
0 10 TEST  10 ok
10 0 TEST  0 1 2 3 4 5 6 7 8 9 ok
HEX ok
FFFF FFF8 TEST  FFF8 FFF9 FFFA FFFB FFFC FFFD FFFE ok
0 FFF8 TEST  FFF8 ok

Note the full 64K range was not possible (unlike 83 +LOOP)


[toc] | [prev] | [next] | [standalone]


#42052

Fromanton@mips.complang.tuwien.ac.at (Anton Ertl)
Date2015-09-17 06:04 +0000
Message-ID<2015Sep17.080430@mips.complang.tuwien.ac.at>
In reply to#42045
"HAA" <someone@microsoft.com> writes:
>Output
>below is from 8086 PolyForth /LOOP.  I was unable to test \LOOP as
>there was none in the implementation I had.
>
>: TEST DO I U. 1 /LOOP ; ok
>0 10 TEST  10 ok
>10 0 TEST  0 1 2 3 4 5 6 7 8 9 ok
>HEX ok
>FFFF FFF8 TEST  FFF8 FFF9 FFFA FFFB FFFC FFFD FFFE ok
>0 FFF8 TEST  FFF8 ok
>
>Note the full 64K range was not possible (unlike 83 +LOOP)

Ok, Gforth's -LOOP uses wraparound arithmetics:

: x ?do i hex. 1 -loop ;  ok
-3 3 cr x 
$3 $2 $1 $0 $FFFFFFFFFFFFFFFF $FFFFFFFFFFFFFFFE  ok
$7ffffffffffffffd $8000000000000001 cr x 
$8000000000000001 $8000000000000000 $7FFFFFFFFFFFFFFF $7FFFFFFFFFFFFFFE  ok

It also works with increments exceeding MAX-N:

: y 0 -1 do i hex. -5 -loop ;  ok
y $FFFFFFFFFFFFFFFF $4  ok

The current implementation does not loop if index=limit.  The current
test corresponds to:

index limit - incr u> if
  ... loop ..
else
  ... exit loop ...
then

And of course this does not loop if index=limit.

An implementation that loops on index=limit would be:

limit newindex - incr u>= if
   ... loop ...
else
   ... exit loop
then

I have changed the implementation accordingly, and it seems to work:

: z 0 0 do i hex. $4000000000000000 -loop ;  ok
cr z 
$0 $C000000000000000 $8000000000000000 $4000000000000000  ok

Looking at the code, it takes the same number of instructions, so the
performance should be similar:

old                                  new
mov  0x0(%r13),%rdx                  mov  0x0(%r13),%rax                
mov  %r15,%rcx                       mov  0x8(%r13),%rsi                
mov  (%rbx),%rdi                     mov  %r15,%rcx                     
lea  0x8(%r15),%r15                  mov  (%rbx),%rdi                   
mov  %rdx,%rsi                       lea  0x8(%r15),%r15                
sub  0x8(%r13),%rdx                  sub  %r14,%rax                     
sub  %r14,%rsi                       sub  %rax,%rsi                     
cmp  %rdx,%r14                       cmp  %rsi,%r14                     
jae  0x4031ec <gforth_engine+1500>   ja   0x4031ec <gforth_engine+1500> 
mov  %rsi,0x0(%r13)                  mov  %rax,0x0(%r13)                
mov  (%rdi),%rdx                     mov  (%rdi),%rdx                   
lea  0x8(%rdi),%rbx                  lea  0x8(%rdi),%rbx                
mov  0x8(%rcx),%r14                  mov  0x8(%rcx),%r14                
mov  %rdx,%rax                       mov  %rdx,%rax                     
jmpq *%rax                           jmpq *%rax                         
mov  %rsi,0x0(%r13)                  mov  %rax,0x0(%r13)                
mov  0x8(%rcx),%r14                  mov  0x8(%rcx),%r14                
add  $0x10,%rbx                      add  $0x10,%rbx                    
mov  -0x8(%rbx),%rdx                 mov  -0x8(%rbx),%rdx               
mov  %rdx,%rax                       mov  %rdx,%rax                     
jmpq *%rax                           jmpq *%rax                         

- anton
-- 
M. Anton Ertl  http://www.complang.tuwien.ac.at/anton/home.html
comp.lang.forth FAQs: http://www.complang.tuwien.ac.at/forth/faq/toc.html
     New standard: http://www.forth200x.org/forth200x.html
   EuroForth 2015: http://www.rigwit.co.uk/EuroForth2015/

[toc] | [prev] | [next] | [standalone]


#41956

FromCoos Haak <chforth@hccnet.nl>
Date2015-09-11 14:16 +0200
Message-ID<bvqy7m57xczo$.1snk2q5aphxr7.dlg@40tude.net>
In reply to#41954
Op Fri, 11 Sep 2015 21:47:44 +1000 schreef HAA:

> Coos Haak wrote:
>>
>> This is not only a question of standard (fig, 79, 83, ANS)
>> but more of implementation.
>> Some DO's flip bits of the limit, some don't.
> 
> The contention of the FD article is that it's not possible to implement a
> 79-LEAVE on an 83-system by the simple mechanism of adjusting the
> limit and/or index values on the return stack.  Are you saying that's false?

No. But I argued that mixing both LEAVEs does not work between
implementations, even if they adhire to the standard.

groet Coos

[toc] | [prev] | [standalone]


Page 2 of 2 — ← Prev page 1 [2]

Back to top | Article view | comp.lang.forth


csiph-web