• Re: Locals on data stack?

    From dxforth@21:1/5 to minforth on Thu May 11 10:38:57 2023
    On 10/05/2023 10:39 pm, minforth wrote:
    none albert schrieb am Mittwoch, 10. Mai 2023 um 13:12:47 UTC+2:
    In article <d66b1778-4063-4777...@googlegroups.com>,
    minforth <minf...@arcor.de> wrote:
    Forth standard section 13.3.3.1.b) stipulates that
    "The (locals) storage resource shall not be the data stack."

    Where did this restriction come from, and with what justification?
    If they were located on the data stack, this would impeded the
    use of the regular data stack.

    Why impeded? Stack frames are the only locals store in most other languages.

    In a naive implementation, Forth words that leave output items on the stack could shift them 'en bloc' downwards and overwrite the discarded frame location.
    This seems easier than moving input items piece-wise away from the stack
    to their local identifiers or a separate locals stack.

    That appears to be the method employed here:

    FD Vol 8 No 3 Stack Number By Name - Rosenfeld M.

    While the article lacks details (missing page or two?) it's strongly suggestive the stack is adjusted on exit.

    Given ANS has already decreed locals shall not use the data stack, perhaps such inquiry can be put down to a fascination with the forbidden.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Anton Ertl@21:1/5 to minforth on Thu May 11 13:49:44 2023
    minforth <minforth@arcor.de> writes:
    My question was triggered by whether it makes sense to keep complete
    stack frames in CPU registers

    As the name says, stack frames are kept on a stack. I guess you means something different, such as "keep the locals in CPU registers that,
    e.g., VFX keeps in a stack frame (on the return stack)". That has
    little to do with locals on the data stack, though.

    given that register-register movements are
    fast and cheap.

    It seems you are thinking about a kind of register allocator that has
    some registers for locals and others for, e.g., data stack items.
    Yes, that's possible and simple. It's also possible to have a more sophisticated register allocator that need few register-register
    moves.

    Perhaps one could get rid of the locals stack as well.

    Most Forth systems don't have a locals stack, so it obviously is
    possible.

    More generally, if you limit your Forth usage in ways that allows
    static depth knowledge by the compiler (as needed for Tevet's scheme),
    you can use registers for everything, and (for recursion and when
    there are not enough registers) have a single stack that contains
    items from all the logical stacks:

    @InProceedings{ertl13-paf,
    author = {M. Anton Ertl},
    title = {{PAF}: A Portable Assembly Language},
    crossref = {euroforth13},
    pages = {30--38},
    url = {http://www.complang.tuwien.ac.at/anton/euroforth/ef13/papers/ertl-paf.pdf},
    OPTnote = {not refereed},
    abstract = {A portable assembly language provides access to
    machine-level features like memory addresses,
    machine words, code addresses, and modulo
    arithmetics, like assembly language, but abstracts
    away differences between architectures like the
    assembly language syntax, instruction encoding,
    register set size, and addressing modes. Forth
    already satisfies a number of the characteristics of
    a portable assembly language, and is therefore a
    good basis. This paper presents PAF, a portable
    assembly language based on Forth, and specifically
    discusses language features that other portable
    assembly languages do not have, and their benefits;
    it also discusses the differences from Forth. The
    main innovations of PAF are: tags indicate the
    control flow for indirect branches and calls; and
    PAF has two kinds of calls and definitions: the ABI
    ones follow the platform's calling convention and
    are useful for interfacing to the outside world,
    while the PAF ones allow tail-call elimination and
    are useful for implementing general control
    structures.}
    }
    @Proceedings{euroforth13,
    title = {29th EuroForth Conference},
    booktitle = {29th EuroForth Conference},
    year = {2013},
    key = {EuroForth'13},
    url = {http://www.complang.tuwien.ac.at/anton/euroforth/ef13/papers/proceedings.pdf}
    }

    - 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: https://forth-standard.org/
    EuroForth 2022: https://euro.theforth.net

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From minforth@21:1/5 to Rob Kellock on Thu May 11 06:32:29 2023
    Rob Kellock schrieb am Mittwoch, 10. Mai 2023 um 23:41:57 UTC+2:
    In a naive implementation, Forth words that leave output items on the stack
    could shift them 'en bloc' downwards and overwrite the discarded frame location.
    This seems easier than moving input items piece-wise away from the stack to their local identifiers or a separate locals stack.
    My Forth implementation is naive, but I'm using it to build web sites and DMX control lighting for stage shows. I use a deque rather a data stack and that way can get a couple of 'locals' at the bottom of the deque. My Forth is built on top of Python.
    I took https://www.openbookproject.net/py4fun/forth/forth.py as my starting point and have developed it from there.

    "Naive" was not meant in any belittling way. Of course it is a valid way.

    Only for background, without going into details: I was thinking of keeping a window of say 10 stack cells in CPU registers, the actual TOS somewhere in the middle of the window. Then discarding and overwriting frames profits from
    fast register movements.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Anton Ertl@21:1/5 to minforth on Thu May 11 14:10:03 2023
    minforth <minforth@arcor.de> writes:
    none albert schrieb am Mittwoch, 10. Mai 2023 um 13:12:47 UTC+2:
    If they were located on the data stack, this would impeded the
    use of the regular data stack.

    Why impeded? Stack frames are the only locals store in most other languages.

    Most other languages don't have a programmer-visible data stack. The
    stack many implementations use is more like the return stack than the
    data stack.

    As for "impeded", consider:

    : map-array ( ... addr u xt -- ... )
    {: xt :}
    cells bounds ?do
    i @ xt execute
    1 cells +loop ;

    create v 3 , -2 , 4 ,
    v 3 ' . map-array
    0 v 3 ' + map-array .

    Where on the data stack would MAP-ARRAY keep the local xt, such that
    the first invocation does not produce a stack underflow, while the
    second can still access the accumulated sum (initially 0)?

    - 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: https://forth-standard.org/
    EuroForth 2022: https://euro.theforth.net

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From minforth@21:1/5 to Anton Ertl on Thu May 11 08:10:07 2023
    Anton Ertl schrieb am Donnerstag, 11. Mai 2023 um 16:19:29 UTC+2:
    minforth <minf...@arcor.de> writes:
    none albert schrieb am Mittwoch, 10. Mai 2023 um 13:12:47 UTC+2:
    If they were located on the data stack, this would impeded the
    use of the regular data stack.

    Why impeded? Stack frames are the only locals store in most other languages. Most other languages don't have a programmer-visible data stack. The
    stack many implementations use is more like the return stack than the
    data stack.

    As for "impeded", consider:

    : map-array ( ... addr u xt -- ... )
    {: xt :}
    cells bounds ?do
    i @ xt execute
    1 cells +loop ;

    Nice example of mingling stack and local parameters, of course allowed in standard
    wild west Forth style.

    Defined à la
    : map-array1 {: addr u xt -- :} ...
    would cause no such problems.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Anton Ertl@21:1/5 to minforth on Thu May 11 15:32:20 2023
    minforth <minforth@arcor.de> writes:
    Defined =C3=A0 la
    : map-array1 {: addr u xt -- :} ...=20
    would cause no such problems.=20

    It still would have the same problems:

    : map-array1 {: addr u xt -- :}
    addr u cells bounds ?do
    i @ xt execute
    1 cells +loop ;

    create v 3 , -2 , 4 ,
    v 3 ' . map-array1
    0 v 3 ' + map-array1 .

    |Where on the data stack would MAP-ARRAY keep the local xt, such that
    |the first invocation does not produce a stack underflow, while the
    |second can still access the accumulated sum (initially 0)?

    Of course with MAP-ARRAY1 you don't have the "..." to warn you that
    there may be accesses further down, but they still happen in the
    second invocation of MAP-ARRAY1.

    - 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: https://forth-standard.org/
    EuroForth 2022: https://euro.theforth.net

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From minforth@21:1/5 to Anton Ertl on Thu May 11 14:12:03 2023
    Anton Ertl schrieb am Donnerstag, 11. Mai 2023 um 17:39:10 UTC+2:
    minforth <minf...@arcor.de> writes:
    Defined =C3=A0 la
    : map-array1 {: addr u xt -- :} ...=20
    would cause no such problems.=20

    It still would have the same problems:
    : map-array1 {: addr u xt -- :}
    addr u cells bounds ?do
    i @ xt execute
    1 cells +loop ;
    create v 3 , -2 , 4 ,
    v 3 ' . map-array1
    0 v 3 ' + map-array1 .
    |Where on the data stack would MAP-ARRAY keep the local xt, such that
    |the first invocation does not produce a stack underflow, while the
    |second can still access the accumulated sum (initially 0)?
    Of course with MAP-ARRAY1 you don't have the "..." to warn you that
    there may be accesses further down, but they still happen in the
    second invocation of MAP-ARRAY1.

    Maybe splitting hairs here, but . is a unary operator and + a binary operator. But the stack notation or locals notation does not reflect it.

    IOW mingling stack input parameters and locals is problematic as you have shown.
    After all Forth is a wonderful language to shoot your own foot when handled carelessly. ;-)

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Gerry Jackson@21:1/5 to Anton Ertl on Thu May 11 21:59:50 2023
    On 11/05/2023 15:10, Anton Ertl wrote:
    minforth <minforth@arcor.de> writes:
    none albert schrieb am Mittwoch, 10. Mai 2023 um 13:12:47 UTC+2:
    If they were located on the data stack, this would impeded the
    use of the regular data stack.

    Why impeded? Stack frames are the only locals store in most other languages.

    Most other languages don't have a programmer-visible data stack. The
    stack many implementations use is more like the return stack than the
    data stack.

    As for "impeded", consider:

    : map-array ( ... addr u xt -- ... )
    {: xt :}
    cells bounds ?do
    i @ xt execute
    1 cells +loop ;

    create v 3 , -2 , 4 ,
    v 3 ' . map-array
    0 v 3 ' + map-array .

    Where on the data stack would MAP-ARRAY keep the local xt, such that
    the first invocation does not produce a stack underflow, while the
    second can still access the accumulated sum (initially 0)?


    You didn't use the word "sensibly" so this will do the job and work with
    any number of stack items below (addr u) in MAP-ARRAY

    : -roll ( xu ... x0 u -- x0 xu ... x1 )
    ?dup if rot >r 1- recurse r> then
    ;

    : bury-xt depth 1- -roll ;
    : get-xt depth 1- pick ;
    : nip-xt depth 1- roll drop ;

    : map-array ( ... addr u xt -- ... )
    bury-xt
    cells bounds ?do
    i @ get-xt execute
    1 cells +loop
    nip-xt
    ;

    create v 3 , -2 , 4 ,
    v 3 ' . map-array 3 -2 4 ok
    0 v 3 ' + map-array . 5 ok
    1 2 3 4 v 3 ' . map-array 3 -2 4 ok 4

    --
    Gerry

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From dxforth@21:1/5 to minforth on Fri May 12 11:32:53 2023
    On 12/05/2023 7:12 am, minforth wrote:
    Anton Ertl schrieb am Donnerstag, 11. Mai 2023 um 17:39:10 UTC+2:
    minforth <minf...@arcor.de> writes:
    Defined =C3=A0 la
    : map-array1 {: addr u xt -- :} ...=20
    would cause no such problems.=20

    It still would have the same problems:
    : map-array1 {: addr u xt -- :}
    addr u cells bounds ?do
    i @ xt execute
    1 cells +loop ;
    create v 3 , -2 , 4 ,
    v 3 ' . map-array1
    0 v 3 ' + map-array1 .
    |Where on the data stack would MAP-ARRAY keep the local xt, such that
    |the first invocation does not produce a stack underflow, while the
    |second can still access the accumulated sum (initially 0)?
    Of course with MAP-ARRAY1 you don't have the "..." to warn you that
    there may be accesses further down, but they still happen in the
    second invocation of MAP-ARRAY1.

    Maybe splitting hairs here, but . is a unary operator and + a binary operator.
    But the stack notation or locals notation does not reflect it.

    IOW mingling stack input parameters and locals is problematic as you have shown.
    After all Forth is a wonderful language to shoot your own foot when handled carelessly. ;-)

    Passing all inputs solves the general problem. Moore advises don't do that.
    In one of his essays, Fox remarked at the lack of 'layers' in Moore's code. Presumably he was referencing unnecessary generalizations.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From minforth@21:1/5 to dxforth on Fri May 12 00:34:48 2023
    dxforth schrieb am Freitag, 12. Mai 2023 um 03:34:56 UTC+2:
    On 12/05/2023 7:12 am, minforth wrote:
    Anton Ertl schrieb am Donnerstag, 11. Mai 2023 um 17:39:10 UTC+2:
    minforth <minf...@arcor.de> writes:
    Defined =C3=A0 la
    : map-array1 {: addr u xt -- :} ...=20
    would cause no such problems.=20

    It still would have the same problems:
    : map-array1 {: addr u xt -- :}
    addr u cells bounds ?do
    i @ xt execute
    1 cells +loop ;
    create v 3 , -2 , 4 ,
    v 3 ' . map-array1
    0 v 3 ' + map-array1 .
    |Where on the data stack would MAP-ARRAY keep the local xt, such that
    |the first invocation does not produce a stack underflow, while the
    |second can still access the accumulated sum (initially 0)?
    Of course with MAP-ARRAY1 you don't have the "..." to warn you that
    there may be accesses further down, but they still happen in the
    second invocation of MAP-ARRAY1.

    Maybe splitting hairs here, but . is a unary operator and + a binary operator.
    But the stack notation or locals notation does not reflect it.

    IOW mingling stack input parameters and locals is problematic as you have shown.
    After all Forth is a wonderful language to shoot your own foot when handled carelessly. ;-)
    Passing all inputs solves the general problem. Moore advises don't do that. In one of his essays, Fox remarked at the lack of 'layers' in Moore's code. Presumably he was referencing unnecessary generalizations.

    Moores and Foxes won't help you. The topic is that stack frames can conflict with
    accessing stack regions below the frames. E.g. (local) frames in the return stack can
    constrain the usage of DO..LOOPs. Similarly, frames in the data stack, as Anton pointed out.

    To solve this, standard section 13.3.3 stipulates a number of syntax restrictions on
    on the user. IOW it requires some coding discipline to use standard locals.

    In case of non-standard "named stack element frames" a similar coding discipline
    would have to be applied. Or, when the application domain (like using a DSL) just
    does not involve access to stack regions below frames, everything is fine.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Anton Ertl@21:1/5 to minforth on Fri May 12 07:16:40 2023
    minforth <minforth@arcor.de> writes:
    Anton Ertl schrieb am Donnerstag, 11. Mai 2023 um 17:39:10 UTC+2:
    minforth <minf...@arcor.de> writes:
    Defined =C3=A0 la
    : map-array1 {: addr u xt -- :} ...=20
    would cause no such problems.=20

    It still would have the same problems:
    : map-array1 {: addr u xt -- :}
    addr u cells bounds ?do
    i @ xt execute
    1 cells +loop ;
    create v 3 , -2 , 4 ,
    v 3 ' . map-array1
    0 v 3 ' + map-array1 .
    |Where on the data stack would MAP-ARRAY keep the local xt, such that
    |the first invocation does not produce a stack underflow, while the
    |second can still access the accumulated sum (initially 0)?
    Of course with MAP-ARRAY1 you don't have the "..." to warn you that
    there may be accesses further down, but they still happen in the
    second invocation of MAP-ARRAY1.

    Maybe splitting hairs here, but . is a unary operator and + a binary operator. >But the stack notation or locals notation does not reflect it.

    The "..." indicates that something is going on below "addr u xt".

    If you want to document the stack effect of the passed xt, one way to
    do it would be:

    : map-array ( ... addr u xt -- ... )
    \ xt has stack effect ( ... x -- ... )

    or in the notation used in the standard:

    : map-array ( i1*x1 addr u xt -- i2*x2 )
    \ xt has stack effect ( i3*x3 x -- i4*x4 )

    or one might replace i1..i4 with i if we want to express the idea that
    one should use balanced stack effects in MAP-ARRAY.

    As for ".", it's not an unary operator, because it does not have the
    stack effect ( x1 -- x2 ).

    - 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: https://forth-standard.org/
    EuroForth 2022: https://euro.theforth.net

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Hans Bezemer@21:1/5 to dxforth on Fri May 12 03:22:23 2023
    On Thursday, May 11, 2023 at 2:38:59 AM UTC+2, dxforth wrote:
    FD Vol 8 No 3 Stack Number By Name - Rosenfeld M.
    It resembles the way the LOCALS library on 4tH works. Of course, since it has its own
    stack, the issues with the data stack top are avoided. https://sourceforge.net/p/forth-4th/code/HEAD/tree/trunk/4th.src/lib/locals.4th

    While the article lacks details (missing page or two?) it's strongly suggestive
    the stack is adjusted on exit.
    That's exactly what happens in 4tH - when exiting the locals stack has to be adjusted
    MANUALLY. It isn't part of core 4tH, so EXIT has no idea what is going on. Of course,
    one could add a few (preprocessor) macros to correct that, but then use of the preprocessor becomes compulsory.

    Both the return stack as well as the data stack CANNOT be accessed directly in 4tH
    (for obvious reasons), so the "Rosenfeld approach" could NEVER work on 4tH. It's
    also one of the reasons that locals on the return stack would become very messy in thew 4tH environment.

    However, R@, R'@ and R"@ (as aliases for I, I' and J) allow the TORS, 2ORS and 3ORS
    to be used as a kind of "read-only" local variables. I've used this on several occasions,
    most notoriously in the "midpoint circle algorithm": https://sourceforge.net/p/forth-4th/code/HEAD/tree/trunk/4th.src/lib/gcircle.4th

    I learned this trick from the FIG editor author.

    Hans Bezemer

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From none) (albert@21:1/5 to minforth@arcor.de on Fri May 12 13:02:41 2023
    In article <d66b1778-4063-4777-acba-7175effdc9b9n@googlegroups.com>,
    minforth <minforth@arcor.de> wrote:
    Forth standard section 13.3.3.1.b) stipulates that
    "The (locals) storage resource shall not be the data stack."

    Where did this restriction come from, and with what justification?

    I vaguely remember old Forths with "named stack elements".
    So "it works" as well...

    Given modern CPUs with sufficient registers to hold lots of
    stack elements there, that a.m. old restriction does not seem to hold
    any more.

    In view of RISCV you have easily 8 registers to spare.
    You could easily use these registers for locals.
    For re-entrant code you have to store the previous values on
    the return stack.
    All other solutions seem obsolete.

    Groetjes Albert
    --
    Don't praise the day before the evening. One swallow doesn't make spring.
    You must not say "hey" before you have crossed the bridge. Don't sell the
    hide of the bear until you shot it. Better one bird in the hand than ten in
    the air. First gain is a cat spinning. - the Wise from Antrim -

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Marcel Hendrix@21:1/5 to none albert on Fri May 12 11:50:48 2023
    On Friday, May 12, 2023 at 1:02:48 PM UTC+2, none albert wrote:
    [..]
    In view of RISCV you have easily 8 registers to spare.
    You could easily use these registers for locals.
    For re-entrant code you have to store the previous values on
    the return stack.
    All other solutions seem obsolete.

    Well... If you have a word using a local, and you call just any
    other word, how would you transparently make sure that after
    that call your register has not been changed? The "other" word
    might use locals too, and call many words that do the same.
    That is not recursion, that is normal use.

    The only way I can see that work is with a real Forth compiler.

    -marcel

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From dxforth@21:1/5 to Hans Bezemer on Sat May 13 09:44:59 2023
    On 12/05/2023 8:22 pm, Hans Bezemer wrote:
    On Thursday, May 11, 2023 at 2:38:59 AM UTC+2, dxforth wrote:
    FD Vol 8 No 3 Stack Number By Name - Rosenfeld M.
    It resembles the way the LOCALS library on 4tH works. Of course, since it has its own
    stack, the issues with the data stack top are avoided. https://sourceforge.net/p/forth-4th/code/HEAD/tree/trunk/4th.src/lib/locals.4th

    While the article lacks details (missing page or two?) it's strongly suggestive
    the stack is adjusted on exit.
    That's exactly what happens in 4tH - when exiting the locals stack has to be adjusted
    MANUALLY. It isn't part of core 4tH, so EXIT has no idea what is going on. Of course,
    one could add a few (preprocessor) macros to correct that, but then use of the
    preprocessor becomes compulsory.

    Both the return stack as well as the data stack CANNOT be accessed directly in 4tH
    (for obvious reasons), so the "Rosenfeld approach" could NEVER work on 4tH. It's
    also one of the reasons that locals on the return stack would become very messy
    in thew 4tH environment.

    However, R@, R'@ and R"@ (as aliases for I, I' and J) allow the TORS, 2ORS and 3ORS
    to be used as a kind of "read-only" local variables. I've used this on several occasions,
    most notoriously in the "midpoint circle algorithm": https://sourceforge.net/p/forth-4th/code/HEAD/tree/trunk/4th.src/lib/gcircle.4th

    I learned this trick from the FIG editor author.

    I'm fairly certain Borland never used locals for their graphics primitives either :)

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From dxforth@21:1/5 to minforth on Sat May 13 15:11:41 2023
    On 12/05/2023 5:34 pm, minforth wrote:
    dxforth schrieb am Freitag, 12. Mai 2023 um 03:34:56 UTC+2:
    On 12/05/2023 7:12 am, minforth wrote:
    Anton Ertl schrieb am Donnerstag, 11. Mai 2023 um 17:39:10 UTC+2:
    minforth <minf...@arcor.de> writes:
    Defined =C3=A0 la
    : map-array1 {: addr u xt -- :} ...=20
    would cause no such problems.=20

    It still would have the same problems:
    : map-array1 {: addr u xt -- :}
    addr u cells bounds ?do
    i @ xt execute
    1 cells +loop ;
    create v 3 , -2 , 4 ,
    v 3 ' . map-array1
    0 v 3 ' + map-array1 .
    |Where on the data stack would MAP-ARRAY keep the local xt, such that
    |the first invocation does not produce a stack underflow, while the
    |second can still access the accumulated sum (initially 0)?
    Of course with MAP-ARRAY1 you don't have the "..." to warn you that
    there may be accesses further down, but they still happen in the
    second invocation of MAP-ARRAY1.

    Maybe splitting hairs here, but . is a unary operator and + a binary operator.
    But the stack notation or locals notation does not reflect it.

    IOW mingling stack input parameters and locals is problematic as you have shown.
    After all Forth is a wonderful language to shoot your own foot when handled >>> carelessly. ;-)
    Passing all inputs solves the general problem. Moore advises don't do that. >> In one of his essays, Fox remarked at the lack of 'layers' in Moore's code. >> Presumably he was referencing unnecessary generalizations.

    Moores and Foxes won't help you.

    Correct. They inform I'm the programmer and perhaps it's me who needs to get his act together.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From minforth@21:1/5 to Marcel Hendrix on Mon May 15 01:28:38 2023
    Marcel Hendrix schrieb am Freitag, 12. Mai 2023 um 20:50:49 UTC+2:
    On Friday, May 12, 2023 at 1:02:48 PM UTC+2, none albert wrote:
    [..]
    In view of RISCV you have easily 8 registers to spare.
    You could easily use these registers for locals.
    For re-entrant code you have to store the previous values on
    the return stack.
    All other solutions seem obsolete.
    Well... If you have a word using a local, and you call just any
    other word, how would you transparently make sure that after
    that call your register has not been changed? The "other" word
    might use locals too, and call many words that do the same.
    That is not recursion, that is normal use.

    The only way I can see that work is with a real Forth compiler.

    From MSVC:
    "The __fastcall convention uses registers for the first four arguments,
    and the stack frame to pass more arguments."
    AFAIU called words that use only up to four arguments run pretty fast.
    Of course if they call other functions they have to save those registers.

    This scheme should also be feasible with a Forth compiler. Forth primitives wouldn't even call other words.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From none) (albert@21:1/5 to minforth@arcor.de on Mon May 15 12:23:22 2023
    In article <dc8f44f6-293f-40e9-9101-6114c300f17an@googlegroups.com>,
    minforth <minforth@arcor.de> wrote:
    Marcel Hendrix schrieb am Freitag, 12. Mai 2023 um 20:50:49 UTC+2:
    On Friday, May 12, 2023 at 1:02:48 PM UTC+2, none albert wrote:
    [..]
    In view of RISCV you have easily 8 registers to spare.
    You could easily use these registers for locals.
    For re-entrant code you have to store the previous values on
    the return stack.
    All other solutions seem obsolete.
    Well... If you have a word using a local, and you call just any
    other word, how would you transparently make sure that after
    that call your register has not been changed? The "other" word
    might use locals too, and call many words that do the same.
    That is not recursion, that is normal use.

    The only way I can see that work is with a real Forth compiler.

    From MSVC:
    "The __fastcall convention uses registers for the first four arguments,
    and the stack frame to pass more arguments."
    AFAIU called words that use only up to four arguments run pretty fast.
    Of course if they call other functions they have to save those registers.

    This scheme should also be feasible with a Forth compiler. Forth primitives >wouldn't even call other words.

    You can have an el-cheapo solution. Only allow locals within words,
    that doesn't call words that call locals itself.
    One step further, if you want to call a word with locals, save you
    locals on the return stack.
    It is so easy, I'm even tempted to do that.
    Groetjes Albert
    --
    Don't praise the day before the evening. One swallow doesn't make spring.
    You must not say "hey" before you have crossed the bridge. Don't sell the
    hide of the bear until you shot it. Better one bird in the hand than ten in
    the air. First gain is a cat spinning. - the Wise from Antrim -

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From minforth@21:1/5 to none albert on Mon May 15 04:14:42 2023
    none albert schrieb am Montag, 15. Mai 2023 um 12:23:26 UTC+2:
    In article <dc8f44f6-293f-40e9...@googlegroups.com>,
    minforth <minf...@arcor.de> wrote:
    Marcel Hendrix schrieb am Freitag, 12. Mai 2023 um 20:50:49 UTC+2:
    On Friday, May 12, 2023 at 1:02:48 PM UTC+2, none albert wrote:
    [..]
    In view of RISCV you have easily 8 registers to spare.
    You could easily use these registers for locals.
    For re-entrant code you have to store the previous values on
    the return stack.
    All other solutions seem obsolete.
    Well... If you have a word using a local, and you call just any
    other word, how would you transparently make sure that after
    that call your register has not been changed? The "other" word
    might use locals too, and call many words that do the same.
    That is not recursion, that is normal use.

    The only way I can see that work is with a real Forth compiler.

    From MSVC:
    "The __fastcall convention uses registers for the first four arguments, >and the stack frame to pass more arguments."
    AFAIU called words that use only up to four arguments run pretty fast.
    Of course if they call other functions they have to save those registers.

    This scheme should also be feasible with a Forth compiler. Forth primitives >wouldn't even call other words.
    You can have an el-cheapo solution. Only allow locals within words,
    that doesn't call words that call locals itself.
    One step further, if you want to call a word with locals, save you
    locals on the return stack.
    It is so easy, I'm even tempted to do that.

    Good one. :-) Does it rain again in Holland?

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