• Re: DO..LOOP and stack shuffling

    From Anton Ertl@21:1/5 to Hans Bezemer on Thu Jul 3 07:50:15 2025
    Hans Bezemer <the.beez.speaks@gmail.com> writes:
    The DO..LOOP advantages - nah, not really. E.g. an "address" loop can be
    done like (a n = address count):

    OVER SWAP /ELEMENT * + >R
    BEGIN DUP R@ < WHILE ( ..) /ELEMENT + REPEAT R> DROP DROP

    No need for BOUNDS DO..LOOP ..

    Great. You can write a counted loop without body with BEGIN ... WHILE
    ... REPEAT. I can write equivalent code shorter, and it will execute
    more efficiently:

    2DROP

    However, things become more interesting when the body does something,
    in particular when it needs access to additional data beyond just I,
    and maybe even modify some of these stack items. E.g., here's a
    definition from Gforth:

    : del-included-files ( addr u -- )
    included-files $@ cell MEM+DO
    I $@ 2over string-prefix? IF I 0 third $del THEN
    LOOP 2drop ;

    That's a relatively easy case, because the loop body does not modify
    addr nor u. You can find documentation on most used words through <https://net2o.de/gforth/Word-Index.html>. INCLUDED-FILES is a
    variable.

    Another one is:

    : usage# ( nt -- n ) \ gforth-internal
    \G count usage of the word @var{nt}
    0 wheres $@ where-struct MEM+DO
    over i where-nt @ = -
    LOOP nip ;

    Here the body reads one additional stack item ( nt ) and modifies
    another one (the count). WHERES is a variable, WHERE-STRUCT is the
    size of an element of the array that WHERES points to.

    So for a lot of applications, I don't really need DO..LOOP and its
    deeply flawed implementation.

    If your implementation of DO..LOOP is deeply flawed, maybe you should
    replace it with a better one.

    And since R@ and I are synonyms

    They are not, not in the standard, and not on a number of systems.
    E.g., consider the following program:

    : foo 10 5 do cr i . r@ . loop ; foo

    On Gforth and iForth, the result of I and R@ are the same, but on lxf,
    sf64, and vfx64, they are not:

    lxf sf64 vfx64
    I R@ I R@ I R@
    5 2147483643 5 0 5 8388608
    6 2147483644 6 0 6 8388608
    7 2147483645 7 0 7 8388608
    8 2147483646 8 0 8 8388608
    9 2147483647 9 0 9 8388608

    - anton






















    , I can
    even use I if I prefer I! :)

    Usually, if I think of it I could even do less DO..LOOP - but you know
    how it is when a pattern has entered your mind. It's like an ear worm.

    But anyways - that was the reason I defined R'@ and R"@ a long time ago.
    It still feels like cheating if I use them, but they're just synonyms of
    I' and J anyways - so they don't take up much space if you want to
    support them.

    As I've shown, in 4tH you can make the code much clearer by
    (temporarily) assigning synonyms to them.

    Now as I was playing with the idea there were a lot of people claiming
    "It makes no sense adding R'@ and R"@. Been there done that."

    But since I'm so easily convinced, I did it anyway. Can't say I
    regretted that, since it allows you to better balance the load between
    both stacks.

    Hans Bezemer

    P.S. If you want to do an equally misconceived FOR..NEXT as eForth has >implemented, place the (..) payload directly behind BEGIN. That will
    make it do 11 iterations when you only asked for 10.




    --
    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: https://forth-standard.org/
    EuroForth 2023 proceedings: http://www.euroforth.org/ef23/papers/
    EuroForth 2024 proceedings: http://www.euroforth.org/ef24/papers/

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)