Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.forth > #41835 > unrolled thread
| Started by | Marcos Cruz <null_email_so_use_my_contact_page@programandala.net> |
|---|---|
| First post | 2015-09-07 20:29 +0000 |
| Last post | 2015-09-11 14:16 +0200 |
| Articles | 18 on this page of 38 — 9 participants |
Back to article view | Back to comp.lang.forth
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]
| From | "HAA" <someone@microsoft.com> |
|---|---|
| Date | 2015-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]
| From | hughaguilar96@gmail.com |
|---|---|
| Date | 2015-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]
| From | Coos Haak <chforth@hccnet.nl> |
|---|---|
| Date | 2015-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]
| From | anton@mips.complang.tuwien.ac.at (Anton Ertl) |
|---|---|
| Date | 2015-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]
| From | hughaguilar96@gmail.com |
|---|---|
| Date | 2015-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]
| From | jim.brakefield@ieee.org |
|---|---|
| Date | 2015-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]
| From | hughaguilar96@gmail.com |
|---|---|
| Date | 2015-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]
| From | "HAA" <someone@microsoft.com> |
|---|---|
| Date | 2015-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]
| From | anton@mips.complang.tuwien.ac.at (Anton Ertl) |
|---|---|
| Date | 2015-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]
| From | "HAA" <someone@microsoft.com> |
|---|---|
| Date | 2015-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]
| From | anton@mips.complang.tuwien.ac.at (Anton Ertl) |
|---|---|
| Date | 2015-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]
| From | "HAA" <someone@microsoft.com> |
|---|---|
| Date | 2015-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]
| From | "Elizabeth D. Rather" <erather@forth.com> |
|---|---|
| Date | 2015-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]
| From | "HAA" <someone@microsoft.com> |
|---|---|
| Date | 2015-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]
| From | anton@mips.complang.tuwien.ac.at (Anton Ertl) |
|---|---|
| Date | 2015-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]
| From | "HAA" <someone@microsoft.com> |
|---|---|
| Date | 2015-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]
| From | anton@mips.complang.tuwien.ac.at (Anton Ertl) |
|---|---|
| Date | 2015-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]
| From | Coos Haak <chforth@hccnet.nl> |
|---|---|
| Date | 2015-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