• Interpretation semantics of EXIT

    From none) (albert@21:1/5 to All on Sun Apr 17 12:57:11 2022
    Newsgroups: comp.lang.forth
    Subject: Interpretation semantics for EXIT
    X-Newsreader: trn 4.0-test77 (Sep 1, 2010)

    For ages now I have used the documented property of ciforth
    that EXIT in interpretation mode exits INTERPRET.
    A simple example would be
    S" 1 2 EXIT 3 4" EVALUATE
    that leaves `` 1 2 '' on the stack.
    EVALUATE takes care that the original input source is
    restored, and so does LOAD and INCLUDE.
    I use this extensively in blocks; a block intended
    for 32 bits MS-Windows is abandoned in 64 bits, or
    Linux.

    I am working on a lisp interpreter, inspired by
    (Chuck Moore's?) BASIC interpreter. In lisp nested data
    structures abound even more.
    (+ 1 2 (* 2 3 4))
    is a typical lisp phrase.
    The basic idea is to start INTERPRET in `` ( '' with a special
    CONTEXT and start a **new INSTANCE** of INTERPRET with
    each next `` ( ''. However in this case you don't
    save and restore the input source, but leave it as is.
    Now define
    ' EXIT ALIAS )
    and you can build a partial datastructure starting
    with the corresponding `` ( '' as soon as the INTERPRET
    has finished.

    A more mainstream application is in REQUIRE.
    A source is included and it is discovered that the facility
    has already been loaded, so the remainder of the source is
    discarded.
    A word that abandons the current input source is long overdue,
    and I'm not quite sure that EXIT is the right name.

    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 albert@cherry. on Mon Apr 18 15:48:06 2022
    albert@cherry.(none) (albert) writes:
    A more mainstream application is in REQUIRE.
    A source is included and it is discovered that the facility
    has already been loaded, so the remainder of the source is
    discarded.

    In Gforth we implement REQUIRE by checking first if the file has
    already been loaded. IIRC the reference implementation of REQUIRED
    and REQUIRE also does this. No need to discard the rest of the source
    for this.

    A word that abandons the current input source is long overdue,

    It seems that we have not needed such a word in Gforth, because we
    don't have one. Others have such a word, so there seems to be some
    need for it.

    and I'm not quite sure that EXIT is the right name.

    Probably not, because EXIT has no interpretation semantics. The EXIT
    and INTERPRET implementations on some systems may work to achieve the
    effects you have in mind (although I doubt that it works for INCLUDED
    and friends on many systems, because INCLUDED is one level out from
    the processing that EVALUATE and LOAD perform).

    As for the interpretation semantics of EXIT, we tried hard to give
    Gforth's EXIT it's execution semantics as interpretation semantics;
    this work is described in [ertl15]. However, in addition to the
    complications described there, we found that we still had not covered
    all the bases, requiring even more complications, so we reverted the
    changes to EXIT, and in the development version EXIT is an immediate
    word that *compiles* the execution semantics of EXIT when used
    interpretively.

    @InProceedings{ertl15,
    author = {M. Anton Ertl and Bernd Paysan},
    title = {From \texttt{exit} to \texttt{set-does>} --- A Story of {Gforth} Re-Implementation},
    crossref = {euroforth15},
    pages = {41--47},
    url = {http://www.euroforth.org/ef15/papers/ertl.pdf},
    url-slides = {http://www.euroforth.org/ef15/papers/ertl-slides.pdf},
    OPTnote = {not refereed},
    abstract = {We changed \code{exit} from an immediate to a
    non-immediate word; this requires changes in the
    de-allocation of locals, which leads to changes in
    the implementation of colon definitions, and to
    generalizing \code{does>} into \code{set-does>}
    which allows the defined word to call arbitrary
    execution tokens. The new implementation of locals
    cleanup can usually be optimized to similar
    performance as the old implementation. The new
    implementation of \code{does>} has performance
    similar to the old implementation, while using
    \code{set-does>} results in speedups in certain
    cases.}
    }

    - anton
    --
    M. Anton Ertl http://www.complang.tuwien.ac.at/anton/home.html
    comp.lang.forth FAQs: http://www.complang.tuwien.ac.at/forth/faq/toc.html
    New standard: http://www.forth200x.org/forth200x.html
    EuroForth 2021: https://euro.theforth.net/2021

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From none) (albert@21:1/5 to Anton Ertl on Tue Apr 19 10:34:56 2022
    In article <2022Apr18.174806@mips.complang.tuwien.ac.at>,
    Anton Ertl <anton@mips.complang.tuwien.ac.at> wrote:
    albert@cherry.(none) (albert) writes:
    A more mainstream application is in REQUIRE.
    A source is included and it is discovered that the facility
    has already been loaded, so the remainder of the source is
    discarded.

    In Gforth we implement REQUIRE by checking first if the file has
    already been loaded. IIRC the reference implementation of REQUIRED
    and REQUIRE also does this. No need to discard the rest of the source
    for this.

    This is one implementation possibility. What I described is common
    in c.

    A word that abandons the current input source is long overdue,

    It seems that we have not needed such a word in Gforth, because we
    don't have one. Others have such a word, so there seems to be some
    need for it.
    I hope I made the case that it is useful.

    and I'm not quite sure that EXIT is the right name.

    Probably not, because EXIT has no interpretation semantics. The EXIT
    and INTERPRET implementations on some systems may work to achieve the
    effects you have in mind (although I doubt that it works for INCLUDED
    and friends on many systems, because INCLUDED is one level out from
    the processing that EVALUATE and LOAD perform).

    A standard program according ISO can not use EXIT in interpretation
    state. That is not a dogma, but a design decision.
    In my implementation EXIT performs a return, i.e. pops a
    continuation address for the program counter, and jumps there.
    If I remove the ?EXEC (that serves to forbid EXIT in compilation
    state), suddenly it performs the useful function of ending INTERPRET.
    Making Forth better by removing a line, isn't that the tao of
    Forth?


    As for the interpretation semantics of EXIT, we tried hard to give
    Gforth's EXIT it's execution semantics as interpretation semantics;
    this work is described in [ertl15]. However, in addition to the >complications described there, we found that we still had not covered
    all the bases, requiring even more complications, so we reverted the
    changes to EXIT, and in the development version EXIT is an immediate
    word that *compiles* the execution semantics of EXIT when used >interpretively.

    I promote the case that EXIT in interpretation mode exits
    INTERPRET. Much to my surprise INTERPRET is not ISO standard.
    The description would be:
    repeat getting words from the input and perform compilation and execution according to STATE until the input is exhausted.
    A quick check reveals that most system has it:
    gforth mpeforth swiftforth.
    I wonder whether it WORD and FIND could make it into the standard
    and INTERPRET doesn't.
    (WORD and FIND hints at implementation internal words, that
    probably are not used in modern implementation.
    INTERPRET OTOH is far from outdated.)


    @InProceedings{ertl15,
    author = {M. Anton Ertl and Bernd Paysan},
    title = {From \texttt{exit} to \texttt{set-does>} --- A Story
    of {Gforth} Re-Implementation},
    crossref = {euroforth15},
    pages = {41--47},
    url = {http://www.euroforth.org/ef15/papers/ertl.pdf},
    url-slides = {http://www.euroforth.org/ef15/papers/ertl-slides.pdf},
    OPTnote = {not refereed},
    abstract = {We changed \code{exit} from an immediate to a
    non-immediate word; this requires changes in the
    de-allocation of locals, which leads to changes in
    the implementation of colon definitions, and to
    generalizing \code{does>} into \code{set-does>}
    which allows the defined word to call arbitrary
    execution tokens. The new implementation of locals
    cleanup can usually be optimized to similar
    performance as the old implementation. The new
    implementation of \code{does>} has performance
    similar to the old implementation, while using
    \code{set-does>} results in speedups in certain
    cases.}
    }

    This confirms my suspicion that LOCAL is the root of all evil ;-)


    - 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 minforth@arcor.de@21:1/5 to none albert on Tue Apr 19 02:24:21 2022
    none albert schrieb am Dienstag, 19. April 2022 um 10:34:58 UTC+2:
    This confirms my suspicion that LOCAL is the root of all evil ;-)


    You'll love closures then. :-)

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From dxforth@21:1/5 to minf...@arcor.de on Wed Apr 20 09:47:52 2022
    On 19/04/2022 19:24, minf...@arcor.de wrote:
    none albert schrieb am Dienstag, 19. April 2022 um 10:34:58 UTC+2:
    This confirms my suspicion that LOCAL is the root of all evil ;-)


    You'll love closures then. :-)

    But a step too far for 200x quotations - all the disadvantages of
    nameless words with little to offer in return :)

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From NN@21:1/5 to none albert on Wed Apr 20 04:16:43 2022
    On Sunday, 17 April 2022 at 11:57:14 UTC+1, none albert wrote:
    Newsgroups: comp.lang.forth
    Subject: Interpretation semantics for EXIT
    X-Newsreader: trn 4.0-test77 (Sep 1, 2010)

    For ages now I have used the documented property of ciforth
    that EXIT in interpretation mode exits INTERPRET.
    A simple example would be
    S" 1 2 EXIT 3 4" EVALUATE
    that leaves `` 1 2 '' on the stack.
    EVALUATE takes care that the original input source is
    restored, and so does LOAD and INCLUDE.
    I use this extensively in blocks; a block intended
    for 32 bits MS-Windows is abandoned in 64 bits, or
    Linux.

    I am working on a lisp interpreter, inspired by
    (Chuck Moore's?) BASIC interpreter. In lisp nested data
    structures abound even more.
    (+ 1 2 (* 2 3 4))
    is a typical lisp phrase.
    The basic idea is to start INTERPRET in `` ( '' with a special
    CONTEXT and start a **new INSTANCE** of INTERPRET with
    each next `` ( ''. However in this case you don't
    save and restore the input source, but leave it as is.
    Now define
    ' EXIT ALIAS )
    and you can build a partial datastructure starting
    with the corresponding `` ( '' as soon as the INTERPRET
    has finished.

    A more mainstream application is in REQUIRE.
    A source is included and it is discovered that the facility
    has already been loaded, so the remainder of the source is
    discarded.
    A word that abandons the current input source is long overdue,
    and I'm not quite sure that EXIT is the right name.

    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

    How about calling it BAIL ?

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Anton Ertl@21:1/5 to albert@cherry. on Wed Apr 20 11:49:42 2022
    albert@cherry.(none) (albert) writes:
    In article <2022Apr18.174806@mips.complang.tuwien.ac.at>,
    Anton Ertl <anton@mips.complang.tuwien.ac.at> wrote:
    albert@cherry.(none) (albert) writes:
    A more mainstream application is in REQUIRE.
    A source is included and it is discovered that the facility
    has already been loaded, so the remainder of the source is
    discarded.

    In Gforth we implement REQUIRE by checking first if the file has
    already been loaded. IIRC the reference implementation of REQUIRED
    and REQUIRE also does this. No need to discard the rest of the source
    for this.

    This is one implementation possibility. What I described is common
    in c.

    C does not have REQUIRE and instead uses a convention of wrapping the
    payload into, e.g.,

    #ifndef _STDIO_H
    #define _STDIO_H 1
    ... payload here ...
    #endif /* <stdio.h> included. */

    and I guess that's what you mean. Despite this convention, C does not
    have a way to prematurely end the processing of a file.

    In any case, in Forth we have REQUIRED/REQUIRE, so even less need for
    such a feature.

    I hope I made the case that it is useful.

    You wrote that you find it useful. That does not tell us why anyone
    else would find it useful.

    A standard program according ISO can not use EXIT in interpretation
    state.

    No. A standard program cannot use the interpretation semantics of
    EXIT.

    That is not a dogma, but a design decision.
    In my implementation EXIT performs a return, i.e. pops a
    continuation address for the program counter, and jumps there.
    If I remove the ?EXEC (that serves to forbid EXIT in compilation
    state), suddenly it performs the useful function of ending INTERPRET.
    Making Forth better by removing a line, isn't that the tao of
    Forth?

    It's certainly a good idea to remove ?EXEC from EXIT, which would make
    your system fail on the following standard code:

    : macro1 exit ; immediate
    : foo macro1 ;

    Better get rid of ?EXEC and ?COMP everywhere. They only check STATE
    at the time when the containing words are performed, which is not
    appropriate for checking whether the interpretation semantics or the compilation semantics of a word are performed.

    It's fascinating that you used ?EXEC for EXIT. My guess is that this
    happened the following way: You saw that EXIT has no interpretation
    semantics, so you put in ?COMP. Of course this failed, probably on
    the first exection of EXIT. So the ?COMP was obviously wrong. As a
    remedy you thought you would put in ?EXEC, and it seemed to work (you
    have no immediate words containing EXIT), so you left it in, but it's
    just as wrong as ?COMP.

    As for having EXIT with interpretation semantics, that's something we
    wanted to support, as detailed in the grandparent posting. It's
    certainly a good idea to add useful functionality beyond the standard,
    but in the benefit was not worth the cost.



    I promote the case that EXIT in interpretation mode exits
    INTERPRET. Much to my surprise INTERPRET is not ISO standard.
    The description would be:
    repeat getting words from the input and perform compilation and execution >according to STATE until the input is exhausted.
    A quick check reveals that most system has it:
    gforth mpeforth swiftforth.
    I wonder whether it WORD and FIND could make it into the standard
    and INTERPRET doesn't.
    (WORD and FIND hints at implementation internal words, that
    probably are not used in modern implementation.
    INTERPRET OTOH is far from outdated.)

    My guess is that WORD and FIND are in Forth-94 because there were no replacements for them in the standard at the time. For Forth-2012,
    there was no replacement for FIND, and WORD is designed to work with
    FIND. If you want to propose to make WORD and FIND obsolescent, now
    the chances are better, because there is FIND-NAME.

    As for INTERPRET, if you want it standardized, make a proposal. You
    may want to provide some usage statistics to support your 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: http://www.forth200x.org/forth200x.html
    EuroForth 2021: https://euro.theforth.net/2021

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Anton Ertl@21:1/5 to minf...@arcor.de on Wed Apr 20 15:24:42 2022
    "minf...@arcor.de" <minforth@arcor.de> writes:
    none albert schrieb am Dienstag, 19. April 2022 um 10:34:58 UTC+2:
    This confirms my suspicion that LOCAL is the root of all evil ;-)


    You'll love closures then. :-)

    Gforth now also has closures that don't involve locals. E.g., you can
    define +FIELD and FCONSTANT as:

    : +field ( n "name" -- )
    [n:d + ;] alias ;

    5 +field x
    7 x . \ prints 12

    What's happening here is that when +FIELD is running, the closure
    consumes one data stack item (n); this is used to build a closure,
    with the needed space allocated in the dictionary. The xt of the
    closure is left on the stack, and the ALIAS creates a word X with that
    xt as its execution semantics. When X is run, n (i.e., 5) is pushed
    on the stack, and the "+" adds it to the 7.

    So the closure mechanism transfers one data stack item from closure
    creation time to closure execution time (and transferring data from
    closure creation time to closure execution time is the functional
    essence of closures, no locals needed for that). We also have
    variants for one double ("[d:d") and one float ("[f:d"), and for
    allocating the closure on the locals stack ("[n:l") and on the heap
    ("[n:h"), and all nine combinations. We don't have variants for more
    stack items; you can use the closures that involve locals if you need
    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: http://www.forth200x.org/forth200x.html
    EuroForth 2021: https://euro.theforth.net/2021

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From minforth@arcor.de@21:1/5 to Anton Ertl on Wed Apr 20 10:14:38 2022
    Anton Ertl schrieb am Mittwoch, 20. April 2022 um 17:51:10 UTC+2:
    "minf...@arcor.de" <minf...@arcor.de> writes:
    none albert schrieb am Dienstag, 19. April 2022 um 10:34:58 UTC+2:
    This confirms my suspicion that LOCAL is the root of all evil ;-)


    You'll love closures then. :-)
    Gforth now also has closures that don't involve locals. E.g., you can
    define +FIELD and FCONSTANT as:

    : +field ( n "name" -- )
    [n:d + ;] alias ;

    5 +field x
    7 x . \ prints 12

    What's happening here is that when +FIELD is running, the closure
    consumes one data stack item (n); this is used to build a closure,
    with the needed space allocated in the dictionary. The xt of the
    closure is left on the stack, and the ALIAS creates a word X with that
    xt as its execution semantics. When X is run, n (i.e., 5) is pushed
    on the stack, and the "+" adds it to the 7.

    So the closure mechanism transfers one data stack item from closure
    creation time to closure execution time (and transferring data from
    closure creation time to closure execution time is the functional
    essence of closures, no locals needed for that). We also have
    variants for one double ("[d:d") and one float ("[f:d"), and for
    allocating the closure on the locals stack ("[n:l") and on the heap
    ("[n:h"), and all nine combinations. We don't have variants for more
    stack items; you can use the closures that involve locals if you need
    that.

    Thanks for that gforth example. IIUC it puts the burden of "lexical scoping"
    on programmer's shoulders. But anyhow: it works, well done.

    Second big step would be do this with named locals i.e. put the burden on compiler's shoulders and let programmers enjoy more readable code. But
    that's way beyond the standard, and every Forth system would take (and
    have to take) a different implementation route.

    Nevertheless I doubt that verbose functional programming makes much
    sense in Forth's niche.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From none) (albert@21:1/5 to Anton Ertl on Thu Apr 21 09:57:29 2022
    In article <2022Apr20.172442@mips.complang.tuwien.ac.at>,
    Anton Ertl <anton@mips.complang.tuwien.ac.at> wrote:
    "minf...@arcor.de" <minforth@arcor.de> writes:
    none albert schrieb am Dienstag, 19. April 2022 um 10:34:58 UTC+2:
    This confirms my suspicion that LOCAL is the root of all evil ;-)


    You'll love closures then. :-)

    Gforth now also has closures that don't involve locals. E.g., you can
    define +FIELD and FCONSTANT as:

    : +field ( n "name" -- )
    [n:d + ;] alias ;

    5 +field x
    7 x . \ prints 12

    What's happening here is that when +FIELD is running, the closure
    consumes one data stack item (n); this is used to build a closure,
    with the needed space allocated in the dictionary. The xt of the
    closure is left on the stack, and the ALIAS creates a word X with that
    xt as its execution semantics. When X is run, n (i.e., 5) is pushed
    on the stack, and the "+" adds it to the 7.

    So the closure mechanism transfers one data stack item from closure
    creation time to closure execution time (and transferring data from
    closure creation time to closure execution time is the functional
    essence of closures, no locals needed for that). We also have
    variants for one double ("[d:d") and one float ("[f:d"), and for
    allocating the closure on the locals stack ("[n:l") and on the heap
    ("[n:h"), and all nine combinations. We don't have variants for more
    stack items; you can use the closures that involve locals if you need
    that.

    So it is similar to
    : CONSTANT , DOES> @ ;
    or defined by a class/oo mechanism :
    _ class CONSTANT M: @ M; , endclass

    What then is de big deal?


    - anton


    --
    "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 luser droog@21:1/5 to none albert on Sat Apr 23 06:22:29 2022
    On Tuesday, April 19, 2022 at 3:34:58 AM UTC-5, none albert wrote:
    In article <2022Apr1...@mips.complang.tuwien.ac.at>,
    Anton Ertl <an...@mips.complang.tuwien.ac.at> wrote:
    Probably not, because EXIT has no interpretation semantics. The EXIT
    and INTERPRET implementations on some systems may work to achieve the >effects you have in mind (although I doubt that it works for INCLUDED
    and friends on many systems, because INCLUDED is one level out from
    the processing that EVALUATE and LOAD perform).
    A standard program according ISO can not use EXIT in interpretation
    state. That is not a dogma, but a design decision.
    In my implementation EXIT performs a return, i.e. pops a
    continuation address for the program counter, and jumps there.
    If I remove the ?EXEC (that serves to forbid EXIT in compilation
    state), suddenly it performs the useful function of ending INTERPRET.
    Making Forth better by removing a line, isn't that the tao of
    Forth?


    [Applause.]

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Anton Ertl@21:1/5 to minf...@arcor.de on Sat Apr 23 16:08:20 2022
    "minf...@arcor.de" <minforth@arcor.de> writes:
    Anton Ertl schrieb am Mittwoch, 20. April 2022 um 17:51:10 UTC+2:
    "minf...@arcor.de" <minf...@arcor.de> writes:
    none albert schrieb am Dienstag, 19. April 2022 um 10:34:58 UTC+2:
    This confirms my suspicion that LOCAL is the root of all evil ;-)


    You'll love closures then. :-)
    Gforth now also has closures that don't involve locals. E.g., you can
    define +FIELD and FCONSTANT as:

    : +field ( n "name" -- )
    [n:d + ;] alias ;

    5 +field x
    7 x . \ prints 12

    What's happening here is that when +FIELD is running, the closure
    consumes one data stack item (n); this is used to build a closure,
    with the needed space allocated in the dictionary. The xt of the
    closure is left on the stack, and the ALIAS creates a word X with that
    xt as its execution semantics. When X is run, n (i.e., 5) is pushed
    on the stack, and the "+" adds it to the 7.

    So the closure mechanism transfers one data stack item from closure
    creation time to closure execution time (and transferring data from
    closure creation time to closure execution time is the functional
    essence of closures, no locals needed for that). We also have
    variants for one double ("[d:d") and one float ("[f:d"), and for
    allocating the closure on the locals stack ("[n:l") and on the heap
    ("[n:h"), and all nine combinations. We don't have variants for more
    stack items; you can use the closures that involve locals if you need
    that.

    Thanks for that gforth example. IIUC it puts the burden of "lexical scoping" >on programmer's shoulders.

    That's one way to see it. But does the programmer want "lexical
    scoping", or something else, with lexical scoping just being the Algol
    60 and Scheme way to provide it?

    In 2018 I wrote up a draft of a paper on closures for Forth, and I
    started with lexical scoping. This might look as follows for the
    example above:

    : +field ( n "name" -- )
    {: n :} [: n + ;] alias ;

    To make it easier to implement I required explicitly listing the
    locals at the start of the closure that are referenced inside the
    closure, and passing the allocation word:

    : +field ( n "name" -- )
    {: n :}
    ['] alloth <[{: : n :} n + ;] alias ;

    Interestingly, the example I gave in the draft is even longer; I don't
    remember what the ":" after the <[{: is intended for. With the
    allocation being part of the closure start word and without the extra
    ":", it could look as follows:

    : +field ( n "name" -- )
    {: n :} d[{: n :} n + ;] alias ;

    Bernd Paysan had the idea to make the implementation even simpler by
    passing the data to the closure on the stack, resulting in the syntax
    in the published paper (but again, the examples in the paper are more
    complex):

    : +field ( n "name" -- )
    [{: n :}d n + ;] alias ;

    This new idea required me to rewrite most of the paper
    [ertl&paysan18], in particular, the examples. One thing I noticed is
    that many of the examples became simpler (sometimes even simpler than
    lexical scoping without the additional requirement), because I no
    longer had to put the value into a local in order to pass it to the
    closure. I could just leave it on the stack, and inside the closure
    it would be a local. This shows IMO that what we want as programmers
    is not lexical scoping, but a way to pass data to the closure.

    In my EuroForth talk I then outlined that it can be done in a
    pure-stack way, without locals. This was intended to be mainly food
    for thought, but some time later Bernd Paysan told me that he found
    that useful for passing single values, and that he had implemented it,
    so one could now write

    : +field ( n "name" -- )
    [n:d + ;] alias ;

    In this case the code is shorter, and once you know what [N:D means, I
    think it's easier to understand. For passing multiple values to the
    closure, this tends to become cumbersome, so for that you still have
    to use the version with locals.

    But of course, purists might prefer passing multiple values from the
    stack(s) at closure-creation time to closure run-time. That is
    certainly possible, and shows that what programmers do with closures
    in most cases does not require lexical scoping.

    Of course, one might say that those who practice point-free functional programming have shown that long ago, but that's a different approach.

    Second big step would be do this with named locals i.e. put the burden on >compiler's shoulders and let programmers enjoy more readable code.

    As outlined above, Gforth has had that before it had [N:D, but it's
    not lexical scoping.

    Last year I wrote a paper [ertl21] about transplanting the ideas I
    learned here to an Algol-family language (C).

    @InProceedings{ertl&paysan18,
    author = {M. Anton Ertl and Bernd Paysan},
    title = {Closures --- the {Forth} way},
    crossref = {euroforth18},
    pages = {17--30},
    url = {http://www.complang.tuwien.ac.at/papers/ertl%26paysan.pdf},
    url2 = {http://www.euroforth.org/ef18/papers/ertl.pdf},
    slides-url = {http://www.euroforth.org/ef18/papers/ertl-slides.pdf},
    video = {https://wiki.forth-ev.de/doku.php/events:ef2018:closures},
    OPTnote = {refereed},
    abstract = {In Forth 200x, a quotation cannot access a local
    defined outside it, and therefore cannot be
    parameterized in the definition that produces its
    execution token. We present Forth closures; they
    lift this restriction with minimal implementation
    complexity. They are based on passing parameters on
    the stack when producing the execution token. The
    programmer has to explicitly manage the memory of
    the closure. We show a number of usage examples.
    We also present the current implementation, which
    takes 109~source lines of code (including some extra
    features). The programmer can mechanically convert
    lexical scoping (accessing a local defined outside)
    into code using our closures, by applying assignment
    conversion and flat-closure conversion. The result
    can do everything one expects from closures,
    including passing Knuth's man-or-boy test and living
    beyond the end of their enclosing definitions.}
    }

    @Proceedings{euroforth18,
    title = {34th EuroForth Conference},
    booktitle = {34th EuroForth Conference},
    year = {2018},
    key = {EuroForth'18},
    url = {http://www.euroforth.org/ef18/papers/proceedings.pdf}
    }

    @InProceedings{ertl21-kps,
    author = {M. Anton Ertl},
    crossref = {kps21},
    title = {The Essence of Closures---A language design
    perspective},
    year = {2021},
    pages = {26--33},
    url = {http://www.complang.tuwien.ac.at/papers/ertl21-kps.pdf},
    url-slides = {http://www.complang.tuwien.ac.at/papers/ertl21-kps-slides.pdf},
    abstract = {Closures are originally associated with lexically
    scoped name binding. However, in the course of
    implementing closures in Gforth, it turned out that
    the actual function (the essence) of closures is to
    communicate data between closure creation and the
    closure execution (with the closure call usually
    being far from the closure creation). This paper
    presents a simple language extension for C:
    two-stage parameter passing, implemented with flat
    closures; the first stage creates a closure, the
    second stage calls it. Nested functions and access
    to outer locals are not needed.}
    }

    @Misc{kps21,
    author = {{KPS 2021}},
    editor = {Hanus, Michael
    and Prott, Kai-Oliver
    and von Hanxleden, Reinhard
    and Domr{\"o}s, S{\"o}ren},
    title = {Tagungsband zum 21. Kolloquium Programmiersprachen und Grundlagen der Programmierung},
    booktitle = {Tagungsband zum 21. Kolloquium Programmiersprachen und Grundlagen der Programmierung},
    year = {2021},
    publisher = {Self-Publishing of Department of Computer Science, Kiel},
    address = {Kiel},
    volume = {2021/7},
    issn = {2194-6639},
    doi = {10.21941/kcss/2021/7},
    url = {https://macau.uni-kiel.de/receive/macau_mods_00002282},
    url2 = {https://doi.org/10.21941/kcss/2021/7},
    file = {:https://macau.uni-kiel.de/servlets/MCRFileNodeServlet/macau_derivate_00003380/kcss_2021_07.pdf:PDF},
    language = {en}
    }

    - anton
    --
    M. Anton Ertl http://www.complang.tuwien.ac.at/anton/home.html
    comp.lang.forth FAQs: http://www.complang.tuwien.ac.at/forth/faq/toc.html
    New standard: http://www.forth200x.org/forth200x.html
    EuroForth 2021: https://euro.theforth.net/2021

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Anton Ertl@21:1/5 to albert@cherry. on Sat Apr 23 17:16:37 2022
    albert@cherry.(none) (albert) writes:
    Gforth now also has closures that don't involve locals. E.g., you can >>define +FIELD and FCONSTANT as:

    : +field ( n "name" -- )
    [n:d + ;] alias ;

    5 +field x
    7 x . \ prints 12

    What's happening here is that when +FIELD is running, the closure
    consumes one data stack item (n); this is used to build a closure,
    with the needed space allocated in the dictionary. The xt of the
    closure is left on the stack, and the ALIAS creates a word X with that
    xt as its execution semantics. When X is run, n (i.e., 5) is pushed
    on the stack, and the "+" adds it to the 7.

    So the closure mechanism transfers one data stack item from closure >>creation time to closure execution time (and transferring data from
    closure creation time to closure execution time is the functional
    essence of closures, no locals needed for that). We also have
    variants for one double ("[d:d") and one float ("[f:d"), and for
    allocating the closure on the locals stack ("[n:l") and on the heap >>("[n:h"), and all nine combinations. We don't have variants for more
    stack items; you can use the closures that involve locals if you need
    that.

    So it is similar to
    : CONSTANT , DOES> @ ;
    or defined by a class/oo mechanism :
    _ class CONSTANT M: @ M; , endclass

    What then is de big deal?

    Yes, I selected an example that Forth programmers may be more familiar
    with than the numeric integration example that I used more heavily in
    the paper and that has led to complaints that people unfamiliar with
    numerical integration cannot follow the example.

    So yes, you can implement this +FIELD with DOES>:

    : +field ( n "name" -- )
    create ,
    does> @ + ;

    (BTW, the stack effect of all +FIELD examples I gave in this thread is non-standard, but that should not detract from the point of the
    example (at least nobody has complained about it yet).

    Here are some differences between closures and CREATE...DOES>:

    * A closure is nameless (so the code above uses ALIAS to give it a
    name); there is no standard way to make a nameless CREATEd word.

    * A closure can be allocated in the dictionary (as done here), on the
    heap, on the locals stack, or using a user-supplied allocation word.
    With CREEATE..DOES>, you are limited to dictionary allocation (and
    its lifetime).

    * [N:D takes a cell off the stack at closre creation time, and pushes
    it on closure execution time, without the programmer having to
    manage the data in between (other than supplying an allocation
    method). With CREATE..DOES>, the programmer has to store the data
    to the dictionary with "," and get it from there with @.

    * [N:D can manage the data in any way it sees fit, and the programmer
    knows very little about that. As a result, the data is immutable
    for the program, so the closure could be inlined, and the data could
    be compiled as a literal (with a very sophisticated compiler). By
    contrast, the user can change the data of a CREATE-+FIELD child with
    >BODY, so even a very sophisticated implementation has to compile a
    fetch of that data.

    Whether you consider these differences a big deal, is up to you.

    - anton
    --
    M. Anton Ertl http://www.complang.tuwien.ac.at/anton/home.html
    comp.lang.forth FAQs: http://www.complang.tuwien.ac.at/forth/faq/toc.html
    New standard: http://www.forth200x.org/forth200x.html
    EuroForth 2021: https://euro.theforth.net/2021

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From dxforth@21:1/5 to luser droog on Sun Apr 24 11:19:03 2022
    On 23/04/2022 23:22, luser droog wrote:
    On Tuesday, April 19, 2022 at 3:34:58 AM UTC-5, none albert wrote:
    In article <2022Apr1...@mips.complang.tuwien.ac.at>,
    Anton Ertl <an...@mips.complang.tuwien.ac.at> wrote:
    Probably not, because EXIT has no interpretation semantics. The EXIT
    and INTERPRET implementations on some systems may work to achieve the
    effects you have in mind (although I doubt that it works for INCLUDED
    and friends on many systems, because INCLUDED is one level out from
    the processing that EVALUATE and LOAD perform).
    A standard program according ISO can not use EXIT in interpretation
    state. That is not a dogma, but a design decision.
    In my implementation EXIT performs a return, i.e. pops a
    continuation address for the program counter, and jumps there.
    If I remove the ?EXEC (that serves to forbid EXIT in compilation
    state), suddenly it performs the useful function of ending INTERPRET.
    Making Forth better by removing a line, isn't that the tao of
    Forth?


    [Applause.]

    Except ANSForth isn't Forth. It's a federation (or confederation if one believes it was a choice) of Forth implementers. EXIT in interpret state
    is one of the many things it couldn't get agreement upon. Mistaking
    ANSForth for a created language is what results in the 'I could have done
    it better' complaints. Well yes, almost anyone could have created a better Forth but that's not what was being offered.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From none) (albert@21:1/5 to dxforth@gmail.com on Sun Apr 24 10:39:05 2022
    In article <t428i6$16k9$1@gioia.aioe.org>, dxforth <dxforth@gmail.com> wrote: >On 23/04/2022 23:22, luser droog wrote:
    On Tuesday, April 19, 2022 at 3:34:58 AM UTC-5, none albert wrote:
    In article <2022Apr1...@mips.complang.tuwien.ac.at>,
    Anton Ertl <an...@mips.complang.tuwien.ac.at> wrote:
    Probably not, because EXIT has no interpretation semantics. The EXIT
    and INTERPRET implementations on some systems may work to achieve the
    effects you have in mind (although I doubt that it works for INCLUDED
    and friends on many systems, because INCLUDED is one level out from
    the processing that EVALUATE and LOAD perform).
    A standard program according ISO can not use EXIT in interpretation
    state. That is not a dogma, but a design decision.
    In my implementation EXIT performs a return, i.e. pops a
    continuation address for the program counter, and jumps there.
    If I remove the ?EXEC (that serves to forbid EXIT in compilation
    state), suddenly it performs the useful function of ending INTERPRET.
    Making Forth better by removing a line, isn't that the tao of
    Forth?


    [Applause.]

    Except ANSForth isn't Forth. It's a federation (or confederation if one >believes it was a choice) of Forth implementers. EXIT in interpret state
    is one of the many things it couldn't get agreement upon. Mistaking
    ANSForth for a created language is what results in the 'I could have done
    it better' complaints. Well yes, almost anyone could have created a better >Forth but that's not what was being offered.

    You could not accuse me of not embracing ANSForth. Proposals in this way
    serve as incremental improvements of Forth.
    Considering ANSForth as dogma, was that something Jeff Fox and Chuck Moore warned about?

    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 Anton Ertl on Sun Apr 24 10:34:05 2022
    In article <2022Apr23.191637@mips.complang.tuwien.ac.at>,
    Anton Ertl <anton@mips.complang.tuwien.ac.at> wrote:
    albert@cherry.(none) (albert) writes:
    Gforth now also has closures that don't involve locals. E.g., you can >>>define +FIELD and FCONSTANT as:

    : +field ( n "name" -- )
    [n:d + ;] alias ;

    5 +field x
    7 x . \ prints 12

    What's happening here is that when +FIELD is running, the closure >>>consumes one data stack item (n); this is used to build a closure,
    with the needed space allocated in the dictionary. The xt of the
    closure is left on the stack, and the ALIAS creates a word X with that
    xt as its execution semantics. When X is run, n (i.e., 5) is pushed
    on the stack, and the "+" adds it to the 7.

    So the closure mechanism transfers one data stack item from closure >>>creation time to closure execution time (and transferring data from >>>closure creation time to closure execution time is the functional
    essence of closures, no locals needed for that). We also have
    variants for one double ("[d:d") and one float ("[f:d"), and for >>>allocating the closure on the locals stack ("[n:l") and on the heap >>>("[n:h"), and all nine combinations. We don't have variants for more >>>stack items; you can use the closures that involve locals if you need >>>that.

    So it is similar to
    : CONSTANT , DOES> @ ;
    or defined by a class/oo mechanism :
    _ class CONSTANT M: @ M; , endclass

    What then is de big deal?

    Yes, I selected an example that Forth programmers may be more familiar
    with than the numeric integration example that I used more heavily in
    the paper and that has led to complaints that people unfamiliar with >numerical integration cannot follow the example.

    So yes, you can implement this +FIELD with DOES>:

    : +field ( n "name" -- )
    create ,
    does> @ + ;

    (BTW, the stack effect of all +FIELD examples I gave in this thread is >non-standard, but that should not detract from the point of the
    example (at least nobody has complained about it yet).

    Here are some differences between closures and CREATE...DOES>:

    * A closure is nameless (so the code above uses ALIAS to give it a
    name); there is no standard way to make a nameless CREATEd word.

    If you allow me to use the alternative oo-ish definition of constant
    `` _ class CONSTANT M: get @ M; , endclass ''
    gives me also a BUILD-CONSTANT that does exactly that,


    * A closure can be allocated in the dictionary (as done here), on the
    heap, on the locals stack, or using a user-supplied allocation word.
    With CREEATE..DOES>, you are limited to dictionary allocation (and
    its lifetime).

    I prefer to separate those interests. As soon as it is important
    to allocate objects to a heap -- and it is, occasionally -- I'm inclined
    to add an extra word to an allocate wordset

    13 \ Make a freshly created object at `HERE permanent. (o -- o )
    14 : >ALLOC DUP >R HERE OVER - DUP ALLOCATE THROW
    15 DUP >R SWAP MOVE R> R> DP ! ;

    If you wish you can redefine BUILD-CONSTANT :
    : BUILD-CONSTANT BUILD-CONSTANT >ALLOC ;


    * [N:D takes a cell off the stack at closre creation time, and pushes
    it on closure execution time, without the programmer having to
    manage the data in between (other than supplying an allocation
    method). With CREATE..DOES>, the programmer has to store the data
    to the dictionary with "," and get it from there with @.

    I agree that one CREATE..DOES> gets you only so far, so it is
    good to think further.


    * [N:D can manage the data in any way it sees fit, and the programmer
    knows very little about that. As a result, the data is immutable
    for the program, so the closure could be inlined, and the data could
    be compiled as a literal (with a very sophisticated compiler). By
    contrast, the user can change the data of a CREATE-+FIELD child with
    BODY, so even a very sophisticated implementation has to compile a
    fetch of that data.

    The idea of objects is that you guide the way the user is to
    handle CONSTANTS as above . In general I have not supplied
    a method a user can change the constant, so that is similar.
    `` _ class CONSTANT M: get @ M; , endclass ''

    So the class definition of CONSTANTS is superior to using
    CREATE in much the same way in this respect.
    (Except for getting through a heavy-handed use of a `this' pointer
    that is similar to use of >BODY ).

    Rules that an optimiser can follow, are in this context maybe
    simpler. I don't believe in the complicated things a compiler
    can do if she is allowed to assume that the e.g. a c-program does
    nothing "undefined". (As do you apparently.)
    Early FORTRAN's had the rule that if a variable was identified
    in two different ways (aliasing), optimisation wasn't allowed, and
    that the programmer has to take care. Those Spartan
    attitudes in regard to optimisation is more the Forth way.
    I guess that closures introduced in Forth would require a lot
    of caveats, that is not worth it, and cramps the Forth way,
    as in IMHO the use of LOCAL values, and global VALUEs.


    Whether you consider these differences a big deal, is up to you.

    For the moment I will prefer simple additions to Forth to
    achieve similar goals. I'm working on an optimiser and that
    may change my opinion.


    - anton

    Groetjes.
    --
    "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 albert@cherry. on Sun Apr 24 16:21:47 2022
    albert@cherry.(none) (albert) writes:
    In article <2022Apr23.191637@mips.complang.tuwien.ac.at>,
    Anton Ertl <anton@mips.complang.tuwien.ac.at> wrote:
    Here are some differences between closures and CREATE...DOES>:

    * A closure is nameless (so the code above uses ALIAS to give it a
    name); there is no standard way to make a nameless CREATEd word.

    If you allow me to use the alternative oo-ish definition of constant
    `` _ class CONSTANT M: get @ M; , endclass ''
    gives me also a BUILD-CONSTANT that does exactly that,

    Sure, but then we are not into comparing Gforth's closures with
    CREATE...DOES>, but comparing them with your OO extension.

    * [N:D can manage the data in any way it sees fit, and the programmer
    knows very little about that. As a result, the data is immutable
    for the program, so the closure could be inlined, and the data could
    be compiled as a literal (with a very sophisticated compiler). By
    contrast, the user can change the data of a CREATE-+FIELD child with
    BODY, so even a very sophisticated implementation has to compile a
    fetch of that data.
    ...
    Rules that an optimiser can follow, are in this context maybe
    simpler. I don't believe in the complicated things a compiler
    can do if she is allowed to assume that the e.g. a c-program does
    nothing "undefined". (As do you apparently.)

    It's unclear what you think that I do apparently, but you can find my
    position on undefined behaviour in C in <http://www.complang.tuwien.ac.at/papers/ertl17kps.pdf>

    Concerning Forth, I think we should eliminate many ambiguous
    conditions or at least define them in the implementations. But I
    think that, e.g., it is not a valuable feature to be able to change
    constants in the way that is possible in classic threaded-code
    systems:

    5 constant x
    : foo x ;
    6 ' x >body !
    x . \ 6 on gforth-0.7.9 gforth-itc-0.7.9 sf-3.11 vfxlin-4.72; crash on iforth foo . \ 6 on gforth-itc-0.7.9; 5 on gforth-0.7.9 sf-3.11 vfxlin-4.72 iforth

    Of course, if you think it if valuable to get 6 from the last line,
    you can use gforth-itc or any other threaded-code system, at a certain
    cost in performance: about a factor 2-3 for gforth-itc compared to
    gforth-fast.

    Likewise, I don't think it is a valuable feature to be able to change
    the offset of +FIELD after it has been defined, so it is useful to be
    able to define it in a way without that feature. If you want that
    feature, you can define it with closures:

    : +field ( n "name" -- )
    here swap , [n:d @ + ;] alias ;

    It's more cumbersome, and there is no easy way to find the cell you
    would change, but if you find and change that cell, the offset will
    change everywhere.

    Alternatively, you can implement [N:D in your system in such a way
    that you can also change the offset with the other [N:D-based
    definitions of +FIELD, just like you can change constants in
    gforth-itc.

    Concerning the complexity of the compiler, compiling a closure into
    another word efficiently is relatively simple: compile the value(s)
    passed into the closure as literal(s), then compile a call to the code
    inside the closure (possibly inlining the call).

    E.g., if I have

    : +field ( n "name" -- )
    [n:d + ;] alias ;

    5 +field x

    : foo x @ ;

    this could be compiled with relatively little effort as

    \ here's a named version of the closure code:
    : +field-closure1-code
    + ;

    : foo 5 +field-closure1-code @ ;

    Compiling that with vfxlin-4.72 gives:

    see foo
    FOO
    ( 080C0AC0 8B5B05 ) MOV EBX, [EBX+05]
    ( 080C0AC3 C3 ) NEXT,
    ( 4 bytes, 2 instructions )

    Whether you consider these differences a big deal, is up to you.

    For the moment I will prefer simple additions to Forth to
    achieve similar goals.

    Implementing [N:D and friends is pretty simple. Currently closures.fs
    has 227 lines (including comment lines and empty lines), but includes
    a lot of extra functionality.

    How big are your simple additions?

    - anton
    --
    M. Anton Ertl http://www.complang.tuwien.ac.at/anton/home.html
    comp.lang.forth FAQs: http://www.complang.tuwien.ac.at/forth/faq/toc.html
    New standard: http://www.forth200x.org/forth200x.html
    EuroForth 2021: https://euro.theforth.net/2021

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From none) (albert@21:1/5 to Anton Ertl on Sun Apr 24 21:07:14 2022
    In article <2022Apr24.182147@mips.complang.tuwien.ac.at>,
    Anton Ertl <anton@mips.complang.tuwien.ac.at> wrote:
    <SNIP>

    Implementing [N:D and friends is pretty simple. Currently closures.fs
    has 227 lines (including comment lines and empty lines), but includes
    a lot of extra functionality.

    How big are your simple additions?

    ALLOCATE : 3 screens ( >ALLOC sneaked in)
    class : 1 screen
    FORMAT&EVAL : 1 screen (needed for class)
    SWAP-DP : 1 screen (scratch compilation area)
    Likewise they contain functionality besides implementing
    defective pseudo-closures.

    These are compacted source library items. The originals were developed
    using files. Reckon some 30 lines for source files per block,
    maybe more if REGRESS (test lines) are present.

    To have an idea of code I use woc (words of code),
    the count doesn't differ between file source and block source.
    The woc-count is 615 in total. The loc-count is not saying much
    depending how generous one is regarding blank lines, or
    the presence of the GPL2 copyright in full.
    The woc count is also not sensitive to a horizontal or
    vertical layout.

    ----------------------
    #!/bin/sh

    cat $1 |\
    sed -e 's/\\ .*//' |\
    sed -e 's/( [^)]*)//g' |\
    sed -e '/\<DOC\>/,/\<ENDDOC\>/d'|\
    sed -e 's/\\D .*//' |\
    wc -w

    exit
    ----------------------



    - anton
    --
    M. Anton Ertl http://www.complang.tuwien.ac.at/anton/home.html

    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 Anton Ertl on Sun Apr 24 22:06:06 2022
    In article <2022Apr20.134942@mips.complang.tuwien.ac.at>,
    Anton Ertl <anton@mips.complang.tuwien.ac.at> wrote:
    albert@cherry.(none) (albert) writes:
    <SNIP>
    Better get rid of ?EXEC and ?COMP everywhere. They only check STATE
    at the time when the containing words are performed, which is not
    appropriate for checking whether the interpretation semantics or the >compilation semantics of a word are performed.

    It's fascinating that you used ?EXEC for EXIT. My guess is that this >happened the following way: You saw that EXIT has no interpretation >semantics, so you put in ?COMP. Of course this failed, probably on
    the first exection of EXIT. So the ?COMP was obviously wrong. As a
    remedy you thought you would put in ?EXEC, and it seemed to work (you
    have no immediate words containing EXIT), so you left it in, but it's
    just as wrong as ?COMP.

    I introduced ?EXEC in my story to get a point across.
    I don't actually use ?EXEC. If you look at my example of INTERPRET,
    you would realize that I don't check compilation mode in EXIT.
    In my implementation EXIT is a code word that pops the high level
    interpreter pointer from the return stack, then goes next.
    It is rigorously equivalent to the return instruction native
    code forth's use.

    ?EXEC is available as a loadable extension if you want to go traditional:
    65( -traditional- ?LOADING ?EXEC TRIAD ABORT" ) \ AvdH C2feb22


    As for having EXIT with interpretation semantics, that's something we
    wanted to support, as detailed in the grandparent posting. It's
    certainly a good idea to add useful functionality beyond the standard,
    but in the benefit was not worth the cost.

    Good to hear that.


    As for INTERPRET, if you want it standardized, make a proposal. You
    may want to provide some usage statistics to support your case.

    INTERPRET blends in in the ciforth model. It is not trivial to
    made it fit to ISO, as this is not a model, and a lot of details
    can go wrong. I will reflect upon the matter.
    If you build a Forth from scratch, you are forced to implement WORD
    with special case BL WORD, but you may not want use that internally. I
    don't want to add another such word.


    - 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 dxforth@21:1/5 to albert on Mon Apr 25 12:16:51 2022
    On 24/04/2022 18:39, albert wrote:
    In article <t428i6$16k9$1@gioia.aioe.org>, dxforth <dxforth@gmail.com> wrote:
    On 23/04/2022 23:22, luser droog wrote:
    On Tuesday, April 19, 2022 at 3:34:58 AM UTC-5, none albert wrote:
    In article <2022Apr1...@mips.complang.tuwien.ac.at>,
    Anton Ertl <an...@mips.complang.tuwien.ac.at> wrote:
    Probably not, because EXIT has no interpretation semantics. The EXIT
    and INTERPRET implementations on some systems may work to achieve the >>>> >effects you have in mind (although I doubt that it works for INCLUDED >>>> >and friends on many systems, because INCLUDED is one level out from
    the processing that EVALUATE and LOAD perform).
    A standard program according ISO can not use EXIT in interpretation
    state. That is not a dogma, but a design decision.
    In my implementation EXIT performs a return, i.e. pops a
    continuation address for the program counter, and jumps there.
    If I remove the ?EXEC (that serves to forbid EXIT in compilation
    state), suddenly it performs the useful function of ending INTERPRET.
    Making Forth better by removing a line, isn't that the tao of
    Forth?


    [Applause.]

    Except ANSForth isn't Forth. It's a federation (or confederation if one >>believes it was a choice) of Forth implementers. EXIT in interpret state >>is one of the many things it couldn't get agreement upon. Mistaking >>ANSForth for a created language is what results in the 'I could have done >>it better' complaints. Well yes, almost anyone could have created a better >>Forth but that's not what was being offered.

    You could not accuse me of not embracing ANSForth. Proposals in this way serve as incremental improvements of Forth.
    Considering ANSForth as dogma, was that something Jeff Fox and Chuck Moore warned about?

    Groetjes Albert

    EXIT was a regular word in Forth-79/83 until someone decided they could 'improve' on it.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Anton Ertl@21:1/5 to albert@cherry. on Mon Apr 25 05:56:26 2022
    albert@cherry.(none) (albert) writes:
    To have an idea of code I use woc (words of code),
    the count doesn't differ between file source and block source.
    The woc-count is 615 in total. The loc-count is not saying much
    depending how generous one is regarding blank lines, or
    the presence of the GPL2 copyright in full.
    The woc count is also not sensitive to a horizontal or
    vertical layout.

    ----------------------
    #!/bin/sh

    cat $1 |\
    sed -e 's/\\ .*//' |\
    sed -e 's/( [^)]*)//g' |\
    sed -e '/\<DOC\>/,/\<ENDDOC\>/d'|\
    sed -e 's/\\D .*//' |\
    wc -w

    exit
    ----------------------

    cat closures.fs |
    sed -e 's/\\ .*//' |
    sed -e 's/( [^)]*)//g' |
    sed -e 's/\\G .*//'|
    sed -e 's/\\D .*//'|
    head -209|
    wc -w
    622

    The "head -209" is there to avoid counting the man-or-boy-test that's
    there as a test (normally inactive).

    - anton
    --
    M. Anton Ertl http://www.complang.tuwien.ac.at/anton/home.html
    comp.lang.forth FAQs: http://www.complang.tuwien.ac.at/forth/faq/toc.html
    New standard: http://www.forth200x.org/forth200x.html
    EuroForth 2021: https://euro.theforth.net/2021

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From luser droog@21:1/5 to dxforth on Wed Apr 27 21:28:52 2022
    On Saturday, April 23, 2022 at 8:19:05 PM UTC-5, dxforth wrote:
    On 23/04/2022 23:22, luser droog wrote:
    On Tuesday, April 19, 2022 at 3:34:58 AM UTC-5, none albert wrote:
    In article <2022Apr1...@mips.complang.tuwien.ac.at>,
    Anton Ertl <an...@mips.complang.tuwien.ac.at> wrote:
    Probably not, because EXIT has no interpretation semantics. The EXIT
    and INTERPRET implementations on some systems may work to achieve the
    effects you have in mind (although I doubt that it works for INCLUDED
    and friends on many systems, because INCLUDED is one level out from
    the processing that EVALUATE and LOAD perform).
    A standard program according ISO can not use EXIT in interpretation
    state. That is not a dogma, but a design decision.
    In my implementation EXIT performs a return, i.e. pops a
    continuation address for the program counter, and jumps there.
    If I remove the ?EXEC (that serves to forbid EXIT in compilation
    state), suddenly it performs the useful function of ending INTERPRET.
    Making Forth better by removing a line, isn't that the tao of
    Forth?


    [Applause.]
    Except ANSForth isn't Forth. It's a federation (or confederation if one believes it was a choice) of Forth implementers. EXIT in interpret state
    is one of the many things it couldn't get agreement upon. Mistaking
    ANSForth for a created language is what results in the 'I could have done
    it better' complaints. Well yes, almost anyone could have created a better Forth but that's not what was being offered.

    I don't know enough about the whole story to weigh in there,
    just saying that Albert made a compelling point. So compelling
    that the rest of the story kinda reads as just noise to me.
    If I can figure out how to use it, my personal forth will do it this way.
    And that's all I'm likely to use anyway.

    Until I stumble across something better.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From dxforth@21:1/5 to luser droog on Thu Apr 28 16:46:23 2022
    On 28/04/2022 14:28, luser droog wrote:
    On Saturday, April 23, 2022 at 8:19:05 PM UTC-5, dxforth wrote:
    On 23/04/2022 23:22, luser droog wrote:
    On Tuesday, April 19, 2022 at 3:34:58 AM UTC-5, none albert wrote:
    In article <2022Apr1...@mips.complang.tuwien.ac.at>,
    Anton Ertl <an...@mips.complang.tuwien.ac.at> wrote:
    Probably not, because EXIT has no interpretation semantics. The EXIT
    and INTERPRET implementations on some systems may work to achieve the
    effects you have in mind (although I doubt that it works for INCLUDED
    and friends on many systems, because INCLUDED is one level out from
    the processing that EVALUATE and LOAD perform).
    A standard program according ISO can not use EXIT in interpretation
    state. That is not a dogma, but a design decision.
    In my implementation EXIT performs a return, i.e. pops a
    continuation address for the program counter, and jumps there.
    If I remove the ?EXEC (that serves to forbid EXIT in compilation
    state), suddenly it performs the useful function of ending INTERPRET.
    Making Forth better by removing a line, isn't that the tao of
    Forth?


    [Applause.]
    Except ANSForth isn't Forth. It's a federation (or confederation if one
    believes it was a choice) of Forth implementers. EXIT in interpret state
    is one of the many things it couldn't get agreement upon. Mistaking
    ANSForth for a created language is what results in the 'I could have done
    it better' complaints. Well yes, almost anyone could have created a better >> Forth but that's not what was being offered.

    I don't know enough about the whole story to weigh in there,
    just saying that Albert made a compelling point. So compelling
    that the rest of the story kinda reads as just noise to me.
    If I can figure out how to use it, my personal forth will do it this way.
    And that's all I'm likely to use anyway.

    Until I stumble across something better.

    For a while I had an EXIT with a ?COMP. To stop interpretation of a screen
    I defined:

    : \\ source >in ! drop ; immediate

    For text files it was extended to:

    -? : \\
    tf? if
    begin tfill 0= until
    end postpone \\ ; immediate

    When EXIT reverted to a regular word I saw little point changing them. What was once a neat trick back in the Fig-Forth days had lost its shine.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Hans Bezemer@21:1/5 to dxforth on Thu Apr 28 05:46:10 2022
    On Monday, April 25, 2022 at 4:16:53 AM UTC+2, dxforth wrote:
    EXIT was a regular word in Forth-79/83 until someone decided they could 'improve' on it.

    I agree. In 4tH, having Forth-79 roots, EXIT is still a very simple word: get TORS,
    put it in the instruction pointer and continue (Ok, some checks are made - agreed).

    It's not that much different from a RET instruction in Z80 - and why should it? It's
    just there as a counterpart for a CALL.

    Of course, if you add several other services (like taking care of locals) it will most
    probably become a bit beefier. That's one of the reasons why I don't like locals in
    the first place.

    Of course I love them in C - but C is not Forth.

    And those who have a history with my ramblings here won't be too surprised to hear that I don't like over-complicated Forths, which absolutely improve in "ease of
    use", but IMHO lose this "simple elegance" quality of Forth I fell in love with.

    So dxforth, I concur with you on this point.

    Hans Bezemer

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From none) (albert@21:1/5 to the.beez.speaks@gmail.com on Thu Apr 28 15:13:52 2022
    In article <ce65773c-3b15-40a3-b57b-bfcaa9d43748n@googlegroups.com>,
    Hans Bezemer <the.beez.speaks@gmail.com> wrote:
    On Monday, April 25, 2022 at 4:16:53 AM UTC+2, dxforth wrote:
    EXIT was a regular word in Forth-79/83 until someone decided they could
    'improve' on it.

    I agree. In 4tH, having Forth-79 roots, EXIT is still a very simple
    word: get TORS,
    put it in the instruction pointer and continue (Ok, some checks are made
    - agreed).

    It's not that much different from a RET instruction in Z80 - and why
    should it? It's
    just there as a counterpart for a CALL.

    Of course, if you add several other services (like taking care of
    locals) it will most
    probably become a bit beefier. That's one of the reasons why I don't
    like locals in
    the first place.

    Of course I love them in C - but C is not Forth.

    And those who have a history with my ramblings here won't be too surprised to >hear that I don't like over-complicated Forths, which absolutely improve
    in "ease of
    use", but IMHO lose this "simple elegance" quality of Forth I fell in love with.

    Lately I became fond of AUTOLOAD
    They CATCH any errors from the interpreting a line.
    If the error is 12 of 10 (undefined) , the name is WANTED through the
    library. If it succeeds, compilation goes on as if nothing happens.
    WANT AUTOLOAD
    SEE LOCATE
    Neither of SEE or LOCATE is in the kernel, but it works.

    Of course AUTOLOAD is a loadable extension, only available after
    WANT AUTOLOAD .


    So dxforth, I concur with you on this point.

    So do I, but it is possible to make life easier without compromising
    the simplicity of the kernel Forth.


    Hans Bezemer

    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 Hans Bezemer@21:1/5 to none albert on Thu Apr 28 08:13:18 2022
    On Thursday, April 28, 2022 at 3:13:55 PM UTC+2, none albert wrote:
    So dxforth, I concur with you on this point.
    So do I, but it is possible to make life easier without compromising
    the simplicity of the kernel Forth.

    True - in 4tH (with it's wildly different architecture) I see the same thing happening. But due to the radical division between "compilation" and "interpretation", I see it's not happening in the (inner) interpreter. It's happening in the compiler - or even the tools on top of the compiler, like
    the preprocessor.

    The VM hasn't become much smarter at all. In 10 (!) years, that code has
    seen only 15 changes - roughly a third of them C syntax related, a third of them architecture related and the final third of them behavior related (incl. new functionality).

    The compiler has seen about fifty changes in the meanwhile - most them
    behavior related.

    Translated to the classical Forth architecture - primitives and inner interpreter
    have hardly changed.

    I dunno how that works out for other Forths - I think it would be an interesting
    question, though.

    Hans Bezemer

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From none) (albert@21:1/5 to the.beez.speaks@gmail.com on Fri Apr 29 11:37:27 2022
    In article <8d0072a1-9127-41b4-9d88-89a001609358n@googlegroups.com>,
    Hans Bezemer <the.beez.speaks@gmail.com> wrote:
    On Thursday, April 28, 2022 at 3:13:55 PM UTC+2, none albert wrote:
    So dxforth, I concur with you on this point.
    So do I, but it is possible to make life easier without compromising
    the simplicity of the kernel Forth.

    True - in 4tH (with it's wildly different architecture) I see the same thing >happening. But due to the radical division between "compilation" and >"interpretation", I see it's not happening in the (inner) interpreter. It's >happening in the compiler - or even the tools on top of the compiler, like >the preprocessor.

    The VM hasn't become much smarter at all. In 10 (!) years, that code has
    seen only 15 changes - roughly a third of them C syntax related, a third of >them architecture related and the final third of them behavior related (incl. >new functionality).

    The compiler has seen about fifty changes in the meanwhile - most them >behavior related.

    Translated to the classical Forth architecture - primitives and inner >interpreter
    have hardly changed.

    I dunno how that works out for other Forths - I think it would be an interesting
    question, though.

    Don't stop looking for simplications. I recently managed the central (FIND) word from 6 to 3 labels and eliminate a third of the underlying
    ~MATCH word.
    The discotheque principle is useful. Nobody gets in, before somebody gets
    out. If you add a word, an other word has to get removed.
    This would be a useful principle for laws also.


    Hans Bezemer

    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 Hans Bezemer@21:1/5 to none albert on Fri Apr 29 03:36:18 2022
    On Friday, April 29, 2022 at 11:37:31 AM UTC+2, none albert wrote:
    Don't stop looking for simplications. I recently managed the central (FIND) word from 6 to 3 labels and eliminate a third of the underlying
    ~MATCH word.
    I recently reprogrammed the inner Accept() word. I was hesitant to touch it since - although murky - it had worked absolutely fine for three decades.

    I must have grown a bit in that time, because I found out how it exactly worked.
    And the code is not only much clearer now - it has additional functionality!

    The discotheque principle is useful. Nobody gets in, before somebody gets out. If you add a word, an other word has to get removed.
    This would be a useful principle for laws also.
    I have this policy that 4tH has 106 reserved tokens. For every one added, one must disappear. That leaves someone who wants to expand on it a clean
    150 ones to play with. Every change in a token bumps up the minor version number. That's why 3.63.x never came to be.

    So yes, I agree on that policy. That's why the compiler itself feeds most of the functionality changes. E.g. I recently added CASE..ENDCASE, but that's
    all handled by the compiler. The (inner) interpreter gets fed the very same tokens
    as before.

    Hans Bezemer

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