• Another example of factoring and locals

    From Anton Ertl@21:1/5 to All on Wed Oct 26 20:51:53 2022
    Today I rewrote SEE-CODE (actually it's factor SEE-CODE-RANGE) to
    display, e.g.

    this instead of this
    ... ...
    $7F7E43202948 r> 1->1 $7F7E43202948 r> 1->1
    7F7E42ECADE4: mov [r15],r8 $7F7E43202950 fill
    7F7E42ECADE7: sub r15,$08 7F7E42ECADE4: mov [r15],r8 7F7E42ECADEB: mov r8,[rbx] 7F7E42ECADE7: sub r15,$08 7F7E42ECADEE: add r13,$08 7F7E42ECADEB: mov r8,[rbx] 7F7E42ECADF2: add rbx,$08 7F7E42ECADEE: add r13,$08 7F7E42ECADF6: mov rcx,-$08[r13] 7F7E42ECADF2: add rbx,$08 7F7E42ECADFA: jmp ecx 7F7E42ECADF6: mov rcx,-$08[r13] 7F7E42ECADFC: nop 7F7E42ECADFA: jmp ecx $7F7E43202950 fill 7F7E42ECADFC: nop
    $7F7E43202958 ;s 1->1 $7F7E43202958 ;s 1->1
    ... ...

    I had to get some additional information from the decompiler
    primitive, so we now have

    decompile-prim2 ( a_code -- useqlen ustart uend c_addr u ulen )

    instead of

    decompile-prim ( a_code -- ustart uend c_addr u ulen )

    but the existing factoring also was not very amenable to the change,
    so I rewrote SEE-CODE-RANGE from scratch, with the following result:

    : see-code-range { addr1 addr2 -- } \ gforth
    addr1 0 0 0 ['] noop case { addr nseqlen d: codeblock xt: cr? }
    addr addr2 u>= ?of endof
    addr @ decompile-prim2 { ulen } ulen 0< ?of
    drop 2drop 2drop
    cr? addr simple-see-word
    addr cell+ nseqlen codeblock ['] cr contof
    nseqlen 0= if codeblock discode 0 0 to codeblock ['] noop to cr? then
    cr? addr see-word.addr type { nseqlen1 ustart uend } ulen if
    ustart 4 spaces 0 .r ." ->" uend .
    assert( codeblock nip 0= )
    addr @ ulen to codeblock then
    addr cell+ nseqlen nseqlen1 max 1- codeblock ['] cr
    next-case
    codeblock discode ;

    As you can see, it uses locals heavily (the word I have written with
    the most locals by far). If you want to follow what's going on on the
    stack, it uses the following additional words:

    simple-see-word ( addr -- )
    discode ( c-addr u -- )
    see-word.addr ( addr -- )

    This code took me a while to write, but apart from the handling of the
    CRs, it worked on the first try. The handling of the CRs is
    complicated, because DISCODE outputs a CR at the start and at the end
    (one might consider this a factoring mistake); we could get rid of
    everything to do with CR? if DISCODE did not have this property. I
    find that the flexible enhanced CASE control structure is a very
    natural way for me to consider the different cases and to keep track
    of what has been covered already.

    For comparison, below you find the old code; it uses fewer locals, and
    is factored into three words, but is it better (apart from the
    functionality difference)? IMO no.

    \ also uses decompile-prim ( addr1 -- addr2 )

    : see-code-word { addr -- len }
    addr see-word.addr addr @ decompile-prim1 dup >r -1 = if
    2drop 2drop addr cell+ addr @ .word drop
    else
    type 4 spaces swap r@ if
    0 .r ." ->" .
    else
    2drop then
    then
    r> ;

    : see-code-next-inline { addr1 addr2 -- addr3 }
    \ decompile starting at addr1 until an inlined primitive is found,
    \ or addr2 is reached; addr3 is addr2 or the next inlined
    \ primitive
    addr1 begin { addr }
    addr addr2 u< while
    addr @ dup decompile-prim = while
    addr cr simple-see-word
    addr cell+
    repeat then
    addr ;

    : see-code-range { addr1 addr2 -- } \ gforth
    cr addr1 begin { a }
    a see-code-word { restlen }
    a cell+ addr2 see-code-next-inline { b }
    a @ b addr2 u< while
    ( a @ ) b @ over - discode
    b
    repeat
    \ now disassemble the remaining a @; we derive the length from
    \ it's primitive
    restlen discode ;
    \ dup decompile-prim dup next-prim swap - discode ;

    - 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 dxforth@21:1/5 to Anton Ertl on Thu Oct 27 14:38:37 2022
    On 27/10/2022 7:51 am, Anton Ertl wrote:

    For comparison, below you find the old code; it uses fewer locals, and
    is factored into three words, but is it better (apart from the
    functionality difference)? IMO no.

    If factoring simplifies code and removes the need for strange Case words,
    IMO that's a good thing.

    : foo ( addr1 addr2 -- )
    >r 0 swap 0 0 ['] noop begin { nseqlen addr d: codeblock xt: cr? }
    addr r@ u>= not while
    addr @ decompile-prim2 { ulen } ulen 0< if
    drop 2drop 2drop
    cr? addr simple-see-word
    nseqlen
    else
    nseqlen 0= if codeblock discode 0 0 to codeblock ['] noop to cr? then
    cr? addr see-word.addr type { nseqlen1 ustart uend } ulen if
    ustart 4 spaces 0 .r ." ->" uend .
    assert( codeblock nip 0= )
    addr @ ulen to codeblock then
    nseqlen nseqlen1 max 1-
    then
    addr cell+ codeblock ['] cr
    repeat r> drop ;

    : see-code-range ( addr1 addr2 -- ) \ gforth
    foo codeblock discode ;

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Anton Ertl@21:1/5 to dxforth on Thu Oct 27 10:32:14 2022
    dxforth <dxforth@gmail.com> writes:
    On 27/10/2022 7:51 am, Anton Ertl wrote:
    If factoring simplifies code and removes the need for strange Case words,
    IMO that's a good thing.

    : foo ( addr1 addr2 -- )
    >r 0 swap 0 0 ['] noop begin { nseqlen addr d: codeblock xt: cr? }
    addr r@ u>= not while
    addr @ decompile-prim2 { ulen } ulen 0< if
    drop 2drop 2drop
    cr? addr simple-see-word
    nseqlen
    else
    nseqlen 0= if codeblock discode 0 0 to codeblock ['] noop to cr? then
    cr? addr see-word.addr type { nseqlen1 ustart uend } ulen if
    ustart 4 spaces 0 .r ." ->" uend .
    assert( codeblock nip 0= )
    addr @ ulen to codeblock then
    nseqlen nseqlen1 max 1-
    then
    addr cell+ codeblock ['] cr
    repeat r> drop ;

    : see-code-range ( addr1 addr2 -- ) \ gforth
    foo codeblock discode ;

    Yes, once one has a working version, one can reorganize it, and in
    this case it's relatively straightforward to replace the
    CASE...NEXT-CASE with a BEGIN ... REPEAT through the introduction of
    an ELSE. But it's helpful to have the additional possibilities while
    creating the code, and then one can switch to the more traditional
    control structures if desired.

    The splitting into two words does not work that way, because CODEBLOCK
    is a local. It's also unnecessary, because you can just append
    "CODEBLOCK DISCODE" to FOO. And the name you chose for FOO also shows
    that FOO is not a useful factor for use by other words.

    Concerning the partial replacement of locals by keeping the values on
    the return stack or data stack, that also can be done more easily in a
    second step. But given that we use locals here anyway, I don't find
    the result in any way preferable.

    If performance was an issue (it is not for this word), on some systems
    that might be a reason to use more data stack (not so sure about
    return stack) items rather than locals; one data stack item (as used
    above) is helpful on most systems, because they keep one data stack
    item in a register across basic block boundaries; it's less clearcut
    for return stack items or more data stack items.

    - 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 dxforth@21:1/5 to Anton Ertl on Thu Oct 27 23:19:50 2022
    On 27/10/2022 9:32 pm, Anton Ertl wrote:

    Concerning the partial replacement of locals by keeping the values on
    the return stack or data stack, that also can be done more easily in a
    second step. But given that we use locals here anyway, I don't find
    the result in any way preferable.

    There it is. I don't find locals preferable in any way. It pushes
    me to find whether there's another, potentially better, solution.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Hans Bezemer@21:1/5 to dxforth on Thu Oct 27 09:11:07 2022
    On Thursday, October 27, 2022 at 2:19:53 PM UTC+2, dxforth wrote:
    On 27/10/2022 9:32 pm, Anton Ertl wrote:
    There it is. I don't find locals preferable in any way. It pushes
    me to find whether there's another, potentially better, solution.
    Hear, hear. I also don't like long definitions. They're a horror to maintain. Short words make the logic comprehensible - at every level. Both the lower level words as well as the higher level words.

    Hans Bezemer

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Anton Ertl@21:1/5 to Hans Bezemer on Thu Oct 27 16:24:41 2022
    Hans Bezemer <the.beez.speaks@gmail.com> writes:
    I also don't like long definitions. They're a horror to maintain.
    Short words make the logic comprehensible - at every level. Both the lower >level words as well as the higher level words.

    I am awaiting you posting code for this problem to support your
    claims.

    - 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 dxforth@21:1/5 to Anton Ertl on Fri Oct 28 19:11:01 2022
    On 28/10/2022 3:24 am, Anton Ertl wrote:
    Hans Bezemer <the.beez.speaks@gmail.com> writes:
    I also don't like long definitions. They're a horror to maintain.
    Short words make the logic comprehensible - at every level. Both the lower >> level words as well as the higher level words.

    I am awaiting you posting code for this problem to support your
    claims.

    It's not enough he doesn't use locals in his own code - he should do
    your coding as well? :)

    The appeal of locals in forth is the idea that somehow they're free.
    Try this test. Replace the locals in your code with regular variables/
    values. Now ask yourself whether you still think it's good code; for
    it should make no difference to 'good code' where the variables are
    located. If one isn't happy with variables external to forth words,
    one shouldn't be happy with those internal to them.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Paul Rubin@21:1/5 to dxforth on Fri Oct 28 01:33:28 2022
    dxforth <dxforth@gmail.com> writes:
    If one isn't happy with variables external to forth words, one
    shouldn't be happy with those internal to them.

    1. The externals make the code harder to understand / maintain since they persist across function calls and can be shared between functions. You can
    use some naming conventions to indicate that this isn't happening, but
    ugh. And you still have to re-initialize the global inside the function
    on every call.

    2. If the function is recursive you can't use global variables. You have to set up a separate stack for them or something. Ugh.

    3. The globals keep occupying storage even when the function is not running.
    I thought Forthers liked stack allocation so that the memory would keep
    getting re-used. Locals give that.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Hans Bezemer@21:1/5 to Paul Rubin on Fri Oct 28 09:12:10 2022
    On Friday, October 28, 2022 at 10:33:30 AM UTC+2, Paul Rubin wrote:
    1. The externals make the code harder to understand / maintain since they persist across function calls and can be shared between functions. You can use some naming conventions to indicate that this isn't happening, but
    ugh. And you still have to re-initialize the global inside the function
    on every call.

    2. If the function is recursive you can't use global variables. You have to set up a separate stack for them or something. Ugh.

    3. The globals keep occupying storage even when the function is not running. I thought Forthers liked stack allocation so that the memory would keep getting re-used. Locals give that.

    I hope you and C become very happy. Oh dear, no! You can blow up your program if you're incapable of balancing your malloc() - free() calls. It's much the same way
    like stack balancing, you know. I hope you and Rust become very happy.

    Hans Bezemer

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From minforth@arcor.de@21:1/5 to Paul Rubin on Fri Oct 28 08:36:27 2022
    Paul Rubin schrieb am Freitag, 28. Oktober 2022 um 10:33:30 UTC+2:
    dxforth <dxf...@gmail.com> writes:
    If one isn't happy with variables external to forth words, one
    shouldn't be happy with those internal to them.
    1. The externals make the code harder to understand / maintain since they persist across function calls and can be shared between functions. You can use some naming conventions to indicate that this isn't happening, but
    ugh. And you still have to re-initialize the global inside the function
    on every call.

    2. If the function is recursive you can't use global variables. You have to set up a separate stack for them or something. Ugh.

    3. The globals keep occupying storage even when the function is not running. I thought Forthers liked stack allocation so that the memory would keep getting re-used. Locals give that.

    +1 Technical aspects and personal tastes put aside, IMO the most important benefits of using locals is instantaneous readability of code.

    The human brain is no stack machine. We think in associations IOW by tagging names to material and non-material things and concepts.

    Forth is a strange animal: by factoring we try to chop long algorithms into smallest
    pieces and then try to give them meaningful names to make the code understandable.
    Within those pieces we allow masochistic stack juggling and some guys even claim
    to be happy.

    But sometimes factorization does not come easily, see Anton's example. It is good that we have the choice to use locals where they are appropriate.

    For quick testing and prototyping I sometimes even use extended locals, in their form:
    : TEST { a b .. | d e .. == f g .. } .. ;
    with
    a b .. standard initialized locals
    d e .. standard uninitialized locals
    == instead of standard --
    f g output locals, non-standard
    All locals can be integers, doubles, floats, complex numbers (plus arrays and structs)

    So in principle FROT could be defined as
    : FROT { f: a b c == b c a } ; \ no code required
    with complex numbers:
    : ZROT { z: a b c == b c a } ; \ no code required

    While this example is close to triviality (the locals compiler is not) real-world code
    with extended locals and good short locals names is VERY readable, and mostly bug
    free from start.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Hans Bezemer@21:1/5 to dxforth on Fri Oct 28 09:14:18 2022
    On Friday, October 28, 2022 at 10:11:08 AM UTC+2, dxforth wrote:
    On 28/10/2022 3:24 am, Anton Ertl wrote:
    Hans Bezemer <the.bee...@gmail.com> writes:
    I also don't like long definitions. They're a horror to maintain.
    Short words make the logic comprehensible - at every level. Both the lower >> level words as well as the higher level words.

    I am awaiting you posting code for this problem to support your
    claims.
    It's not enough he doesn't use locals in his own code - he should do
    your coding as well? :)

    ROFL! We're slowly becoming soulmates I think. I was contemplating my
    answer along the same line of thought - before I read your post. ;-)

    Hans Bezemer

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Hans Bezemer@21:1/5 to minf...@arcor.de on Fri Oct 28 09:28:43 2022
    On Friday, October 28, 2022 at 5:36:28 PM UTC+2, minf...@arcor.de wrote:
    Paul Rubin schrieb am Freitag, 28. Oktober 2022 um 10:33:30 UTC+2:
    dxforth <dxf...@gmail.com> writes:
    If one isn't happy with variables external to forth words, one
    shouldn't be happy with those internal to them.
    1. The externals make the code harder to understand / maintain since they persist across function calls and can be shared between functions. You can use some naming conventions to indicate that this isn't happening, but
    ugh. And you still have to re-initialize the global inside the function
    on every call.
    If you need a carload of variables, you've forgotten (or completely disregarded)
    the first rule of "Thinking Forth", which is "STAMP OUT THE VARIABLES"!

    2. If the function is recursive you can't use global variables. You have to set up a separate stack for them or something. Ugh.
    See rule number one.

    3. The globals keep occupying storage even when the function is not running.
    I thought Forthers liked stack allocation so that the memory would keep getting re-used. Locals give that.
    So does C. It also introduces the penalty of stack frame creation and destruction.

    +1 Technical aspects and personal tastes put aside, IMO the most important benefits of using locals is instantaneous readability of code.
    If you need locals for that, you're not doing it correctly. Short definitions allow for
    readability - not locals.

    The human brain is no stack machine. We think in associations IOW by tagging names to material and non-material things and concepts.
    We were spoiled by Fortran, which allowed us to translate mathematical formulas almost directly to working code. Blame mathematics for that notation.

    Forth is a strange animal: by factoring we try to chop long algorithms into smallest
    pieces and then try to give them meaningful names to make the code understandable.
    Within those pieces we allow masochistic stack juggling and some guys even claim
    to be happy.
    If there is excessive stack juggling, it might be because you're (a) a totally incompetent
    Forth programmer, (b) a lazy Forth programmer, who feels good translating C code
    directly to Forth without studying the algorithm and (c) in some circumstances it's
    not worth, needed or even desired to reduce the amount of stack juggling. My rule of
    the thumb is - if I can't understand it I rewrite it.

    But sometimes factorization does not come easily, see Anton's example. It is good that we have the choice to use locals where they are appropriate.
    Nobody says it is or should be easy! It requires thought and some tinkering. If you just want to churn out code quickly, you should do Forth - but Python! However,
    often library code is the hardest to get right IMHO. Application code - not so much.
    I was able to create a 64K Forth source in 5 days. In a professional setting. It never
    missed a beat in its entire lifetime - despite the excessive diagnostic code.

    Hans Bezemer

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Paul Rubin@21:1/5 to minf...@arcor.de on Fri Oct 28 19:28:59 2022
    "minf...@arcor.de" <minforth@arcor.de> writes:
    For quick testing and prototyping I sometimes even use extended
    locals, in their form:
    : TEST { a b .. | d e .. == f g .. } .. ;

    That is cool, what Forth implements that? I haven't seen it before.
    Just ending the word with "f g" seems like enough though:

    : swap { a b } b a ;

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Paul Rubin@21:1/5 to Hans Bezemer on Fri Oct 28 19:25:08 2022
    Hans Bezemer <the.beez.speaks@gmail.com> writes:
    I thought Forthers liked stack allocation so that the memory would keep
    getting re-used. Locals give that.
    So does C. It also introduces the penalty of stack frame creation and destruction.

    If you mean the frame pointer, you don't really need that, it just makes debugging easier. You can pass -ffomit-frame-pointer to gcc to omit it.

    But sometimes factorization does not come easily, see Anton's
    example. It is good that we have the choice to use locals where they
    are appropriate.

    Nobody says it is or should be easy! It requires thought and some
    tinkering. If you just want to churn out code quickly, you should do
    Forth - but Python!

    Is there some benefit gained from that thought and tinkering and loss of productivity? Does it make the code faster, more reliable, or anything
    like that? Otherwise it sounds like masochism or some misplaced
    ideological extremism, like "the stack operators cannot fail--they can
    only be failed".

    Here is the simplest way I can see to multiply of two complex numbers
    (x=a+bi, y=c+di, z=x*y):

    : z* { F: a F: b F: c F: d -- F: ac-bd F: ad+bc }
    a c f* b d f* f- a d f* b c f* f+ ;

    That example could use FVARIABLEs instead of locals but it would be a
    lot messier imho. There are no FVALUEs in standard Forth iirc, so you
    have to use @ everywhere, and then your auditing process has to make
    sure nothing else uses those variables, including by having anything
    aliased to the pointers in the variables, and so on. There is no
    equivalent of the return stack to stash intermediate FP values, so stack juggling becomes harder. Maybe it is still possible, but who wants to
    spend the debugging effort? I can't believe it helps readability.

    I have another example that uses FP locals and is recursive, so moving
    them to FVARIABLEs isn't even workable. I don't see a general approach
    other than an auxiliary FP stack implement in user code. Ugh.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From dxforth@21:1/5 to Paul Rubin on Sat Oct 29 14:16:03 2022
    On 28/10/2022 7:33 pm, Paul Rubin wrote:
    dxforth <dxforth@gmail.com> writes:
    If one isn't happy with variables external to forth words, one
    shouldn't be happy with those internal to them.

    1. The externals make the code harder to understand / maintain since they persist across function calls and can be shared between functions. You can use some naming conventions to indicate that this isn't happening, but
    ugh. And you still have to re-initialize the global inside the function
    on every call.

    2. If the function is recursive you can't use global variables. You have to set up a separate stack for them or something. Ugh.

    3. The globals keep occupying storage even when the function is not running. I thought Forthers liked stack allocation so that the memory would keep getting re-used. Locals give that.

    Oh, I'm not advocating variables - locals or otherwise. What I see is a lot
    of promiscuous use of the former as if there were no cost. Here's an example of using extra locals - not out of necessity - but 'style':

    https://gforth.org/manual/Locals-programming-style.html

    In C, locals are unavoidable - it's not a matter of style or choice. In Forth, locals are all about style. The more the better so we're told. Unfortunately Forth was never designed for it. Compared to data stack, the return stack is the smaller - intended only to hold return addresses and the occasional temp. Nested definitions using locals will quickly eat it up. You decide whether style is worth the cost.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From dxforth@21:1/5 to Paul Rubin on Sat Oct 29 16:04:14 2022
    On 29/10/2022 1:25 pm, Paul Rubin wrote:
    ...
    Here is the simplest way I can see to multiply of two complex numbers (x=a+bi, y=c+di, z=x*y):

    : z* { F: a F: b F: c F: d -- F: ac-bd F: ad+bc }
    a c f* b d f* f- a d f* b c f* f+ ;

    That example could use FVARIABLEs instead of locals but it would be a
    lot messier imho. There are no FVALUEs in standard Forth iirc, so you
    have to use @ everywhere, and then your auditing process has to make
    sure nothing else uses those variables, including by having anything
    aliased to the pointers in the variables, and so on. There is no
    equivalent of the return stack to stash intermediate FP values, so stack juggling becomes harder. Maybe it is still possible, but who wants to
    spend the debugging effort? I can't believe it helps readability.

    How many times will you code Z* ? FWIW FSLIB already has it.

    I have another example that uses FP locals and is recursive, so moving
    them to FVARIABLEs isn't even workable. I don't see a general approach
    other than an auxiliary FP stack implement in user code. Ugh.

    FP locals isn't supported by any standard. Some folks have suggested
    there should be a F>R R>F which would allow recursive f/p variables.
    IIRC Wil Baden had a scheme that used memory at HERE as f/p locals.
    The situations you present as requiring locals are obscure enough that
    there is almost always another way. But you have to want to find it.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From dxforth@21:1/5 to Hans Bezemer on Sat Oct 29 16:20:03 2022
    On 29/10/2022 3:14 am, Hans Bezemer wrote:
    On Friday, October 28, 2022 at 10:11:08 AM UTC+2, dxforth wrote:
    On 28/10/2022 3:24 am, Anton Ertl wrote:
    Hans Bezemer <the.bee...@gmail.com> writes:
    I also don't like long definitions. They're a horror to maintain.
    Short words make the logic comprehensible - at every level. Both the lower >>>> level words as well as the higher level words.

    I am awaiting you posting code for this problem to support your
    claims.
    It's not enough he doesn't use locals in his own code - he should do
    your coding as well? :)

    ROFL! We're slowly becoming soulmates I think. I was contemplating my
    answer along the same line of thought - before I read your post. ;-)

    It's not as if we hadn't been here before and don't know the answers :)

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From minforth@arcor.de@21:1/5 to Paul Rubin on Fri Oct 28 23:46:15 2022
    Paul Rubin schrieb am Samstag, 29. Oktober 2022 um 04:29:03 UTC+2:
    "minf...@arcor.de" <minf...@arcor.de> writes:
    For quick testing and prototyping I sometimes even use extended
    locals, in their form:
    : TEST { a b .. | d e .. == f g .. } .. ;
    That is cool, what Forth implements that? I haven't seen it before.
    Just ending the word with "f g" seems like enough though:

    : swap { a b } b a ;

    This would be a SWAP defined in standard Forth with single braces à la gforth. For such extremely short definitions there is no benefit from output locals.

    But consider complicated algorithms (in my case signal processing math).
    There it helps when the compiler does the stack juggling for you by parsing
    the stack comment COMPLETELY. Standard Forth stops halfway in the process
    by ignoring everything after -- . But sometimes it is a waste of programmer's time
    when he has to keep track of the machine state/stacks instead of concentrating on the algorithm.

    F.ex.
    : DEARCHMEAN { tagname tstart tend f: factor | sum == rec: tagrec f: mval n: flag }
    < algorithm > ;
    extracts the the archived signal 'tagname' between points of time tstart to tend and
    calculates the mean signal value mval using the fp-locals factor and sum. The extracted
    time series record tagrec and and a flag are returned as well. The "living stack comment"
    says it all. Your eyes don't have to scan the following algo code to find out where/when
    final results are put on the stack, moved into the correct order, and intermediate
    calculations are cleared/dropped away. Let the compiler do this for you. The algo's
    code becomes uncluttered, more readable, and shorter.

    Some smart guys think that this smells too much of Python. But they ignore that this is
    still Forth, ultra-compact for embedding, and fast enough in 98% of all cases.

    And there is a second advantage: when the compiler knows the outputs of a word, it
    can raise a warning when it is connected to a word with non-matching input characteristic.
    This compile-time I/O matching can be very helpful, but not always.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Gerry Jackson@21:1/5 to Hans Bezemer on Sat Oct 29 08:41:25 2022
    On 28/10/2022 17:28, Hans Bezemer wrote:
    On Friday, October 28, 2022 at 5:36:28 PM UTC+2,minf...@arcor.de wrote:
    Paul Rubin schrieb am Freitag, 28. Oktober 2022 um 10:33:30 UTC+2:
    dxforth<dxf...@gmail.com> writes:
    If one isn't happy with variables external to forth words, one
    shouldn't be happy with those internal to them.
    1. The externals make the code harder to understand / maintain since they >>> persist across function calls and can be shared between functions. You can >>> use some naming conventions to indicate that this isn't happening, but
    ugh. And you still have to re-initialize the global inside the function
    on every call.
    If you need a carload of variables, you've forgotten (or completely disregarded)
    the first rule of "Thinking Forth", which is "STAMP OUT THE VARIABLES"!


    You don't seem to practice what you preach e.g.

    \ -----------------------------------------------------------
    \ 4tH library - string CONCAT - Copyright 2012 J.L. Bezemer
    \ You can redistribute this file and/or modify it under
    \ the terms of the GNU General Public License

    [UNDEFINED] concat [IF]
    variable __concat \ destination address

    : concat ( a1 n1 .. ai ni i a2 -- a2 n2)
    __concat ! 1- dup \ save destination, setup counter
    begin dup while rot >r rot >r 1- repeat drop >r __concat @ place r>
    begin dup while r> r> __concat @ +place 1- repeat drop __concat @ count
    ; \ first transfer to Rstack, then append
    \ ----------------------------------------------------------

    Seems a bit of a dog's breakfast to me: unnecesssary use of a variable,
    lengthy definition and unnecessary call to PLACE, crashes if i=0,
    incorrect & misleading stack comment. Compare with:

    : concat ( ca1 u1 .. can un n ca -- ca+1 u )
    0 over c! swap
    [: ?dup if 2swap 2>r 1- recurse dup 2r> rot +place then ;]
    execute count
    ;


    --
    Gerry

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Marcel Hendrix@21:1/5 to Gerry Jackson on Sat Oct 29 01:05:40 2022
    On Saturday, October 29, 2022 at 9:41:27 AM UTC+2, Gerry Jackson wrote:
    [..]
    Seems a bit of a dog's breakfast to me: unnecesssary use of a variable, lengthy definition and unnecessary call to PLACE, crashes if i=0,
    incorrect & misleading stack comment. Compare with:

    : concat ( ca1 u1 .. can un n ca -- ca+1 u )
    0 over c! swap
    [: ?dup if 2swap 2>r 1- recurse dup 2r> rot +place then ;]
    execute count
    ;

    FORTH> : concats ( ca1 u1 .. can un n -- ca u ) 1- 0 max 0 ?DO $+ LOOP ; FORTH> S" Hello" S" , " S" world" S" !" 4 concats
    [2]FORTH> type Hello, world! ok

    -marcel

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Hans Bezemer@21:1/5 to Gerry Jackson on Sat Oct 29 06:14:53 2022
    On Saturday, October 29, 2022 at 9:41:27 AM UTC+2, Gerry Jackson wrote:
    incorrect & misleading stack comment.
    I now see where your comment about "misleading stack comment" comes
    from. In 4tH ASCIIZ strings are used - and a2 is actually the address that is returned.

    That your code works is because the first line effectively terminates
    the target string - and the abstraction of +PLACE does the heavy lifting.

    But I forgive you ;-)

    Hans Bezemer

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Hans Bezemer@21:1/5 to Gerry Jackson on Sat Oct 29 05:45:50 2022
    On Saturday, October 29, 2022 at 9:41:27 AM UTC+2, Gerry Jackson wrote:
    If you need a carload of variables, you've forgotten (or completely disregarded)
    the first rule of "Thinking Forth", which is "STAMP OUT THE VARIABLES"!

    You don't seem to practice what you preach e.g.
    Well, the only lesson one could take from it is "there is always someone more clever
    than you" - which IMHO is just a fact of life. You will probably find more examples in
    the 500+ libraries I wrote - if you dig really well.

    However, if this is the only example you found in 75 KLOC of 4tH, I think I'm not doing
    too bad. BTW, it's a clever piece of code. Kudos!

    Hans Bezemer

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Anton Ertl@21:1/5 to Hans Bezemer on Sat Oct 29 13:34:32 2022
    Hans Bezemer <the.beez.speaks@gmail.com> writes:
    On Friday, October 28, 2022 at 10:11:08 AM UTC+2, dxforth wrote:
    On 28/10/2022 3:24 am, Anton Ertl wrote:
    Hans Bezemer <the.bee...@gmail.com> writes:
    I also don't like long definitions. They're a horror to maintain.
    Short words make the logic comprehensible - at every level. Both the lower
    level words as well as the higher level words.

    I am awaiting you posting code for this problem to support your
    claims.
    It's not enough he doesn't use locals in his own code - he should do
    your coding as well? :)

    I did do my own coding. Hans Bezemer just made general claims, so I
    called him to show that there is substance to his words (and it's
    about long definitions, not locals).

    ROFL! We're slowly becoming soulmates I think. I was contemplating my
    answer along the same line of thought - before I read your post. ;-)

    Apparently there is no substance to your words. As for being
    soulmates, dxforth has posted code to demonstrate a part of his
    positions (and his code actually inspired me to transform the control
    structure in the way he suggested).

    - 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 dxforth@21:1/5 to Marcel Hendrix on Sun Oct 30 02:57:39 2022
    On 29/10/2022 7:05 pm, Marcel Hendrix wrote:

    FORTH> : concats ( ca1 u1 .. can un n -- ca u ) 1- 0 max 0 ?DO $+ LOOP ; FORTH> S" Hello" S" , " S" world" S" !" 4 concats
    [2]FORTH> type Hello, world! ok

    : concats <# 0 ?do holds loop 0 0 #> ;

    s" Hello" s" , " s" world" s" !" 4 concats type Hello, world! ok

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Hans Bezemer@21:1/5 to Anton Ertl on Sat Oct 29 11:09:37 2022
    On Saturday, October 29, 2022 at 3:41:08 PM UTC+2, Anton Ertl wrote:
    I did do my own coding.
    What can I say. It shows. LOL!

    Apparently there is no substance to your words. As for being
    soulmates, dxforth has posted code to demonstrate a part of his
    positions (and his code actually inspired me to transform the control structure in the way he suggested).
    C'mon. Do you know how old I am? Do you really expect me to dance to
    your tune? That's how kids challenge each other in kindergarten!

    Hans Bezemer

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Paul Rubin@21:1/5 to dxforth on Sat Oct 29 14:27:41 2022
    dxforth <dxforth@gmail.com> writes:
    How many times will you code Z* ? FWIW FSLIB already has it.

    Z* is a simple example. The issue comes up with some regularity.

    FP locals isn't supported by any standard.

    Hmm, I didn't realize that, I mostly use gforth. It is unfortunate.

    Some folks have suggested there should be a F>R R>F which would allow recursive f/p variables.

    That could help, but might as well support FP locals directly.

    IIRC Wil Baden had a scheme that used memory at HERE as f/p locals.

    That sounds pretty messy. Was it hooked into (LOCAL) somehow? What
    happens if your function ALLOTs something after making the locals? Does
    the space for the locals not get reclaimed?

    The situations you present as requiring locals are obscure enough that
    there is almost always another way. But you have to want to find it.

    The examples I gave were real. I don't claim anything "requires" locals
    in the sense that finding another way is impossible. But finding and implementing another way obviously imposes costs, and I don't currently
    see an offsetting benefit. Before wanting to find the other way, I'd
    first want to know what I'd gain from finding it. If I have a method
    that works, why search for ways to make more pain for myself instead
    of just getting on with it?

    In Forth, locals are all about style... Unfortunately Forth was never designed for it. Compared to data stack, the return stack is the
    smaller - intended only to hold return addresses and the occasional
    temp. Nested definitions using locals will quickly eat it up.

    The return stack being smaller depends on the implementation ofc. Some implementations (gforth) use a separate locals stack. An optimizing
    compiler can in some cases put the locals in registers which is cheaper
    than putting them on any stack. They can also be in the heap, which
    unlike even the data stack, can have non-contiguous locals areas without
    much hassle.

    Admittedly I've been using gforth on machines with gigabytes of memory
    but I don't see a big issue even on small MCU's. Of course you have to maintain some awareness of stack usage from locals, but you have to
    maintain that awareness for everything else too.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From dxforth@21:1/5 to Paul Rubin on Sun Oct 30 12:59:43 2022
    On 30/10/2022 8:27 am, Paul Rubin wrote:
    dxforth <dxforth@gmail.com> writes:
    How many times will you code Z* ? FWIW FSLIB already has it.

    Z* is a simple example. The issue comes up with some regularity.

    FP locals isn't supported by any standard.

    Hmm, I didn't realize that, I mostly use gforth. It is unfortunate.

    Unfortunate has been the mixed messaging. Moore couldn't be more explicit locals had no place in Forth. Still, better one can find that out for
    oneself. Locals in Forth can be likened to chocolate. Irresistible to
    the sweet-toothed.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Paul Rubin@21:1/5 to dxforth on Sat Oct 29 22:37:43 2022
    dxforth <dxforth@gmail.com> writes:
    Unfortunate has been the mixed messaging. Moore couldn't be more explicit locals had no place in Forth.

    Moore, I've heard of that guy. Isn't he the one who invented PICK and
    ROLL because his Forth didn't have locals? Once you've turned the stack
    into an indexible array, you might as well be able to give names to the
    slots.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From dxforth@21:1/5 to Paul Rubin on Sun Oct 30 17:16:21 2022
    On 30/10/2022 4:37 pm, Paul Rubin wrote:
    dxforth <dxforth@gmail.com> writes:
    Unfortunate has been the mixed messaging. Moore couldn't be more explicit >> locals had no place in Forth.

    Moore, I've heard of that guy. Isn't he the one who invented PICK and
    ROLL because his Forth didn't have locals? Once you've turned the stack
    into an indexible array, you might as well be able to give names to the slots.

    It appears he found them superfluous:

    "The words that manipulate that stack are DUP, DROP and OVER period. There's
    no ..., well SWAP is very convenient and you want it, but it isn't a machine
    instruction. But no PICK no ROLL, none of the complex operators to let you
    index down into the stack."

    "It is necessary to have variables."

    http://www.ultratechnology.com/1xforth.htm

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Paul Rubin@21:1/5 to Marcel Hendrix on Sun Oct 30 00:44:14 2022
    Marcel Hendrix <mhx@iae.nl> writes:
    http://www.ultratechnology.com/1xforth.htm
    Somebody should restore these tapes. My hunch is that there will
    be surprising nuance.

    I'm sure I watched that video on youtube years ago. It looks like it
    has been re-uploaded more recently, by Gavino, a surprising and nice contribution.

    https://www.youtube.com/watch?v=pSnNy7IpVMg

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Marcel Hendrix@21:1/5 to dxforth on Sun Oct 30 00:25:48 2022
    On Sunday, October 30, 2022 at 7:16:24 AM UTC+1, dxforth wrote:
    [..]
    "The words that manipulate that stack are DUP, DROP and OVER period. There's no ..., well SWAP is very convenient and you want it, but it isn't a machine instruction. But no PICK no ROLL, none of the complex operators to let you index down into the stack."

    "It is necessary to have variables."

    That is simply describing what 'a machine' has available. The final statement is a logical conclusion.

    http://www.ultratechnology.com/1xforth.htm

    Somebody should restore these tapes. My hunch is that there will
    be surprising nuance.

    -marcel

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From dxforth@21:1/5 to Paul Rubin on Sun Oct 30 20:20:30 2022
    On 30/10/2022 6:44 pm, Paul Rubin wrote:
    Marcel Hendrix <mhx@iae.nl> writes:
    http://www.ultratechnology.com/1xforth.htm
    Somebody should restore these tapes. My hunch is that there will
    be surprising nuance.

    I'm sure I watched that video on youtube years ago. It looks like it
    has been re-uploaded more recently, by Gavino, a surprising and nice contribution.

    https://www.youtube.com/watch?v=pSnNy7IpVMg

    No - the unexpurgated version ...

    https://youtu.be/ZYlOV7K-xOU?t=49

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Marcel Hendrix@21:1/5 to dxforth on Sun Oct 30 03:38:39 2022
    On Sunday, October 30, 2022 at 10:20:33 AM UTC+1, dxforth wrote:
    [..]
    https://youtu.be/ZYlOV7K-xOU?t=49

    I admit it is dead-on with respect to the underlying sentiments
    in this discussion :--)

    -marcel

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From S Jack@21:1/5 to dxforth on Sun Oct 30 05:56:33 2022
    On Sunday, October 30, 2022 at 1:16:24 AM UTC-5, dxforth wrote:

    http://www.ultratechnology.com/1xforth.htm

    ColorForth and Moore's vision are intriguing; however, I'm out of time
    for transforming into a "moti" and beginning new adventure. If I were
    younger, I would eagerly start with ColorForth and begin some endeavor of
    UXN like "Past proofing".
    --
    me

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Hans Bezemer@21:1/5 to Paul Rubin on Sun Oct 30 05:44:29 2022
    On Sunday, October 30, 2022 at 6:37:46 AM UTC+1, Paul Rubin wrote:
    dxforth <dxf...@gmail.com> writes:
    Moore, I've heard of that guy. Isn't he the one who invented PICK and
    ROLL because his Forth didn't have locals? Once you've turned the stack
    into an indexible array, you might as well be able to give names to the slots.
    Well, in his 1993 interview he was quoted to have said: "But no PICK no
    ROLL, none of the complex operators to let you index down into the stack.
    This is the only part of the stack, these first two elements, that you have
    any business worrying about". (http://www.ultratechnology.com/moore4th.htm)

    It's also explicitly listed in "Thinking Forth" - although that one was not written
    by Moore. It's just the penultimate work on Forth philosophy..

    So it must have been another Moore, I guess.. There are so many Moores writing Forth..

    Hans Bezemer

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Hans Bezemer@21:1/5 to Paul Rubin on Sun Oct 30 06:37:15 2022
    On Sunday, October 30, 2022 at 6:37:46 AM UTC+1, Paul Rubin wrote:
    Moore, I've heard of that guy. Isn't he the one who invented PICK and
    ROLL because his Forth didn't have locals? Once you've turned the stack
    into an indexible array, you might as well be able to give names to the slots.

    BTW - PICK and ROLL do not make a stack into an indexable array. Even
    when using dynamic memory (unless you reallocate it by a resize) I can
    be pretty much assured that every time I get an indexed element, it points
    to the very same memory address. However, if I do a "5 PICK", the next time
    I do a "5 PICK" it will get me the contents of a very different address. If I want the same element I have to issue "6 PICK".

    ROLL - on the other hand - shifts the contents. You may get the same address, but completely different content. The ontology of ROLL is more difficult, though
    - I agree. It's more a question of semantics here.

    So, PICK does NOT turn a stack into an "indexable array" - which makes the
    next argument "being able to give names to the slots" completely untenable.

    Hans Bezemer

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Gerry Jackson@21:1/5 to Marcel Hendrix on Sun Oct 30 15:00:09 2022
    On 29/10/2022 09:05, Marcel Hendrix wrote:
    On Saturday, October 29, 2022 at 9:41:27 AM UTC+2, Gerry Jackson wrote:
    [..]
    Seems a bit of a dog's breakfast to me: unnecesssary use of a variable,
    lengthy definition and unnecessary call to PLACE, crashes if i=0,
    incorrect & misleading stack comment. Compare with:

    : concat ( ca1 u1 .. can un n ca -- ca+1 u )
    0 over c! swap
    [: ?dup if 2swap 2>r 1- recurse dup 2r> rot +place then ;]
    execute count
    ;

    FORTH> : concats ( ca1 u1 .. can un n -- ca u ) 1- 0 max 0 ?DO $+ LOOP ; FORTH> S" Hello" S" , " S" world" S" !" 4 concats
    [2]FORTH> type Hello, world! ok


    So your $+ prepends a string to another into some buffer. See DX alternative

    --
    Gerry

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Gerry Jackson@21:1/5 to dxforth on Sun Oct 30 15:09:21 2022
    On 29/10/2022 16:57, dxforth wrote:
    On 29/10/2022 7:05 pm, Marcel Hendrix wrote:

    FORTH> : concats ( ca1 u1 .. can un n -- ca u )  1- 0 max 0 ?DO  $+
    LOOP ;
    FORTH> S" Hello"  S" , "  S" world"  S" !"  4 concats
    [2]FORTH> type Hello, world! ok

    : concats  <# 0 ?do holds loop 0 0 #> ;

    s" Hello"  s" , "  s" world"  s" !"  4 concats type Hello, world! ok


    Yes that's much simpler even with the inelegance of having to provide 2
    cells on the stack for #> to drop.

    Seeing that solution is ironic and humbling. I knew that <# ... #> and
    indeed have posted something about that on c.l.f in the past. I've no explanation about why I didn't think of that in my response to Hans
    Bezemer, I suppose his solution pointed me into using +PLACE and I
    didn't think beyond that.

    --
    Gerry

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Gerry Jackson@21:1/5 to Hans Bezemer on Sun Oct 30 15:30:14 2022
    On 29/10/2022 14:14, Hans Bezemer wrote:
    On Saturday, October 29, 2022 at 9:41:27 AM UTC+2, Gerry Jackson wrote:
    incorrect & misleading stack comment.
    I now see where your comment about "misleading stack comment" comes
    from. In 4tH ASCIIZ strings are used - and a2 is actually the address that is returned.

    Sorry about that, I wasn't aware that 4th used zero terminated strings
    and just assumed that standard counted strings were used. So presumably
    your version of COUNT does it by actually counting the characters.

    That your code works is because the first line effectively terminates
    the target string - and the abstraction of +PLACE does the heavy lifting.


    It's fortuitous that a 0 byte means an empty string for both ways of representing a string.

    But I forgive you ;-)
    Thank you

    --
    Gerry

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From dxforth@21:1/5 to S Jack on Mon Oct 31 10:05:37 2022
    On 30/10/2022 11:56 pm, S Jack wrote:
    On Sunday, October 30, 2022 at 1:16:24 AM UTC-5, dxforth wrote:

    http://www.ultratechnology.com/1xforth.htm

    ColorForth and Moore's vision are intriguing; however, I'm out of time
    for transforming into a "moti" and beginning new adventure. If I were younger, I would eagerly start with ColorForth and begin some endeavor of
    UXN like "Past proofing".

    Chasing visions is likely to bring one back to where one started.

    https://en.wikisource.org/wiki/Time_and_the_Gods#The_Sorrow_of_Search

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From dxforth@21:1/5 to Gerry Jackson on Mon Oct 31 10:55:12 2022
    On 31/10/2022 2:09 am, Gerry Jackson wrote:
    On 29/10/2022 16:57, dxforth wrote:
    On 29/10/2022 7:05 pm, Marcel Hendrix wrote:

    FORTH> : concats ( ca1 u1 .. can un n -- ca u )  1- 0 max 0 ?DO  $+ LOOP ;
    FORTH> S" Hello"  S" , "  S" world"  S" !"  4 concats
    [2]FORTH> type Hello, world! ok

    : concats  <# 0 ?do holds loop 0 0 #> ;

    s" Hello"  s" , "  s" world"  s" !"  4 concats type Hello, world! ok


    Yes that's much simpler even with the inelegance of having to provide 2 cells on the stack for #> to drop.

    Seeing that solution is ironic and humbling. I knew that <# ... #> and indeed have posted something about that on c.l.f in the past. I've no explanation about why I didn't think of that in my response to Hans Bezemer, I suppose his solution pointed me
    into using +PLACE and I didn't think beyond that.

    I had considered an iterative solution similar to the original:

    \ +string ( a1 u1 a2 u2 -- a2 u3 )

    : concat ( a1 u1 ... an un n dest -- dest len )
    0 0 begin 2>r over while swap 1- swap 2swap repeat
    swap begin 2r> over while 2swap +string repeat 2drop ;

    Not sure the problem is particularly real. Akin to painting oneself into
    a corner then having to find a way out. There has to be a better way...

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Paul Rubin@21:1/5 to dxforth on Sun Oct 30 16:48:55 2022
    dxforth <dxforth@gmail.com> writes:
    It appears he [Moore] found them superfluous:
    "The words that manipulate that stack are DUP, DROP and OVER
    period. There's no ..., well SWAP is very convenient and you want it,
    but it isn't a machine instruction. But no PICK no ROLL, none of the
    complex operators to let you index down into the stack."

    PICK and ROLL have to have come from somewhere: if it wasn't Moore, then
    who? And what about ROT, -ROT, >R, and R>?

    I get that Moore used VARIABLEs for everything that I'd use locals for.
    He also used CODE when Forth got in the way too much.

    Back in the 1970s, computers were limited, programs were necessarily
    small, and Moore espoused rewriting programs from the ground up instead
    of maintaining them. The main problem facing programmers was how to
    make their program implement behaviour X, for whatever X happened to be
    that day. They'd put a lot of effort into coding and testing X, and
    then they were done.

    Today, the main problem facing programmers is ensuring the absence of behaviours rather than their presence. Writing code is way easier than
    it used to be, because tools are better and computers are faster. But maintaining is harder since programs are bigger and have more people
    hacking at them. If you use a VARIABLE to save a temporary value used
    by a word, then anyone modifying that word, when they see that variable,
    now has to check that no other word uses the variable and depends on it
    for communication. Or worse, communicates through the memory cell
    occupied by that variable but through some sneaky alias. VALUE avoids
    aliasing (no idea whether Moore used them), but locals make both issues
    go away.

    Finally, while I can't doubt Moore's genius, I've never understood the
    vision that says the pure stack VM fits every programming problem.
    Register allocation and spilling is one of the messier parts of
    traditional compilers even when there are plenty of registers that don't
    have weird special purposes. In Forth, there are only 3 or so
    "registers" (T, N, and R), and each is special. Why be so vehement that
    a human rather than a machine should be juggling them? I can understand
    taht locals (if supported) complicate the traditional threaded Forth interpreter, but I don't know how much Moore valued that. I know he did
    like stack hardware (his many Forth chips) but that came later.

    So the pure "stack plus VARIABLEs" seems "not even wrong" to me. I
    don't understand the motivation behind it well enough to disagree per
    se. And I've never seen an explanation that made sense. They have all
    seemed like grasping at straws.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From dxforth@21:1/5 to Paul Rubin on Mon Oct 31 12:27:49 2022
    On 31/10/2022 10:48 am, Paul Rubin wrote:
    dxforth <dxforth@gmail.com> writes:
    It appears he [Moore] found them superfluous:
    "The words that manipulate that stack are DUP, DROP and OVER
    period. There's no ..., well SWAP is very convenient and you want it,
    but it isn't a machine instruction. But no PICK no ROLL, none of the
    complex operators to let you index down into the stack."

    PICK and ROLL have to have come from somewhere: if it wasn't Moore, then
    who? And what about ROT, -ROT, >R, and R>?

    I get that Moore used VARIABLEs for everything that I'd use locals for.

    You use locals because it's easier and more-or-less idiot-proof. Moore
    claims it leads to inefficiency. Can't speak for his use but if I have
    to use a variable as a temp, I do so sparingly - unlike locals which are largely about 'readability' and therefore quantity.

    He also used CODE when Forth got in the way too much.

    Don't know but when it comes to apps there's has to be a good enough
    reason before I'll use CODE.

    Today, the main problem facing programmers is ensuring the absence of behaviours rather than their presence. Writing code is way easier than
    it used to be, because tools are better and computers are faster. But maintaining is harder since programs are bigger and have more people
    hacking at them. If you use a VARIABLE to save a temporary value used
    by a word, then anyone modifying that word, when they see that variable,
    now has to check that no other word uses the variable and depends on it
    for communication. Or worse, communicates through the memory cell
    occupied by that variable but through some sneaky alias. VALUE avoids aliasing (no idea whether Moore used them), but locals make both issues
    go away.

    I think you overstate such use of variables, but how are they a problem
    when defined local to the routine which uses it?


    Finally, while I can't doubt Moore's genius, I've never understood the
    vision that says the pure stack VM fits every programming problem.

    Saving the world is tough - even for the newer programming systems you
    talk about. For me, it's enough that I've been able to create a tool
    I'm both comfortable using and is challenging at the same time.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Paul Rubin@21:1/5 to dxforth on Sun Oct 30 19:04:49 2022
    dxforth <dxforth@gmail.com> writes:
    You use locals because it's easier and more-or-less idiot-proof. Moore claims it leads to inefficiency.

    Yes, idiot proofing is always a good goal when programming ;). The inefficiency depends on the implementation, I'd expect. It may also be
    that code execution profiles have changed since Moore's heyday. DJB
    made that claim in an article called "Demise Of The Optimizing Compiler"
    or some such. Basically the execution time of programs nowadays is concentrated almost entirely in a few hot spots. Those spots may have
    to be tuned for efficiency, but the rest of the program's efficiency
    almost doesn't matter. It was different in the 1970s, where efficiency mattered everywhere in the program.

    if I have to use a variable as a temp, I do so sparingly - unlike
    locals which are largely about 'readability' and therefore quantity.

    Not sure what you mean about quantity, but I look at the gforth manual's
    locals version of MAX compared with a traditional one (both untested):

    : max1 ( a b -- max ) 2dup > if drop else nip then ;
    : max2 { a b -- max } a b > if a else b then ;

    the locals version has less source code and (if compiled) maybe less
    object code as well.

    Similarly you recently posted elsewhere (158 source chars):

    : concat ( a1 u1 ... an un n dest -- dest len )
    0 0 begin 2>r over while swap 1- swap 2swap repeat
    swap begin 2r> over while 2swap +string repeat 2drop ;

    A locals version (untested) is 165 chars mostly due to extra whitespace
    that could be squished out:

    : concat2 ( a1 u1 ... an un n dest -- dest len )
    { n dest } 0 { len }
    n 0 ?do
    { a u } a u dest len +string
    u len + to len
    loop
    dest len ;

    I can't begin to understand the stack juggling version so can't be sure
    the two do the same thing. I also don't see how to implement 2SWAP with
    just DUP, DROP, OVER. I guess it could be done with variables.

    I think you overstate such use of variables, but how are they a problem
    when defined local to the routine which uses it?

    How do you do that? Variables are always globals, I thought. Another
    issue with them that I forgot to mention is non-reentrancy. Like if you implement 2SWAP with variables and an interrupt handler uses it while
    another call to 2SWAP is in progress, you get a Heisenbug. Oops.

    Saving the world is tough - even for the newer programming systems you
    talk about. For me, it's enough that I've been able to create a tool
    I'm both comfortable using and is challenging at the same time.

    I like my tools to be comfortable and powerful. Challenge should come
    from using them on bigger and tougher problems, not from making even
    easy problems a pain to solve.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Doug Hoffman@21:1/5 to Paul Rubin on Sun Oct 30 19:44:01 2022
    On Sunday, October 30, 2022 at 10:05:16 PM UTC-4, Paul Rubin wrote:

    I also don't see how to implement 2SWAP with
    just DUP, DROP, OVER.

    Use the return stack as a "local variable holder"
    and use ROT and SWAP.

    : 2swap ( x1 x2 x3 x4 -- x3 x4 x1 x2 )
    >r rot rot r> swap rot swap ;

    Truthfully, I don't see much difference between conventional locals
    and using the return stack for same. With the latter you don't get names
    though it is likely more efficient. But IMO is just as "impure" as locals. Locals are much easier to use/debug/maintain-changes. If you are
    not resource limited and the locals version is fast enough then I
    leave it at that.

    -Doug

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Paul Rubin@21:1/5 to Doug Hoffman on Sun Oct 30 19:54:27 2022
    Doug Hoffman <dhoffman888@gmail.com> writes:
    I also don't see how to implement 2SWAP with just DUP, DROP, OVER.
    Use the return stack as a "local variable holder"
    and use ROT and SWAP.

    I'm doing by the quote from Chuck Moore about DUP, DROP, and OVER (and
    maybe SWAP) being the only legit stack primitives, so no ROT. He does
    use the return stack in his own code though.

    Truthfully, I don't see much difference between conventional locals
    and using the return stack for same.

    There is no RPICK in standard Forth, so you can't get at the internal
    slots. Moore even frowns on regular PICK. Also, you have to be able to
    pop the locals if the word exits through an exception. (LOCAL) had to
    be added to the standard to allow that, since the VM has to handle the unwinding in that situation.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From dxforth@21:1/5 to Paul Rubin on Mon Oct 31 14:18:07 2022
    On 31/10/2022 1:04 pm, Paul Rubin wrote:
    dxforth <dxforth@gmail.com> writes:

    if I have to use a variable as a temp, I do so sparingly - unlike
    locals which are largely about 'readability' and therefore quantity.

    Not sure what you mean about quantity, but I look at the gforth manual's locals version of MAX compared with a traditional one (both untested):

    : max1 ( a b -- max ) 2dup > if drop else nip then ;
    : max2 { a b -- max } a b > if a else b then ;

    the locals version has less source code and (if compiled) maybe less
    object code as well.

    I'd have written:

    : max1 ( a b -- max ) 2dup < if swap then drop ;

    Compare them under VFX and see what you get.

    Similarly you recently posted elsewhere (158 source chars):

    : concat ( a1 u1 ... an un n dest -- dest len )
    0 0 begin 2>r over while swap 1- swap 2swap repeat
    swap begin 2r> over while 2swap +string repeat 2drop ;

    A locals version (untested) is 165 chars mostly due to extra whitespace
    that could be squished out:

    : concat2 ( a1 u1 ... an un n dest -- dest len )
    { n dest } 0 { len }
    n 0 ?do
    { a u } a u dest len +string
    u len + to len
    loop
    dest len ;

    I can't begin to understand the stack juggling version so can't be sure
    the two do the same thing.

    Ditto for me for the locals version. Perhaps it's a matter of what one
    is used to? If one's goal is to jump between languages using more or
    less the same code, then maybe you'll want to use locals in Forth.
    Personally I don't and think it a terrible idea.

    I think you overstate such use of variables, but how are they a problem
    when defined local to the routine which uses it?

    How do you do that? Variables are always globals, I thought.

    Give an example how it's a problem.

    Another
    issue with them that I forgot to mention is non-reentrancy. Like if you implement 2SWAP with variables and an interrupt handler uses it while
    another call to 2SWAP is in progress, you get a Heisenbug. Oops.

    You could make it a USER variable :)

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Hans Bezemer@21:1/5 to Paul Rubin on Mon Oct 31 01:41:20 2022
    On Monday, October 31, 2022 at 3:05:16 AM UTC+1, Paul Rubin wrote:
    dxforth <dxf...@gmail.com> writes:
    Yes, idiot proofing is always a good goal when programming ;).
    According to both Moore and Dijkstra, idiots shouldn't be programming.

    Hans Bezemer

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Hans Bezemer@21:1/5 to Doug Hoffman on Mon Oct 31 01:40:08 2022
    On Monday, October 31, 2022 at 3:44:03 AM UTC+1, Doug Hoffman wrote:
    On Sunday, October 30, 2022 at 10:05:16 PM UTC-4, Paul Rubin wrote:

    I also don't see how to implement 2SWAP with
    just DUP, DROP, OVER.
    Use the return stack as a "local variable holder"
    and use ROT and SWAP.

    : 2swap ( x1 x2 x3 x4 -- x3 x4 x1 x2 )
    r rot rot r> swap rot swap ;
    Really?! Even my computer can do better!

    $ pp4th -x stackopt.4th abcd cdab
    - Trying a 1 word solution..
    No solutions.
    - Trying a 2 word solution..
    No solutions.
    - Trying a 3 word solution..
    No solutions.
    - Trying a 4 word solution..
    rot >r rot r>

    Hans Bezemer

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From none) (albert@21:1/5 to dxforth@gmail.com on Mon Oct 31 11:15:26 2022
    In article <tjn8al$1ssh$1@gioia.aioe.org>, dxforth <dxforth@gmail.com> wrote: >On 31/10/2022 10:48 am, Paul Rubin wrote:
    dxforth <dxforth@gmail.com> writes:
    It appears he [Moore] found them superfluous:
    "The words that manipulate that stack are DUP, DROP and OVER
    period. There's no ..., well SWAP is very convenient and you want it,
    but it isn't a machine instruction. But no PICK no ROLL, none of the
    complex operators to let you index down into the stack."

    PICK and ROLL have to have come from somewhere: if it wasn't Moore, then
    who? And what about ROT, -ROT, >R, and R>?

    I get that Moore used VARIABLEs for everything that I'd use locals for.

    You use locals because it's easier and more-or-less idiot-proof. Moore >claims it leads to inefficiency. Can't speak for his use but if I have
    to use a variable as a temp, I do so sparingly - unlike locals which are >largely about 'readability' and therefore quantity.

    locals is not enough, you need dlocals,flocals
    You are actually brains washed by c.
    "
    #include whatever

    int gcd( int a, int b)
    { float hesp;
    double x;
    long int x ;
    hesp inteact(a, x);
    return items(a, hesp);
    }
    "
    You can have this type behaviour. with

    VOCABULARY gcdlist ALSO gcdlist

    int a int b
    float hesp
    double x
    long_int x
    : gcd
    b ! a !
    a @ x 2@ hesp F@ inteact hesp F!
    a @ ,hesp F@ items
    ;

    previous

    It is good that you are not looking at Pascal, then
    we would have local definitions adding to the
    abominations of the local type zoo (LOCAL FLOCAL DLOCAL DFLOCAL ..)

    In the above picture we could easily add after
    long_int x
    the line
    : inteact do this do that mysterious F@ ;

    proving the superiority of classical approach of forth.

    I can't stand the idea that so,eome duplicates VARIABLE
    into VALUES (it is sooo much works to fetch them..)
    and then LOCAL VALUES (duplicating the scope restriction
    that are present in Forth).

    Groetjes Albert
    --
    "in our communism country Viet Nam, people are forced to be
    alive and in the western country like US, people are free to
    die from Covid 19 lol" duc ha
    albert@spe&ar&c.xs4all.nl &=n http://home.hccnet.nl/a.w.m.van.der.horst

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From none) (albert@21:1/5 to no.email@nospam.invalid on Mon Oct 31 11:25:59 2022
    In article <87a65c66u4.fsf@nightsong.com>,
    Paul Rubin <no.email@nospam.invalid> wrote:
    Doug Hoffman <dhoffman888@gmail.com> writes:
    I also don't see how to implement 2SWAP with just DUP, DROP, OVER.
    Use the return stack as a "local variable holder"
    and use ROT and SWAP.

    I'm doing by the quote from Chuck Moore about DUP, DROP, and OVER (and
    maybe SWAP) being the only legit stack primitives, so no ROT. He does
    use the return stack in his own code though.

    Once strings are introduced as a proper pair (not zero-ended)
    you need SPSWAP and PSSWAP for swapping a single and a double.
    I can't see Chuck Moore object to that.
    I use these preferably, because I (like Chuck) have difficulty
    remembering the stack diagram of ROT.

    Truthfully, I don't see much difference between conventional locals
    and using the return stack for same.

    There is no RPICK in standard Forth, so you can't get at the internal
    slots. Moore even frowns on regular PICK. Also, you have to be able to
    pop the locals if the word exits through an exception. (LOCAL) had to
    be added to the standard to allow that, since the VM has to handle the >unwinding in that situation.

    PICK is no use. It does something right though, it leaves parameters
    on the data stack instead of copying to un undisclosed location.
    I experimented with a frame pointer that marks
    a position on the stack and names data items from there with an offset.
    This works but I was not convinced to show it here on comp.lang.forth.
    (but a one-screener and not invasive.)

    Groetjes Albert
    --
    "in our communism country Viet Nam, people are forced to be
    alive and in the western country like US, people are free to
    die from Covid 19 lol" duc ha
    albert@spe&ar&c.xs4all.nl &=n http://home.hccnet.nl/a.w.m.van.der.horst

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From dxforth@21:1/5 to Hans Bezemer on Mon Oct 31 22:03:12 2022
    On 31/10/2022 7:41 pm, Hans Bezemer wrote:
    On Monday, October 31, 2022 at 3:05:16 AM UTC+1, Paul Rubin wrote:

    Yes, idiot proofing is always a good goal when programming ;).
    According to both Moore and Dijkstra, idiots shouldn't be programming.

    I felt the same way after quashing a bug that randomly deleted files :)

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Stephen Pelc@21:1/5 to Paul Rubin on Mon Oct 31 11:49:08 2022
    On 31 Oct 2022 at 00:48:55 CET, "Paul Rubin" <no.email@nospam.invalid> wrote:

    In Forth, there are only 3 or so
    "registers" (T, N, and R), and each is special. Why be so vehement that
    a human rather than a machine should be juggling them?

    If you consider the whole Forth VM there are rather more:
    TOS, NOS, PSP \ T, N, data stack pointer
    TOR, RSP \ R, return stack pointer
    TOF, FSP \ top of floats, float stack pointer
    LP \ local pointer
    UP \ user area pointer
    For stack underflow checking you need three more. On a modern optimising
    Forth.
    it's easy to find oneself using six to eight CPU registers for the VM and the same
    again for code generation, and a couple of special purpose registers.

    Stephen
    --
    Stephen Pelc, stephen@vfxforth.com
    MicroProcessor Engineering, Ltd. - More Real, Less Time
    133 Hill Lane, Southampton SO15 5AF, England
    tel: +44 (0)23 8063 1441, +44 (0)78 0390 3612,
    +34 649 662 974
    http://www.mpeforth.com - free VFX Forth downloads

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Doug Hoffman@21:1/5 to the.bee...@gmail.com on Mon Oct 31 08:10:34 2022
    On Monday, October 31, 2022 at 4:40:09 AM UTC-4, the.bee...@gmail.com wrote:

    : 2swap ( x1 x2 x3 x4 -- x3 x4 x1 x2 )
    r rot rot r> swap rot swap ;
    Really?! Even my computer can do better!
    rot >r rot r>

    Thanks for pointing that out Hans.
    VFX's optimizer lulled me into thinking that
    what I showed was efficient. My bad!

    -Doug

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Doug Hoffman@21:1/5 to Paul Rubin on Mon Oct 31 08:30:31 2022
    On Sunday, October 30, 2022 at 10:54:29 PM UTC-4, Paul Rubin wrote:
    Doug Hoffman <dhoff...@gmail.com> writes:
    I also don't see how to implement 2SWAP with just DUP, DROP, OVER.
    Use the return stack as a "local variable holder"
    and use ROT and SWAP.
    I'm doing by the quote from Chuck Moore about DUP, DROP, and OVER (and
    maybe SWAP) being the only legit stack primitives, so no ROT. He does
    use the return stack in his own code though.
    Truthfully, I don't see much difference between conventional locals
    and using the return stack for same.
    There is no RPICK in standard Forth, so you can't get at the internal
    slots. Moore even frowns on regular PICK. Also, you have to be able to
    pop the locals if the word exits through an exception. (LOCAL) had to
    be added to the standard to allow that, since the VM has to handle the unwinding in that situation.

    Meh. What Moore has stated in recent decades also has little to do with standard Forth.

    My point, which I should have stated explicitly, is that detractors of locals generally say that their use impedes factoring because items are
    not on the data stack. But often these same people have no issue
    with putting items on the return stack, which must also impede factoring
    for the same reason. Though I really don't subscribe to the impede
    factoring issue in either case.

    Frequently-used core-type words like 2swap should not use locals.
    In higher level problem specific words locals have a place in the code I write.

    That was fun. What next, a debate about blocks vs text files?

    -Doug

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Hans Bezemer@21:1/5 to Gerry Jackson on Mon Oct 31 08:48:58 2022
    On Sunday, October 30, 2022 at 4:30:16 PM UTC+1, Gerry Jackson wrote:
    Sorry about that, I wasn't aware that 4th used zero terminated strings
    and just assumed that standard counted strings were used. So presumably
    your version of COUNT does it by actually counting the characters.
    Yes - found out pretty quickly that abstracting STRING words worked in most situations - so I rarely have problems porting stuff with "cooked" strings. Unless someone uses COUNT as C@+ equivalent :-(

    Note that the overhead of "counting strings" is negligible, since 4tH promotes the addr/count representation - just like ANS Forth. Only when getting stuff from string variables or ," compiled strings or +PLACE counting strings is required.

    It's fortuitous that a 0 byte means an empty string for both ways of representing a string.
    Yeah - I thought so too! I'm so used to ASCIIZ strings it didn't dawn upon me this might have been written for COUNTed strings. There I got the idea about the stack item!

    Hans Bezemer

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From minforth@arcor.de@21:1/5 to Doug Hoffman on Mon Oct 31 09:10:55 2022
    Doug Hoffman schrieb am Montag, 31. Oktober 2022 um 16:30:33 UTC+1:
    On Sunday, October 30, 2022 at 10:54:29 PM UTC-4, Paul Rubin wrote:
    Doug Hoffman <dhoff...@gmail.com> writes:
    I also don't see how to implement 2SWAP with just DUP, DROP, OVER.
    Use the return stack as a "local variable holder"
    and use ROT and SWAP.
    I'm doing by the quote from Chuck Moore about DUP, DROP, and OVER (and maybe SWAP) being the only legit stack primitives, so no ROT. He does
    use the return stack in his own code though.
    Truthfully, I don't see much difference between conventional locals
    and using the return stack for same.
    There is no RPICK in standard Forth, so you can't get at the internal slots. Moore even frowns on regular PICK. Also, you have to be able to
    pop the locals if the word exits through an exception. (LOCAL) had to
    be added to the standard to allow that, since the VM has to handle the unwinding in that situation.
    Meh. What Moore has stated in recent decades also has little to do with standard Forth.

    My point, which I should have stated explicitly, is that detractors of locals generally say that their use impedes factoring because items are
    not on the data stack. But often these same people have no issue
    with putting items on the return stack, which must also impede factoring
    for the same reason. Though I really don't subscribe to the impede
    factoring issue in either case.

    Frequently-used core-type words like 2swap should not use locals.
    In higher level problem specific words locals have a place in the code I write.

    That was fun. What next, a debate about blocks vs text files?

    I'd suggest state-smartness. Seems to attract flies too.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Marcel Hendrix@21:1/5 to Anton Ertl on Mon Oct 31 10:35:07 2022
    On Monday, October 31, 2022 at 6:20:55 PM UTC+1, Anton Ertl wrote:
    [..]
    Let's see how VFX64 fares:

    r rot rot r> swap rot swap rot >r rot r> 2swap
    [..]
    For comparison, lxf is analytical about the return stack and compiles
    them all to the same code (21 bytes, but 32-bit code rather than
    64-bit code):
    [..]
    FORTH> : tt >r rot rot r> swap rot swap rot >r rot r> 2swap ; ok
    FORTH> ' tt idis
    $0133DC40 : tt
    $0133DC4A pop rbx
    $0133DC4B pop rdi
    $0133DC4C pop rax
    $0133DC4D pop rdx
    $0133DC4E push rdi
    $0133DC4F push rbx
    $0133DC50 push rdx
    $0133DC51 push rax
    $0133DC52 ;
    FORTH> : tt2 tt 2swap 2swap 2swap .S ; ok
    FORTH> see tt2
    Flags: ANSI
    $0133DCC0 : tt2
    $0133DCCA pop rbx
    $0133DCCB pop rdi
    $0133DCCC pop rax
    $0133DCCD mov rdx, [rsp] qword
    $0133DCD1 push rax
    $0133DCD2 push rdi
    $0133DCD3 push rbx
    $0133DCD4 jmp .S+10 ( $012BEA0A ) offset NEAR
    $0133DCD9 ;
    FORTH> : tt3 1. 2. tt tt tt .S ; ok
    FORTH> see tt3
    Flags: ANSI
    $0133DCC0 : tt3
    $0133DCCA push 2 b#
    $0133DCCC push 0 b#
    $0133DCCE push 1 b#
    $0133DCD0 push 0 b#
    $0133DCD2 jmp .S+10 ( $012BEA0A ) offset NEAR
    $0133DCD7 ;

    -marcel

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Anton Ertl@21:1/5 to Doug Hoffman on Mon Oct 31 17:09:40 2022
    Doug Hoffman <dhoffman888@gmail.com> writes:
    On Monday, October 31, 2022 at 4:40:09 AM UTC-4, the.bee...@gmail.com wrote:

    : 2swap ( x1 x2 x3 x4 -- x3 x4 x1 x2 )
    r rot rot r> swap rot swap ;
    Really?! Even my computer can do better!
    rot >r rot r>

    Thanks for pointing that out Hans.
    VFX's optimizer lulled me into thinking that
    what I showed was efficient. My bad!

    Let's see how VFX64 fares:

    r rot rot r> swap rot swap rot >r rot r> 2swap
    PUSH RBX PUSH QWORD [RBP+08] MOV RDX, RBX
    POP RDX POP RDX MOV RBX, [RBP+08]
    MOV RBX, [RBP+08] MOV RCX, [RBP+10] MOV [RBP+08], RDX
    MOV [RBP+08], RDX MOV RAX, [RBP] MOV RDX, [RBP+10]
    MOV RDX, [RBP+10] MOV [RBP], RCX MOV RCX, [RBP]
    MOV RCX, [RBP] MOV [RBP+10], RAX MOV [RBP], RDX
    MOV [RBP], RDX MOV [RBP+08], RBX MOV [RBP+10], RCX
    MOV [RBP+10], RCX MOV RBX, RDX RET/NEXT
    RET/NEXT RET/NEXT 28 Bytes
    27 bytes 29 Bytes

    For comparison, lxf is analytical about the return stack and compiles
    them all to the same code (21 bytes, but 32-bit code rather than
    64-bit code):

    r rot rot r> swap rot swap rot >r rot r> 2swap
    mov eax , [ebp+4h] mov eax , [ebp+4h] mov eax , [ebp+4h]
    mov [ebp+4h] , ebx mov [ebp+4h] , ebx mov [ebp+4h] , ebx
    mov ebx , eax mov ebx , eax mov ebx , eax
    mov eax , [ebp+8h] mov eax , [ebp+8h] mov eax , [ebp+8h]
    mov ecx , [ebp] mov ecx , [ebp] mov ecx , [ebp]
    mov [ebp+8h] , ecx mov [ebp+8h] , ecx mov [ebp+8h] , ecx
    mov [ebp] , eax mov [ebp] , eax mov [ebp] , eax
    ret near ret near ret near

    - 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 P Falth@21:1/5 to Anton Ertl on Mon Oct 31 10:45:23 2022
    On Monday, 31 October 2022 at 18:20:55 UTC+1, Anton Ertl wrote:
    Doug Hoffman <dhoff...@gmail.com> writes:
    On Monday, October 31, 2022 at 4:40:09 AM UTC-4, the.bee...@gmail.com wrote:

    : 2swap ( x1 x2 x3 x4 -- x3 x4 x1 x2 )
    r rot rot r> swap rot swap ;
    Really?! Even my computer can do better!
    rot >r rot r>

    Thanks for pointing that out Hans.
    VFX's optimizer lulled me into thinking that
    what I showed was efficient. My bad!
    Let's see how VFX64 fares:

    r rot rot r> swap rot swap rot >r rot r> 2swap
    PUSH RBX PUSH QWORD [RBP+08] MOV RDX, RBX
    POP RDX POP RDX MOV RBX, [RBP+08]
    MOV RBX, [RBP+08] MOV RCX, [RBP+10] MOV [RBP+08], RDX
    MOV [RBP+08], RDX MOV RAX, [RBP] MOV RDX, [RBP+10]
    MOV RDX, [RBP+10] MOV [RBP], RCX MOV RCX, [RBP]
    MOV RCX, [RBP] MOV [RBP+10], RAX MOV [RBP], RDX
    MOV [RBP], RDX MOV [RBP+08], RBX MOV [RBP+10], RCX
    MOV [RBP+10], RCX MOV RBX, RDX RET/NEXT
    RET/NEXT RET/NEXT 28 Bytes
    27 bytes 29 Bytes

    For comparison, lxf is analytical about the return stack and compiles
    them all to the same code (21 bytes, but 32-bit code rather than
    64-bit code):

    r rot rot r> swap rot swap rot >r rot r> 2swap
    mov eax , [ebp+4h] mov eax , [ebp+4h] mov eax , [ebp+4h]
    mov [ebp+4h] , ebx mov [ebp+4h] , ebx mov [ebp+4h] , ebx
    mov ebx , eax mov ebx , eax mov ebx , eax
    mov eax , [ebp+8h] mov eax , [ebp+8h] mov eax , [ebp+8h]
    mov ecx , [ebp] mov ecx , [ebp] mov ecx , [ebp]
    mov [ebp+8h] , ecx mov [ebp+8h] , ecx mov [ebp+8h] , ecx
    mov [ebp] , eax mov [ebp] , eax mov [ebp] , eax
    ret near ret near ret near

    Also the locals version will produce the same code!

    : s2 {: a b c d -- c d a b :} c d a b ; ok
    see s2
    A4A5D4 409CB2 21 C80000 5 normal S2

    409CB2 8B4504 mov eax , [ebp+4h]
    409CB5 895D04 mov [ebp+4h] , ebx
    409CB8 8BD8 mov ebx , eax
    409CBA 8B4508 mov eax , [ebp+8h]
    409CBD 8B4D00 mov ecx , [ebp]
    409CC0 894D08 mov [ebp+8h] , ecx
    409CC3 894500 mov [ebp] , eax
    409CC6 C3 ret near
    ok

    Peter

    - 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 Marcel Hendrix@21:1/5 to P Falth on Mon Oct 31 13:18:17 2022
    On Monday, October 31, 2022 at 6:45:25 PM UTC+1, P Falth wrote:
    [..]
    Also the locals version will produce the same code!

    : s2 {: a b c d -- c d a b :} c d a b ; ok
    see s2
    A4A5D4 409CB2 21 C80000 5 normal S2

    409CB2 8B4504 mov eax , [ebp+4h]
    409CB5 895D04 mov [ebp+4h] , ebx
    409CB8 8BD8 mov ebx , eax
    409CBA 8B4508 mov eax , [ebp+8h]
    409CBD 8B4D00 mov ecx , [ebp]
    409CC0 894D08 mov [ebp+8h] , ecx
    409CC3 894500 mov [ebp] , eax
    409CC6 C3 ret near

    In this particular case I can match that (but not in general).

    FORTH> : s2 params| a b c d | c d a b ; ok
    FORTH> see s2
    Flags: TOKENIZE, ANSI
    : s2 (4)PARAMS %c %d %a %b ; ok
    FORTH> ' s2 idis
    $0133E080 : s2
    $0133E08A pop rbx
    $0133E08B pop rdi
    $0133E08C pop rax
    $0133E08D pop rdx
    $0133E08E push rdi
    $0133E08F push rbx
    $0133E090 push rdx
    $0133E091 push rax
    $0133E092 ;
    FORTH> : test 1 2 3 4 s2 .S ; ok
    FORTH> see test
    Flags: ANSI
    $0133E100 : test
    $0133E10A push 3 b#
    $0133E10C push 4 b#
    $0133E10E push 1 b#
    $0133E110 push 2 b#
    $0133E112 jmp .S+10 ( $012BEA0A ) offset NEAR

    -marcel

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From dxforth@21:1/5 to Doug Hoffman on Tue Nov 1 13:18:36 2022
    On 1/11/2022 2:30 am, Doug Hoffman wrote:

    What Moore has stated in recent decades also has little to do with
    standard Forth.

    He did say the latter "did not describe Forth, but a language with the
    same name"! Not sure 'language' is even appropriate - 'unrealized ideal'
    would be closer. One would be hard pressed to find a language as drawn-out
    and divisive as 'Standard Forth' (any incarnation). If anyone is writing applications 'in Forth', it's because they've stopped pursuing 'the vision splendid', accepted what they have, and the short time in which they have
    to do it.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From dxforth@21:1/5 to Doug Hoffman on Tue Nov 1 14:46:52 2022
    On 1/11/2022 2:30 am, Doug Hoffman wrote:

    My point, which I should have stated explicitly, is that detractors of locals generally say that their use impedes factoring because items are
    not on the data stack. But often these same people have no issue
    with putting items on the return stack, which must also impede factoring
    for the same reason.

    'These same people' are judicious in their use of return stack. They don't have so many items that they need to name them, or require the system to
    manage it for them :)

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Doug Hoffman@21:1/5 to dxforth on Tue Nov 1 04:44:33 2022
    On Monday, October 31, 2022 at 11:46:55 PM UTC-4, dxforth wrote:

    'These same people' are judicious in their use of return stack. They don't have so many items that they need to name them, or require the system to manage it for them :)

    Yes. As it should be. I'm a habitual user of the return stack when it is all
    I need (as opposed to resorting to locals). Very handy and efficient.

    -Doug

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From antispam@math.uni.wroc.pl@21:1/5 to Paul Rubin on Tue Nov 1 13:19:16 2022
    Paul Rubin <no.email@nospam.invalid> wrote:
    dxforth <dxforth@gmail.com> writes:
    It appears he [Moore] found them superfluous:
    "The words that manipulate that stack are DUP, DROP and OVER
    period. There's no ..., well SWAP is very convenient and you want it,
    but it isn't a machine instruction. But no PICK no ROLL, none of the complex operators to let you index down into the stack."

    PICK and ROLL have to have come from somewhere: if it wasn't Moore, then
    who? And what about ROT, -ROT, >R, and R>?

    I get that Moore used VARIABLEs for everything that I'd use locals for.
    He also used CODE when Forth got in the way too much.

    Back in the 1970s, computers were limited, programs were necessarily
    small, and Moore espoused rewriting programs from the ground up instead
    of maintaining them. The main problem facing programmers was how to
    make their program implement behaviour X, for whatever X happened to be
    that day. They'd put a lot of effort into coding and testing X, and
    then they were done.

    Today, the main problem facing programmers is ensuring the absence of behaviours rather than their presence. Writing code is way easier than
    it used to be, because tools are better and computers are faster. But maintaining is harder since programs are bigger and have more people
    hacking at them. If you use a VARIABLE to save a temporary value used
    by a word, then anyone modifying that word, when they see that variable,
    now has to check that no other word uses the variable and depends on it
    for communication. Or worse, communicates through the memory cell
    occupied by that variable but through some sneaky alias. VALUE avoids aliasing (no idea whether Moore used them), but locals make both issues
    go away.

    Finally, while I can't doubt Moore's genius, I've never understood the
    vision that says the pure stack VM fits every programming problem.
    Register allocation and spilling is one of the messier parts of
    traditional compilers even when there are plenty of registers that don't
    have weird special purposes. In Forth, there are only 3 or so
    "registers" (T, N, and R), and each is special. Why be so vehement that
    a human rather than a machine should be juggling them? I can understand
    taht locals (if supported) complicate the traditional threaded Forth interpreter,

    I think thatsome voices here vastly overestimate extra complexity.
    AFAICS at runtime it is enough to have bunch of extra primitives:
    add and subtract from return stack pointer (could be single primitive)
    and two primitives fpr each local, one for reading, the other for
    storing. If one sticks to standard limit of 16 locals that is 33
    primitives. And they are very simple, one or two machine instructions
    for real work (plus whatever boilerplate is needed for dispatch).

    At compile time main effort is to add new transient part to dictionary.
    One needs to decide where to put it. With standard restriction
    of local declarations fitting on single line one could use a fixed
    size area of order 120-200 bytes. One needs to modify search for
    words to look there before main dictionary. And of course one needs
    parsing word to recognize locals.

    Together that adds some bulk, probably around 500-1000 bytes to
    code space and say extra 200 bytes during compile, but I do not
    think it is really complication.

    but I don't know how much Moore valued that. I know he did
    like stack hardware (his many Forth chips) but that came later.

    So the pure "stack plus VARIABLEs" seems "not even wrong" to me. I
    don't understand the motivation behind it well enough to disagree per
    se. And I've never seen an explanation that made sense. They have all seemed like grasping at straws.


    --
    Waldek Hebisch

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From dxforth@21:1/5 to Doug Hoffman on Wed Nov 2 01:23:02 2022
    On 1/11/2022 10:44 pm, Doug Hoffman wrote:
    On Monday, October 31, 2022 at 11:46:55 PM UTC-4, dxforth wrote:

    'These same people' are judicious in their use of return stack. They don't >> have so many items that they need to name them, or require the system to
    manage it for them :)

    Yes. As it should be. I'm a habitual user of the return stack when it is all I need (as opposed to resorting to locals). Very handy and efficient.

    Are you saying Forth is inadequate - or that it's your choice to extend it
    with locals? If Forth is inadequate it would mean I've wasted 40 years on
    a bum steer. Locals users too.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Marcel Hendrix@21:1/5 to anti...@math.uni.wroc.pl on Tue Nov 1 09:34:48 2022
    On Tuesday, November 1, 2022 at 2:19:21 PM UTC+1, anti...@math.uni.wroc.pl wrote:
    [..]
    I think thatsome voices here vastly overestimate extra complexity.
    AFAICS at runtime it is enough to have bunch of extra primitives:
    add and subtract from return stack pointer (could be single primitive)
    and two primitives fpr each local, one for reading, the other for
    storing. If one sticks to standard limit of 16 locals that is 33
    primitives. And they are very simple, one or two machine instructions
    for real work (plus whatever boilerplate is needed for dispatch).

    Aren't you forgetting what happens when you call a word that also
    uses locals? What about recursion? What happens when bot locals
    and the R-stack are used?

    At compile time main effort is to add new transient part to dictionary.
    [..]

    Complexity depends on simply *implementing* locals versus *optimizing* them. The former is indeed trivially simple.

    Another problem: what to do with SEE ?

    -marcel

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Anton Ertl@21:1/5 to Marcel Hendrix on Tue Nov 1 17:49:32 2022
    Marcel Hendrix <mhx@iae.nl> writes:
    On Tuesday, November 1, 2022 at 2:19:21 PM UTC+1, anti...@math.uni.wroc.pl wrote:
    [..]
    I think thatsome voices here vastly overestimate extra complexity.
    AFAICS at runtime it is enough to have bunch of extra primitives:
    add and subtract from return stack pointer (could be single primitive)
    and two primitives fpr each local, one for reading, the other for
    storing. If one sticks to standard limit of 16 locals that is 33
    primitives. And they are very simple, one or two machine instructions
    for real work (plus whatever boilerplate is needed for dispatch).

    Actually, you need only one primitive with an immediate argument N for
    reading local N and one primitive with an immediate argument M for
    writing local M.

    Aren't you forgetting what happens when you call a word that also
    uses locals? What about recursion?

    The locals are on the return stack in his model (like in many
    systems), so calls to other words with locals are covered, including
    recursion.

    What happens when bot locals
    and the R-stack are used?

    The standard has restrictions on mixing that. I think if he wants
    minimal complexity, he will also impose these restrictions in programs
    on his system (like many systems with locals on the return stack do).

    Another problem: what to do with SEE ?

    Most native-code systems show the native code in disassembled form, so apparently it's not that important that the result of SEE is similar
    to the source code. If you want to see that source code, use LOCATE.
    In Gforth, SEE shows you the primitives for code generated for locals.
    E.g.:

    : my2swap {: a b c d :} c d a b ; ok
    see my2swap
    : my2swap
    >l >l >l >l @local2 @local3 @local0 @local1 lp+!# 32 ; ok

    - 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@arcor.de@21:1/5 to anti...@math.uni.wroc.pl on Tue Nov 1 23:37:53 2022
    anti...@math.uni.wroc.pl schrieb am Dienstag, 1. November 2022 um 14:19:21 UTC+1:
    Paul Rubin <no.e...@nospam.invalid> wrote:
    dxforth <dxf...@gmail.com> writes:
    It appears he [Moore] found them superfluous:
    "The words that manipulate that stack are DUP, DROP and OVER
    period. There's no ..., well SWAP is very convenient and you want it,
    but it isn't a machine instruction. But no PICK no ROLL, none of the complex operators to let you index down into the stack."

    PICK and ROLL have to have come from somewhere: if it wasn't Moore, then who? And what about ROT, -ROT, >R, and R>?

    I get that Moore used VARIABLEs for everything that I'd use locals for.
    He also used CODE when Forth got in the way too much.

    Back in the 1970s, computers were limited, programs were necessarily
    small, and Moore espoused rewriting programs from the ground up instead
    of maintaining them. The main problem facing programmers was how to
    make their program implement behaviour X, for whatever X happened to be that day. They'd put a lot of effort into coding and testing X, and
    then they were done.

    Today, the main problem facing programmers is ensuring the absence of behaviours rather than their presence. Writing code is way easier than
    it used to be, because tools are better and computers are faster. But maintaining is harder since programs are bigger and have more people hacking at them. If you use a VARIABLE to save a temporary value used
    by a word, then anyone modifying that word, when they see that variable, now has to check that no other word uses the variable and depends on it
    for communication. Or worse, communicates through the memory cell
    occupied by that variable but through some sneaky alias. VALUE avoids aliasing (no idea whether Moore used them), but locals make both issues
    go away.

    Finally, while I can't doubt Moore's genius, I've never understood the vision that says the pure stack VM fits every programming problem.
    Register allocation and spilling is one of the messier parts of
    traditional compilers even when there are plenty of registers that don't have weird special purposes. In Forth, there are only 3 or so
    "registers" (T, N, and R), and each is special. Why be so vehement that
    a human rather than a machine should be juggling them? I can understand taht locals (if supported) complicate the traditional threaded Forth interpreter,
    I think thatsome voices here vastly overestimate extra complexity.
    AFAICS at runtime it is enough to have bunch of extra primitives:
    add and subtract from return stack pointer (could be single primitive)
    and two primitives fpr each local, one for reading, the other for
    storing. If one sticks to standard limit of 16 locals that is 33
    primitives. And they are very simple, one or two machine instructions
    for real work (plus whatever boilerplate is needed for dispatch).

    At compile time main effort is to add new transient part to dictionary.
    One needs to decide where to put it. With standard restriction
    of local declarations fitting on single line one could use a fixed
    size area of order 120-200 bytes.

    With locals declarations in one line you can parse the declarations twice
    by resetting >in to {: after first encounter of :}. It makes the locals compiler
    only slightly more complex.

    Use the the first parsing stage to calculate the required locals frame size
    in the return stack. Advantage: the next step for fp, buffer/strings, structure locals is well prepared.

    Locals are seldom worth the effort when one deals only with integers.

    FWIW I found string locals very helpful in the past. Very often they can release you from explicit buffer management or setting up a string stack.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Hans Bezemer@21:1/5 to anti...@math.uni.wroc.pl on Wed Nov 2 03:28:11 2022
    On Tuesday, November 1, 2022 at 2:19:21 PM UTC+1, anti...@math.uni.wroc.pl wrote:
    I think that some voices here vastly overestimate extra complexity.
    I did locals in my uBASIC interpreter - because it's BASIC - a Fortran derivative - it's fitting. But it requires setting up and releasing a stack frame,
    copying values there - that's a whole lot of overhead. For some ugly C-ism.
    As if we didn't have enough of those in ANS Forth.

    AFAICS at runtime it is enough to have bunch of extra primitives:
    add and subtract from return stack pointer (could be single primitive)
    and two primitives fpr each local, one for reading, the other for
    storing. If one sticks to standard limit of 16 locals that is 33
    primitives. And they are very simple, one or two machine instructions
    for real work (plus whatever boilerplate is needed for dispatch).
    33 primitives? And you call that "minor overhead"? My entire VM has about
    100 primitives.

    Hans Bezemer

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Hans Bezemer@21:1/5 to dxforth on Wed Nov 2 04:04:56 2022
    On Tuesday, November 1, 2022 at 3:23:07 PM UTC+1, dxforth wrote:
    Are you saying Forth is inadequate - or that it's your choice to extend it with locals? If Forth is inadequate it would mean I've wasted 40 years on
    a bum steer. Locals users too.
    True. Thinking about programming in a Forth way has significantly influenced my C style. Now I need to go the opposite way: translating C to Forth, so I can have loads of local variables - and write functions (not words) of five pages without ever posing the question: "Do I really need those - or can I do something
    clever to eradicate them?"

    See: https://sourceforge.net/p/forth-4th/wiki/This%20is%20Forth/ and https://sourceforge.net/p/forth-4th/wiki/Understand%20your%20algorithm/

    Hans Bezemer

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Brian Fox@21:1/5 to the.bee...@gmail.com on Wed Nov 2 06:53:34 2022
    On Wednesday, November 2, 2022 at 7:04:58 AM UTC-4, the.bee...@gmail.com wrote:
    On Tuesday, November 1, 2022 at 3:23:07 PM UTC+1, dxforth wrote:
    Are you saying Forth is inadequate - or that it's your choice to extend it with locals? If Forth is inadequate it would mean I've wasted 40 years on
    a bum steer. Locals users too.
    True. Thinking about programming in a Forth way has significantly influenced my
    C style. Now I need to go the opposite way: translating C to Forth, so I can have loads of local variables - and write functions (not words) of five pages without ever posing the question: "Do I really need those - or can I do something
    clever to eradicate them?"

    See: https://sourceforge.net/p/forth-4th/wiki/This%20is%20Forth/ and https://sourceforge.net/p/forth-4th/wiki/Understand%20your%20algorithm/

    Hans Bezemer

    Off topic but ever since you started making videos I can't read your
    written stuff without hearing your voice in my head. :-)))
    (with the interesting "Nederlandse" accent of course)

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Paul Rubin@21:1/5 to dxforth on Wed Nov 2 15:26:03 2022
    dxforth <dxforth@gmail.com> writes:
    Oh, I'm not advocating variables - locals or otherwise. What I see is a lot of promiscuous use of the former as if there were no cost. Here's an example of using extra locals - not out of necessity - but 'style':

    https://gforth.org/manual/Locals-programming-style.html

    In that example, there is some stuff in locals, but getting rid of the
    locals would mean keeping the same stuff on the data stack (and maybe
    partly the return stack). The total memory used is the same. In some
    systems the return (or locals) stack might be too small, but if you're
    going to use locals (or anything else) at all, obviously you want to
    size the stacks to accomodate your usage.

    If anyone is writing applications 'in Forth', it's because they've
    stopped pursuing 'the vision splendid' ...

    Heh, I like that expression. I had to look up its origin, a book from
    1913 about some faction in the Anglican church. I will have to look at
    the book one of these days. It's the vision itself that I've never
    completely understood. I ought to read more of Dr. Ting's "Zen of
    Forth" books, I suppose.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From dxforth@21:1/5 to Paul Rubin on Thu Nov 3 13:46:27 2022
    On 3/11/2022 9:26 am, Paul Rubin wrote:
    dxforth <dxforth@gmail.com> writes:
    Oh, I'm not advocating variables - locals or otherwise. What I see is a lot >> of promiscuous use of the former as if there were no cost. Here's an example
    of using extra locals - not out of necessity - but 'style':

    https://gforth.org/manual/Locals-programming-style.html

    In that example, there is some stuff in locals, but getting rid of the
    locals would mean keeping the same stuff on the data stack (and maybe
    partly the return stack). The total memory used is the same. In some systems the return (or locals) stack might be too small, but if you're
    going to use locals (or anything else) at all, obviously you want to
    size the stacks to accomodate your usage.

    My point was it went from 4 locals to 6 for reasons of style. It may be C-style to expend resources this way (I wouldn't know) but I doubt it's Moore's. But back to your comment. You argue the same resources are
    being spent (albeit differently apportioned) so it really doesn't matter whether one is using locals or stack operators. I suspect you are not
    alone. But what are implications of using locals in Forth? It's this:
    A stack-based language that cannot exist without the help of locals has
    failed and therefore does not deserve to exist.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From antispam@math.uni.wroc.pl@21:1/5 to Marcel Hendrix on Thu Nov 3 02:56:06 2022
    Marcel Hendrix <mhx@iae.nl> wrote:
    On Tuesday, November 1, 2022 at 2:19:21 PM UTC+1, anti...@math.uni.wroc.pl wrote:
    [..]
    I think thatsome voices here vastly overestimate extra complexity.
    AFAICS at runtime it is enough to have bunch of extra primitives:
    add and subtract from return stack pointer (could be single primitive)
    and two primitives fpr each local, one for reading, the other for
    storing. If one sticks to standard limit of 16 locals that is 33 primitives. And they are very simple, one or two machine instructions
    for real work (plus whatever boilerplate is needed for dispatch).

    Aren't you forgetting what happens when you call a word that also
    uses locals? What about recursion? What happens when bot locals
    and the R-stack are used?

    Anton answered this.


    At compile time main effort is to add new transient part to dictionary.
    [..]

    Complexity depends on simply *implementing* locals versus *optimizing* them. The former is indeed trivially simple.

    I have spent some time working on "optimizing" codegen for two stack
    VM with locals. I mean input was sequence of Forth-like operations
    and codegen produced machine code. AFAICS result was worse than
    your Forth. But offender were not locals. In fact, careful
    use of local gave best code. One trouble was insufficient stack
    tracking, sometimes items were forced on data stack not because
    they had to be there, but only because codegen was unable to
    track them. Another trouble was too naive register allocator, which
    did not do well with temporaries. But if you had small number
    of locals it would put them all in registers. And if all temporaries
    were immediately put into locals, then computation could do work
    in registers and you would get resonably good code. In other
    words, one could use locals to tell compiler which things should
    go into registers.

    If you say that optimizing locals in _your_ Forth takes substantial
    effort, then I belive. I know in principle how to write better
    register allocator and do not think it is very hard. But existing
    code was micro-optimized in many places and is hard to modify.

    So, this is not absolute difficulty of solving problem, but rather
    trouble with modifying existing program (plus limited time that
    I could spent on this). But with different compiler structure
    or when starting anew I could do better. And I _know_ that one
    can generate pretty efficient code for locals in rather simple
    compiler.

    --
    Waldek Hebisch

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Paul Rubin@21:1/5 to dxforth on Wed Nov 2 20:31:15 2022
    dxforth <dxforth@gmail.com> writes:
    My point was it went from 4 locals to 6 for reasons of style. It may be C-style to expend resources this way (I wouldn't know)

    In C these days, the extra locals wouldn't expend any resources in most
    cases, since the compiler would optimize them away.

    but I doubt it's Moore's.

    This I don't know. A traditional thread Forth interpreter (Moore's
    invention) is probably 10x slower than CODE doing the same thing, but
    Moore only used CODE when he had to. If 9x extra compute cycles is
    fine, why are a few memory cells a big deal?

    There's a similar thing from the Forth stylistic convention that words
    should consume their arguments. The convention makes your code more understandable but it means consuming a little more data stack space
    than necessary, and running some extra dups and drops.

    But what are implications of using locals in Forth? It's this: A
    stack-based language that cannot exist without the help of locals has
    failed and therefore does not deserve to exist.

    Well, Moore used VARIABLEs instead of locals, so the pure stack vision
    already failed because of that. One could simply say Forth works better
    in the presence of some impurity. Locals are another, perhaps cleaner,
    way to add the impurity.

    There is a similar thing in functional programming called "point-free
    style". That style avoids using named function parameters, so instead
    of "f x = sqrt (sin x)" you'd say "f = sqrt . sin". Nice, but it can
    get really confusing, like "f x y z = (x+y)*z" becomes "f = ((*) .) . (+)".

    Point-free is a nice theoretical construct and you can apparently
    write every program that way, but for practical purposes it's much nicer
    to use named parameters except in the simpler cases. The feeling of
    point-free coding is not that much different from Forth stackrobatics.
    It can be fun but if your goal is to write programs that work, it's
    not that good a use of mental energy.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From antispam@math.uni.wroc.pl@21:1/5 to Hans Bezemer on Thu Nov 3 03:50:41 2022
    Hans Bezemer <the.beez.speaks@gmail.com> wrote:
    On Tuesday, November 1, 2022 at 2:19:21 PM UTC+1, anti...@math.uni.wroc.pl wrote:
    I think that some voices here vastly overestimate extra complexity.
    I did locals in my uBASIC interpreter - because it's BASIC - a Fortran derivative - it's fitting. But it requires setting up and releasing a stack frame,
    copying values there - that's a whole lot of overhead. For some ugly C-ism. As if we didn't have enough of those in ANS Forth.

    Copying values is not really overhead. Normally values are copied
    because you need to preserve them, so it is part of computation
    and needs to be done one way or anouther. In fact, bulk copy
    in many cases is most officient way to do this.

    AFAICS at runtime it is enough to have bunch of extra primitives:
    add and subtract from return stack pointer (could be single primitive)
    and two primitives fpr each local, one for reading, the other for
    storing. If one sticks to standard limit of 16 locals that is 33 primitives. And they are very simple, one or two machine instructions
    for real work (plus whatever boilerplate is needed for dispatch).
    33 primitives? And you call that "minor overhead"? My entire VM has about
    100 primitives.

    I am not sure what is troubling you here. That they are called
    "primitives"? Access primitives are very simple and very similar
    to each other, conceptually there is almost no increase in complexity.
    That they need to be coded in assembler? Albert's ciforth has about
    300 words defiend in assembler, and from glance at his code I think
    that most is longer than proposed primitives. So it seems that one
    would get 5-7% increase in amount of assembler code and to that
    matter simpler than much of the rest. Of course, you may that pride
    that you need less assember code. However, I take pragmatic view
    here: assembler is problematic because one can do tricky things
    which are hard to understand. But the primitives are so simple that
    there is not problem with understanding.

    One extra remark: as Anton noted instead of 32 access primitives
    I could use just 2. But AFACS in threaded code each use of
    Anton version would add 2 words of code (one for primitive itself,
    second for parameter). And assembly code of primitive would
    be a bit more complex. My version when used needs just one
    word of code. And assembly should be pretty efficient, at least
    as efficient as named constant or value and possibly more efficient.
    Which means that when used in good way locals should lead to
    smaller and more efficient code.

    Maybe you are worried about used dictionary slots? AFAICS Forthers
    are not shy about defining small special purpose words that
    get used once or twice. Looking at extras for Mecrisp I saw
    MCU definition files that define hundreds of constants, so even
    for small targets people use a lot dictionary slots. So,
    I call those 33 slots minor overhead.

    And you may not belive, but I have reasons to think that
    using locals within Forth implementation (not for style, but
    when it leads to gain!) would make code smaller, likely
    compensating space taken by primitives.

    --
    Waldek Hebisch

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From dxforth@21:1/5 to Paul Rubin on Thu Nov 3 15:10:36 2022
    On 3/11/2022 2:31 pm, Paul Rubin wrote:
    dxforth <dxforth@gmail.com> writes:
    My point was it went from 4 locals to 6 for reasons of style. It may be
    C-style to expend resources this way (I wouldn't know)

    In C these days, the extra locals wouldn't expend any resources in most cases, since the compiler would optimize them away.

    AFAIK optimizers do a better job when the code presented is already optimal.

    But what are implications of using locals in Forth? It's this: A
    stack-based language that cannot exist without the help of locals has
    failed and therefore does not deserve to exist.

    Well, Moore used VARIABLEs instead of locals, so the pure stack vision already failed because of that.

    Does he?

    One could simply say Forth works better
    in the presence of some impurity. Locals are another, perhaps cleaner,
    way to add the impurity.

    Well, in that case I'd say you're more desperate to use Forth than I am.
    No way would I tolerate using a broken language :)

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Paul Rubin@21:1/5 to dxforth on Wed Nov 2 21:36:54 2022
    dxforth <dxforth@gmail.com> writes:
    AFAIK optimizers do a better job when the code presented is already optimal.

    These days optimizers work by first splitting everything out into
    separate variables so that nothing is ever updated (static single
    assignment or SSA form), and then recombining the variables. I have
    never implemented SSA and don't understand it perfectly, but I believe
    the SSA forms of the 4-local and 6-local versions of that code would be
    very similar. Anton would know this much better than I do.

    Well, Moore used VARIABLEs instead of locals,
    Does he?

    I believe so. I remember looking at cmforth and some of the GA144 code
    and seeing variables used that way. I also remember asking Elizabeth
    about the complex multiplication example, and her replying that Moore
    didn't hesitate to use CODE if it made things easier. He wasn't a
    purist about staying with Forth words.

    In the 1970s there just wasn't room for purity in software. Maybe APL
    came closest. Lisp was born from the most purest mathematical
    abstraction (lambda calculus) but its implementations were full of low
    level hackery. The purest language now is Haskell but it is also full
    of hacks.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From dxforth@21:1/5 to Paul Rubin on Thu Nov 3 16:29:34 2022
    On 3/11/2022 3:36 pm, Paul Rubin wrote:
    dxforth <dxforth@gmail.com> writes:
    [...]
    Well, Moore used VARIABLEs instead of locals,
    Does he?

    I believe so. I remember looking at cmforth and some of the GA144 code
    and seeing variables used that way. I also remember asking Elizabeth
    about the complex multiplication example, and her replying that Moore
    didn't hesitate to use CODE if it made things easier. He wasn't a
    purist about staying with Forth words.

    I've nothing against the occasional variable or CODE when it makes sense. That's a different proposition to dumping everything to locals because
    one views stack operators as either ugly or clumsy.

    In the 1970s there just wasn't room for purity in software. Maybe APL
    came closest. Lisp was born from the most purest mathematical
    abstraction (lambda calculus) but its implementations were full of low
    level hackery. The purest language now is Haskell but it is also full
    of hacks.

    You've read Moore's stance on locals, which has never changed. Others
    will go where their interest and thinking takes them. It's not my problem.
    My interest is in discovering whether Moore's system works. I can't do
    that if I'm using locals.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From none) (albert@21:1/5 to antispam@math.uni.wroc.pl on Thu Nov 3 12:13:38 2022
    In article <tjvdqh$3vo$1@gioia.aioe.org>, <antispam@math.uni.wroc.pl> wrote:

    One extra remark: as Anton noted instead of 32 access primitives
    I could use just 2. But AFACS in threaded code each use of
    Anton version would add 2 words of code (one for primitive itself,
    second for parameter). And assembly code of primitive would
    be a bit more complex. My version when used needs just one
    word of code. And assembly should be pretty efficient, at least
    as efficient as named constant or value and possibly more efficient.
    Which means that when used in good way locals should lead to
    smaller and more efficient code.

    Maybe you are worried about used dictionary slots? AFAICS Forthers
    are not shy about defining small special purpose words that
    get used once or twice. Looking at extras for Mecrisp I saw
    MCU definition files that define hundreds of constants, so even
    for small targets people use a lot dictionary slots. So,
    I call those 33 slots minor overhead.

    <SNIP>
    I am not sure what is troubling you here. That they are called
    "primitives"? Access primitives are very simple and very similar
    to each other, conceptually there is almost no increase in complexity.
    That they need to be coded in assembler? Albert's ciforth has about
    300 words defiend in assembler, and from glance at his code I think
    that most is longer than proposed primitives. So it seems that one
    would get 5-7% increase in amount of assembler code and to that
    matter simpler than much of the rest. Of course, you may that pride
    that you need less assember code. However, I take pragmatic view
    here: assembler is problematic because one can do tricky things
    which are hard to understand. But the primitives are so simple that
    there is not problem with understanding.

    Putting the record straight:
    ciforth has 300 core words, but there are only 82+3 code words.
    Please point out what is not deemed a primitive in the following list:

    Code definition : NOOP
    Code definition : LIT
    Code definition : EXECUTE
    Code definition : SKIP
    Code definition : 0BRANCH
    Code definition : (+LOOP)
    Code definition : (DO)
    Code definition : (?DO)
    Code definition : I
    Code definition : J
    Code definition : UNLOOP
    Code definition : CMOVE
    Code definition : MOVE
    Code definition : FARMOVE
    Code definition : UM*
    Code definition : UM/MOD
    Code definition : AND
    Code definition : OR
    Code definition : XOR
    Code definition : INVERT
    Code definition : DSP@
    Code definition : DSP!
    Code definition : RSP@
    Code definition : RSP!
    Code definition : EXIT
    Code definition : CO
    Code definition : >R
    Code definition : R>
    Code definition : RDROP
    Code definition : 0=
    Code definition : 0<
    Code definition : +
    Code definition : D+
    Code definition : NEGATE
    Code definition : DNEGATE
    Code definition : OVER
    Code definition : DROP
    Code definition : NIP
    Code definition : 2DROP
    Code definition : SWAP
    Code definition : DUP
    Code definition : 2DUP
    Code definition : 2SWAP
    Code definition : 2OVER
    Code definition : +!
    Code definition : TOGGLE
    Code definition : @
    Code definition : C@
    Code definition : 2@
    Code definition : !
    Code definition : C!
    Code definition : 2!
    Code definition : FAR@
    Code definition : FAR!
    Code definition : _
    Code definition : $@
    Code definition : ALIGNED
    Code definition : -
    Code definition : =
    Code definition : <
    Code definition : U<
    Code definition : <>
    Code definition : ROT
    Code definition : FILL
    Code definition : CORA
    Code definition : $^
    Code definition : $/
    Code definition : $\
    Code definition : S>D
    Code definition : LSHIFT
    Code definition : RSHIFT
    Code definition : M*
    Code definition : SM/REM
    Code definition : 2/
    Code definition : 2*
    Code definition : PC@
    Code definition : PC!
    Code definition : PW@
    Code definition : PW!
    Code definition : XOS
    Code definition : XOS5
    Alias : BRANCH
    Alias : (;)
    Alias : : R@

    <SNIP>
    And you may not belive, but I have reasons to think that
    using locals within Forth implementation (not for style, but
    when it leads to gain!) would make code smaller, likely
    compensating space taken by primitives.

    Interesting observation, but it doesn't chime with me.
    A can't think of a high level word in the kernel that
    would benefit from locals.

    This is about as bad at it gets (decompiled, not formatted):
    : FORGET-VOC 2DUP SWAP U< IF SWAP >R >WID BEGIN DUP DUP BEGIN >LFA @
    DUP R@ U< UNTIL SWAP >LFA ! >LFA @ DUP 0= UNTIL DROP R> ELSE >VFA @
    VOC-LINK ! ONLY FORTH DEFINITIONS THEN ;

    Note that I think nothing of tucking away something on the return
    stack that I need later. IMO it beats coming up with a sensible
    name for a local.

    Waldek Hebisch

    Groetjes Albert
    --
    "in our communism country Viet Nam, people are forced to be
    alive and in the western country like US, people are free to
    die from Covid 19 lol" duc ha
    albert@spe&ar&c.xs4all.nl &=n http://home.hccnet.nl/a.w.m.van.der.horst

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Doug Hoffman@21:1/5 to dxforth on Thu Nov 3 03:40:09 2022
    On Tuesday, November 1, 2022 at 10:23:07 AM UTC-4, dxforth wrote:
    On 1/11/2022 10:44 pm, Doug Hoffman wrote:
    On Monday, October 31, 2022 at 11:46:55 PM UTC-4, dxforth wrote:

    'These same people' are judicious in their use of return stack.

    As am I and I believe everyone else I've seen use the return stack
    to stash data stack items.


    I'm a habitual user of the return stack when it is all
    I need (as opposed to resorting to locals).

    As am I.
    Did I say that all colon definitions I write use locals?


    Are you saying ... that it's your choice to extend [Forth]
    with locals?

    You give me too much credit. I have never extended a Forth
    to have locals. The experts that created VFXForth, SwiftForth,
    iForth, Gforth, iMops, and other Forths have already done it.


    If Forth is inadequate it would mean I've wasted 40 years on
    a bum steer. Locals users too.

    I don't follow that logic. How could the way I, or anyone else,
    use Forth impact whether or not you have wasted your time?

    -Doug

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From minforth@arcor.de@21:1/5 to dxforth on Thu Nov 3 06:06:22 2022
    dxforth schrieb am Donnerstag, 3. November 2022 um 06:29:37 UTC+1:
    My interest is in discovering whether Moore's system works.

    Did it work for himself? I gathered that he changed it all the time.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Paul Rubin@21:1/5 to All on Thu Nov 3 09:51:13 2022
    This is about as bad at it gets (decompiled, not formatted):
    : FORGET-VOC 2DUP SWAP U< IF SWAP >R >WID BEGIN DUP DUP BEGIN >LFA @
    DUP R@ U< UNTIL SWAP >LFA ! >LFA @ DUP 0= UNTIL DROP R> ELSE >VFA @
    VOC-LINK ! ONLY FORTH DEFINITIONS THEN ;

    I had to guess at the stack effects of the internal words and have no
    idea what the parameters are supposed to mean, but this looks roughly
    like:

    : FORGET-VOC { a b }
    b a u< IF
    b >WID
    BEGIN
    BEGIN b >LFA @ { c } c a U< UNTIL
    b >LFA !
    b 0= UNTIL
    b c a
    ELSE
    a b >VFA @
    VOC-LINK ! ONLY FORTH DEFINITIONS
    THEN ;

    Actually that is probably wrong since there is a different amount of
    stuff on the stack depending on which branch of the IF is taken.
    Some comments and stack diagrams would surely help.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Hans Bezemer@21:1/5 to Doug Hoffman on Thu Nov 3 11:41:53 2022
    On Thursday, November 3, 2022 at 11:40:10 AM UTC+1, Doug Hoffman wrote:
    As am I and I believe everyone else I've seen use the return stack
    to stash data stack items.
    That's only half the story. I learned this trick from the guy who wrote the FIG editor - you don't randomly place stuff there, you place the stuff that is either
    constant or almost constant.

    So - you triage your parameters. Those who change a LOT go on the
    data stack and those who (barely) change go on the return stack.
    In 4tH, you have R@, R'@ and R"@. And then it starts to make even MORE
    sense. You can also map those with I, I' and J - with NO overhead.

    The TORS contains the stuff that barely changes., while R'@ and R"@ are
    pure constants.

    Did I say that all colon definitions I write use locals?
    CONCAT didn't - I loved it. You see, you are perfectly capable to do better ;-)

    I understand the sentiment about "throwing away the experience". Forth
    not only made me a better programmer, it also forced me to delve deeper
    in an algorithm in order to REALLY understand it. LOCALs allow a much
    shallower way of implementing it. It also allows me to waste resources -
    simply because I can away with it.

    If you'd asked me 10 - 20 years ago to make a preprocessor that exceeds
    M4 I wouldn't have known where to begin. In Forth, it grew organically. And
    at some moment I thought "Wow, did I really make this?"

    I also wrote what must be one of the smallest DBMSes (400 lines or so). Again, a task so daunting in any other languages I probably never would have attempted.

    And all this because every single element is forced to be so small, it seems almost trivial. And all there is is the flow of data through the stack. Every tiny
    mistake is punished by a crash. That will teach you discipline.

    There is no such mechanism at work when using locals. All words are brute connected by an interface that is the stack frame. And instead of flowing almost invisibly through the program there is this point where data becomes painfully explicit - like C.

    It is not a matter of passing parameters in a different way, it's a way of thinking
    that is radically different. It is that that newbies fail to comprehend - and often
    even fail to master. That's why they drop out.

    IMHO it isn't a different way to pass and handle data, it is a different and way of
    thinking and designing. And LOCALs aren't about "making things easier", but
    a concession to make things workable for lesser gods and sloppy programmers.

    I have a lib that does LOCALs - but I never use it. I have embraced this other way of approaching the problem - and it works for me. I don't see any use in dropping it (and yes, at times I wrestle with the stack as well) and trade it for
    an IMHO inferior way of converting an idea into working code.

    Hans Bezemer

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Marcel Hendrix@21:1/5 to the.bee...@gmail.com on Thu Nov 3 15:34:22 2022
    On Thursday, November 3, 2022 at 7:41:55 PM UTC+1, the.bee...@gmail.com wrote: [..]
    and trade it for an IMHO inferior way of converting an idea into working code.

    It was demonstrated to you (e.g., by Peter Fälth) that it doesn't matter
    how you write the Forth source, it converts to the same code, given a reasonable compiler.

    -marcel

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Hans Bezemer@21:1/5 to Marcel Hendrix on Thu Nov 3 16:42:15 2022
    On Thursday, November 3, 2022 at 11:34:23 PM UTC+1, Marcel Hendrix wrote:
    On Thursday, November 3, 2022 at 7:41:55 PM UTC+1, the.bee...@gmail.com wrote:
    [..]
    If you're talking about a mechanical proces like code generation
    You're missing the entire point I'm trying to make.

    Hans Bezemer
    and trade it for an IMHO inferior way of converting an idea into working code.
    It was demonstrated to you (e.g., by Peter Fälth) that it doesn't matter how you write the Forth source, it converts to the same code, given a reasonable compiler.

    -marcel

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Paul Rubin@21:1/5 to dxforth on Thu Nov 3 17:47:21 2022
    dxforth <dxforth@gmail.com> writes:
    So now one is dependent on "a reasonable compiler". GCC here we come.

    You don't have to depend on a compiler at all, but without one, you're
    running interpreted Forth which is maybe 10x slower. That 10x is not
    too bad, compared to the 50x or more slowdown you get from Python. With
    a rudimentary compiler you might get 3x instead of 10x.

    Maybe coding style (locals or whatever) can change the 10x to 15x or
    vice versa. If you care about that, using a compiler sounds like a
    better way to recover the missed speed than warping your mind trying to optimize interpreted code at the source level. And as usual, if you
    have to optimize at all, it is likely to just be in a few hot spots of
    the program.

    Remember too that even an almost minimal Forth target these days
    (Raspberry Pi Pico) is probably 100x faster than the 16 bit
    minicomputers where Forth originated. That gives you a lot of breathing
    space. There is no need for 3+length dictionaries any more, and we
    can also use more relaxed and expressive coding styles.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From dxforth@21:1/5 to Marcel Hendrix on Fri Nov 4 11:15:18 2022
    On 4/11/2022 9:34 am, Marcel Hendrix wrote:
    On Thursday, November 3, 2022 at 7:41:55 PM UTC+1, the.bee...@gmail.com wrote:
    [..]
    and trade it for an IMHO inferior way of converting an idea into working code.

    It was demonstrated to you (e.g., by Peter Fälth) that it doesn't matter
    how you write the Forth source, it converts to the same code, given a reasonable compiler.

    So now one is dependent on "a reasonable compiler". GCC here we come.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From dxforth@21:1/5 to Doug Hoffman on Fri Nov 4 16:05:51 2022
    On 3/11/2022 9:40 pm, Doug Hoffman wrote:
    On Tuesday, November 1, 2022 at 10:23:07 AM UTC-4, dxforth wrote:
    ...
    If Forth is inadequate it would mean I've wasted 40 years on
    a bum steer. Locals users too.

    I don't follow that logic. How could the way I, or anyone else,
    use Forth impact whether or not you have wasted your time?

    How else to describe a language that folks say they can't use unless
    locals are added.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Paul Rubin@21:1/5 to dxforth on Thu Nov 3 22:38:49 2022
    dxforth <dxforth@gmail.com> writes:
    How else to describe a language that folks say they can't use unless
    locals are added.

    No software is ever finished until its last user is dead. So all
    software is inadequate in one way or another. We do what we can in
    order to get by anyway.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From P Falth@21:1/5 to Marcel Hendrix on Thu Nov 3 23:46:34 2022
    On Thursday, 3 November 2022 at 23:34:23 UTC+1, Marcel Hendrix wrote:
    On Thursday, November 3, 2022 at 7:41:55 PM UTC+1, the.bee...@gmail.com wrote:
    [..]
    and trade it for an IMHO inferior way of converting an idea into working code.
    It was demonstrated to you (e.g., by Peter Fälth) that it doesn't matter how you write the Forth source, it converts to the same code, given a reasonable compiler.

    -marcel

    But only if you have the right example code to compile!
    In this case my code generator produces the same result with locals or without. When you have a break in a basic block ( a call, a controlflow point) the locals
    needs to be placed in a known place, in the case of lxf the return stack.
    This generates extra code.
    The problem is the way locals are specified, they have a scope of the whole word, they are released just at the end of the definition.
    Stack parameters have instead a dynamic scope, they are duped, or droped or consumed as arguments to a word as decided by the programmer.

    Of course a multipass compiler could determine the scope of each local and improve the code generation. Lxf is just a simple 1 pass compiler. The reason you can make code generation for locals look good with lxf is that they are implementedto rest on the return stack. I put in some effort to get a good
    code generation for the R-stack use. The locals was for free after that.

    In my own Forth programming I do not use locals. I have not seen the need
    for them and I do not like the way they are specified to look like a comment! In lxf I have instead another feature n LBUFFER: <name> that reserves n
    byte on the return stack that can be accessed with ! @ at <name>. Just like a variable. This is useful to pass structures to systems call for example.

    Best Regards
    Peter

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From dxforth@21:1/5 to Paul Rubin on Fri Nov 4 18:42:27 2022
    On 4/11/2022 4:38 pm, Paul Rubin wrote:
    dxforth <dxforth@gmail.com> writes:
    How else to describe a language that folks say they can't use unless
    locals are added.

    No software is ever finished until its last user is dead. So all
    software is inadequate in one way or another. We do what we can in
    order to get by anyway.

    Oh, I'd say organized Forth is absolutely dead. I agree with your
    last line.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From minforth@arcor.de@21:1/5 to P Falth on Fri Nov 4 01:27:13 2022
    P Falth schrieb am Freitag, 4. November 2022 um 07:46:36 UTC+1:
    In my own Forth programming I do not use locals. I have not seen the need
    for them and I do not like the way they are specified to look like a comment! In lxf I have instead another feature n LBUFFER: <name> that reserves n
    byte on the return stack that can be accessed with ! @ at <name>. Just like a variable. This is useful to pass structures to systems call for example.

    These are good points:
    a) when there is no need, then there is no use case
    b) standard Forth locals syntax looks strange
    c) standard Forth locals are too limited, practical applications often have to deal
    with data objects like structures and (dynamic) strings/arrays; at least fp-locals
    should be there

    As long as one does only "scratch on the ground" i.e. can solve one's task with some standard words and only integer addresses and numbers as arguments,
    locals wouldn't pay their rent.

    I am old school myseld, and by myself I use a lot of paper and pencil to understand/tune
    data structures and algorithms before I fire up the computer. Then I am rather sure
    to have got the thinking right and am happy to leave as much bit&byte lifting as possible
    to the compiler. It is a waste of programmer's time to burden him with syntax mistakes.

    Whether manual deep factoring is good programming or not, is a matter of personal
    likes and experience. Moore and his acolytes live with their experience. There are good cases where deep factoring works, there are many cases where deep factoring would break data flows and algorithms apart. Always keep in mind that code needs to stay maintainable, particularly when you work in a team, and it must not require solving jigsaw code puzzles.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From none) (albert@21:1/5 to no.email@nospam.invalid on Fri Nov 4 11:47:46 2022
    In article <87tu3gc77i.fsf@nightsong.com>,
    Paul Rubin <no.email@nospam.invalid> wrote:
    This is about as bad at it gets (decompiled, not formatted):
    : FORGET-VOC 2DUP SWAP U< IF SWAP >R >WID BEGIN DUP DUP BEGIN >LFA @
    DUP R@ U< UNTIL SWAP >LFA ! >LFA @ DUP 0= UNTIL DROP R> ELSE >VFA @
    VOC-LINK ! ONLY FORTH DEFINITIONS THEN ;

    I had to guess at the stack effects of the internal words and have no
    idea what the parameters are supposed to mean, but this looks roughly
    like:

    : FORGET-VOC { a b }
    b a u< IF
    b >WID
    BEGIN
    BEGIN b >LFA @ { c } c a U< UNTIL
    b >LFA !
    b 0= UNTIL
    b c a
    ELSE
    a b >VFA @
    VOC-LINK ! ONLY FORTH DEFINITIONS
    THEN ;

    Actually that is probably wrong since there is a different amount of
    stuff on the stack depending on which branch of the IF is taken.
    Some comments and stack diagrams would surely help.

    It was not intended to be analysed, but to show how approximately
    the most complicated words look. Probably the decompiler had
    the control structures wrong hence the return stack imbalance.
    In actual source code it look (first part shown).

    _HEADER({FORGET-VOC},{FORGV},{DOCOL})
    DC TDUP
    DC SWAP
    DC ULESS
    _0BRANCH(FORGV1)
    _C{ Forget part of contents.}
    DC SWAP
    DC TOR
    DC TWID
    FORGV0:
    ....

    Remember the kernel is code in assembler.

    Groetjes Albert
    --
    "in our communism country Viet Nam, people are forced to be
    alive and in the western country like US, people are free to
    die from Covid 19 lol" duc ha
    albert@spe&ar&c.xs4all.nl &=n http://home.hccnet.nl/a.w.m.van.der.horst

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Jon Nicoll@21:1/5 to Paul Rubin on Fri Nov 4 15:16:18 2022
    On Thursday, November 3, 2022 at 4:36:56 AM UTC, Paul Rubin wrote:
    dxforth <dxf...@gmail.com> writes:
    AFAIK optimizers do a better job when the code presented is already optimal.
    These days optimizers work by first splitting everything out into
    separate variables so that nothing is ever updated (static single
    assignment or SSA form), and then recombining the variables. I have
    never implemented SSA and don't understand it perfectly, but I believe
    the SSA forms of the 4-local and 6-local versions of that code would be
    very similar. Anton would know this much better than I do.
    Well, Moore used VARIABLEs instead of locals,
    Does he?

    I believe so. I remember looking at cmforth and some of the GA144 code
    and seeing variables used that way. I also remember asking Elizabeth
    about the complex multiplication example, and her replying that Moore
    didn't hesitate to use CODE if it made things easier. He wasn't a
    purist about staying with Forth words.

    In the 1970s there just wasn't room for purity in software. Maybe APL
    came closest. Lisp was born from the most purest mathematical
    abstraction (lambda calculus) but its implementations were full of low
    level hackery. The purest language now is Haskell but it is also full
    of hacks.

    I have wondered about that myself - hacks in the implementation of
    'pure' languages. Thanks for these snippets.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From dxforth@21:1/5 to albert on Sat Nov 5 10:46:20 2022
    On 4/11/2022 9:47 pm, albert wrote:
    In article <87tu3gc77i.fsf@nightsong.com>,
    Paul Rubin <no.email@nospam.invalid> wrote:
    This is about as bad at it gets (decompiled, not formatted):
    : FORGET-VOC 2DUP SWAP U< IF SWAP >R >WID BEGIN DUP DUP BEGIN >LFA @
    DUP R@ U< UNTIL SWAP >LFA ! >LFA @ DUP 0= UNTIL DROP R> ELSE >VFA @
    VOC-LINK ! ONLY FORTH DEFINITIONS THEN ;

    I had to guess at the stack effects of the internal words and have no
    idea what the parameters are supposed to mean, but this looks roughly
    like:

    : FORGET-VOC { a b }
    b a u< IF
    b >WID
    BEGIN
    BEGIN b >LFA @ { c } c a U< UNTIL
    b >LFA !
    b 0= UNTIL
    b c a
    ELSE
    a b >VFA @
    VOC-LINK ! ONLY FORTH DEFINITIONS
    THEN ;

    Actually that is probably wrong since there is a different amount of
    stuff on the stack depending on which branch of the IF is taken.
    Some comments and stack diagrams would surely help.

    It was not intended to be analysed, but to show how approximately
    the most complicated words look.

    Fig-Forth's FORGET was simple but it broke once vocabs were added.
    Consequently the code to trim dictionaries back to a usable state
    became ever more complicated as dictionaries became more complicated.
    Whether it was worth it is debatable but that's how it evolved.
    This is for a single-thread, split dictionary with separated headers:

    : (forget) ( nfa dps dp -- )
    dp 2! >r \ starting maximums
    voc-link begin \ trim vocs > nfa
    @ dup cell- @ cell+ \ vocab nfa
    r@ u<
    until dup voc-link !
    begin
    dup cell- @ \ scan remaining vocs
    dup h@ begin
    dup r@ u< 0= \ for each word >= nfa
    while
    -alias if \ not an alias
    dup name> \ get its xt
    xdp tuck @
    umin swap ! \ trim dict
    then
    n>name
    repeat
    swap h!
    @ ?dup 0= \ until all vocs done
    until
    r> dup dph !
    (idph) @ u< if \ below fence?
    protect \ fix bootup values
    then
    prunes ; \ run prunes list

    : EMPTY ( -- )
    forth definitions (idph) @ (idp) 2@ (forget) ;

    : FORGET ( "name" -- )
    get-current context ! name? -alias 0= abort" is alias"
    swap limit over u< if dp @ else dps @ swap then (forget) ;

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From dxforth@21:1/5 to minf...@arcor.de on Sat Nov 5 12:15:51 2022
    On 4/11/2022 12:06 am, minf...@arcor.de wrote:
    dxforth schrieb am Donnerstag, 3. November 2022 um 06:29:37 UTC+1:
    My interest is in discovering whether Moore's system works.

    Did it work for himself? I gathered that he changed it all the time.

    Not the basics AFAIK. No mega-compiler, no locals, no creeping complexity.
    It was those who came after that did all that for one reason or another.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From S Jack@21:1/5 to dxforth on Fri Nov 4 19:38:42 2022
    On Friday, November 4, 2022 at 6:46:23 PM UTC-5, dxforth wrote:

    Fig-Forth's FORGET was simple but it broke once vocabs were added.

    Using Fig and oldest simple vocabularies. Upgraded FORGET to update
    word lists in all existing vocabularies. Didn't bother to fix any
    broken VOC-LINK chain; however, I did fence vocabularies when created.
    If some FORGET includes a vocabulary, fence will alert and the chain
    can be fixed manually. Never had to; not a problem I expect to deal
    with.
    --
    me

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Paul Rubin@21:1/5 to dxforth on Fri Nov 4 20:51:38 2022
    dxforth <dxforth@gmail.com> writes:
    Oh, I'd say organized Forth is absolutely dead. I agree with your
    last line.

    Well, what was organized Forth trying to do when it was alive? Was it
    trying to crank out working code by hook or by crook, or was it trying
    to pursue a vision of stack combinator purity? If it was merely trying
    to crank out code, I still think locals help with that, and haven't seen persuasive reasoning to the contrary. If it was trying to pursue purity
    then obviously locals are a no-no, ok fine. It may make me a philistine
    but I don't think the vision has held up that well. Lambda calculus has
    held up a lot better.

    In Ting's writings I see both approaches. In Jeff Fox's, I can't always
    tell what he is getting at. And Moore sometimes seems to be operating
    in a different world than the rest of us.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From dxforth@21:1/5 to Paul Rubin on Sat Nov 5 17:49:59 2022
    On 5/11/2022 2:51 pm, Paul Rubin wrote:
    dxforth <dxforth@gmail.com> writes:
    Oh, I'd say organized Forth is absolutely dead. I agree with your
    last line.

    Well, what was organized Forth trying to do when it was alive? Was it
    trying to crank out working code by hook or by crook, or was it trying
    to pursue a vision of stack combinator purity? If it was merely trying
    to crank out code, I still think locals help with that, and haven't seen persuasive reasoning to the contrary.

    According to Forth Inc it was quite successful in the Moore era. Can't
    say the same for the standardization efforts which was language created
    by committee.

    And Moore sometimes seems to be operating
    in a different world than the rest of us.

    He did say he didn't create Forth for you. What you do with it is your business.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Marcel Hendrix@21:1/5 to dxforth on Sat Nov 5 03:21:52 2022
    On Saturday, November 5, 2022 at 7:50:11 AM UTC+1, dxforth wrote:
    [..]
    He did say he didn't create Forth for you. What you do with it is your business.

    That effectively kills all discussion. What does it matter then
    what he said, or what you or I say?

    -marcel

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From dxforth@21:1/5 to Marcel Hendrix on Sat Nov 5 22:21:06 2022
    On 5/11/2022 9:21 pm, Marcel Hendrix wrote:
    On Saturday, November 5, 2022 at 7:50:11 AM UTC+1, dxforth wrote:
    [..]
    He did say he didn't create Forth for you. What you do with it is your
    business.

    That effectively kills all discussion. What does it matter then
    what he said, or what you or I say?

    ISTM Paul did that when he said Moore was "operating in a different
    world to the rest of us". Paul has all but said that he won't use
    Forth unless he can use locals. What can one say to that? It would
    appear ANS TC was similarly pressured:

    A.13

    "It has been further argued that users who have elected to become
    dependent on locals tend to be locked into a single vendor and have
    little motivation to join the group that it is hoped will broadly
    accept ANS Forth unless the Standard addresses their problems."

    There's certainly no "purity" there - just the promise of supporters
    for ANS if the TC acquiesced.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Paul Rubin@21:1/5 to dxforth on Sat Nov 5 14:27:29 2022
    dxforth <dxforth@gmail.com> writes:
    ISTM Paul did that when he said Moore was "operating in a different
    world to the rest of us". Paul has all but said that he won't use
    Forth unless he can use locals.

    I haven't said that, I've said that I find locals make Forth easier for
    me to use. I find Forth difficult compared with other languages even
    with locals, but I use it for some things anyway because it is
    interesting.

    There's certainly no "purity" there - just the promise of supporters
    for ANS if the TC acquiesced.

    The TC was an industry group, I thought. As far as I can tell, the
    opposition to locals is more from an artistic perspective than an
    engineering one. I'm fine with doing stuff for artistic reasons, but I
    had imagined that the TC's audience was more concerned with
    practicality.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From dxforth@21:1/5 to Paul Rubin on Sun Nov 6 12:19:26 2022
    On 6/11/2022 8:27 am, Paul Rubin wrote:
    dxforth <dxforth@gmail.com> writes:
    ISTM Paul did that when he said Moore was "operating in a different
    world to the rest of us". Paul has all but said that he won't use
    Forth unless he can use locals.

    I haven't said that, I've said that I find locals make Forth easier for
    me to use. I find Forth difficult compared with other languages even
    with locals, but I use it for some things anyway because it is
    interesting.

    Just about every introductory text to Forth says to minimize variables
    and your response is you find it too difficult.

    There's certainly no "purity" there - just the promise of supporters
    for ANS if the TC acquiesced.

    The TC was an industry group, I thought. As far as I can tell, the opposition to locals is more from an artistic perspective than an
    engineering one.

    RM:
    Do you consider yourself a scientist, an engineer, an artist or a craftsman?

    CM:
    I put ‘engineer’ in the box on forms. Sometimes I put ‘computer engineer’
    in a big box.

    I'm fine with doing stuff for artistic reasons, but I
    had imagined that the TC's audience was more concerned with
    practicality.

    Looks to me they were more interested in numbers. Not that it got them
    many 'happy campers' given the ensuing furore of type of locals. Such
    is politics.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Paul Rubin@21:1/5 to dxforth on Sat Nov 5 23:08:24 2022
    dxforth <dxforth@gmail.com> writes:
    Just about every introductory text to Forth says to minimize variables
    and your response is you find it too difficult.

    If you mean VARIABLEs then of course I want to minimize those. I'm not
    trying to be a wise-acre but I have thought of VARIABLEs and locals as
    distinct things. Locals get rid of the need for (some) variables.

    Looks to me they [the TC] were more interested in numbers. Not that
    it got them many 'happy campers' given the ensuing furore of type of
    locals. Such is politics.

    I don't see the downside. The compromise basically was to add (LOCAL)
    to implementations that didn't already have it. That's a new primitive,
    but the other stuff can be done in terms of it using Forth words. I
    hope that implementing (LOCAL) didn't cause anyone too much pain. Once
    it was there, nobody was required to use it, but it was available for
    those who wanted it.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From dxforth@21:1/5 to Paul Rubin on Sun Nov 6 19:47:13 2022
    On 6/11/2022 5:08 pm, Paul Rubin wrote:
    dxforth <dxforth@gmail.com> writes:
    Just about every introductory text to Forth says to minimize variables
    and your response is you find it too difficult.

    If you mean VARIABLEs then of course I want to minimize those. I'm not trying to be a wise-acre but I have thought of VARIABLEs and locals as distinct things.

    That may be true of other languages which rely on locals as a mechanism
    for parameter passing. It's not true of Forth which uses the stack for
    that. In Forth, locals are just variables to be avoided.

    Looks to me they [the TC] were more interested in numbers. Not that
    it got them many 'happy campers' given the ensuing furore of type of
    locals. Such is politics.

    I don't see the downside. The compromise basically was to add (LOCAL)
    to implementations that didn't already have it. That's a new primitive,
    but the other stuff can be done in terms of it using Forth words. I
    hope that implementing (LOCAL) didn't cause anyone too much pain. Once
    it was there, nobody was required to use it, but it was available for
    those who wanted it.

    Yes - for those who hadn't grasped the difference between Forth and other languages. I'll admit it - I was one of them. The mere inclusion of locals
    in ANS-Forth had me fooled. For quite a long time I thought locals were
    a part of Forth - until a chance reading of a post by Jeff Fox.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Marcel Hendrix@21:1/5 to dxforth on Sun Nov 6 05:15:30 2022
    On Sunday, November 6, 2022 at 9:47:16 AM UTC+1, dxforth wrote:
    On 6/11/2022 5:08 pm, Paul Rubin wrote:
    dxforth <dxf...@gmail.com> writes:
    Yes - for those who hadn't grasped the difference between Forth and other languages. I'll admit it - I was one of them. The mere inclusion of locals
    in ANS-Forth had me fooled. For quite a long time I thought locals were
    a part of Forth - until a chance reading of a post by Jeff Fox.

    Did any of Jeff's Forth code get archived somewhere? I never was able
    to find anything he actually wrote himself.

    -marcel

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From dxforth@21:1/5 to Marcel Hendrix on Mon Nov 7 10:25:55 2022
    On 7/11/2022 12:15 am, Marcel Hendrix wrote:
    On Sunday, November 6, 2022 at 9:47:16 AM UTC+1, dxforth wrote:
    On 6/11/2022 5:08 pm, Paul Rubin wrote:
    dxforth <dxf...@gmail.com> writes:
    Yes - for those who hadn't grasped the difference between Forth and other
    languages. I'll admit it - I was one of them. The mere inclusion of locals >> in ANS-Forth had me fooled. For quite a long time I thought locals were
    a part of Forth - until a chance reading of a post by Jeff Fox.

    Did any of Jeff's Forth code get archived somewhere? I never was able
    to find anything he actually wrote himself.

    There's LZ-4TH.ZIP and ISING.ARC in the Taygeta forth archives from the
    late 80's. From his later period there were his chip emulators which should
    be available from his web pages. Like Moore, very little application code seems to have made it into the public domain. I suppose one could say the
    same of other commercial developers...

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From dxforth@21:1/5 to Marcel Hendrix on Mon Nov 7 14:27:29 2022
    On 7/11/2022 12:15 am, Marcel Hendrix wrote:
    On Sunday, November 6, 2022 at 9:47:16 AM UTC+1, dxforth wrote:
    On 6/11/2022 5:08 pm, Paul Rubin wrote:
    dxforth <dxf...@gmail.com> writes:
    Yes - for those who hadn't grasped the difference between Forth and other
    languages. I'll admit it - I was one of them. The mere inclusion of locals >> in ANS-Forth had me fooled. For quite a long time I thought locals were
    a part of Forth - until a chance reading of a post by Jeff Fox.

    Did any of Jeff's Forth code get archived somewhere? I never was able
    to find anything he actually wrote himself.

    If it's 'local-less' code that you want to see, I believe there's plenty
    of that about already. SwiftForth sources contain relatively few instances
    of locals, often around parameter-heavy API calls. According to an old
    post by Elizabeth I happened to see, SwiftX doesn't support locals at all.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Paul Rubin@21:1/5 to dxforth on Sun Nov 6 20:41:48 2022
    dxforth <dxforth@gmail.com> writes:
    For quite a long time I thought locals were a part of Forth - until a
    chance reading of a post by Jeff Fox.

    It might have been this (3 parts): http://www.ultratechnology.com/forth.htm

    A very interesting article. I read it some years ago (it's one of the
    things that got/kept me interested in Forth) and I just re-read it. It contains wisdom that can be learned from but that I think shouldn't be
    taken too literally.

    Among other ideas in the article:

    - Optimizing compilers are too complicated. It's better for your
    compiler/interpreter to make slow code just to make the implementation
    simpler, because you if your applications are minimalistic enough,
    they will run fast anyway.

    - Blocks instead of files. I thought this one had resolved some decades ago.

    - No floating point arithmetic. Used scaled integers instead, and
    concoct your own measurement units in your app to make the scaled
    arithmetic work out efficiently. He quotes Chuck regarding OKAD:

    I originally chose mV for internal units. But using 6400 mV = 4096
    units replaces a divide with a shift and requires only 2 multiplies
    per transistor.

    - Tail recursion instead of loops. Ok, Haskellers like this too. But I
    thought someone was complaining about it here on clf just recently.

    - "Face the problem, think about it until you can picture the solution
    as about 1K of code or less. Until then you don't really understand it."

    - Eliminate SMUDGE so any reference to an existing word becomes a recursive
    call. If you want to redefine the word, think of a new name for it.
    (I'm not sure I understand this bit--it's in the part about cmForth).

    - Late binding is slow, based on implementating with S" DUP" EVALUATE
    I mean who does that? Late binding to most of us basically means DEFER.

    - Say X X X X X instead of using a loop. CASE is an abomination. Do
    lots of your application at compile time instead of run time, to keep
    stuff out of the final executable. I thought most compilers did that

    - "Removing wordlists is also one of the techniques that greatly
    simplified other words in the system and allowed Chuck to build a 1K
    sized Forth that can compile applications in a click."

    - replace ! and @ with A! and A@, having an A register in the virtual
    machine that also has an autoincrement mode

    Some of this stuff is hardware oriented, some makes sense, and some just
    makes me smile. Got a distributed company and want to run your own
    payroll? Your software will have to deal with the tax codes of 100s of overlapping jurisdictions. Good luck fitting that in 1K of code.
    Software defined radio, video codec, etc.? Same thing. Connect your
    computer to the internet? A 1K TCP stack might be sort of possible, but
    TLS is probably not doable in that. Want it to have wifi or bluetooth?
    Don't get me started.

    The article has no mention of multitasking (Forth's traditional
    cooperative multitasker is breathtakingly simple and is another thing
    that impressed me about Forth). I had thought Polyforth was done by
    Chuck but maybe I'm wrong.

    There's lots more, I've only scratched the surface. So I don't
    understand why it is that locals in particular draw ire while everything
    else skates by.

    Somewhere in the talk of using factoring instead of locals, the need to
    name the factors seems to have forgotten. If avoiding thinking up names
    for the locals speaks in favor of stack juggling, the similar need to
    name small factors shouldn't be ignored. (I usually name factors FOO.1,
    FOO.2 etc. though).

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From minforth@arcor.de@21:1/5 to Paul Rubin on Mon Nov 7 00:25:44 2022
    Paul Rubin schrieb am Montag, 7. November 2022 um 05:41:54 UTC+1:
    dxforth <dxf...@gmail.com> writes:
    For quite a long time I thought locals were a part of Forth - until a chance reading of a post by Jeff Fox.
    It might have been this (3 parts): http://www.ultratechnology.com/forth.htm ...
    There's lots more, I've only scratched the surface. So I don't
    understand why it is that locals in particular draw ire while everything
    else skates by.

    People love hot topics, particularly the heaters love them. Yet it is only
    old stuff warmed up. Couple of years ago it had been OOP etc.

    Those recommendations by Fox/Moore read like coming from a
    (macro) assembler perspective. No surprise there. Forth can be a powerful
    macro assembler.

    But when you have to handle fat data objects in your embedded systems
    you need more adequate tooling. Since Forth can be extended easily,
    why not tool up Forth with what is needed.

    AFAIU exactly THIS was Moore's philosophy. I guess he would have laughed
    at "language purity" arguments.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Anton Ertl@21:1/5 to Paul Rubin on Mon Nov 7 07:42:32 2022
    Paul Rubin <no.email@nospam.invalid> writes:
    It might have been this (3 parts): http://www.ultratechnology.com/forth.htm ...
    Among other ideas in the article:

    - Optimizing compilers are too complicated. It's better for your
    compiler/interpreter to make slow code just to make the implementation
    simpler, because you if your applications are minimalistic enough,
    they will run fast anyway.

    One interesting aspect of our recent work in Gforth is that a number
    of individually simple features synergize to provide optimizations I
    had not foreseen:

    1) The compile-time literal stack (intended for constant folding)

    2) SET-OPTIMIZER that can set the implementation of COMPILE, for each
    word individually.

    E.g., in the general case +LOOP requires relatively complex and slow
    checking of whether the loop should continue or end (in the absence of
    an overflow flag). /LOOP is faster, but works only for positive
    operands. In the typical case the operand is a constant. So, with
    the literal stack we can check if there is a constant operand, and
    whether it is positive, and if so, optimize +LOOP to /LOOP:

    \ optimize +loop (not quite folding)
    : replace-(+loop) ( xt1 -- xt2 )
    case
    ['] (+loop) of ['] (/loop)# endof
    ['] (+loop)-lp+!# of ['] (/loop)#-lp+!# endof
    -21 throw
    endcase ;

    : (+loop)-optimizer ( xt -- )
    lits# 1 u>= if
    lits> dup 0> if
    swap replace-(+loop) peephole-compile, , exit then
    lits then
    peephole-compile, ;

    ' (+loop)-optimizer optimizes (+loop)
    ' (+loop)-optimizer optimizes (+loop)-lp+!#

    OPTIMIZES is like SET-OPTIMIZER, but applies to the word in the input
    stream, not the most recently defined word. This actually optimizes
    LIT n (+LOOP) to (/LOOP)# n, and we don't have /LOOP.

    Of course, one might say that these kinds of optimizations are too
    complicated, but I think that they are individually
    simple and understandable, so are nice.

    - Blocks instead of files. I thought this one had resolved some decades ago.

    The fans of blocks don't try to proselytize on clf anymore, that's
    all.

    - Tail recursion instead of loops. Ok, Haskellers like this too. But I
    thought someone was complaining about it here on clf just recently.

    People who perform return-address manipulation need to know what
    pushes return addresses and what does not. If you have written such
    code for classical Forth, where every call pushes a return address, it
    is likely to break on a Forth that performs tail-call elimination. If
    you have written such code for a Forth system that performs tail-call elimination, it depends on the particular way that tail-call
    elimination is implemented.

    - Eliminate SMUDGE so any reference to an existing word becomes a recursive
    call. If you want to redefine the word, think of a new name for it.
    (I'm not sure I understand this bit--it's in the part about cmForth).

    This has to do with using tail recursion for loops. In classical
    Forth, if you write

    : foo ... if ... foo then ;

    it complains that FOO is undefined (or calls an older definition of
    FOO if there is one).

    - Late binding is slow, based on implementating with S" DUP" EVALUATE
    I mean who does that?

    Some people have been proposing to use EVALUATE im immediate words to
    produce STATE-smart macros (that also have lots of other dependencies
    beyond STATE). I recommend avoiding such practices.

    Late binding to most of us basically means DEFER.

    Well, it's not late name binding, but it can be used for things like
    mutual recursion for which programmers in languages with late name
    binding like Lisp and Postscript use late name binding.

    - Say X X X X X instead of using a loop. CASE is an abomination. Do
    lots of your application at compile time instead of run time, to keep
    stuff out of the final executable. I thought most compilers did that

    I am not aware of Forth compilers that unroll loops. And in any case,
    Jeff Fox would consider that to be a case of a too complicated
    compiler.

    Connect your
    computer to the internet? A 1K TCP stack might be sort of possible, but
    TLS is probably not doable in that.

    The traditionalist answer has been to get rid of the overcomplicated specification, and redesign based on the requirements. Bernd Paysan
    has done that in net2o, and the parts that replace TCP and TLS have
    been done for several years. He does not provide the classical
    network API to make net2o a drop-in replacement for TCP and TLS; maybe
    that would be too complicated, too. Instead, he has gone on to
    implement additional functionality (what's usually in a browser).

    There's lots more, I've only scratched the surface. So I don't
    understand why it is that locals in particular draw ire while everything
    else skates by.

    That's an interesting question. Why did Andrew Haley disparage
    recognizers that require relatively little code, while accepting
    without comment the SUBSTITUTE proposal that requires much more code.
    I think I asked him that, and his answer was along the lines that the
    text interpreter (for which the recognizer proposal would standardize
    a part) is a fundamental part of Forth, while SUBSTITUTE is
    peripheral. Maybe the reason is similar for stack vs. locals.

    There may also be the usual elitism at work. Some programmers brought
    up the hard way think of themselves as elite because of that, and
    resent locals which, if accepted, make all their elite competences
    appear worthless. You can also see the same effect in C where there
    are people who viciously defend undefined behaviour, believe in
    resulting optimization effects of mythical dimensions, and declare
    that anybody who thinks differently should switch to a lesser
    programming language.

    - 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 none) (albert@21:1/5 to Anton Ertl on Mon Nov 7 11:24:25 2022
    In article <2022Nov7.084232@mips.complang.tuwien.ac.at>,
    Anton Ertl <anton@mips.complang.tuwien.ac.at> wrote:
    <SNIP>
    That's an interesting question. Why did Andrew Haley disparage
    recognizers that require relatively little code, while accepting
    without comment the SUBSTITUTE proposal that requires much more code.
    I think I asked him that, and his answer was along the lines that the
    text interpreter (for which the recognizer proposal would standardize
    a part) is a fundamental part of Forth, while SUBSTITUTE is
    peripheral. Maybe the reason is similar for stack vs. locals.

    The poor man's solution of recognizers (PREFIX) comes at the
    cost of two lines in the kernel. And it can't be disparaged for
    the same reason as adding SUBSTITUTE.
    The impact on the text interpreter is invisible.


    - anton

    Groetjes Albert
    --
    "in our communism country Viet Nam, people are forced to be
    alive and in the western country like US, people are free to
    die from Covid 19 lol" duc ha
    albert@spe&ar&c.xs4all.nl &=n http://home.hccnet.nl/a.w.m.van.der.horst

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From none) (albert@21:1/5 to no.email@nospam.invalid on Mon Nov 7 11:16:01 2022
    In article <87r0yf1ilv.fsf@nightsong.com>,
    Paul Rubin <no.email@nospam.invalid> wrote:
    dxforth <dxforth@gmail.com> writes:
    For quite a long time I thought locals were a part of Forth - until a
    chance reading of a post by Jeff Fox.

    It might have been this (3 parts): http://www.ultratechnology.com/forth.htm

    A very interesting article. I read it some years ago (it's one of the
    things that got/kept me interested in Forth) and I just re-read it. It >contains wisdom that can be learned from but that I think shouldn't be
    taken too literally.

    Among other ideas in the article:

    - Optimizing compilers are too complicated. It's better for your
    compiler/interpreter to make slow code just to make the implementation
    simpler, because you if your applications are minimalistic enough,
    they will run fast anyway.

    I only partly agree with this. The basic compiler should be as simple
    as possible. Then when/if you need speed you haven't to content with
    tricks that get in the way. I succeeded in an experimental optimiser
    with ciforth that can optimise the prime counting Byte benchmark
    to the level of Swiftforth or MEP-forth.


    - Blocks instead of files. I thought this one had resolved some decades ago.

    That opinion have overlooked some opportunities. The library that comes
    with ciforth is a block file. It provides a nice granularity, features conditional compilation.The cc allows booting, msdos, MS-windows, linux,
    apple 16/32/64 share the same library.
    Normally ciforth slurps its source file. If you insist having line
    buffered i/o the block buffers serve double duty as file input buffers.


    - No floating point arithmetic. Used scaled integers instead, and
    concoct your own measurement units in your app to make the scaled
    I originally chose mV for internal units. But using 6400 mV = 4096
    units replaces a divide with a shift and requires only 2 multiplies
    per transistor.

    If you have an i86 with a floating point stack implementation fp
    is a small effort. It can come in handy.


    - Tail recursion instead of loops. Ok, Haskellers like this too. But I
    thought someone was complaining about it here on clf just recently.

    - "Face the problem, think about it until you can picture the solution
    as about 1K of code or less. Until then you don't really understand it."

    Exaggeration. Most of my Forth solutions to euler problems (300+)
    qualify though.


    - Eliminate SMUDGE so any reference to an existing word becomes a recursive
    call. If you want to redefine the word, think of a new name for it.
    (I'm not sure I understand this bit--it's in the part about cmForth).

    I'm redefining words as in
    : difficult .... ;
    \ : difficult .s difficult .s ;
    all the time.
    You need to forego this.
    This is to advocate recursion over looping, and then you've got
    do tail-optimisation for reason of return stack overflow.
    Well I call this sectarian drivel.


    - Late binding is slow, based on implementating with S" DUP" EVALUATE
    I mean who does that? Late binding to most of us basically means DEFER.

    Remember FORGET-VOC the other day.

    The phrase `` >NFA @ @ '' is incomprehensible.
    : nt>namelength ">NFA @ @" EVALUATE ; IMMEDIATE
    I contend that the :I that automatically inlines has no such
    disadvantages.
    :I nt>namelength >NFA @ @ ;
    Note >R and I can be used in these inline macro's.


    - Say X X X X X instead of using a loop. CASE is an abomination. Do
    lots of your application at compile time instead of run time, to keep
    stuff out of the final executable. I thought most compilers did that

    The example is of course crc. Most Forth implementations calculate
    the speed up tables at compile time. A c-implementation has to choose
    between an initialisation calculation at run time, or a two stage process
    where tables are included.
    Regards CASE. I think it is superfluous. At least the c switch
    construction allows baffling optimisations.


    - "Removing wordlists is also one of the techniques that greatly
    simplified other words in the system and allowed Chuck to build a 1K
    sized Forth that can compile applications in a click."
    In the Gbyte area I am a proponent of wordlists. It is not
    complicated per se, and it opens a wealth of possibilities
    such as sealing user commands, temporarily loading and trimming
    an assembler etc.


    - replace ! and @ with A! and A@, having an A register in the virtual
    machine that also has an autoincrement mode

    This is micro-optimisation directed at the hardware at hand.


    Some of this stuff is hardware oriented, some makes sense, and some just >makes me smile. Got a distributed company and want to run your own
    payroll? Your software will have to deal with the tax codes of 100s of >overlapping jurisdictions. Good luck fitting that in 1K of code.
    Software defined radio, video codec, etc.? Same thing. Connect your >computer to the internet? A 1K TCP stack might be sort of possible, but
    TLS is probably not doable in that. Want it to have wifi or bluetooth?
    Don't get me started.

    You are of course right. I'd like to have seen the rebuttal of Jeff Fox

    The article has no mention of multitasking (Forth's traditional
    cooperative multitasker is breathtakingly simple and is another thing
    that impressed me about Forth). I had thought Polyforth was done by
    Chuck but maybe I'm wrong.

    There's lots more, I've only scratched the surface. So I don't
    understand why it is that locals in particular draw ire while everything
    else skates by.

    Somewhere in the talk of using factoring instead of locals, the need to
    name the factors seems to have forgotten. If avoiding thinking up names
    for the locals speaks in favor of stack juggling, the similar need to
    name small factors shouldn't be ignored. (I usually name factors FOO.1, >FOO.2 etc. though).

    Valid point. I see professor Veltman's software package schoonschip
    and he ended naming files after his daughters.
    Probably it is asking to much to find a language prowess like
    Bob Dylan's under software developers.

    Groetjes Albert
    --
    "in our communism country Viet Nam, people are forced to be
    alive and in the western country like US, people are free to
    die from Covid 19 lol" duc ha
    albert@spe&ar&c.xs4all.nl &=n http://home.hccnet.nl/a.w.m.van.der.horst

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Marcel Hendrix@21:1/5 to minf...@arcor.de on Mon Nov 7 03:43:24 2022
    On Monday, November 7, 2022 at 9:25:46 AM UTC+1, minf...@arcor.de wrote:
    Paul Rubin schrieb am Montag, 7. November 2022 um 05:41:54 UTC+1:
    dxforth <dxf...@gmail.com> writes:
    For quite a long time I thought locals were a part of Forth - until a chance reading of a post by Jeff Fox.
    It might have been this (3 parts): http://www.ultratechnology.com/forth.htm ...
    There's lots more, I've only scratched the surface. So I don't
    understand why it is that locals in particular draw ire while everything else skates by.
    People love hot topics, particularly the heaters love them. Yet it is only old stuff warmed up. Couple of years ago it had been OOP etc.

    Those recommendations by Fox/Moore read like coming from a
    (macro) assembler perspective. No surprise there. Forth can be a powerful macro assembler.

    But when you have to handle fat data objects in your embedded systems
    you need more adequate tooling. Since Forth can be extended easily,
    why not tool up Forth with what is needed.

    AFAIU exactly THIS was Moore's philosophy. I guess he would have laughed
    at "language purity" arguments.

    Forth has many faces, maybe as many faces as it has users.
    Given a sufficiently powerful system, a domain expert can, and will, extend it in a fashion that quickly becomes completely incomprehensible to other Forth users. CM is a prime example of that. Unfortunately, it does not scale.

    -marcel

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From dxforth@21:1/5 to Anton Ertl on Mon Nov 7 22:19:00 2022
    On 7/11/2022 6:42 pm, Anton Ertl wrote:

    There may also be the usual elitism at work. Some programmers brought
    up the hard way think of themselves as elite because of that, and
    resent locals which, if accepted, make all their elite competences
    appear worthless.

    I agree there's no elitism in bringing locals to a language whose creator expressly refutes them. More a beginner's mistake. Elitism is when they refuse to accept 'No' because they know better.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From minforth@arcor.de@21:1/5 to Marcel Hendrix on Mon Nov 7 05:40:12 2022
    Marcel Hendrix schrieb am Montag, 7. November 2022 um 12:43:26 UTC+1:
    On Monday, November 7, 2022 at 9:25:46 AM UTC+1, minf...@arcor.de wrote:
    Paul Rubin schrieb am Montag, 7. November 2022 um 05:41:54 UTC+1:
    dxforth <dxf...@gmail.com> writes:
    For quite a long time I thought locals were a part of Forth - until a chance reading of a post by Jeff Fox.
    It might have been this (3 parts): http://www.ultratechnology.com/forth.htm
    ...
    There's lots more, I've only scratched the surface. So I don't
    understand why it is that locals in particular draw ire while everything else skates by.
    People love hot topics, particularly the heaters love them. Yet it is only old stuff warmed up. Couple of years ago it had been OOP etc.

    Those recommendations by Fox/Moore read like coming from a
    (macro) assembler perspective. No surprise there. Forth can be a powerful macro assembler.

    But when you have to handle fat data objects in your embedded systems
    you need more adequate tooling. Since Forth can be extended easily,
    why not tool up Forth with what is needed.

    AFAIU exactly THIS was Moore's philosophy. I guess he would have laughed
    at "language purity" arguments.
    Forth has many faces, maybe as many faces as it has users.
    Given a sufficiently powerful system, a domain expert can, and will, extend it
    in a fashion that quickly becomes completely incomprehensible to other Forth users. CM is a prime example of that. Unfortunately, it does not scale.


    True. It is very unfortunate, and perhaps one of the big reasons why Forth is stalling,
    that there is no standardized module or library concept in Forth.

    [ Just one example: I use a comprehensive, battle-proven and fast linear algebra library
    system in Forth. Small enough to run in-the-loop in MCUs. But it requires the presence
    of three other small modules: complex math, dynamic vectors/arrays, basic digital filtering.
    The latter three are no big deal for engineers.

    But it would be unusable for other Forth users. Why? Because the module concept has its own syntax incl. namespace management. It can't use some standard syntax
    because there is none. ]

    Consequence: the Forth software "world" is characterized by inventing wheels over
    and over, and thus creating mutually incomprehensible DSLs every time.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From minforth@arcor.de@21:1/5 to Marcel Hendrix on Mon Nov 7 05:44:53 2022
    Marcel Hendrix schrieb am Montag, 7. November 2022 um 12:43:26 UTC+1:
    Forth has many faces, maybe as many faces as it has users.
    Given a sufficiently powerful system, a domain expert can, and will, extend it
    in a fashion that quickly becomes completely incomprehensible to other Forth users. CM is a prime example of that. Unfortunately, it does not scale.

    True. It is very unfortunate, and perhaps one of the big reasons why Forth is stalling,
    that there is no standardized module or library concept in Forth.

    [ Just one example: I use a comprehensive, battle-proven and fast linear algebra library
    system in Forth. Small enough to run in-the-loop in MCUs. But it requires the presence
    of three other small modules: complex math, dynamic vectors/arrays, basic digital filtering.
    The latter three are no big deal for engineers.

    But it would be unusable for other Forth users. Why? Because the module concept has its own syntax incl. namespace management. It can't use some standard syntax
    because there is none. ]

    Consequence: the Forth software "world" is characterized by re-inventing wheels over
    and over, and thus creating mutually incomprehensible DSLs every time.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From minforth@arcor.de@21:1/5 to dxforth on Mon Nov 7 06:58:48 2022
    dxforth schrieb am Montag, 7. November 2022 um 15:30:41 UTC+1:
    On 7/11/2022 3:41 pm, Paul Rubin wrote:
    dxforth <dxf...@gmail.com> writes:
    For quite a long time I thought locals were a part of Forth - until a
    chance reading of a post by Jeff Fox.

    It might have been this (3 parts): http://www.ultratechnology.com/forth.htm

    A very interesting article. I read it some years ago (it's one of the things that got/kept me interested in Forth) and I just re-read it. It contains wisdom that can be learned from but that I think shouldn't be taken too literally.
    Jeff could be a bit like Hugh but his point that I related about locals in Forth not serving the same function as locals in C is indisputable.

    LOL! No hughish necromancy before next halloween! He might love you too!

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From dxforth@21:1/5 to Paul Rubin on Tue Nov 8 01:30:36 2022
    On 7/11/2022 3:41 pm, Paul Rubin wrote:
    dxforth <dxforth@gmail.com> writes:
    For quite a long time I thought locals were a part of Forth - until a
    chance reading of a post by Jeff Fox.

    It might have been this (3 parts): http://www.ultratechnology.com/forth.htm

    A very interesting article. I read it some years ago (it's one of the
    things that got/kept me interested in Forth) and I just re-read it. It contains wisdom that can be learned from but that I think shouldn't be
    taken too literally.

    Jeff could be a bit like Hugh but his point that I related about locals in Forth not serving the same function as locals in C is indisputable.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Hans Bezemer@21:1/5 to dxforth on Mon Nov 7 08:01:19 2022
    On Monday, November 7, 2022 at 3:30:41 PM UTC+1, dxforth wrote:
    Jeff could be a bit like Hugh but his point that I related about locals in Forth not serving the same function as locals in C is indisputable.
    True. You could let data flow over a stack in C (with a little trouble). However, it's alien to the very concept of C, which uses stack frames
    as its primary data flow mechanism. It's the same way with Forth.
    In Forth, it's the stack - not locals. And locals are as alien.

    Hans Bezemer

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From minforth@arcor.de@21:1/5 to the.bee...@gmail.com on Mon Nov 7 09:06:42 2022
    the.bee...@gmail.com schrieb am Montag, 7. November 2022 um 17:01:21 UTC+1:
    However, it's alien to the very concept of C, which uses stack frames
    as its primary data flow mechanism.

    Modern 64-bit C passes most arguments through CPU registers.
    Times are a-changing ...

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Anton Ertl@21:1/5 to Marcel Hendrix on Mon Nov 7 22:24:24 2022
    Marcel Hendrix <mhx@iae.nl> writes:
    Given a sufficiently powerful system, a domain expert can, and will, extend it >in a fashion that quickly becomes completely incomprehensible to other Forth >users. CM is a prime example of that. Unfortunately, it does not scale.

    I disagree. Chuck Moore's work on Forth is an example that is not
    only comprehensible to others, but has inspired many others to use it,
    adapt it to their needs, extend it, and do their own things with it.
    And it scaled quite well. Thousands of people have used Forth.

    That does not mean that every Forth application written by a domain
    expert will be comprehensible, usable by others, and so on. One has
    to work on that, typically follow a few blind alleys until one finds
    the right way to do things and everythings falls into place. It helps
    to keep both the implementation and the interface simple, it does not
    help to keep the implementation simple at the cost of interface
    complexity. If the interface is easy, but the implementation complex,
    you get a black box, which is not Forth-like, but may or may not be
    successful with users; you will have trouble finding people to
    maintain the black box, though.

    - 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 Anton Ertl@21:1/5 to minf...@arcor.de on Mon Nov 7 22:25:47 2022
    "minf...@arcor.de" <minforth@arcor.de> writes:
    Modern 64-bit C passes most arguments through CPU registers.
    Times are a-changing ...

    C calling conventions on 32-bit architectures such as ARM (1985), MIPS
    (1986), SPARC (1986) etc. all pass parameters through registers.
    Given the age and current status of these architectures, I hesitate to
    call them modern.

    - 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 Paul Rubin@21:1/5 to Anton Ertl on Mon Nov 7 15:06:13 2022
    anton@mips.complang.tuwien.ac.at (Anton Ertl) writes:
    Chuck Moore's work on Forth is an example that is not only
    comprehensible to others, but has inspired many others to use it,
    adapt it to their needs, extend it, and do their own things with it.
    And it scaled quite well. Thousands of people have used Forth.

    Forth itself is useful and inspiring, but when I look at actual Forth
    code written by Chuck Moore, maybe it's just me, but I have found it
    quite incomprehensible. That basically means cmForth and some of his
    GA144 code, so far. I don't know what else is out there.

    It helps to keep both the implementation and the interface simple, it
    does not help to keep the implementation simple at the cost of
    interface complexity.

    The Jeff Fox article calls rather for keeping the implementation simple
    at all costs. For example, having OKAD work in 6400/4096ths of a
    millivolt (or maybe the reciprocal of that) instead of directly in
    millivolts. It seems almost like an extreme caricature of what Dick
    Gabriel called the New Jersey approach in "Worse Is Better" ( https://www.dreamsongs.com/RiseOfWorseIsBetter.html ). And Gabriel's description of the New Jersey approach was itself already a caricature.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Paul Rubin@21:1/5 to minf...@arcor.de on Mon Nov 7 16:01:26 2022
    "minf...@arcor.de" <minforth@arcor.de> writes:
    I wonder if Forth performance could be improved by keeping a larger
    stack segment in CPU registers, than by meanwhile classic
    TOS-only-caching.

    TOS+NOS is also a thing. Mecrisp keeps more stack slots in registers
    but has an actual register allocator, so maybe you meant something
    simpler.

    AFAIU the bottleneck is bringing the stack to its canonical state, but
    this could be reduced by keeping some registers in reserve (top stack
    segment "floating" in CPU registers).

    Mecrisp has some code for tidying the stack like that, but I thought it
    was because the word being compiled didn't know where it was being
    called from, so it had to present a consistent stack picture wherever
    the caller was.

    In the case where the compiler knows there is only one call site, the
    word can be inlined. If there is more than one call site, but they are
    known (say there are 3 of them), I wonder if it's feasible to allocate
    the registers so that the shared stack slots all end up in the same
    registers.

    In the end, passing top stack segments already through registers would
    about eliminate the difference to using locals.

    Once the compiler is that fancy, putting locals in registers seems
    natural.

    Ditzel's original CRISP cpu had a stack cache that may have been almost
    as good as registers. I wonder if something that could come back someday.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From minforth@arcor.de@21:1/5 to Anton Ertl on Mon Nov 7 15:46:51 2022
    Anton Ertl schrieb am Montag, 7. November 2022 um 23:29:52 UTC+1:
    "minf...@arcor.de" <minf...@arcor.de> writes:
    Modern 64-bit C passes most arguments through CPU registers.
    Times are a-changing ...
    C calling conventions on 32-bit architectures such as ARM (1985), MIPS (1986), SPARC (1986) etc. all pass parameters through registers.
    Given the age and current status of these architectures, I hesitate to
    call them modern.

    Yes, the fastcall calling convention offers itself for CPUs having sufficient numbers of registers.

    I wonder if Forth performance could be improved by keeping a larger stack segment in CPU registers, than by meanwhile classic TOS-only-caching.
    AFAIU the bottleneck is bringing the stack to its canonical state, but this could be reduced by keeping some registers in reserve (top stack segment "floating" in CPU registers).

    In the end, passing top stack segments already through registers would
    about eliminate the difference to using locals.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From dxforth@21:1/5 to minf...@arcor.de on Tue Nov 8 11:32:30 2022
    On 8/11/2022 4:06 am, minf...@arcor.de wrote:
    the.bee...@gmail.com schrieb am Montag, 7. November 2022 um 17:01:21 UTC+1:
    However, it's alien to the very concept of C, which uses stack frames
    as its primary data flow mechanism.

    Modern 64-bit C passes most arguments through CPU registers.
    Times are a-changing ...

    Forth and C VM's know nothing about that. See MPE's 'Programming Forth'.

    Jeff remarked locals-in-Forth users would come up with all sorts of rationalizations for doing so, and that's certainly been true.

    "Don't use local variables. Don't come up with new syntaxs for describing
    them and new schemes for implementing them. You can make local variables
    very efficient especially if you have local registers to store them in,
    but don't. It's bad. It's wrong." - C.M.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From dxforth@21:1/5 to Paul Rubin on Tue Nov 8 13:08:18 2022
    On 8/11/2022 10:06 am, Paul Rubin wrote:
    anton@mips.complang.tuwien.ac.at (Anton Ertl) writes:
    Chuck Moore's work on Forth is an example that is not only
    comprehensible to others, but has inspired many others to use it,
    adapt it to their needs, extend it, and do their own things with it.
    And it scaled quite well. Thousands of people have used Forth.

    Forth itself is useful and inspiring, but when I look at actual Forth
    code written by Chuck Moore, maybe it's just me, but I have found it
    quite incomprehensible. That basically means cmForth and some of his
    GA144 code, so far.

    Perhaps because you haven't worked your way up to it. Well, neither have
    I - mainly due to lack of motivation.

    I don't know what else is out there.

    There's plenty of forth code about which demonstrates locals are rarely,
    if ever, needed - and it didn't require a Moore or Fox to do it. If
    dismissing all and focussing on the exceptions that is the game, then who
    is the one being pure and perfect?

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Marcel Hendrix@21:1/5 to Anton Ertl on Mon Nov 7 22:13:50 2022
    On Monday, November 7, 2022 at 11:24:53 PM UTC+1, Anton Ertl wrote:
    Marcel Hendrix <m...@iae.nl> writes:
    [..]
    Chuck Moore's work on Forth is an example that is not
    only comprehensible to others, but has inspired many others to use it,
    adapt it to their needs, extend it, and do their own things with it.
    And it scaled quite well. Thousands of people have used Forth.

    That is meta-true for Forth as a language concept. But how many
    engineers use CM's tools as-is in their daily work?

    -marcel

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Paul Rubin@21:1/5 to dxforth on Mon Nov 7 23:22:38 2022
    dxforth <dxforth@gmail.com> writes:
    There's plenty of forth code about which demonstrates locals are
    rarely, if ever, needed

    Yes, that code shows that stuff can usually or always be done without
    locals. I don't doubt that. What I don't understand is what makes a without-locals version superior to a locals version.

    "Don't use local variables. Don't come up with new syntaxs for
    describing them and new schemes for implementing them. You can make
    local variables very efficient especially if you have local registers
    to store them in, but don't. It's bad. It's wrong." - C.M.

    I doubt C.M. was one for faith in authority, and I haven't yet figured
    out what is in his mind when he says things like that. Ideas that have
    been mentioned:

    1. Locals complicate the compiler. Jeff Fox's essay mentions C.M.'s
    compiler uses just 1K of code. Adding locals would make it bigger.

    2. Locals are less efficient at runtime. They take more cpu cycles.

    3. They use more memory, return stack cells or whatever.

    4.. Locals interfere with some kind of Forth spirituality at which I
    have currently not reached enlightenment. The one true way is
    through commune with the Cosmic Stack Machine.

    My reactions:

    1. Most of us are using bigger compilers already, even non-ANS. For
    example, Mecrisp is around 12K. Gforth is bigger still, but it is ANS,
    so it has already left the path and doesn't count.

    2. Jeff's article is emphatic, it is ok for the code to be slow, or else
    he wouldn't disapprove of optimizing compilers so much. Anyway, this is
    a trade-off that can be visited on a per-word basis.

    3. Ok, running out of memory is a thing in small processors, but it's
    best to get something working and then worry about squeezing stack cells
    if you have to. Premature optimization and all that.

    4. This I have no idea about, but I had thought early on that C.M. saw
    Forth as a spiritual relation of Lisp, even though its formalism is
    completely different. I see that as being mostly about interactive development, code executed at compile time, and simple, user-redefinable syntax, rather than the stack VM per se. So again I don't understand
    the issue with locals. There have even been parsing words for infix
    syntax written for Forth. Locals have to be pretty minor compared to
    that.

    Jeff Fox's essay also said to avoid over-abstraction, but then talks
    about the pure stack VM, which is itself an abstraction inversion when
    run on a register machine.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From dxforth@21:1/5 to Paul Rubin on Tue Nov 8 19:18:26 2022
    On 8/11/2022 6:22 pm, Paul Rubin wrote:
    dxforth <dxforth@gmail.com> writes:
    There's plenty of forth code about which demonstrates locals are
    rarely, if ever, needed

    Yes, that code shows that stuff can usually or always be done without
    locals. I don't doubt that. What I don't understand is what makes a without-locals version superior to a locals version.

    For the same reason forth texts and teachers encourage you not to use
    variables - it stunts your growth as a forth programmer.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From minforth@arcor.de@21:1/5 to Paul Rubin on Tue Nov 8 01:20:24 2022
    Paul Rubin schrieb am Dienstag, 8. November 2022 um 01:01:29 UTC+1:
    "minf...@arcor.de" <minf...@arcor.de> writes:
    I wonder if Forth performance could be improved by keeping a larger
    stack segment in CPU registers, than by meanwhile classic
    TOS-only-caching.
    TOS+NOS is also a thing. Mecrisp keeps more stack slots in registers
    but has an actual register allocator, so maybe you meant something
    simpler.
    AFAIU the bottleneck is bringing the stack to its canonical state, but
    this could be reduced by keeping some registers in reserve (top stack segment "floating" in CPU registers).
    Mecrisp has some code for tidying the stack like that, but I thought it
    was because the word being compiled didn't know where it was being
    called from, so it had to present a consistent stack picture wherever
    the caller was.

    Indeed, too many stack states would increase code size and might even
    prevent inlining. It seems more a feasible technique for VMs with a limited number of primitives. During runtime the stack would probably reside
    in a CPU cache anyway for fast access.

    And, not to forget, the Standard prohibits this kind of optimization, aka
    named stack elements. Instead it stipulates that locals must not use the
    data stack as storage resource. Seems to have become a bit backwoodish
    today.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Anton Ertl@21:1/5 to minf...@arcor.de on Tue Nov 8 10:26:05 2022
    "minf...@arcor.de" <minforth@arcor.de> writes:
    I wonder if Forth performance could be improved by keeping a larger stack >segment in CPU registers, than by meanwhile classic TOS-only-caching.

    When I last measured it (Figure 7-9 of [ertl&gregg05]), keeping only
    one stack item in a register was better than two for single-state
    stack caching (the line labeled "n"), and using the state with one
    stack item in a register as canonical state was not worse then keeping
    more items in a register as canonical state even for multi-state stack
    caching (with the reset to the canonical state happening at basic
    block boundaries). Of course, things may have changed now: With Intel
    and AMD CPUs making register-register moves cost almost nothing, the
    additional moves of using a canonical state with more stack items in
    registers may cost less than the benefit we get from the possible
    reduction in loads and stores.

    AFAIU the bottleneck is bringing the stack to its canonical state, but this >could be reduced by keeping some registers in reserve (top stack segment >"floating" in CPU registers).

    That's multi-state stack caching, and Gforth has used this for a while
    on architectures with enough registers. It does not reset to the
    canonical state between primitives in a basic block.

    In the end, passing top stack segments already through registers would
    about eliminate the difference to using locals.

    Given a compiler that is analytical about stack items of all stacks
    and about locals, and works at the colon definition level (rather than
    the basic block level), I expect essentially the same code from
    keeping data on the stack or keeping it in locals: they all are mapped
    to registers. Now I only have to write such a compiler:-).

    @InProceedings{ertl&gregg05,
    author = {M. Anton Ertl and David Gregg},
    title = {Stack Caching in {Forth}},
    crossref = {euroforth05},
    pages = {6--15},
    url = {http://www.complang.tuwien.ac.at/papers/ertl%26gregg05.ps.gz},
    pdfurl = {http://www.complang.tuwien.ac.at/anton/euroforth2005/papers/ertl%26gregg05.pdf},
    OPTnote = {not refereed},
    abstract = {Stack caching speeds Forth up by keeping stack items
    in registers, reducing the number of memory accesses
    for stack items. This paper describes our work on
    extending Gforth's stack caching implementation to
    support more than one register in the canonical
    state, and presents timing results for the resulting
    Forth system. For single-representation stack
    caches, keeping just one stack item in registers is
    usually best, and provides speedups up to a factor
    of 2.84 over the straight-forward stack
    representation. For stack caches with multiple stack
    representations, using the one-register
    representation as canonical representation is
    usually optimal, resulting in an overall speedup of
    up to a factor of 3.80 (and up to a factor of 1.53
    over single-representation stack caching).}
    }
    @Proceedings{euroforth05,
    title = {21st EuroForth Conference},
    booktitle = {21st EuroForth Conference},
    year = {2005},
    key = {EuroForth'05},
    editor = {M. Anton Ertl},
    url = {http://www.complang.tuwien.ac.at/anton/euroforth2005/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@arcor.de@21:1/5 to Anton Ertl on Tue Nov 8 03:11:04 2022
    Anton Ertl schrieb am Dienstag, 8. November 2022 um 11:44:57 UTC+1:
    Given a compiler that is analytical about stack items of all stacks
    and about locals, and works at the colon definition level (rather than
    the basic block level), I expect essentially the same code from
    keeping data on the stack or keeping it in locals: they all are mapped
    to registers. Now I only have to write such a compiler:-).

    :o) this smells a bit of a stack-state dependent JIT colon def. compiler.
    Piece of cake.

    Peter Fälth demonstrated his system generating the same code with or
    without locals using CPU registers. I am not into wild guessing how, or
    whether some stack caching is involved or not, but it was impressive.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Anton Ertl@21:1/5 to Paul Rubin on Tue Nov 8 09:39:48 2022
    Paul Rubin <no.email@nospam.invalid> writes:
    anton@mips.complang.tuwien.ac.at (Anton Ertl) writes:
    Chuck Moore's work on Forth is an example that is not only
    comprehensible to others, but has inspired many others to use it,
    adapt it to their needs, extend it, and do their own things with it.
    And it scaled quite well. Thousands of people have used Forth.

    Forth itself is useful and inspiring, but when I look at actual Forth
    code written by Chuck Moore, maybe it's just me, but I have found it
    quite incomprehensible. That basically means cmForth and some of his
    GA144 code, so far.

    I find the cmForth code that includes the shadow screens <https://github.com/ForthHub/cmFORTH/blob/combined/cmforth.fth> mostly comprehensible. Of course when he deals with the machine code of his architecture and uses octal numbers for the instructions without
    giving them names first, it's hard to follow, but the shadow screens
    allow you to get the gist of it. E.g., (reformatted for fitting in
    70-char lines):

    \ PACK sets the return bit, if an instruction does not reference
    \ the Return stack. Otherwise it compiles a return. It exits
    \ from EXIT with POP DROP .
    FORTH : PACK ( a n - a) 160257 AND 140201 XOR IF
    40 SWAP +! ELSE DROP 100040 , THEN POP DROP ;

    The Jeff Fox article calls rather for keeping the implementation simple
    at all costs. For example, having OKAD work in 6400/4096ths of a
    millivolt (or maybe the reciprocal of that) instead of directly in >millivolts.

    That's a common technique with fixed-point, and to some extent even
    with FP. In TeX Knuth uses lengths in terms of 1/65536ths of a point
    IIRC.

    It seems almost like an extreme caricature of what Dick
    Gabriel called the New Jersey approach in "Worse Is Better" ( >https://www.dreamsongs.com/RiseOfWorseIsBetter.html ).

    Well, of course what Jeff Fox (or dxforth) wrote may misrepresent the
    positions of Chuck Moore, although we also get some of his own
    writings.

    But anyway, in 1971 Chuck Moore and Ken Thompson (Mr. New Jersey
    approach) were both working on minicomputers of the time, and Moore
    created Forth, and Thompson created Unix. Both Forth and Unix became successful, with Forth switching to micros when they became powerful
    enough, and Unix growing with the minis and switching to micros only
    later in the 1980s. This already shows a difference.

    When micros grew beyond the size of the minis Forth was originally
    designed for, Chuck Moore refused to take advantage of that (in
    particular, he advocated 3 chars+length even when memory was no longer
    so tight that we could not afford the full length; most of the Forth
    community did not follow him in that instance).

    Competition sprung up (e.g., Turbo Pascal) that made use of the
    additional opportunities to provide a more comfortable experience to
    many programmers than Forth. Some of the Forth community jumped over
    to using these things, some tried to make good use of the additional
    memory (but failed in the Valdocs case), some insisted on the
    superiority of the old ways (screens etc.).

    Moore went on to design Forth hardware, OKad, Machine Forth, and
    ColorForth, all of which were less successful than Forth.

    Thompson continued with further research OSs (Plan 9, Inferno), which
    did not become products, and the Go language, which is a product, and
    seems to be quite successful (certainly more successful than Forth is
    these days, and, coming back to Gabriel's paper, probably also more
    successful than Common Lisp).

    - 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 dxforth@21:1/5 to Anton Ertl on Tue Nov 8 23:50:35 2022
    On 8/11/2022 8:39 pm, Anton Ertl wrote:

    Well, of course what Jeff Fox (or dxforth) wrote may misrepresent the positions of Chuck Moore, although we also get some of his own
    writings.

    'You can't trust those two, but you can trust the person who sells them
    down the river.' Did I interpret that correctly? I wouldn't want to be accused of misrepresenting you.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Anton Ertl@21:1/5 to dxforth on Tue Nov 8 18:34:06 2022
    dxforth <dxforth@gmail.com> writes:
    "Don't use local variables. Don't come up with new syntaxs for describing
    them and new schemes for implementing them. You can make local variables
    very efficient especially if you have local registers to store them in,
    but don't. It's bad. It's wrong." - C.M.

    Reference needed.

    - 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 Anton Ertl@21:1/5 to Marcel Hendrix on Tue Nov 8 18:35:06 2022
    Marcel Hendrix <mhx@iae.nl> writes:
    On Monday, November 7, 2022 at 11:24:53 PM UTC+1, Anton Ertl wrote:
    Marcel Hendrix <m...@iae.nl> writes:
    [..]
    Chuck Moore's work on Forth is an example that is not
    only comprehensible to others, but has inspired many others to use it,
    adapt it to their needs, extend it, and do their own things with it.
    And it scaled quite well. Thousands of people have used Forth.

    That is meta-true for Forth as a language concept. But how many
    engineers use CM's tools as-is in their daily work?

    These days, probably not that many. It seems that his Forth systems
    after 1978 (cmForth and ColorForth are known to me, are there others)
    were not very popular. But in any case, if his old (1971-1978) Forth
    had been incomprehensible, Forth would not have seen the takeup it has
    seen. Dean Sanderson would have been unable to design microForth,
    Seltzer and Ragsdale would have been unable to do fig-Forth, and so
    on.

    And I think that given Chuck Moores stance on on rewriting code and
    adapting it for the purpose at hand, he considers the concepts more
    valuable than the 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: https://forth-standard.org/
    EuroForth 2022: https://euro.theforth.net

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Anton Ertl@21:1/5 to Paul Rubin on Tue Nov 8 18:05:06 2022
    Paul Rubin <no.email@nospam.invalid> writes:
    Mecrisp has some code for tidying the stack like that, but I thought it
    was because the word being compiled didn't know where it was being
    called from, so it had to present a consistent stack picture wherever
    the caller was.

    That's a reason for C with its separate compilation or Lisp with its
    dynamic binding, but it's no reason for direct calls in Forth. In
    Forth the direct caller always knows what it calls. So the compiler
    could compile a word such that it expects its inputs in arbitrary
    registers, and puts its output in arbitrary registers, with arbitrary
    registers destroyed by the word. And it can then compile almost all
    direct callers to deal with that interface.

    The exception is direct recursion, where the call typically has to be
    compiled before the word is compllete and you know the individual
    interface. A (not very efficient) way to deal with that is to treat a recursive call like an indirect call; or you compile the paths with
    the recursive calls only after compiling the base case path, then you
    fix the interface, then you compile the remaining paths.

    For indirect calls (EXECUTE, DEFER), a fixed calling convention is
    needed; that can be achieved by providing a wrapper around the
    individual interface.

    Ditzel's original CRISP cpu had a stack cache that may have been almost
    as good as registers. I wonder if something that could come back someday.

    No. There's a reason why nobody imitated CRISP. Although nowadays we
    have hardware that can bypass the actual store->load latency in some
    cases when loading from a recently-stored address, reducing the
    latency from 5 or so to 1 cycle. Still, this does not happen reliably
    enough and it uses load/store unit resources (2 loads and 1 store per
    cycle or somesuch vs. 10 register reads and 5 register writes or
    somesuch), so using registers is still the way to go.

    - 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 Paul Rubin@21:1/5 to Anton Ertl on Tue Nov 8 11:20:43 2022
    anton@mips.complang.tuwien.ac.at (Anton Ertl) writes:
    if [C.M.'s] old (1971-1978) Forth had been incomprehensible, Forth
    would not have seen the takeup it has seen. Dean Sanderson would have
    been unable to design microForth, Seltzer and Ragsdale would have been
    unable to do fig-Forth, and so on... And I think ... [C.M.]
    considers the concepts more valuable than the code.

    Did Sanderson etc. do their implementations by studying C.M.'s source
    code, or did they simply reimplement its behaviour? I find Forth's
    concepts to be mostly understandable. What I found hard to understand
    was the actual Forth code written by C.M. that I looked at. I also
    found fig-Forth to be hard to understand, if that matters. I'm
    unfamiliar with microForth.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From dxforth@21:1/5 to Anton Ertl on Wed Nov 9 09:53:46 2022
    On 9/11/2022 5:34 am, Anton Ertl wrote:
    dxforth <dxforth@gmail.com> writes:
    "Don't use local variables. Don't come up with new syntaxs for describing
    them and new schemes for implementing them. You can make local variables >> very efficient especially if you have local registers to store them in,
    but don't. It's bad. It's wrong." - C.M.

    Reference needed.

    According to Google the source of the quote has been mentioned on c.l.f. on
    at least 38 occasions over the years, most recently:

    https://groups.google.com/g/comp.lang.forth/c/Wcn1OXpDSzI/m/dEyaxHSKAQAJ

    https://groups.google.com/g/comp.lang.forth/c/Wcn1OXpDSzI/m/Q1fWbUCPAQAJ

    The quote from Moore himself:

    https://youtu.be/pSnNy7IpVMg?t=3192

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Hans Bezemer@21:1/5 to Anton Ertl on Wed Nov 9 00:25:22 2022
    On Tuesday, November 8, 2022 at 11:25:56 AM UTC+1, Anton Ertl wrote:
    But anyway, in 1971 Chuck Moore and Ken Thompson (Mr. New Jersey
    approach) were both working on minicomputers of the time, and Moore
    created Forth, and Thompson created Unix. Both Forth and Unix became successful, with Forth switching to micros when they became powerful
    enough, and Unix growing with the minis and switching to micros only
    later in the 1980s. This already shows a difference.
    There are, however, remarkable similarities between the Forth and Unix design. First, in Forth everything is a word. In Unix, everything is a file. Second, in Forth,
    data is passed transparently and implicitly by the stack. In Unix, data can be passed transparently and implicitly by pipes.

    Hans Bezemer

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Anton Ertl@21:1/5 to dxforth on Wed Nov 9 09:33:32 2022
    dxforth <dxforth@gmail.com> writes:
    On 9/11/2022 5:34 am, Anton Ertl wrote:
    dxforth <dxforth@gmail.com> writes:
    "Don't use local variables. Don't come up with new syntaxs for describing >>> them and new schemes for implementing them. You can make local variables >>> very efficient especially if you have local registers to store them in, >>> but don't. It's bad. It's wrong." - C.M.

    Reference needed.

    According to Google the source of the quote has been mentioned on c.l.f. on >at least 38 occasions over the years, most recently:

    https://groups.google.com/g/comp.lang.forth/c/Wcn1OXpDSzI/m/dEyaxHSKAQAJ

    https://groups.google.com/g/comp.lang.forth/c/Wcn1OXpDSzI/m/Q1fWbUCPAQAJ

    More directly, you mean

    http://www.ultratechnology.com/1xforth.htm

    The quote from Moore himself:

    https://youtu.be/pSnNy7IpVMg?t=3192

    Thanks.

    Looking at it again, it's an interesting juxtaposition: First Chuck
    Moore talks about the registers A and R in i21 (and I think he has
    kept them in his more recent cores), which are useful for MOVE, and he
    says that A acts much like a local variable. This leads him to talk
    about locals, which he rejects without giving a reason, and then he
    goes on to talk about variables, which he considers necessary.
    This ties in with some things we have discussed repeatedly over the
    years. One reason for having locals was for implementing words that
    have so many items in constant use that a pure-stack variant is
    cumbersome. An example is MOVE (or, for additional difficulty,
    consider a FAXPY-like[1] word on a system with floats on the data stack).
    The answer of Elizabeth Rather (IIRC) has been that for
    performance-critical words like MOVE, one would write them in assembly language. For me that's an admission that her kind of Forth is
    insufficient for writing these words.

    With Forth in hardware, Chuck Moore could not cop out to a more
    capable assembler, but he still had a need to write MOVE (probably not
    FAXPY), and because traditional Forth was not adequate for that, he
    added A and enhanced the capabilities of R. This inspired some people
    to think about adding registers to Forth (I dimly remember a talk by
    Stephen Pelc), but it seems the idea eventually has not caught on.

    I understand why Moore did these additions, and I can see why he did
    not want to add locals to his system (especially with both stacks only
    6 items deep), but for Forth on general-purpose machines, locals are
    superior to these registers: you can have more of them if needed
    (e.g., for FAXPY), can name them as appropriate, and don't need to
    worry about them being destroyed by a word you call.

    There is one property of A (but not R) and (global) variables that
    locals and the return stack don't have: you can split a word (as far
    as control structures permit) into two parts and data flows through A
    and variables automatically between these parts; with locals you have
    to arrange explicit passing of these values through the stack. One
    can see this as an advantage of A and variables in making factoring
    easy, or one can see this as an advantage of locals in forcing to make
    the data flow explicit and therefore easier to follow. The latter
    advantage is more important for me.

    In any case, in classic Forth Moore had provided two stacks instead of registers despite running on machines that had registers. Why not
    expose some of those registers under names like A and R in classic
    Forth, and why has A and R not caught on in other Forth systems after
    Chuck Moore added them to machine Forth (as the buzz at the time
    shows, people were open to this idea)?

    The stack provides a nice and convenient interfaces between words,
    while register-based interfaces tend to be messy: In any case, you
    have to write code for saving and restoring some registers, which is
    handled automatically in a stack-based interface; moreover, if each
    word has its individual interface for optimum performance, it's hard
    to remember, and if you use a common calling convention, you have to
    write code for complying with it even though you see how you could do
    better by using an individual interface. Better avoid these problems
    and stick to the stack.

    [1] FAXPY ( ra f-x nstridex f-y nstridey ucount -- ) multiplies ra
    with f-x and adds the result to f-y, where f-x and f-y are arrays and
    ucount elements are accessed with strides nstridex and nstridey,
    respectively. This is the Forth float variant of BLAS's SAXPY,
    DAXPY, CAXPY and ZAXPY routines.

    - 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 none) (albert@21:1/5 to no.email@nospam.invalid on Wed Nov 9 11:17:41 2022
    In article <87o7th2qyc.fsf@nightsong.com>,
    Paul Rubin <no.email@nospam.invalid> wrote:
    anton@mips.complang.tuwien.ac.at (Anton Ertl) writes:
    if [C.M.'s] old (1971-1978) Forth had been incomprehensible, Forth
    would not have seen the takeup it has seen. Dean Sanderson would have
    been unable to design microForth, Seltzer and Ragsdale would have been
    unable to do fig-Forth, and so on... And I think ... [C.M.]
    considers the concepts more valuable than the code.

    Did Sanderson etc. do their implementations by studying C.M.'s source
    code, or did they simply reimplement its behaviour? I find Forth's
    concepts to be mostly understandable. What I found hard to understand
    was the actual Forth code written by C.M. that I looked at. I also
    found fig-Forth to be hard to understand, if that matters. I'm
    unfamiliar with microForth.

    ciforth is actually fig-Forth 5.4.0.
    The cvs archive version 1.0 is a copy of a 8086 fig-Forth.
    I changed it gradually to 32 bits and replacing BUILD> DOES> with
    create/does.
    There was no point in time the code was hard to modify or understand.
    There was an insight that create-words have actually two data field,
    (one data pointer) that can independantly be modified. 1]
    There was an insight that literals can be handled by modular,
    all but regular words.
    These required thinking hard to be implemented
    but the fig-Forth code was no hurdle at all.

    1] Ting came to the same insight with C++ implementation.

    Groetjes Albert
    --
    "in our communism country Viet Nam, people are forced to be
    alive and in the western country like US, people are free to
    die from Covid 19 lol" duc ha
    albert@spe&ar&c.xs4all.nl &=n http://home.hccnet.nl/a.w.m.van.der.horst

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Anton Ertl@21:1/5 to Hans Bezemer on Wed Nov 9 10:43:02 2022
    Hans Bezemer <the.beez.speaks@gmail.com> writes:
    There are, however, remarkable similarities between the Forth and Unix design. >First, in Forth everything is a word. In Unix, everything is a file. Second, in Forth,
    data is passed transparently and implicitly by the stack. In Unix, data can be >passed transparently and implicitly by pipes.

    So yes, both systems centered around a few common abstractions, but
    these abstractions were far enough from each other that they show more difference than commonality.

    Comonalities are that they were on small machines, and they were
    somewhat comprehensive systems, while these days we tend to think of
    Unix as OS, and of Forth as a programming language. Both had no
    memory protection (Unix acquired virtual memory only with 3BSD in
    1979), both acquired multi-tasking (and multi-user) pretty soon.

    But the OS/language difference has been there from the start, only
    deepened later; as I wrote in
    <2007Dec2.152201@mips.complang.tuwien.ac.at>:

    |One difference between Forth and Unix from the start was that Unix had
    |files and executables, thus supporting a hard compilation/run-time
    |boundary in programming language implementations (and making
    |programming languages without that restrictions less favoured), having |several programming languages, and requiring an additional interpreter
    |(the shell) for executing programs.

    - 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 dxforth@21:1/5 to Anton Ertl on Wed Nov 9 22:55:32 2022
    On 9/11/2022 8:33 pm, Anton Ertl wrote:
    ...
    One reason for having locals was for implementing words that
    have so many items in constant use that a pure-stack variant is
    cumbersome.

    Both are complicated solutions AFAICS. One has lots of stack
    operations and the other has lots of variables. They're as bad
    as each other. Were folks to see that, they might look for
    another solution.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From none) (albert@21:1/5 to Anton Ertl on Wed Nov 9 14:59:48 2022
    In article <2022Nov9.103332@mips.complang.tuwien.ac.at>,
    Anton Ertl <anton@mips.complang.tuwien.ac.at> wrote:
    <SNIP>

    [1] FAXPY ( ra f-x nstridex f-y nstridey ucount -- ) multiplies ra
    with f-x and adds the result to f-y, where f-x and f-y are arrays and
    ucount elements are accessed with strides nstridex and nstridey, >respectively. This is the Forth float variant of BLAS's SAXPY,
    DAXPY, CAXPY and ZAXPY routines.

    This can be done with nested loops: I and J
    Rejecting local variables and then using I and J
    (actually similar to adding a special A registers.)
    that are a sort of register variables with a special purpose?
    I have to admit that feels like cheating.
    It makes the case for locals stronger, but local
    TO-VALUEs have the same cludgy feeling as I and J.

    I feels like you are not going to be able to program, beyond a
    certain level of complexity.


    - anton

    Groetjes Albert
    --
    "in our communism country Viet Nam, people are forced to be
    alive and in the western country like US, people are free to
    die from Covid 19 lol" duc ha
    albert@spe&ar&c.xs4all.nl &=n http://home.hccnet.nl/a.w.m.van.der.horst

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From antispam@math.uni.wroc.pl@21:1/5 to Paul Rubin on Wed Nov 9 17:07:29 2022
    Paul Rubin <no.email@nospam.invalid> wrote:
    dxforth <dxforth@gmail.com> writes:
    My point was it went from 4 locals to 6 for reasons of style. It may be C-style to expend resources this way (I wouldn't know)

    In C these days, the extra locals wouldn't expend any resources in most cases, since the compiler would optimize them away.

    but I doubt it's Moore's.

    This I don't know. A traditional thread Forth interpreter (Moore's invention) is probably 10x slower than CODE doing the same thing, but
    Moore only used CODE when he had to. If 9x extra compute cycles is
    fine, why are a few memory cells a big deal?

    I think origin of Forth explain this. In his book "PROGRAMMING
    A PROBLEM-ORIENTED-LANGUAGE" Moore write about "programs with
    input". In more clear language he wanted to have interactive
    command processor. For processing user commands even minis
    from 1970 and early micros have enough speed that you can lose
    some (not too much, but factor of 10 is acceptable). OTOH
    some minis were quite small. More writes about 4kB RAM, but
    I think that he could put only very stripped down system on
    such machine, full system that he outlines probably need
    something between 8 and 16 kB RAM (FIG Forth executable is
    slightly bigger than 6kB, but needs extra memory for block
    buffers and for words defined in Forth).

    --
    Waldek Hebisch

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Anton Ertl@21:1/5 to dxforth on Wed Nov 9 17:22:38 2022
    dxforth <dxforth@gmail.com> writes:
    On 9/11/2022 8:33 pm, Anton Ertl wrote:
    ...
    One reason for having locals was for implementing words that
    have so many items in constant use that a pure-stack variant is
    cumbersome.

    Both are complicated solutions AFAICS. One has lots of stack
    operations and the other has lots of variables. They're as bad
    as each other. Were folks to see that, they might look for
    another solution.

    What would be your solution? Elizabeth Rather suggested assembler,
    and I expect that's what Chuck Moore used before doing his own
    hardware. On i21 he then added A and enhanced R.

    - 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@arcor.de@21:1/5 to none albert on Wed Nov 9 09:18:26 2022
    none albert schrieb am Mittwoch, 9. November 2022 um 14:59:51 UTC+1:
    In article <2022Nov...@mips.complang.tuwien.ac.at>,
    Anton Ertl <an...@mips.complang.tuwien.ac.at> wrote:
    <SNIP>

    [1] FAXPY ( ra f-x nstridex f-y nstridey ucount -- ) multiplies ra
    with f-x and adds the result to f-y, where f-x and f-y are arrays and >ucount elements are accessed with strides nstridex and nstridey, >respectively. This is the Forth float variant of BLAS's SAXPY,
    DAXPY, CAXPY and ZAXPY routines.
    This can be done with nested loops: I and J
    Rejecting local variables and then using I and J
    (actually similar to adding a special A registers.)
    that are a sort of register variables with a special purpose?
    I have to admit that feels like cheating.
    It makes the case for locals stronger, but local
    TO-VALUEs have the same cludgy feeling as I and J.


    Any 'reasonable' implementation would use CPU vector registers
    when available. So any argumentation based on single scalar
    stack or local elements (these are the only ones treated in the
    Forth standard) barely counts.

    The BLAS interfaced is explained here: https://www.ibm.com/docs/en/essl/6.2?topic=vss-saxpy-daxpy-caxpy-zaxpy-multiply-vector-by-scalar-add-vector-store-in-vector

    With my non-standard array/buffer/matrix locals I could define this in
    a one-liner:
    : DAXPY { f: ra M: X Y == Y } ra X mscale Y m+ ;
    \ mscale : vectorized scalar multiply
    \ m+ : vectorized add
    Alternatively: looping over all elements and applying fused multiply-add function FMA; there are many ways to Rome.

    So limiting oneself to what the Standard or Mr. Moore said or not said
    is close to mental self-multilation IMO.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Anton Ertl@21:1/5 to albert@cherry. on Wed Nov 9 17:26:10 2022
    albert@cherry.(none) (albert) writes:
    In article <2022Nov9.103332@mips.complang.tuwien.ac.at>,
    Anton Ertl <anton@mips.complang.tuwien.ac.at> wrote:
    <SNIP>

    [1] FAXPY ( ra f-x nstridex f-y nstridey ucount -- ) multiplies ra
    with f-x and adds the result to f-y, where f-x and f-y are arrays and >>ucount elements are accessed with strides nstridex and nstridey, >>respectively. This is the Forth float variant of BLAS's SAXPY,
    DAXPY, CAXPY and ZAXPY routines.

    This can be done with nested loops: I and J

    Please demonstrate. I see only one loop.

    Rejecting local variables and then using I and J
    (actually similar to adding a special A registers.)
    that are a sort of register variables with a special purpose?
    I have to admit that feels like cheating.

    Unlike the A register, the loop parameters are stack-managed.

    But note that machine Forth (and, I think, colorForth) has no
    ?DO...LOOP.

    So let's do a few Forth variants of AXPY (the integer sibling of
    FAXPY, probably not needed by anyone, but similar to what we would see
    for FAXPY with 1-cell floats; all untested):

    \ Gforth with locals
    : axpy1 {: na a-x nstridex a-y nstridey ucount -- :}
    a-x a-y ucount 0 ?do {: a-x1 a-y1 :}
    a-x1 @ na * a-y1 +!
    a-x1 nstridex + a-y1 nstridey + loop
    2drop ;

    \ Standard Forth without locals
    : axpy2 ( na a-x nstridex a-y nstridey ucount -- )
    >r >r rot r> swap rot r> 0 do ( na nstridex nstridey a-x1 a-y1 )
    over @ 5 pick * over +!
    2over rot + >r + r> loop
    2drop 2drop drop ;

    \ Standard Forth without locals, loop, and with tail recursion (machine-Forth-like)
    : axpy3 ( na a-x nstridex a-y nstridey ucount -- )
    dup 0> if
    4 pick @ 6 pick * 3 pick +!
    >r dup >r + >r dup >r + r> r> r> r> 1- recurse
    then ;

    Ok, writing AXPY2 and AXPY3 was not too hard, but reading is a
    different issue.

    I guess that Chuck Moore would consider the stride parameters to be
    too general and would eliminate them; and that's usually also a good
    idea on current general-purpose architectures: try to arrange your
    data so that the x and y array elements you access are contiguous,
    possibly by copying them around first (which pays off if you then
    access the array more than once); and in Forth splitting axpy into rearrangement, computation, and rearrangement (with the rearrangement
    steps hopefully unnecessary) would reduce the number of needed items
    accessed in each 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: https://forth-standard.org/
    EuroForth 2022: https://euro.theforth.net

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From minforth@arcor.de@21:1/5 to anti...@math.uni.wroc.pl on Wed Nov 9 11:03:16 2022
    anti...@math.uni.wroc.pl schrieb am Mittwoch, 9. November 2022 um 18:07:31 UTC+1:
    Paul Rubin <no.e...@nospam.invalid> wrote:
    dxforth <dxf...@gmail.com> writes:
    My point was it went from 4 locals to 6 for reasons of style. It may be C-style to expend resources this way (I wouldn't know)

    In C these days, the extra locals wouldn't expend any resources in most cases, since the compiler would optimize them away.

    but I doubt it's Moore's.

    This I don't know. A traditional thread Forth interpreter (Moore's invention) is probably 10x slower than CODE doing the same thing, but
    Moore only used CODE when he had to. If 9x extra compute cycles is
    fine, why are a few memory cells a big deal?

    I think origin of Forth explain this. In his book "PROGRAMMING
    A PROBLEM-ORIENTED-LANGUAGE" Moore write about "programs with
    input". In more clear language he wanted to have interactive
    command processor. For processing user commands even minis
    from 1970 and early micros have enough speed that you can lose
    some (not too much, but factor of 10 is acceptable). OTOH
    some minis were quite small. More writes about 4kB RAM, but
    I think that he could put only very stripped down system on
    such machine, full system that he outlines probably need
    something between 8 and 16 kB RAM (FIG Forth executable is
    slightly bigger than 6kB, but needs extra memory for block
    buffers and for words defined in Forth).

    To get a feeling (nostalgic for us oldtimers) for the available "interactive command processors" of that time, watch:

    https://www.youtube.com/watch?v=_DTpQ4Kk2wA

    It is not about Forth but about APL, a very interesting matrix processing language. But those teletype terminals had been high luxury. We poor
    students had to shuffle shoe boxes full with stacks of punch cards around... ;o)

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Paul Rubin@21:1/5 to Anton Ertl on Wed Nov 9 13:23:21 2022
    anton@mips.complang.tuwien.ac.at (Anton Ertl) writes:
    Unix as OS, and of Forth as a programming language. Both had no
    memory protection (Unix acquired virtual memory only with 3BSD in
    1979), both acquired multi-tasking (and multi-user) pretty soon.

    Unix had memory protection on the PDP-11, long before it got virtual
    memory. The PDP-11/40 and friends had memory segments with protection registers, so processes couldn't clobber each other or reach into the
    kernel. With earlier models (11/20, PDP-7 etc.) you could crash a whole timesharing system by having a pointer bug in your program. I thought
    that Unix had multi-tasking from the beginning, but am not sure.

    I'd be interested to know if Forth used memory protection on machines
    that had it in that era.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Anton Ertl@21:1/5 to minf...@arcor.de on Wed Nov 9 21:59:50 2022
    "minf...@arcor.de" <minforth@arcor.de> writes:
    none albert schrieb am Mittwoch, 9. November 2022 um 14:59:51 UTC+1:
    In article <2022Nov...@mips.complang.tuwien.ac.at>,
    Anton Ertl <an...@mips.complang.tuwien.ac.at> wrote:
    <SNIP>

    [1] FAXPY ( ra f-x nstridex f-y nstridey ucount -- ) multiplies ra
    with f-x and adds the result to f-y, where f-x and f-y are arrays and
    ucount elements are accessed with strides nstridex and nstridey,
    respectively. This is the Forth float variant of BLAS's SAXPY,
    DAXPY, CAXPY and ZAXPY routines.
    ...
    Any 'reasonable' implementation would use CPU vector registers
    when available. So any argumentation based on single scalar
    stack or local elements (these are the only ones treated in the
    Forth standard) barely counts.

    The point of the example is not how to get a fast FAXPY on a
    mainstream CPU, but how to deal with the many values that are all used
    in the loop.

    With my non-standard array/buffer/matrix locals I could define this in
    a one-liner:
    : DAXPY { f: ra M: X Y == Y } ra X mscale Y m+ ;
    \ mscale : vectorized scalar multiply
    \ m+ : vectorized add

    The question is: How have you implemented MSCALE and M+? If it's not
    in Forth, this indicates that Forth is not up to the task, which one
    may consider to be ok, or which one may consider to be a challenge to
    make Forth more versatile.

    And wrt 1xForth, how would one implement FAXPY or AXPY on machine
    Forth for i21?

    - 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@arcor.de@21:1/5 to Anton Ertl on Wed Nov 9 15:22:42 2022
    Anton Ertl schrieb am Mittwoch, 9. November 2022 um 23:09:30 UTC+1:
    With my non-standard array/buffer/matrix locals I could define this in
    a one-liner:
    : DAXPY { f: ra M: X Y == Y } ra X mscale Y m+ ;
    \ mscale : vectorized scalar multiply
    \ m+ : vectorized add
    The question is: How have you implemented MSCALE and M+? If it's not
    in Forth, this indicates that Forth is not up to the task, which one
    may consider to be ok, or which one may consider to be a challenge to
    make Forth more versatile.

    Those exemplary vector words could be implemented in slow high-level Forth
    but are actually primitives using AVX operators.

    But this is besides the point. F.ex. in a scalar imperative language one has to add
    matrices in a nested loop (here in C form, Forth would be similar):
    for (i = 0; i < n; i++)
    for (j = 0; j < n; j++)
    a[i][j] += b[i][j];
    In a language that supports arrays one would just write A = A + B. Nothing spectacular in many high-level languages.

    The challenge had been how to bring this concept into Forth, so that the
    code remains embeddable without having to pull in external algebra libraries.

    Solution elements:
    1) a matrix stack (similar to a dynamic string stack, nothing new)
    matrix elements are just fat pointers to the "real" arrays/vectors in heap 2) global matrix values (they have a name)
    3) matrix locals (they have names too)
    4) some elementary words to operate with a.m. matrices (elementary linear
    algebra, some I/O)

    From a programmers perspective the most important element of these became matrix locals. Not because they replaced equivalent matrix stack juggling,
    but because they have NAMES!

    Algorithms prototyped in MATLAB/SIMULINK can now be "transported"
    literally into Forth without reengineering. The syntax only looks like a postfix Matlab formulation. Finetuning follows in Forth.

    I am not selling anything here. But the discussion in this thread whether locals
    are evil practice, and that real programmers instead factor longish stack ops like hell into small digestible chunks is complete BS.

    Why? Because locals are means towards higher abstraction and solution orientation!
    See my example.

    Torturing a stack machine is hidden sadism. ;o)

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From dxforth@21:1/5 to Anton Ertl on Thu Nov 10 11:27:30 2022
    On 10/11/2022 4:22 am, Anton Ertl wrote:
    dxforth <dxforth@gmail.com> writes:
    On 9/11/2022 8:33 pm, Anton Ertl wrote:
    ...
    One reason for having locals was for implementing words that
    have so many items in constant use that a pure-stack variant is
    cumbersome.

    Both are complicated solutions AFAICS. One has lots of stack
    operations and the other has lots of variables. They're as bad
    as each other. Were folks to see that, they might look for
    another solution.

    What would be your solution? Elizabeth Rather suggested assembler,
    and I expect that's what Chuck Moore used before doing his own
    hardware. On i21 he then added A and enhanced R.

    Firstly I don't see more variables and variable operations as a
    solution. Apparently many do. When 99% of the world of the world's
    languages is using variables both to solve its problems and craft
    its functions, it's perhaps no surprise forthers will also come to
    see them as a solution too - such is the conscious (and unconscious)
    bias.

    For cherry-picked worst-case examples used to justify locals, if
    hand-coded assembler does a better job than either stack or locals,
    what's wrong with that?

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From dxforth@21:1/5 to minf...@arcor.de on Thu Nov 10 11:49:58 2022
    On 10/11/2022 10:22 am, minf...@arcor.de wrote:
    ...
    Torturing a stack machine is hidden sadism. ;o)

    Don't do it then. Force-feeding stack machines with locals to produce
    a C result, is akin to force-feeding geese to produce “foie gras” :)

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Marcel Hendrix@21:1/5 to dxforth on Wed Nov 9 22:18:09 2022
    On Thursday, November 10, 2022 at 1:27:32 AM UTC+1, dxforth wrote:
    [..]
    For cherry-picked worst-case examples used to justify locals, if
    hand-coded assembler does a better job than either stack or locals,
    what's wrong with that?

    You need *very* "complicated" matrix-math to have a simple micro do
    embedded control of the switched-mode power supplies that are
    literally everywhere. One can set about implementing everything in
    Forth from scratch, but it will take a single person a decade to get
    a debugged library that is good enough to start experimenting
    with the real problems at hand. (I am talking from experience).

    Now some people may want to take this route, others may prefer
    to start with the real problem and work back to the minimum
    that is needed in their Forth to get results. In such a case one
    wants minf's approach.

    In Forth, the problem is that the libraries developed with such
    approaches work only on certain machines for certain persons,
    and that the certain persons have absolutely no problems with
    that.

    -marcel

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From none) (albert@21:1/5 to All on Thu Nov 10 09:59:48 2022
    In article <676b958b-5bce-46e0-9dab-bbc9599af1edn@googlegroups.com>,
    <SNIP>
    The challenge had been how to bring this concept into Forth, so that the
    code remains embeddable without having to pull in external algebra libraries.

    Solution elements:
    1) a matrix stack (similar to a dynamic string stack, nothing new)
    matrix elements are just fat pointers to the "real" arrays/vectors in heap
    2) global matrix values (they have a name)
    3) matrix locals (they have names too)
    4) some elementary words to operate with a.m. matrices (elementary linear
    algebra, some I/O)

    Given that you rarely needs generate matrix in a recursive fashion,
    isolation by wordlist is a feasible solution.
    Heap beats stack. If I wanted to program in this vein, I surely
    wanted to ALLOCATE matrices.
    So in fact 2 and 3 require no special measures in a Forth.


    From a programmers perspective the most important element of these became >matrix locals. Not because they replaced equivalent matrix stack juggling, >but because they have NAMES!

    Right.


    Groetjes Albert
    --
    "in our communism country Viet Nam, people are forced to be
    alive and in the western country like US, people are free to
    die from Covid 19 lol" duc ha
    albert@spe&ar&c.xs4all.nl &=n http://home.hccnet.nl/a.w.m.van.der.horst

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From dxforth@21:1/5 to Marcel Hendrix on Thu Nov 10 20:24:04 2022
    On 10/11/2022 5:18 pm, Marcel Hendrix wrote:
    On Thursday, November 10, 2022 at 1:27:32 AM UTC+1, dxforth wrote:
    [..]
    For cherry-picked worst-case examples used to justify locals, if
    hand-coded assembler does a better job than either stack or locals,
    what's wrong with that?

    You need *very* "complicated" matrix-math to have a simple micro do
    embedded control of the switched-mode power supplies that are
    literally everywhere. One can set about implementing everything in
    Forth from scratch, but it will take a single person a decade to get
    a debugged library that is good enough to start experimenting
    with the real problems at hand. (I am talking from experience).

    I'm not aware Moore promised ready-made solutions, or said programmers
    would have the capacity to do it themselves. What Standard Forth
    promised, I leave to its administration to elucidate.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Anton Ertl@21:1/5 to Paul Rubin on Thu Nov 10 17:35:42 2022
    Paul Rubin <no.email@nospam.invalid> writes:
    anton@mips.complang.tuwien.ac.at (Anton Ertl) writes:
    if [C.M.'s] old (1971-1978) Forth had been incomprehensible, Forth
    would not have seen the takeup it has seen. Dean Sanderson would have
    been unable to design microForth, Seltzer and Ragsdale would have been
    unable to do fig-Forth, and so on... And I think ... [C.M.]
    considers the concepts more valuable than the code.

    Did Sanderson etc. do their implementations by studying C.M.'s source
    code, or did they simply reimplement its behaviour?

    <https://www.forth.com/resources/forth-programming-language/#233_Influences>: |Although Sanderson worked closely with Moore and shared most of his
    |basic philosophies, differences in style and approach were
    |inevitable. But the major new influence came from the broader customer
    |base that resulted from the wider marketing of microFORTH. It was
    |customer pressure that brought back multiprogramming, and this larger |customer base also caused standards groups to form.

    <https://www.forth.com/resources/forth-programming-language/#31_The_Forth_Interest_Group>:
    |Ragsdale then looked for someone with the knowledge of microFORTH and |intimate familiarity with the 6502 to port a version of microFORTH to
    |the 6502. He found Maj. Robert Selzer, who had used microFORTH for an
    |AMI 6800 development system on an Army project and was privately
    |developing a standalone editor/assembler/linker package for the
    |6502. Selzer wrote a 6502 Forth assembler, and used the Army’s
    |microFORTH metacompiler to target compile the first 6502 stand-alone
    |Forth for the Jolt single board computer.
    |
    |Selzer and Ragsdale subsequently made substantial modifications and |improvements to the model

    That's all I know about that topic.

    What I found hard to understand
    was the actual Forth code written by C.M. that I looked at. I also
    found fig-Forth to be hard to understand, if that matters. I'm
    unfamiliar with microForth.

    Can you give examples? Both figForth and cmForth have been documented extensively by C.H. Ting ("System Guide to fig-Forth" and "Footsteps
    in an Empty Valley"), but I found I could understand <https://github.com/ForthHub/cmFORTH/blob/combined/cmforth.fth> for
    the most part with just the code and the shadow screens. I have not
    looked at fig-Forth for a long time, but looking at it again, it lacks stack-effect comments, but with knowledge of the stack effects and
    some of the principles behind fig-Forth most of the code is quite understandable to me.

    - 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 Anton Ertl@21:1/5 to dxforth on Thu Nov 10 18:35:35 2022
    dxforth <dxforth@gmail.com> writes:
    On 10/11/2022 4:22 am, Anton Ertl wrote:
    What would be your solution? Elizabeth Rather suggested assembler,
    and I expect that's what Chuck Moore used before doing his own
    hardware. On i21 he then added A and enhanced R.

    Firstly I don't see more variables and variable operations as a
    solution. Apparently many do. When 99% of the world of the world's >languages is using variables both to solve its problems and craft
    its functions, it's perhaps no surprise forthers will also come to
    see them as a solution too - such is the conscious (and unconscious)
    bias.

    This does not tell me how you would solve the problem.

    For cherry-picked worst-case examples used to justify locals, if
    hand-coded assembler does a better job than either stack or locals,
    what's wrong with that?

    It's not Forth. Also, people who reject locals usually claim that a
    good Forth programmer can do without them, and typically there are
    also claims made that factoring is helpful.

    Concerning "cherry-picked example", one example is enough to refute a
    general claim.

    - 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 Anton Ertl@21:1/5 to minf...@arcor.de on Thu Nov 10 18:06:41 2022
    "minf...@arcor.de" <minforth@arcor.de> writes:
    Anton Ertl schrieb am Mittwoch, 9. November 2022 um 23:09:30 UTC+1:
    With my non-standard array/buffer/matrix locals I could define this in
    a one-liner:
    : DAXPY { f: ra M: X Y == Y } ra X mscale Y m+ ;
    \ mscale : vectorized scalar multiply
    \ m+ : vectorized add
    The question is: How have you implemented MSCALE and M+? If it's not
    in Forth, this indicates that Forth is not up to the task, which one
    may consider to be ok, or which one may consider to be a challenge to
    make Forth more versatile.

    Those exemplary vector words could be implemented in slow high-level Forth >but are actually primitives using AVX operators.
    ...
    Solution elements:
    1) a matrix stack (similar to a dynamic string stack, nothing new)
    matrix elements are just fat pointers to the "real" arrays/vectors in heap
    2) global matrix values (they have a name)
    3) matrix locals (they have names too)
    4) some elementary words to operate with a.m. matrices (elementary linear
    algebra, some I/O)

    That's somewhat similar to my vector work (see references below and my incomplete implementation <https://github.com/AntonErtl/vectors>),
    except that there are no vector locals (you could have them by using
    V! on a cell-sized local buffer), and I am not sure whether your
    global matrix corresponds to what I do by V!ing to a variable.

    My implementation is based on generating GNU C code for the various
    words from Forth, compiling this code and dynamically linking the
    result; this code uses the GNU C extension <https://gcc.gnu.org/onlinedocs/gcc/extensions-to-the-c-language-family/using-vector-instructions-through-built-in-functions.html>.
    There is also a slow path in standard Forth.

    I find this state of affairs unsatisfying. I think that we should be
    able to write such code in Forth and get competetive performance.

    @InProceedings{ertl17,
    author = {M. Anton Ertl},
    title = {{SIMD} and Vectors},
    crossref = {euroforth17},
    pages = {25--36},
    url = {http://www.euroforth.org/ef17/papers/ertl.pdf},
    video = {https://wiki.forth-ev.de/lib/exe/fetch.php/events:ef2017:simd-vectors.mp4},
    OPTnote = {refereed},
    abstract = {Many programs have parts with significant data
    parallelism, and many CPUs provide SIMD instructions
    for processing data-parallel parts faster. The weak
    link in this chain is the programming language. We
    propose a vector wordset so that Forth programmers
    can make use of SIMD instructions to speed up the
    data-parallel parts of their applications. The
    vector wordset uses a separate vector stack
    containing opaque vectors with run-time determined
    length. Preliminary results using one benchmark
    show a factor~8 speedup of a simple vector
    implementation over scalar Gforth code, a smaller
    (factor 1.8) speedup over scalar VFX code; another
    factor of 3 is possible on this benchmark with a
    more sophisticated implementation. However, vectors
    have an overhead; this overhead is amortized in this
    benchmark at vector lengths between 3 and 250
    (depending on which variants we compare).}
    }

    @Proceedings{euroforth17,
    title = {33rd EuroForth Conference},
    booktitle = {33rd EuroForth Conference},
    year = {2017},
    key = {EuroForth'17},
    url = {http://www.complang.tuwien.ac.at/anton/euroforth/ef17/papers/proceedings.pdf}
    }

    @InProceedings{ertl18manlang,
    author = {M. Anton Ertl},
    title = {Software Vector Chaining},
    booktitle = {15th International Conference on Managed Languages &
    Runtimes (Manlang'18)},
    year = {2018},
    pages = {Article-18},
    url = {http://www.complang.tuwien.ac.at/papers/ertl18manlang.pdf},
    doi = {10.1145/3237009.3237021},
    abstract = {Providing vectors of run-time determined length as
    opaque value types is a good interface between the
    machine-level SIMD instructions and portable
    application-oriented programming languages.
    Implementing vector operations requires a loop that
    breaks the vector into SIMD-register-sized chunks.
    A compiler can fuse the loops of several vector
    operations together. However, during normal
    compilation this is only easy if no other control
    structures are involved. This paper explores an
    alternative: collect a trace of vector operations at
    run-time (following the program control flow during
    this collecting step), and then perform the combined
    vector loop. This arrangement has a certain
    run-time overhead, but its implementation is simpler
    and can happen independently, in a library.
    Preliminary performance results indicate that the
    overhead makes this approach beneficial only for
    long vectors ($>1$KB). For shorter vectors, unfused
    loops should be used in a library setting.
    Fortunately, this choice can be made at run time,
    individually for each vector operation.}
    }

    @InProceedings{ertl18chaining,
    author = {M. Anton Ertl},
    title = {Software Vector Chaining},
    crossref = {euroforth18},
    pages = {54-55},
    url = {http://www.euroforth.org/ef18/papers/ertl-chaining.pdf},
    url-slides = {http://www.euroforth.org/ef18/papers/ertl-chaining-slides.pdf},
    video = {https://wiki.forth-ev.de/doku.php/events:ef2018:vectors},
    OPTnote = {presentation slides, paper published at Manlang'18},
    abstract = {Providing vectors of run-time determined length as
    opaque value types is a good interface between the
    machine-level SIMD instructions and portable
    application-oriented programming languages.
    Implementing vector operations requires a loop that
    breaks the vector into SIMD-register-sized chunks.
    A compiler can fuse the loops of several vector
    operations together. However, during normal
    compilation this is only easy if no other control
    structures are involved. This paper explores an
    alternative: collect a trace of vector operations at
    run-time (following the program control flow during
    this collecting step), and then perform the combined
    vector loop. This arrangement has a certain
    run-time overhead, but its implementation is simpler
    and can happen independently, in a library.
    Preliminary performance results indicate that the
    overhead makes this approach beneficial only for
    long vectors ($>1$KB). For shorter vectors, unfused
    loops should be used in a library setting.
    Fortunately, this choice can be made at run time,
    individually for each vector operation.}
    }

    @Proceedings{euroforth18,
    title = {34th EuroForth Conference},
    booktitle = {34th EuroForth Conference},
    year = {2018},
    key = {EuroForth'18},
    url = {http://www.euroforth.org/ef18/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 Paul Rubin@21:1/5 to dxforth on Thu Nov 10 12:47:40 2022
    dxforth <dxforth@gmail.com> writes:
    For cherry-picked worst-case examples used to justify locals, if
    hand-coded assembler does a better job than either stack or locals,
    what's wrong with that?

    The worst-case examples are where using pure stack ops causes pain so excruciating that it stops your work, unless some other approach is
    found.

    But there are also more numerous non-worst-case examples, where the
    stack ops cause only moderate pain that doesn't completely stop the
    work. It only distracts from the work and slows it down. This pain is endurable, but I still don't understand why inviting it on purpose is
    not masochism.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From dxforth@21:1/5 to Paul Rubin on Fri Nov 11 12:04:46 2022
    On 11/11/2022 7:47 am, Paul Rubin wrote:
    dxforth <dxforth@gmail.com> writes:
    For cherry-picked worst-case examples used to justify locals, if
    hand-coded assembler does a better job than either stack or locals,
    what's wrong with that?

    The worst-case examples are where using pure stack ops causes pain so excruciating that it stops your work, unless some other approach is
    found.

    Pure variable ops cause pain to forthers. What now?

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From minforth@arcor.de@21:1/5 to Anton Ertl on Thu Nov 10 16:29:44 2022
    Anton Ertl schrieb am Donnerstag, 10. November 2022 um 19:35:00 UTC+1:
    That's somewhat similar to my vector work (see references below and my incomplete implementation <https://github.com/AntonErtl/vectors>),
    except that there are no vector locals (you could have them by using
    V! on a cell-sized local buffer), and I am not sure whether your
    global matrix corresponds to what I do by V!ing to a variable.

    My implementation is based on generating GNU C code for the various
    words from Forth, compiling this code and dynamically linking the
    result; this code uses the GNU C extension <https://gcc.gnu.org/onlinedocs/gcc/extensions-to-the-c-language-family/using-vector-instructions-through-built-in-functions.html>.
    There is also a slow path in standard Forth.

    I find this state of affairs unsatisfying. I think that we should be
    able to write such code in Forth and get competetive performance.

    AFAIU your project it has a more generic approach to map a rather
    comprehensive range of SIMD instructions to Forth words that operate
    on a stack of vectors with different data types.

    My system is much narrower ie. application-oriented. Coding of vector-numeric primitives
    is somewhat like described here: https://www.codeproject.com/Articles/874396/Crunching-Numbers-with-AVX-and-AVX Vectors in my applications are mostly time series of measured/calculated data. So the requirements are more special/narrower than generic.

    Matrix/vector values and locals occupy just 2 cells: heap memory address plus encoded
    data info. Matrices/vectors in heap comprise dimensions, type info, signal tag, etc. pvelus
    of course the vector "data string". For instance, vector addition uses the type info
    to select the suitable intrinsic instruction. Kind of dumb operator overloading,
    but coded within the primitive, without generic Forth words like in your project

    As to further developing your vector project, with all due respect, I doubt that this path leads to
    more satisfactory results simply because there is way too much variety between CPU
    generations and brands (and C compilers). I would leave those SIMD/AVX instructions
    in their assembler or bultins/intrinsics world, but you may of course have other ideas
    of which I am not aware.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From dxforth@21:1/5 to Anton Ertl on Fri Nov 11 13:05:13 2022
    On 11/11/2022 5:35 am, Anton Ertl wrote:
    dxforth <dxforth@gmail.com> writes:
    On 10/11/2022 4:22 am, Anton Ertl wrote:
    What would be your solution? Elizabeth Rather suggested assembler,
    and I expect that's what Chuck Moore used before doing his own
    hardware. On i21 he then added A and enhanced R.

    Firstly I don't see more variables and variable operations as a
    solution. Apparently many do. When 99% of the world of the world's
    languages is using variables both to solve its problems and craft
    its functions, it's perhaps no surprise forthers will also come to
    see them as a solution too - such is the conscious (and unconscious)
    bias.

    This does not tell me how you would solve the problem.

    By avoiding them. If my hands are so tied that I can't, I'll go for
    the least worst option. AFAIR I've never used locals - at least not
    in code written for myself as I consider them lazy and promiscuous.

    For cherry-picked worst-case examples used to justify locals, if
    hand-coded assembler does a better job than either stack or locals,
    what's wrong with that?

    It's not Forth.

    Since when. ISTR Moore saying something to the effect portability
    was a myth.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lars Brinkhoff@21:1/5 to Paul Rubin on Fri Nov 11 07:40:35 2022
    Paul Rubin wrote:
    Blocks instead of files. I thought this one had resolved some decades
    ago.

    I'm using blocks in my day job right now. What do bare metal Forths
    with things like flash storage do these days?

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From minforth@arcor.de@21:1/5 to Lars Brinkhoff on Thu Nov 10 23:58:50 2022
    Lars Brinkhoff schrieb am Freitag, 11. November 2022 um 08:40:38 UTC+1:
    Paul Rubin wrote:
    Blocks instead of files. I thought this one had resolved some decades
    ago.

    I'm using blocks in my day job right now. What do bare metal Forths
    with things like flash storage do these days?

    Blocks are still viable. Huffman-compressed text takes less storage.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Anton Ertl@21:1/5 to minf...@arcor.de on Fri Nov 11 07:41:33 2022
    "minf...@arcor.de" <minforth@arcor.de> writes:
    For instance, vector addition uses the type info
    to select the suitable intrinsic instruction. Kind of dumb operator overloading,
    but coded within the primitive, without generic Forth words like in your project

    I think I decided to let the programmer specify the type mainly to
    follow Forth tradition, but also to avoid the need to decide what
    happens when the programmer wants to mix types. E.g.,

    ( dfv1 dfv2 ) vdup 0e df>=vs ( dfv1 dfv2 xv ) andv ( dfv1 dfv3 ) df+v ( dfv4 )

    When ANDV sees a vector of DFs (64-bit floats) and a vector of Xs
    (64-bit integers), what should the result be? I as programmer know
    that I want to mask the FP numbers here, but on another occasion I
    might want to extract the mantissa fields or somesuch. The most
    plausible result is that ANDV produces a bit-vector. When an
    overloading +v sees a DF vector and a bit vector, what kind of
    addition should it do? With DF+V, it's clear that it should do a DF
    addition.

    But this issue can be resolved (e.g., by explicitly specifying the
    result type of the ANDV), and maybe overloaded operators are
    preferable in the end. Normally Forth has few types (cells and
    double-cells, sometimes with unsigned variants, characters in memory,
    and one float type on the FP stack), while there are 10 different
    vector types in my vector wordset; it may be that this is too much
    mental load on the programmer and that the Forth system should take
    care of that.

    As to further developing your vector project, with all due respect, I doubt that this path leads to
    more satisfactory results simply because there is way too much variety between CPU
    generations and brands (and C compilers). I would leave those SIMD/AVX instructions
    in their assembler or bultins/intrinsics world, but you may of course have other ideas
    of which I am not aware.

    It's not sure which path you mean. The current implementation deals
    with the variety between architectures by delegating it to gcc. The
    difference between CPUs supporting more or fewer instruction set
    extensions can be dealt with by compiling for the CPU variety at hand.
    Given that the C code is in principle compiled when the vector wordset
    is loaded, this could relatively straightforward; in practice the
    compiled code is cached, and currently the caching does not take the
    CPU variant into account.

    In a path I would hope for we provide lower-level SIMD facilities
    directly in Forth so that we don't need to defect to C or assembly
    language. That path would suffer from the vastness of the SIMD
    instruction sets, so it needs a lot of effort, and we may not see
    enough interest in that path and its benefits to make this effort.
    But in a hypothetical future where Forth occupies the close-to-machine
    space that C is retreating from we should be taking this path.

    - 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 none) (albert@21:1/5 to dxforth@gmail.com on Fri Nov 11 10:25:44 2022
    In article <tkkako$1sl1$1@gioia.aioe.org>, dxforth <dxforth@gmail.com> wrote: <SNIP>

    Since when. ISTR Moore saying something to the effect portability
    was a myth.

    He was wrong. gcc and gforth are portable to an undeniable extent.
    Hell, programs written in ciforth are portable across a spectrum
    of OSes.

    The only point he can possibly contest, is that he don't think it's
    worth the effort.

    We recently discussed the compiling of pforth. There was a hitch and
    it ultimately succeeded. This cannot be compared with writing pforth
    from scratch.

    Groetjes Albert

    --
    "in our communism country Viet Nam, people are forced to be
    alive and in the western country like US, people are free to
    die from Covid 19 lol" duc ha
    albert@spe&ar&c.xs4all.nl &=n http://home.hccnet.nl/a.w.m.van.der.horst

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From dxforth@21:1/5 to albert on Fri Nov 11 21:08:03 2022
    On 11/11/2022 8:25 pm, albert wrote:
    In article <tkkako$1sl1$1@gioia.aioe.org>, dxforth <dxforth@gmail.com> wrote:
    <SNIP>

    Since when. ISTR Moore saying something to the effect portability
    was a myth.

    He was wrong. gcc and gforth are portable to an undeniable extent.
    Hell, programs written in ciforth are portable across a spectrum
    of OSes.

    The only point he can possibly contest, is that he don't think it's
    worth the effort.

    We recently discussed the compiling of pforth. There was a hitch and
    it ultimately succeeded. This cannot be compared with writing pforth
    from scratch.

    I chased down some references re Moore on portability. Folks can make
    of them what they will. It's with good reason he's a thorn to many :)

    http://www.ultratechnology.com/antiansi.htm http://www.ultratechnology.com/levels.htm

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From none) (albert@21:1/5 to minf...@arcor.de on Fri Nov 11 10:17:37 2022
    In article <1155bad1-7e20-47e4-b7b5-b53c82390b4cn@googlegroups.com>, minf...@arcor.de <minforth@arcor.de> wrote:
    Lars Brinkhoff schrieb am Freitag, 11. November 2022 um 08:40:38 UTC+1:
    Paul Rubin wrote:
    Blocks instead of files. I thought this one had resolved some decades
    ago.

    I'm using blocks in my day job right now. What do bare metal Forths
    with things like flash storage do these days?

    Blocks are still viable. Huffman-compressed text takes less storage.

    The way I use blocks is wasting 40%, compared to regular text files, but the overhead allows the library to be organized as a database of sorts.
    It could be compressed to 25% for transporting.
    On the other hand, the library don't take a zillion files, and is the
    same accross linux apple and MS, and 16/32/64.

    250 Kbyte. This include an assembler, floating point, a full screen
    editor for MSDOS, compilation and scripting (not in the kernel),
    debugging tools, and tools that install on a hard disk, other tools.
    Space is not everything.

    It is not all that hard to come up with a ISO compatible FILE wordset
    in MSP430. Willem Ouwerkerk did it.
    I have made a FILE wordset, that uses a tig Gbyte memory stick,
    that should work on a OS that handles the USB communication to the stick.

    Groetjes Albert
    --
    "in our communism country Viet Nam, people are forced to be
    alive and in the western country like US, people are free to
    die from Covid 19 lol" duc ha
    albert@spe&ar&c.xs4all.nl &=n http://home.hccnet.nl/a.w.m.van.der.horst

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From minforth@arcor.de@21:1/5 to Anton Ertl on Fri Nov 11 02:53:55 2022
    Anton Ertl schrieb am Freitag, 11. November 2022 um 09:45:37 UTC+1:
    "minf...@arcor.de" <minf...@arcor.de> writes:
    For instance, vector addition uses the type info
    to select the suitable intrinsic instruction. Kind of dumb operator overloading,
    but coded within the primitive, without generic Forth words like in your project
    I think I decided to let the programmer specify the type mainly to
    follow Forth tradition, but also to avoid the need to decide what
    happens when the programmer wants to mix types. E.g.,

    ( dfv1 dfv2 ) vdup 0e df>=vs ( dfv1 dfv2 xv ) andv ( dfv1 dfv3 ) df+v ( dfv4 )

    When ANDV sees a vector of DFs (64-bit floats) and a vector of Xs
    (64-bit integers), what should the result be? I as programmer know
    that I want to mask the FP numbers here, but on another occasion I
    might want to extract the mantissa fields or somesuch. The most
    plausible result is that ANDV produces a bit-vector. When an
    overloading +v sees a DF vector and a bit vector, what kind of
    addition should it do? With DF+V, it's clear that it should do a DF
    addition.

    But this issue can be resolved (e.g., by explicitly specifying the
    result type of the ANDV), and maybe overloaded operators are
    preferable in the end. Normally Forth has few types (cells and
    double-cells, sometimes with unsigned variants, characters in memory,
    and one float type on the FP stack), while there are 10 different
    vector types in my vector wordset; it may be that this is too much
    mental load on the programmer and that the Forth system should take
    care of that.

    Forth is typeless, so for compound data (strings, structures, vector strides etc)
    it can only "pass by reference" not "pass by value". Or one has to set
    up special stacks for each data type which is cumbersome. And one has to
    decide whether a <T>DUP just copies the reference address/pointer or also
    the data payload which means slow cloning. A hypothetical vector wordset would have to make such decisions, because SIMD instructions work with compound groups of cells.

    IOW there are many things to consider before making a vector wordset really usable
    and profitable for more runtime speed.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Andy Valencia@21:1/5 to albert@cherry. on Fri Nov 11 07:19:22 2022
    albert@cherry.(none) (albert) writes:
    I'm using blocks in my day job right now. What do bare metal Forths
    with things like flash storage do these days?
    Blocks are still viable. Huffman-compressed text takes less storage.
    The way I use blocks is wasting 40%, compared to regular text files,
    ...

    I have never, in any day job, had a need for my text storage to be
    compressed. I'm aware of outliers like Wikireader:

    https://en.wikipedia.org/wiki/Wikireader

    but they are simply that--outliers. ForthOS (block based) uses less
    than 1 megabyte for _all_ the system source in block format. I'd be
    hard pressed to find a target where I could metacompile and didn't have
    the flash budget for that kind of storage. Or where the compressed
    format (about half a meg) would save the day.

    It's much more interesting to compare and contrast times when
    viewing data block-style content is easier or harder than looking at
    it as a byte stream. Sort of like communication over TCP streams
    or UDP packets (or UDP with a companion reliable delivery mechanism
    on top).

    Andy Valencia
    Home page: https://www.vsta.org/andy/
    To contact me: https://www.vsta.org/contact/andy.html

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Paul Rubin@21:1/5 to Lars Brinkhoff on Fri Nov 11 13:55:00 2022
    Lars Brinkhoff <lars.spam@nocrew.org> writes:
    I'm using blocks in my day job right now. What do bare metal Forths
    with things like flash storage do these days?

    Blocks might be viable in some environments like that, but it seems like
    a narrow niche. Implementing blocks in a Forth hosted under an OS that
    has files seems silly.

    In a bare metal MCU Forth with flash storage and USB (Raspberry Pi Pico,
    say), a FAT filesystem is very useful since it allows mounting the MCU
    as a flash drive and transferring files super conveniently. It does
    take up some code space but the Pico has plenty. A smaller processor
    like an Arduino has less code space, but also too little RAM for block
    buffers. You have to hunt around to find an MCU with just the right
    specs to make blocks attractive.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From dxforth@21:1/5 to Paul Rubin on Sat Nov 12 10:46:48 2022
    On 12/11/2022 8:55 am, Paul Rubin wrote:
    Lars Brinkhoff <lars.spam@nocrew.org> writes:
    I'm using blocks in my day job right now. What do bare metal Forths
    with things like flash storage do these days?

    Blocks might be viable in some environments like that, but it seems like
    a narrow niche. Implementing blocks in a Forth hosted under an OS that
    has files seems silly.

    When character calls to the file-based OS prove too slow, you implement
    a local block and communicate with that :)

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From none) (albert@21:1/5 to no.email@nospam.invalid on Sat Nov 12 12:56:23 2022
    In article <877d012m2z.fsf@nightsong.com>,
    Paul Rubin <no.email@nospam.invalid> wrote:
    Lars Brinkhoff <lars.spam@nocrew.org> writes:
    I'm using blocks in my day job right now. What do bare metal Forths
    with things like flash storage do these days?

    Blocks might be viable in some environments like that, but it seems like
    a narrow niche. Implementing blocks in a Forth hosted under an OS that
    has files seems silly.

    In a bare metal MCU Forth with flash storage and USB (Raspberry Pi Pico, >say), a FAT filesystem is very useful since it allows mounting the MCU
    as a flash drive and transferring files super conveniently. It does
    take up some code space but the Pico has plenty. A smaller processor
    like an Arduino has less code space, but also too little RAM for block >buffers. You have to hunt around to find an MCU with just the right
    specs to make blocks attractive.

    Using a FAT file-system on flash is the pinnacle of ridiculousness.
    It is base on the notion of cylinder,track, sector subdivision.
    Actually a flash file system is based on blocks.
    There is a more sensible format:
    Tape archive, from POSIX 1003.1-1990.
    It was intended for tapes, but it is equally useful for flash,
    the option to random access blocks adds to their usefulness.
    The POSIX standard has full blown options to store any file properties,
    long and case sensitive file names, owners etc.
    It was easy to implement it. Most effort went into the file properties,
    there was a lot of them.

    Linux allows mounting tape archives.

    filetar.frt :
    308 lines, total 836 words of codes.
    (I cold publish it here, if wanted)

    A POSIX tape archive can be dumped on tape, pardon flash
    using dd.

    Groetjes Albert
    --
    "in our communism country Viet Nam, people are forced to be
    alive and in the western country like US, people are free to
    die from Covid 19 lol" duc ha
    albert@spe&ar&c.xs4all.nl &=n http://home.hccnet.nl/a.w.m.van.der.horst

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Anton Ertl@21:1/5 to minf...@arcor.de on Sat Nov 12 18:18:26 2022
    "minf...@arcor.de" <minforth@arcor.de> writes:
    Forth is typeless,

    That's a misnomer. Forth has a bunch of types, e.g., signed single
    integers, unsigned double integers, characters, addresses, floats.

    so for compound data (strings, structures, vector strides etc)
    it can only "pass by reference" not "pass by value". Or one has to set
    up special stacks for each data type which is cumbersome. And one has to >decide whether a <T>DUP just copies the reference address/pointer or also
    the data payload which means slow cloning. A hypothetical vector wordset would >have to make such decisions, because SIMD instructions work with compound >groups of cells.

    My existing (high-level) vector wordset has value semantics, not
    reference semantics. Each vector has a length in bytes. What the
    bytes mean is up to the programmer; but given that there is already
    some meta-data with each vector, adding the type to the meta-data
    would be a small step.

    VDUP is a relatively cheap operation (implementation-wise it copies a
    pointer and increases a reference count), because the value semantics
    come from the lack of operations that change existing vectors, not
    from always copying the data around.

    For a low-level SIMD wordset my current thinking is to reflect the
    SIMD registers of the architecture at hand in a stack. E.g., on a CPU
    with AVX2 we would have a stack of 256-bit items. The interpretation
    of the bits would be up to the operation you perform, as it is on the architectures (and currently in my high-level vector wordset).

    - 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 Paul Rubin@21:1/5 to albert@cherry. on Sat Nov 12 14:44:50 2022
    albert@cherry.(none) (albert) writes:
    Using a FAT file-system on flash is the pinnacle of ridiculousness.

    Everybody does it now. Buy a USB pen drive at the store and it will
    already be formatted for FAT.

    It is base on the notion of cylinder,track, sector subdivision.

    Doesn't matter, that just gets mapped to a block number (LBA
    translation). Windows systems still use FAT even though computers
    mostly have SSD's now instead of spinning discs.

    There is a more sensible format:
    Tape archive, from POSIX 1003.1-1990.

    It is not so easy to modify those, add new files, delete them, etc. It
    is an archive format, not a file system.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From dxforth@21:1/5 to Paul Rubin on Sun Nov 13 15:01:50 2022
    On 7/11/2022 3:41 pm, Paul Rubin wrote:
    ...
    I had thought Polyforth was done by Chuck but maybe I'm wrong.

    It's been reported Polyforth was a combined effort between several Forth Inc staff and Moore. Moore would later go on to say:

    "Forth doesn't need to be complicated. Classic Forth started out simple, it
    gradually accreted layers of complexity. At Forth Inc. that kind of became
    the company culture. We had this package and we were selling it and we were
    exploiting it and we were stuck with it."

    Vendors are stuck, Standard Forth is stuck, the majority of languages are stuck -
    thanks to the need to be backwards compatible. To do otherwise would be to alienate the customer base.

    There's lots more, I've only scratched the surface. So I don't
    understand why it is that locals in particular draw ire while everything
    else skates by.

    Perhaps because of the propaganda that 'stack juggling' is rife in forth
    and locals somehow solve it.

    Somewhere in the talk of using factoring instead of locals, the need to
    name the factors seems to have forgotten. If avoiding thinking up names
    for the locals speaks in favor of stack juggling, the similar need to
    name small factors shouldn't be ignored. (I usually name factors FOO.1, FOO.2 etc. though).

    Factors are subroutines which deserve to be named. Variables deserve to be named. Items on a stack do not - as Jeff Fox explained.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From none) (albert@21:1/5 to no.email@nospam.invalid on Sun Nov 13 11:11:51 2022
    In article <8735an3i8t.fsf@nightsong.com>,
    Paul Rubin <no.email@nospam.invalid> wrote:
    albert@cherry.(none) (albert) writes:
    Using a FAT file-system on flash is the pinnacle of ridiculousness.

    Everybody does it now. Buy a USB pen drive at the store and it will
    already be formatted for FAT.

    It is base on the notion of cylinder,track, sector subdivision.

    Doesn't matter, that just gets mapped to a block number (LBA
    translation). Windows systems still use FAT even though computers
    mostly have SSD's now instead of spinning discs.

    It does matter: complicated, different formats, and royalties over
    32 Gbyte to be payed to Microsoft (as I remember correctly).

    You will be hard pressed to find a FAT within 800 words of code.
    Pretty please point me to a FAT stack that can run on a
    single board computers.


    There is a more sensible format:
    Tape archive, from POSIX 1003.1-1990.

    It is not so easy to modify those, add new files, delete them, etc. It
    is an archive format, not a file system.

    Most pen drive are used as an archive anyway.
    \ ISO (sc - ior)
    : DELETE-FILE '(OPEN-EXISTING-FILE)
    CATCH DUP IF NIP NIP EXIT THEN DROP
    &X typechar C! DUP 'write-header
    CATCH DUP IF NIP EXIT THEN DROP
    fd[] NONE SWAP ! 0 ;

    Was that hard?

    I guess you mean that it is not fit to replace a real
    disk, with random deletions and creations *all the time*.
    Might I remember you how the track record is from FAT
    under these circumstance?
    I rather write a defragger for POSIX 1003.1-1990.

    Groetjes Albert
    --
    "in our communism country Viet Nam, people are forced to be
    alive and in the western country like US, people are free to
    die from Covid 19 lol" duc ha
    albert@spe&ar&c.xs4all.nl &=n http://home.hccnet.nl/a.w.m.van.der.horst

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Anton Ertl@21:1/5 to Paul Rubin on Sun Nov 13 18:42:11 2022
    Paul Rubin <no.email@nospam.invalid> writes:
    albert@cherry.(none) (albert) writes:
    Using a FAT file-system on flash is the pinnacle of ridiculousness.

    Everybody does it now. Buy a USB pen drive at the store and it will
    already be formatted for FAT.

    A USB stick (and also an SSD) has a flash translation layer (FTL) that
    emulates a system with 512-Byte blocks on the flash device. For a raw
    flash device (i.e., without FTL) FAT is not a good idea. It would be
    slow and it would wear out the FAT (meta-data) blocks quickly. One
    file system designed for raw flash is JFFS2.

    - 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 Marcel Hendrix@21:1/5 to minf...@arcor.de on Sun Nov 13 12:11:57 2022
    On Sunday, November 13, 2022 at 8:38:55 PM UTC+1, minf...@arcor.de wrote:
    [..]
    Once again this demonstrates that a Forth in C can save a lot of pain.

    That is a big step... In iForth all the OS and external library stuff is located
    in a server that is written in C and Fortran. iForth is written in itself. Externals are accessed through numbered system calls. This makes
    it easy to support different operating systems and their various revisions.

    -marcel

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From minforth@arcor.de@21:1/5 to Anton Ertl on Sun Nov 13 11:38:53 2022
    Anton Ertl schrieb am Sonntag, 13. November 2022 um 19:51:39 UTC+1:
    Paul Rubin <no.e...@nospam.invalid> writes:
    albert@cherry.(none) (albert) writes:
    Using a FAT file-system on flash is the pinnacle of ridiculousness.

    Everybody does it now. Buy a USB pen drive at the store and it will
    already be formatted for FAT.
    A USB stick (and also an SSD) has a flash translation layer (FTL) that emulates a system with 512-Byte blocks on the flash device. For a raw
    flash device (i.e., without FTL) FAT is not a good idea. It would be
    slow and it would wear out the FAT (meta-data) blocks quickly. One
    file system designed for raw flash is JFFS2.

    Such deep level details are usually hidden from the unsuspecting user
    through a suitable API library, f.ex.: https://docs.arduino.cc/tutorials/portenta-h7/reading-writing-flash-memory#block-device-blocks

    Once again this demonstrates that a Forth in C can save a lot of pain.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Paul Rubin@21:1/5 to dxforth on Sun Nov 13 15:31:23 2022
    dxforth <dxforth@gmail.com> writes:
    It's been reported Polyforth was a combined effort between several
    Forth Inc staff and Moore. Moore would later go on to say:... "Forth
    doesn't need to be complicated. Classic Forth started out simple..."

    Ok, but did classic Forth have multitasking? Is Moore known to have
    approved of it, or maybe disapproved? Do the current Forth purists have
    a view on the matter?

    Perhaps because of the propaganda that 'stack juggling' is rife in forth
    and locals somehow solve it.

    I didn't think it was under debate that stack juggling is confusing.
    Locals are one approach to dealing with it, maybe a barbaric one. The
    purist alternative is to instead use finer grained factoring.

    Both of those approaches introduce more names into the program. So
    whatever drawbacks locals might have, "they make the programmer think up
    more names" doesn't seem to be one. In fact, locals usually have
    re-usable temporary names like "a" and "b", while factor names usually
    have to be globally unique.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Paul Rubin@21:1/5 to albert@cherry. on Sun Nov 13 15:56:51 2022
    albert@cherry.(none) (albert) writes:
    [FAT] It does matter: complicated, different formats, and royalties
    over 32 Gbyte to be payed to Microsoft (as I remember correctly).

    No, you are thinking of VFAT and NTFS, which had some obstacles like
    that in the past but I think not in the present. I'm pretty sure FAT32
    never had such an issue. VFAT was the FAT extension that allowed long filenames with arbitrary characters, but FAT32 file systems with 8.3
    filenames work fine on large disks. Per Wikipedia it supports up to 2TB
    with 512 byte sectors or 16TB with 4KB sectors. After that I guess you
    have to use partitions.

    You will be hard pressed to find a FAT within 800 words of code.

    What is special about the number "800 words of code"? And why on earth
    should it matter in a context where disks above 32GB are an issue?

    Pretty please point me to a FAT stack that can run on a
    single board computers.

    Do you have a particular SBC in mind? Do you mean a flash stick that
    plugs into a USB host port on the SBC? Yes, that exists (for SBC's with
    host ports), but maybe of more relevance, small SBC's now often have
    on-board flash memory and a USB client port. So when you plug the SBC
    into a host computer's USB port, it appears as a file system, and you
    can drag and drop files, edit them, and so on. That is terrifically
    pleasant and convenient. Here is a board that I have used that way:

    https://www.adafruit.com/product/3501

    You plug it in and your application source code is there on the "USB
    drive". You can edit it on your PC with your favorite text editor,
    save the file with the usual editing command instead of needing a
    special tool, reload it in the interpreter, and run it.

    I believe the Raspberry Pi Pico Micropython environment works the same
    way, though I haven't tried it. I think it would be great to have a
    Forth environment for the Pico that was similar. I remember 4e4th which
    ran on a 4 euro MSP430 board. The Pico is even cheaper at 4 USD and it
    has 2MB of on-board flash, which is plenty for this approach. The
    Adafruit board that I mentioned has only 256KB, which is a little bit
    cramped, but is still very nice.

    It is not so easy to modify those, add new files, delete them, etc. It
    is an archive format, not a file system.

    Most pen drive are used as an archive anyway.
    : DELETE-FILE '(OPEN-EXISTING-FILE) ...
    Was that hard?

    I have no idea what exactly that did (overwrote a file header in the
    middle of a tar archive, in a way that didn't mess up the rest of the archive?), but what if you want to edit a file?

    I guess you mean that it is not fit to replace a real
    disk, with random deletions and creations *all the time*.
    Might I remember you how the track record is from FAT
    under these circumstance?

    FAT works fine for that. In the hard disk era you did have to defrag
    now and then. So what?

    I rather write a defragger for POSIX 1003.1-1990.

    So POSIX 1003.1-1990 and FAT both need defragging. That doesn't sound
    like an advantage for POSIX 1003.1-1990.

    FAT isn't great, it is crap in some ways, but it is very universal.
    Imagine how usable Forth would be if it didn't support decimal numbers
    for input and output. There are some things worth doing to accomodate
    human users, even if they aren't the most technically convenient things
    to do.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From dxforth@21:1/5 to Paul Rubin on Mon Nov 14 13:16:15 2022
    On 14/11/2022 10:31 am, Paul Rubin wrote:
    dxforth <dxforth@gmail.com> writes:
    It's been reported Polyforth was a combined effort between several
    Forth Inc staff and Moore. Moore would later go on to say:... "Forth
    doesn't need to be complicated. Classic Forth started out simple..."

    Ok, but did classic Forth have multitasking? Is Moore known to have
    approved of it, or maybe disapproved? Do the current Forth purists have
    a view on the matter?

    See 2.4.3.6 Multiprogramming

    https://www.forth.com/resources/forth-programming-language/


    Perhaps because of the propaganda that 'stack juggling' is rife in forth
    and locals somehow solve it.

    I didn't think it was under debate that stack juggling is confusing.
    Locals are one approach to dealing with it, maybe a barbaric one. The
    purist alternative is to instead use finer grained factoring.

    Stack juggling implies there are too many items on the stack. Fix that and
    you may not need variables.

    Both of those approaches introduce more names into the program.

    With differing effect. Factors reduce code complexity, whereas variables maintain it.

    So whatever drawbacks locals might have, "they make the programmer think up more names" doesn't seem to be one. In fact, locals usually have
    re-usable temporary names like "a" and "b", while factor names usually
    have to be globally unique.

    ISTM one well-named factor that simplifies code is better than a complicated definition peppered with lazily-named locals. Forth style vs. C

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From none) (albert@21:1/5 to Anton Ertl on Mon Nov 14 12:09:17 2022
    In article <2022Nov13.194211@mips.complang.tuwien.ac.at>,
    Anton Ertl <anton@mips.complang.tuwien.ac.at> wrote:
    Paul Rubin <no.email@nospam.invalid> writes:
    albert@cherry.(none) (albert) writes:
    Using a FAT file-system on flash is the pinnacle of ridiculousness.

    Everybody does it now. Buy a USB pen drive at the store and it will >>already be formatted for FAT.

    A USB stick (and also an SSD) has a flash translation layer (FTL) that >emulates a system with 512-Byte blocks on the flash device. For a raw
    flash device (i.e., without FTL) FAT is not a good idea. It would be
    slow and it would wear out the FAT (meta-data) blocks quickly. One
    file system designed for raw flash is JFFS2.

    On the other and a tape archive format is mostly serial access.


    - anton

    Groetjes Albert
    --
    "in our communism country Viet Nam, people are forced to be
    alive and in the western country like US, people are free to
    die from Covid 19 lol" duc ha
    albert@spe&ar&c.xs4all.nl &=n http://home.hccnet.nl/a.w.m.van.der.horst

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From none) (albert@21:1/5 to no.email@nospam.invalid on Mon Nov 14 12:22:33 2022
    In article <87v8ni1lf8.fsf@nightsong.com>,
    Paul Rubin <no.email@nospam.invalid> wrote:
    dxforth <dxforth@gmail.com> writes:
    It's been reported Polyforth was a combined effort between several
    Forth Inc staff and Moore. Moore would later go on to say:... "Forth
    doesn't need to be complicated. Classic Forth started out simple..."

    Ok, but did classic Forth have multitasking? Is Moore known to have
    approved of it, or maybe disapproved? Do the current Forth purists have
    a view on the matter?

    I think this is a moot question. My program tmanx manages to play
    different instruments parallel, while filling a number of high priority
    queues that are handled in parallel. That is a tailor made solutions
    for multi tasking on two priority levels. That is in the spirit of Forth.
    Not: inventing multi tasking, add bells and whistles and lean back.
    "What are we going to do with it?"

    In fact ciforth has pre-emptive and cooperative multi tasking in its
    library and neither are used in tmanx.

    Perhaps because of the propaganda that 'stack juggling' is rife in forth
    and locals somehow solve it.

    I didn't think it was under debate that stack juggling is confusing.
    Locals are one approach to dealing with it, maybe a barbaric one. The
    purist alternative is to instead use finer grained factoring.

    Both of those approaches introduce more names into the program. So
    whatever drawbacks locals might have, "they make the programmer think up
    more names" doesn't seem to be one. In fact, locals usually have
    re-usable temporary names like "a" and "b", while factor names usually
    have to be globally unique.

    Names have to mean something. a x y z are merely placeholders.
    Anton Ertl goes in the direction of composite objects, matrices
    vectors. That is the way to go. In fact that is more or less
    object oriented.
    I have an object oriented implementation of ALLOCATE c.s.
    where names are meaningful, and stack juggling is largely eliminated.

    Groetjes Albert
    --
    "in our communism country Viet Nam, people are forced to be
    alive and in the western country like US, people are free to
    die from Covid 19 lol" duc ha
    albert@spe&ar&c.xs4all.nl &=n http://home.hccnet.nl/a.w.m.van.der.horst

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From dxforth@21:1/5 to albert on Mon Nov 14 23:34:39 2022
    On 14/11/2022 10:22 pm, albert wrote:
    In article <87v8ni1lf8.fsf@nightsong.com>,
    Paul Rubin <no.email@nospam.invalid> wrote:
    dxforth <dxforth@gmail.com> writes:
    It's been reported Polyforth was a combined effort between several
    Forth Inc staff and Moore. Moore would later go on to say:... "Forth
    doesn't need to be complicated. Classic Forth started out simple..."

    Ok, but did classic Forth have multitasking? Is Moore known to have
    approved of it, or maybe disapproved? Do the current Forth purists have
    a view on the matter?

    I think this is a moot question. [...]

    More interesting was the reference to 'Forth purists'. What cheek Moore
    has telling beginners how the language ought to be applied :)

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Stephen Pelc@21:1/5 to All on Mon Nov 14 14:54:08 2022
    On 13 Nov 2022 at 11:11:51 CET, "none) (albert" <none) (albert> wrote:

    You will be hard pressed to find a FAT within 800 words of code.
    Pretty please point me to a FAT stack that can run on a
    single board computers.

    The MPE FATfiler (derived from code by Brad Eckert) has been doing FAT12/16/32 for 32 bit embedded systems for 15+ years. Nowadays it is often in conjunction with
    our USB and or PowerNet TCP/IP stacks.

    Stephen
    --
    Stephen Pelc, stephen@vfxforth.com
    MicroProcessor Engineering, Ltd. - More Real, Less Time
    133 Hill Lane, Southampton SO15 5AF, England
    tel: +44 (0)23 8063 1441, +44 (0)78 0390 3612,
    +34 649 662 974
    http://www.mpeforth.com - free VFX Forth downloads

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Anton Ertl@21:1/5 to Paul Rubin on Mon Nov 14 14:56:43 2022
    Paul Rubin <no.email@nospam.invalid> writes:
    Lars Brinkhoff <lars.spam@nocrew.org> writes:
    I'm using blocks in my day job right now. What do bare metal Forths
    with things like flash storage do these days?

    Blocks might be viable in some environments like that

    I don't think that Forth blocks/screens, which were designed for disk
    drives are a good abstraction for flash, which has different
    properties than the devices that blocks were designed for, in
    particular much larger erase blocks than write blocks, and both sizes
    depend on the device, while disk sectors grew from 128 bytes to 512
    bytes and then stayed there for a long time, and 1KB screens/blocks
    were good enough for all these sizes; of course, these days with 4KB
    disk blocks and SMR drives 1KB screens/blocks are no longer good for
    disk drives, either.

    I have outlined some ideas for source code storage in flash with
    single-byte write granularity (and a 16KB erase block size, but that's
    not so important for my ideas; it does make it inconvenient to use
    blocks, though) in <2019Apr19.185811@mips.complang.tuwien.ac.at>. For
    flash with larger write granularity we need other approaches.

    In a bare metal MCU Forth with flash storage and USB (Raspberry Pi Pico, >say), a FAT filesystem is very useful since it allows mounting the MCU
    as a flash drive and transferring files super conveniently.

    The more typical setup is to have the permanent storage on the big
    computer, talk to the MCU, and supply the source code stored on the
    big computer through the same interface (Gerald Wodni and Joerg
    Voelker call this a Forth console, but I have not seen this term used
    in clf). No need for a FAT on the MCU in this case.

    - 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 Anton Ertl@21:1/5 to minf...@arcor.de on Mon Nov 14 15:17:25 2022
    "minf...@arcor.de" <minforth@arcor.de> writes:
    Anton Ertl schrieb am Sonntag, 13. November 2022 um 19:51:39 UTC+1:
    A USB stick (and also an SSD) has a flash translation layer (FTL) that
    emulates a system with 512-Byte blocks on the flash device. For a raw
    flash device (i.e., without FTL) FAT is not a good idea. It would be
    slow and it would wear out the FAT (meta-data) blocks quickly. One
    file system designed for raw flash is JFFS2.

    Such deep level details are usually hidden from the unsuspecting user
    through a suitable API library

    Sure you can hide the details from the user in some way: The FTL
    presents the same interface as a disk drive to the user, and a file
    system like JFFS2 presents the usual POSIX file system interface
    (open, close, read, write, etc.).

    But in this case the details are important if you want to get
    performance and longevity from the device, so I think that the disk
    interface is not the way to go. The file system interface is better,
    but a file system like JFFS2 is quite complex.

    This seems like a situation where a new interface might offer
    significant benefits in performance, device longevity, and
    implementation simplicity compared to what we have now.

    - 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@arcor.de@21:1/5 to Anton Ertl on Mon Nov 14 07:56:47 2022
    Anton Ertl schrieb am Montag, 14. November 2022 um 16:25:47 UTC+1:
    "minf...@arcor.de" <minf...@arcor.de> writes:
    Anton Ertl schrieb am Sonntag, 13. November 2022 um 19:51:39 UTC+1:
    A USB stick (and also an SSD) has a flash translation layer (FTL) that
    emulates a system with 512-Byte blocks on the flash device. For a raw
    flash device (i.e., without FTL) FAT is not a good idea. It would be
    slow and it would wear out the FAT (meta-data) blocks quickly. One
    file system designed for raw flash is JFFS2.

    Such deep level details are usually hidden from the unsuspecting user >through a suitable API library
    Sure you can hide the details from the user in some way: The FTL
    presents the same interface as a disk drive to the user, and a file
    system like JFFS2 presents the usual POSIX file system interface
    (open, close, read, write, etc.).

    But in this case the details are important if you want to get
    performance and longevity from the device, so I think that the disk
    interface is not the way to go. The file system interface is better,
    but a file system like JFFS2 is quite complex.

    This seems like a situation where a new interface might offer
    significant benefits in performance, device longevity, and
    implementation simplicity compared to what we have now.

    IMO the file or block data transfer issue had been solved long ago.
    I would be more interested to see more XIP-enabled flash memories. Execute-In-Place could present more opportunities for Forth applications
    in embedded systems like MCUs.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Paul Rubin@21:1/5 to albert@cherry. on Mon Nov 14 13:17:17 2022
    albert@cherry.(none) (albert) writes:
    My program tmanx manages to play different instruments parallel, while filling a number of high priority queues that are handled in
    parallel. That is a tailor made solutions for multi tasking on two
    priority levels. That is in the spirit of Forth.... In fact ciforth
    has pre-emptive and cooperative multi tasking in its library and
    neither are used in tmanx.

    Well, if that application was tailor made for multi-tasking, why didn't
    you use it?

    Not: inventing multi tasking, add bells and whistles and lean back.
    "What are we going to do with it?"

    Multi-tasking and applications for it were well known way before Forth
    was invented. The usual application is i/o to multiple channels
    concurrently. Consider a "guess the number" game that communicates with
    a TTY, the type of thing most beginning programmers have written. Now
    suppose you want to do that on 20 separate terminals. Obviously there
    are many ways to do that, but multi-tasking is a simple and convenient
    one. Same thing happens if you want to control a bunch of different lab instruments, etc.

    Coroutines are another useful technique. Knuth vol. 1 made the case for
    them being better than subroutines all the way back in 1968. They are considered a little bit esoteric in most languages even now, but I
    notice that the GreenArrays chip has a machine instruction for a
    coroutine switch, so I take that as evidence that Moore found coroutines
    to be worthwhile.

    Names have to mean something. a x y z are merely placeholders.

    You mean like the loop indexes i j k that are built into the language,
    or seen all the time in mathematics? They are perfectly legitimate,
    just like you'd use n to denote a quantity of something, or x as the arg
    to your square root function. Or names like "length" or "height" or "tax-amount" are perfectly meaningful and can be used as local names in
    as many different word definitions as you like, but if they become word
    or VARIABLE names, they have to be globally unique, not so nice.

    In fact locals let you simplify Forth. Forth's stack primitives (OVER,
    DROP, and friends) have to be implemented as CODE because there is no
    good way to write them in Forth. But with locals it is trivial:

    : OVER { a b } a b a ;
    : DROP { a } ;

    and so on. Fwiw I don't see benefit to using more meaningful names for
    those locals. I don't even know what names would be more meaningful
    than just a and b.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From dxforth@21:1/5 to Paul Rubin on Tue Nov 15 13:44:19 2022
    On 15/11/2022 8:17 am, Paul Rubin wrote:

    In fact locals let you simplify Forth. Forth's stack primitives (OVER,
    DROP, and friends) have to be implemented as CODE because there is no
    good way to write them in Forth. But with locals it is trivial:

    : OVER { a b } a b a ;
    : DROP { a } ;

    And where did the locals come from if not via CODE and Forth stack primitives - virgin birth?

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Paul Rubin@21:1/5 to dxforth on Mon Nov 14 21:29:30 2022
    dxforth <dxforth@gmail.com> writes:
    : OVER { a b } a b a ;
    : DROP { a } ;
    And where did the locals come from if not via CODE and Forth stack
    primitives - virgin birth?

    The same place the Forth interpreter itself came from, i.e. typically metacompilation. I guess virgin birth could be a metaphor for that.
    Yes you do need one or two new primitives, to access the locals stack
    which depending on the implementation might be in the return stack.
    Then the text interpreter generates code that uses those primitives.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Paul Rubin@21:1/5 to Anton Ertl on Mon Nov 14 21:44:40 2022
    anton@mips.complang.tuwien.ac.at (Anton Ertl) writes:
    I don't think that Forth blocks/screens, which were designed for disk
    drives are a good abstraction for flash, which has different
    properties than the devices that blocks were designed for

    Maybe this is right, though it could be that the flash included in MCU's
    has friendlier characteristics (though smaller capacity) than the very
    dense NAND flash used in SSD's, SD cards, and the like. And if the idea
    is to use the blocks for program storage, write wear shouldn't be a big
    issue, even with no sector remapping. You only use write cycles when
    you update the program. Having an active, frequently updated database
    in flash could be more of a problem.

    source code storage in flash with single-byte write granularity (and a
    16KB erase block size

    If you can reserve a 16KB block S for scratch storage, you can do an erase-copy-erase-copy operation to update any smaller block. It's ugly
    but it probably suffices for code editing and the like.

    FRAM as found in some TI MSP430 processors is a super nice medium for
    blocks of course: https://www.ti.com/tool/MSP-EXP430FR5994

    Unfortunately, non-MSP430 FRAM processors aren't currently available.
    I hope that changes someday.

    The more typical setup is to have the permanent storage on the big
    computer, talk to the MCU, and supply the source code stored on the
    big computer through the same interface.... No need for a FAT on the
    MCU in this case.

    That sounds like it needs special software on the big computer, which is
    a disadvantage compared to simply writing out files with your favorite
    editing program. I guess it is workable though.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From dxforth@21:1/5 to Paul Rubin on Tue Nov 15 17:43:01 2022
    On 15/11/2022 4:29 pm, Paul Rubin wrote:
    dxforth <dxforth@gmail.com> writes:
    : OVER { a b } a b a ;
    : DROP { a } ;
    And where did the locals come from if not via CODE and Forth stack
    primitives - virgin birth?

    The same place the Forth interpreter itself came from, i.e. typically metacompilation. I guess virgin birth could be a metaphor for that.

    All of which were done long before the idea of locals, rendering your definitions superfluous.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From none) (albert@21:1/5 to dxforth@gmail.com on Tue Nov 15 10:06:57 2022
    In article <tkuue4$4ol$1@gioia.aioe.org>, dxforth <dxforth@gmail.com> wrote: >On 15/11/2022 8:17 am, Paul Rubin wrote:

    In fact locals let you simplify Forth. Forth's stack primitives (OVER,
    DROP, and friends) have to be implemented as CODE because there is no
    good way to write them in Forth. But with locals it is trivial:

    : OVER { a b } a b a ;
    : DROP { a } ;

    And where did the locals come from if not via CODE and Forth stack primitives -
    virgin birth?


    LOL
    Groetjes Albert
    --
    "in our communism country Viet Nam, people are forced to be
    alive and in the western country like US, people are free to
    die from Covid 19 lol" duc ha
    albert@spe&ar&c.xs4all.nl &=n http://home.hccnet.nl/a.w.m.van.der.horst

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Anton Ertl@21:1/5 to Paul Rubin on Tue Nov 15 08:44:49 2022
    Paul Rubin <no.email@nospam.invalid> writes:
    Coroutines are another useful technique. Knuth vol. 1 made the case for
    them being better than subroutines all the way back in 1968. They are >considered a little bit esoteric in most languages even now, but I
    notice that the GreenArrays chip has a machine instruction for a
    coroutine switch, so I take that as evidence that Moore found coroutines
    to be worthwhile.

    Which instruction do you mean? From what I know about the Greenarrays
    stuff, I very much doubt it, for the following reasons:

    1) Proper coroutines (not very limited little brother advocated here
    by some under the name CO) require switching both stacks (and
    transferring a given number of cells from one stack to the other);
    that would be a complex operation on the c18 core, which has hardware
    stacks.

    2) The Greenarrays chips have very limited memory per core (64 or 128
    words or so). Coroutines share the same core, making the memory per
    coroutine even smaller.

    3) The Greenarrays chips have lots of cores that one wants to utilize,
    and very little communication overhead between them. Why use
    coroutining, a technique that one uses if one has few cores, or to
    avoid communication overhead between the cores?

    - 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 none) (albert@21:1/5 to no.email@nospam.invalid on Tue Nov 15 10:06:32 2022
    In article <87mt8t1bj6.fsf@nightsong.com>,
    Paul Rubin <no.email@nospam.invalid> wrote:
    albert@cherry.(none) (albert) writes:
    My program tmanx manages to play different instruments parallel, while
    filling a number of high priority queues that are handled in
    parallel. That is a tailor made solutions for multi tasking on two
    priority levels. That is in the spirit of Forth.... In fact ciforth
    has pre-emptive and cooperative multi tasking in its library and
    neither are used in tmanx.

    Well, if that application was tailor made for multi-tasking, why didn't
    you use it?

    It was not "tailor made for multi-tasking". It required multi-tasking
    of some sort. Molding my application to my tools is the exact thing
    to go against the spirit of Forth. I had to extend the multi-tasking
    to have a high and low priority tasks.

    The way to extend tools is to write a *number* of programs that
    require levels of priority. Then discover the common traits.
    Then maybe add it to the library.

    Not: inventing multi tasking, add bells and whistles and lean back.
    "What are we going to do with it?"

    <NIP>
    Coroutines are another useful technique. Knuth vol. 1 made the case for
    them being better than subroutines all the way back in 1968. They are >considered a little bit esoteric in most languages even now, but I
    notice that the GreenArrays chip has a machine instruction for a
    coroutine switch, so I take that as evidence that Moore found coroutines
    to be worthwhile.

    I have a CO word in ciforth. I use it all the time.
    In ciforth it is also one instruction:
    (Symbolic names are used for the registers representing
    the High level Interpretor Pointer and Return stack POinter.) CODE_HEADER({CO},{CO}) 2]
    XCHG HIP,[RPO]
    _NEXT
    Maybe Intel agrees with Moore.

    CO is most useful in decorators, i.a. :
    { .S CO .S } 'tobedebugged decorated 1]
    That means temporarily print the stack diagram before and
    after tobedebugged is executed, until such time it
    has to be `undecorated.

    'tobedebugged undecorated


    Names have to mean something. a x y z are merely placeholders.

    You mean like the loop indexes i j k that are built into the language,
    or seen all the time in mathematics? They are perfectly legitimate,
    just like you'd use n to denote a quantity of something, or x as the arg
    to your square root function. Or names like "length" or "height" or >"tax-amount" are perfectly meaningful and can be used as local names in
    as many different word definitions as you like, but if they become word
    or VARIABLE names, they have to be globally unique, not so nice.

    In fact locals let you simplify Forth. Forth's stack primitives (OVER,
    DROP, and friends) have to be implemented as CODE because there is no
    good way to write them in Forth. But with locals it is trivial:

    : OVER { a b } a b a ;
    : DROP { a } ;

    and so on. Fwiw I don't see benefit to using more meaningful names for
    those locals. I don't even know what names would be more meaningful
    than just a and b.

    Seriously? You use a locals package that has DROP and OVER all
    over the place ... to define DROP and OVER ?
    (I have no gripe with conventions in mathematics like i is index,
    x is unknown, p is prime. )


    1] I use the { } to replace the clunky :NONAME construction.
    2] This is actual code lifted from the generic source.
    --
    "in our communism country Viet Nam, people are forced to be
    alive and in the western country like US, people are free to
    die from Covid 19 lol" duc ha
    albert@spe&ar&c.xs4all.nl &=n http://home.hccnet.nl/a.w.m.van.der.horst

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Anton Ertl@21:1/5 to Paul Rubin on Tue Nov 15 09:05:28 2022
    Paul Rubin <no.email@nospam.invalid> writes:
    anton@mips.complang.tuwien.ac.at (Anton Ertl) writes:
    I don't think that Forth blocks/screens, which were designed for disk
    drives are a good abstraction for flash, which has different
    properties than the devices that blocks were designed for

    Maybe this is right, though it could be that the flash included in MCU's
    has friendlier characteristics (though smaller capacity) than the very
    dense NAND flash used in SSD's, SD cards, and the like.

    They still have very different characteristics from the disk drives
    that blocks/screens were designed for. The blocks/screen interface
    does not give you all the benefits of the nice flash, while at the
    same time introducing inefficiencies to work around the mismatch
    between the screen/block interface and the characteristics in other
    areas.

    And if the idea
    is to use the blocks for program storage, write wear shouldn't be a big >issue, even with no sector remapping.

    Maybe. But even for (source?) program storage, why stick with the
    block interface? That's just intellectual lazyness from the
    traditionalists; they are not even being purists here, because Forth
    means striving for a simple, efficient solution (and for purists: even
    when it's not necessary), not sticking to an outdated interface.

    You only use write cycles when
    you update the program. Having an active, frequently updated database
    in flash could be more of a problem.

    So, basically, the blocks interface is a bad fit, but if you use it
    rarely enough, you can live with it.

    source code storage in flash with single-byte write granularity (and a
    16KB erase block size

    If you can reserve a 16KB block S for scratch storage, you can do an >erase-copy-erase-copy operation to update any smaller block. It's ugly
    but it probably suffices for code editing and the like.

    The first MCU I found that fit "from ST, 1MB Flash" is the
    STM32F405/415, which has 192KB RAM. You suggest to waste 16KB of that
    on the blocks interface (and having a write amplification factor of
    16, which means that the writes are 16 times slower than with a better interface, and the flash wears out 16 times faster.

    Well, at least UPDATE and SAVE-BUFFERS is separated in the blocks
    interface, so you have the chance to update multiple blocks in the
    same erase block before erasing and writing them with one
    SAVE-BUFFERS. But of course you also could need to save the buffer
    because you need it for getting another block into RAM.

    And this is the kind of nice small non-NAND flash that you get with
    MCUs:

    * You can read directly from it, which is not well utilized with the
    blocks interface; note that with that interface you even have to
    copy into RAM when you want to read from the block, because that's
    what the interface requires: BLOCK gives you the address of a RAM
    buffer that you can the write to several times.

    * You can write bytewise to it, which is also not well utilized with
    the blocks interface, which only supports writing a block at a time.

    * You can erase 16KB at a time, which does not fit the 1KB
    screen/blocks interface well, as discussed above.

    Paraphrasing the
    <https://en.wikipedia.org/wiki/Law_of_the_instrument>: If all you have
    is traditional Forth, everything looks like a nail.

    FRAM as found in some TI MSP430 processors is a super nice medium for
    blocks of course: https://www.ti.com/tool/MSP-EXP430FR5994

    FRAM is a super nice medium for everything, because it is a persistent
    RAM. Of course you can let most of its benefits go to waste by using
    a blocks interface on it, but why would you do that? Just treat it as
    RAM.

    Unfortunately, non-MSP430 FRAM processors aren't currently available.
    I hope that changes someday.

    Doubtful. Non-flash persistent memory was the coming thing of the
    2010s (one of the selling points of the 2015 Skylake was that it
    supports Optane memory), but that future has not arrived. Flash
    progressed faster than the competing technologies, and apparently it
    is outcompeting even FRAM (or maybe battery-backed SRAM is
    outcompeting FRAM). MSP430 is on the way out, and even among MSP430
    MCUs there are few with FRAM.

    The more typical setup is to have the permanent storage on the big
    computer, talk to the MCU, and supply the source code stored on the
    big computer through the same interface.... No need for a FAT on the
    MCU in this case.

    That sounds like it needs special software on the big computer, which is
    a disadvantage compared to simply writing out files with your favorite >editing program. I guess it is workable though.

    You write files with your favourite editing program on the big
    computer, and when you type "include foo.4th" in the Forth console,
    the file is read on the big computer and transferred to the MCU. You
    need some communications program anyway, because you need to control
    the Forth system on the MCU. Traditionally the console worked across
    a serial connection (and the serial connection did not present a
    mass-storage interface to the OS on the big computer), but I don't see
    any advantage in switching to a setup where you use some of the flash
    on the MCU for a FAT file system, and access that as USB mass storage,
    and the Forth system on the MCU loads from that.

    - 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 Anton Ertl@21:1/5 to albert@cherry. on Tue Nov 15 10:48:21 2022
    albert@cherry.(none) (albert) writes:
    Forth's stack primitives (OVER,
    DROP, and friends) have to be implemented as CODE because there is no
    good way to write them in Forth. But with locals it is trivial:

    : OVER { a b } a b a ;
    : DROP { a } ;

    and so on. Fwiw I don't see benefit to using more meaningful names for >>those locals. I don't even know what names would be more meaningful
    than just a and b.

    Seriously? You use a locals package that has DROP and OVER all
    over the place ... to define DROP and OVER ?

    If you put it that way:

    The definitions of DROP and OVER in Gforth (the Forth-level
    replacements are elided here) are:

    drop ( w -- ) core
    ALIVE_DEBUGGING(w);

    over ( w1 w2 -- w1 w2 w1 ) core

    And yes, this code is processed using a Forth program that has DROP
    and OVER all over the place (18 and 27 occurences, respectively).

    The ALIVE_DEBUGGING(w) ensures that "w" is actually accessed in the
    debugging engine, so that you see a stack underflow at the DROP. If
    it was not there, a later primitive would perform the access and the
    stack underflow would be reported for that primitive; e.g., in a
    sequence DROP R@ it would be reported for the R@, which would be
    confusing.

    - 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 none) (albert@21:1/5 to Anton Ertl on Tue Nov 15 14:23:06 2022
    In article <2022Nov15.100528@mips.complang.tuwien.ac.at>,
    Anton Ertl <anton@mips.complang.tuwien.ac.at> wrote:
    Paul Rubin <no.email@nospam.invalid> writes: >>anton@mips.complang.tuwien.ac.at (Anton Ertl) writes:
    I don't think that Forth blocks/screens, which were designed for disk
    drives are a good abstraction for flash, which has different
    properties than the devices that blocks were designed for

    Maybe this is right, though it could be that the flash included in MCU's >>has friendlier characteristics (though smaller capacity) than the very >>dense NAND flash used in SSD's, SD cards, and the like.

    They still have very different characteristics from the disk drives
    that blocks/screens were designed for. The blocks/screen interface
    does not give you all the benefits of the nice flash, while at the
    same time introducing inefficiencies to work around the mismatch
    between the screen/block interface and the characteristics in other
    areas.

    And if the idea
    is to use the blocks for program storage, write wear shouldn't be a big >>issue, even with no sector remapping.

    Maybe. But even for (source?) program storage, why stick with the
    block interface? That's just intellectual lazyness from the
    traditionalists; they are not even being purists here, because Forth
    means striving for a simple, efficient solution (and for purists: even
    when it's not necessary), not sticking to an outdated interface.

    You only use write cycles when
    you update the program. Having an active, frequently updated database
    in flash could be more of a problem.

    So, basically, the blocks interface is a bad fit, but if you use it
    rarely enough, you can live with it.

    source code storage in flash with single-byte write granularity (and a
    16KB erase block size

    If you can reserve a 16KB block S for scratch storage, you can do an >>erase-copy-erase-copy operation to update any smaller block. It's ugly
    but it probably suffices for code editing and the like.

    The first MCU I found that fit "from ST, 1MB Flash" is the
    STM32F405/415, which has 192KB RAM. You suggest to waste 16KB of that
    on the blocks interface (and having a write amplification factor of
    16, which means that the writes are 16 times slower than with a better >interface, and the flash wears out 16 times faster.

    Well, at least UPDATE and SAVE-BUFFERS is separated in the blocks
    interface, so you have the chance to update multiple blocks in the
    same erase block before erasing and writing them with one
    SAVE-BUFFERS. But of course you also could need to save the buffer
    because you need it for getting another block into RAM.

    And this is the kind of nice small non-NAND flash that you get with
    MCUs:

    * You can read directly from it, which is not well utilized with the
    blocks interface; note that with that interface you even have to
    copy into RAM when you want to read from the block, because that's
    what the interface requires: BLOCK gives you the address of a RAM
    buffer that you can the write to several times.

    * You can write bytewise to it, which is also not well utilized with
    the blocks interface, which only supports writing a block at a time.

    * You can erase 16KB at a time, which does not fit the 1KB
    screen/blocks interface well, as discussed above.

    Paraphrasing the
    <https://en.wikipedia.org/wiki/Law_of_the_instrument>: If all you have
    is traditional Forth, everything looks like a nail.

    FRAM as found in some TI MSP430 processors is a super nice medium for >>blocks of course: https://www.ti.com/tool/MSP-EXP430FR5994

    FRAM is a super nice medium for everything, because it is a persistent
    RAM. Of course you can let most of its benefits go to waste by using
    a blocks interface on it, but why would you do that? Just treat it as
    RAM.

    Unfortunately, non-MSP430 FRAM processors aren't currently available.
    I hope that changes someday.

    Doubtful. Non-flash persistent memory was the coming thing of the
    2010s (one of the selling points of the 2015 Skylake was that it
    supports Optane memory), but that future has not arrived. Flash
    progressed faster than the competing technologies, and apparently it
    is outcompeting even FRAM (or maybe battery-backed SRAM is
    outcompeting FRAM). MSP430 is on the way out, and even among MSP430
    MCUs there are few with FRAM.

    The more typical setup is to have the permanent storage on the big
    computer, talk to the MCU, and supply the source code stored on the
    big computer through the same interface.... No need for a FAT on the
    MCU in this case.

    That sounds like it needs special software on the big computer, which is
    a disadvantage compared to simply writing out files with your favorite >>editing program. I guess it is workable though.

    You write files with your favourite editing program on the big
    computer, and when you type "include foo.4th" in the Forth console,
    the file is read on the big computer and transferred to the MCU. You
    need some communications program anyway, because you need to control
    the Forth system on the MCU. Traditionally the console worked across
    a serial connection (and the serial connection did not present a
    mass-storage interface to the OS on the big computer), but I don't see
    any advantage in switching to a setup where you use some of the flash
    on the MCU for a FAT file system, and access that as USB mass storage,
    and the Forth system on the MCU loads from that.

    I agree with you on the bulk of the points.

    There are advantages too, not to be overlooked.

    I implemented a Forth on the Renesas, a 16 bit Forth,
    with a couple of 100 kbyte of flash available, used
    for the Forth image and blocks.
    Remark that flash falls outside the normal memory range.

    -At startup the Forth is copied from flash to RAM, such that
    I didn't have to change to a model that have to run from
    flash.
    - I had a source library available on blocks, making available
    a quantity of software that doesn't fit in 64 k compiled.
    - the flash image can be modified from within Forth such that
    at the next reset it is used.
    - the source library can be modified or extended from with Forth
    - free blocks can receive an application.

    I had written a flasher and the only modification for a source
    is to restrict the lines to 63 bytes, then flash it in the free blocks.

    This system was described in Vierte Dimension around 2007.

    I hope to use this model for the raspberry pico.

    - anton

    Groetjes Albert
    --
    "in our communism country Viet Nam, people are forced to be
    alive and in the western country like US, people are free to
    die from Covid 19 lol" duc ha
    albert@spe&ar&c.xs4all.nl &=n http://home.hccnet.nl/a.w.m.van.der.horst

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Paul Rubin@21:1/5 to Anton Ertl on Tue Nov 15 12:26:12 2022
    anton@mips.complang.tuwien.ac.at (Anton Ertl) writes:
    [coroutines] Which instruction do you mean? From what I know about
    the Greenarrays stuff, I very much doubt it

    They call it EX, and it simply swaps the program counter with the top of
    the return stack, leaving it up to the application to make any data
    stack adjustments. One of their docs explained that its purpose was essentially a coroutine switch, though I don't remember if it actually
    used the word coroutine. I'm having trouble finding the doc right now,
    though I notice that they have just posted some updates. It's
    interesting to see that they are still at it.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Paul Rubin@21:1/5 to Anton Ertl on Sat Nov 26 12:28:50 2022
    anton@mips.complang.tuwien.ac.at (Anton Ertl) writes:
    And if the idea is to use the blocks for program storage, write wear >>shouldn't be a big issue, even with no sector remapping.
    Maybe. But even for (source?) program storage, why stick with the
    block interface?

    Well, maybe you want to port some existing blocks code, or maybe there
    is a blocks editor that you like to use. Obviously in this day and age,
    you would only implement blocks if you want to use blocks, but it's
    reasonable to suppose that someone might want to do that.

    You only use write cycles when you update the program. Having an
    active, frequently updated database in flash could be more of a problem.
    So, basically, the blocks interface is a bad fit, but if you use it
    rarely enough, you can live with it.

    I think it is fine to use blocks as program storage and edit all day
    with blocks editors using flash, saving when you want to. There are
    some applications that use blocks as a database and update it very
    frequently. I don't know how common those were. That style of
    application might get into trouble with write wear, and could be better
    off using some other representation.

    If you can reserve a 16KB block S for scratch storage, you can do an >>erase-copy-erase-copy operation to update any smaller block....

    The first MCU I found that fit "from ST, 1MB Flash" is the
    STM32F405/415, which has 192KB RAM. You suggest to waste 16KB of that
    on the blocks interface

    16K of the 1MB flash doesn't sound like that big a deal. Of course it
    is better if you can do it with ram, though then there is a failure mode
    if the power goes out during the update.

    which means that the writes are 16 times slower than with a better
    interface, and the flash wears out 16 times faster.

    If this is for program editing it is probably fine. The few
    milliseconds per update won't be noticed, and it will be quite a long
    time before write wear matters. Yes you might have to treat the MCU as
    a consumable during long term program development. If the flash is good
    for 1e5 erase cycles and you save a block 1e3 times a day during
    editing, you're good for 1e2 days if you're editing the same block over
    and over. You do repeatedly hit the scratch sector, so maybe you'd want
    to allocate several of them. Or if you're updating the same few program
    blocks all day, maybe you could have some remapping scheme in the blocks
    layer.

    Did anyone actually use blocks like that? They used them a lot with
    floppy discs, I believe, and those were so slow that this amount of
    updating seems unlikely. And doing that much development with a
    resident Forth and a blocks editor also sounds masochistic.

    Paraphrasing the
    <https://en.wikipedia.org/wiki/Law_of_the_instrument>: If all you have
    is traditional Forth, everything looks like a nail.

    Of course the same thing goes for the rest of Forth, like the stacks,
    the dictionary, etc.

    FRAM is a super nice medium for everything... Just treat it as RAM.

    You can't really do that, because it is slower than ram, and subject to
    write wear. In the MSP430 FRAM mcu's, the FRAM requires wait states
    when the cpu runs faster than 8 mhz, and they say it is good for 1e15
    erase cycles, though it's not clear how that is measured (i.e. whether
    it's for the entire FRAM segment or what). For the Fujitsu FRAM chips
    on Adafruit (e.g. https://www.adafruit.com/product/1895 ), the data
    sheet says 1e12 cycles for each bit, and seemingly about 1μS access
    time, though that is for an SPI interface so maybe the underlying medium
    is faster. Anyway, at 1e6 updates per second (say you have TOS in a
    FRAM cell in a Forth program running 24/7), you can use up the 1e12
    cycles in a few weeks, not so great.

    For this reason, the MSP430 FRAM mcu's have some SRAM in addition to
    FRAM. IIRC, the one I linked has 256K FRAM and 8K SRAM. So you would
    put the Forth stacks and frequently used variables in SRAM, and the dictionaries, program code, etc. in FRAM.

    MSP430 is on the way out, and even among MSP430 MCUs there are few
    with FRAM.

    MSP430 is on the way out because nobody wants 16 bit MCUs any more.
    There are quite a few FRAM models though. TI brought out some ARM parts
    to succeed the MSP430 but said that the ARM architecture (I guess that
    means hard IP blocks from Arm Ltd.) didn't work with their FRAM fab
    process. That leaves open the hope of them someday introducing, say,
    RISC-V MCU's with FRAM.

    You write files with your favourite editing program on the big
    computer, and when you type "include foo.4th" in the Forth console,
    the file is read on the big computer and transferred to the MCU. You
    need some communications program anyway, because you need to control
    the Forth system on the MCU.

    You mean the host-side communications program would support some feature
    where the remote side could request that the host send a file? I guess
    that is doable, but it means you can no longer use a generic terminal
    emulator. At that point, you might as well have a tethered Forth where
    the compiler is also on the host side.

    I don't see any advantage in switching to a setup where you use some
    of the flash on the MCU for a FAT file system, and access that as USB
    mass storage, and the Forth system on the MCU loads from that.

    It is very nice. It means you plug the MCU into a USB port and the
    files are right there. You can move it around between computers, and
    you don't need any special software on the host. Give it a try with one
    of the little Adafruit boards sometime. You buy the board, plug it in,
    and you immediately see a CircuitPython prompt on the (emulated) serial
    port, plus a bunch of Python files on the mass storage device. You can
    edit the Python files with your host-side editor and press the reset
    button on the MCU board, and the MCU interpreter reboots and loads
    "main.py" again. The initial main.py that you get pulses the LED in
    different colors, and then you can edit or replace that file.

    You don't have to install anything on either the host or the MCU. It is
    all already there, assuming the host has a terminal emulator. It would
    be great to have a Forth environment like that, for such boards.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From dxforth@21:1/5 to Paul Rubin on Sun Nov 27 18:14:24 2022
    On 27/11/2022 7:28 am, Paul Rubin wrote:
    ...
    At that point, you might as well have a tethered Forth where
    the compiler is also on the host side.

    Works for the forth vendors. Arduino users would be chomping at
    the bit to have one of those :)

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Paul Rubin@21:1/5 to dxforth on Sat Nov 26 23:50:12 2022
    dxforth <dxforth@gmail.com> writes:
    Works for the forth vendors. Arduino users would be chomping at
    the bit to have one of those :)

    Yeah, I started writing something like that for the STM8 once, but had
    to put it aside. Later I got into a discussion with Anton about doing
    it for the AVR8. It would be fairly retargetable either way though. I
    still think about it sometimes, but I have too many other things going
    on.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From dave_thompson_2@comcast.net@21:1/5 to no.email@nospam.invalid on Mon Jan 9 02:45:49 2023
    (sorry for delay, I misfiled this somehow and just found it)

    On Wed, 09 Nov 2022 13:23:21 -0800, Paul Rubin
    <no.email@nospam.invalid> wrote:

    anton@mips.complang.tuwien.ac.at (Anton Ertl) writes:
    Unix as OS, and of Forth as a programming language. Both had no
    memory protection (Unix acquired virtual memory only with 3BSD in
    1979), both acquired multi-tasking (and multi-user) pretty soon.

    Unix had memory protection on the PDP-11, long before it got virtual
    memory. The PDP-11/40 and friends had memory segments with protection registers, so processes couldn't clobber each other or reach into the

    Yes.

    kernel. With earlier models (11/20, PDP-7 etc.) you could crash a whole timesharing system by having a pointer bug in your program. I thought
    that Unix had multi-tasking from the beginning, but am not sure.

    A stock 11/20 had no protection, but the one used in Bell Labs did;
    see https://www.bell-labs.com/usr/dmr/www/odd.html at the bottom.

    The earlier and short-lived PDP-7 version had no protection, and only
    one user and one process.

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