• How does the input stream traditionally work?

    From Paul Rubin@no.email@nospam.invalid to comp.lang.forth on Fri Mar 13 15:10:13 2026
    From Newsgroup: comp.lang.forth

    They can really be nested, right? So there's a REPL that can load files
    that can load other files, there is EVALUATE, there are parsing words
    that intercept the input stream from when they are invoked, etc. So the current input source has to at least conceptually be maintained on a
    stack.

    Is there typically an explicit stack for this inside a text interpreter?
    Is it normally just done with recursion and the usual D and R stacks?
    Using stack juggling in the implementations where the person doesn't
    want to use local variables?

    Wondering what is usual in this.
    --- Synchronet 3.21d-Linux NewsLink 1.2
  • From peter@peter.noreply@tin.it to comp.lang.forth on Sat Mar 14 10:12:39 2026
    From Newsgroup: comp.lang.forth

    On Fri, 13 Mar 2026 15:10:13 -0700
    Paul Rubin <no.email@nospam.invalid> wrote:

    They can really be nested, right? So there's a REPL that can load files
    that can load other files, there is EVALUATE, there are parsing words
    that intercept the input stream from when they are invoked, etc. So the current input source has to at least conceptually be maintained on a
    stack.

    Is there typically an explicit stack for this inside a text interpreter?
    Is it normally just done with recursion and the usual D and R stacks?
    Using stack juggling in the implementations where the person doesn't
    want to use local variables?

    Wondering what is usual in this.

    Check out the standard words SAVE-INPUT and RESTORE-INPUT!

    Here is Evaluate from ntf64 as an example

    : EVALUATE ( addr u -- )
    save-input 2>r
    (#src) ! (src) ! 0 >in ! -1 sid ! 0 blk ! ['] refill-evaluate [refill] !
    s" Evaluate:" sourcename place
    ['] interpret catch
    dup -1 < if .source then
    restore-input drop
    throw ;

    save-input in my implementation only leaves a pointer to a structure,
    holding all input state, on the stack and a count of 1. That info is saved on the return stack. Every input source starts it own interpreter, catches its result and if thrown prints out where it was in the source.

    There are of course many ways of doing this!

    BR
    Peter

    --- Synchronet 3.21d-Linux NewsLink 1.2
  • From anton@anton@mips.complang.tuwien.ac.at (Anton Ertl) to comp.lang.forth on Sat Mar 14 11:26:49 2026
    From Newsgroup: comp.lang.forth

    Paul Rubin <no.email@nospam.invalid> writes:
    They can really be nested, right?

    What would make you doubt that?

    Is there typically an explicit stack for this inside a text interpreter?

    I don't think there is anything typical here, because INCLUDED and
    EVALUATE were introduced after the great increase in the number of
    Forth systems in the 1980s; so everybody came up with their own
    implementation.

    Gforth currently creates a new input buffer at the start of INCLUDED
    (actually its factor EVALUATE-PARSING-NAMED-FILE, but I will use
    "INCLUDED" in the following) and frees it at the end, and includes a
    link to the previous input buffer in the data structure of the input
    buffer, forming a stack implemented as a linked list.

    Is it normally just done with recursion and the usual D and R stacks?

    Of course there is an (indirect) recursion when you call INCLUDED
    while INCLUDED is already running. If you look at the stack effect of INCLUDED, LOAD, and EVALUATE, you will find that they are not allowed
    to use the data stack for their storage needs, The return stack is
    available for such purposes, however.

    Using stack juggling in the implementations where the person doesn't
    want to use local variables?

    In Gforth the locals implementation is in a file that is INCLUDED. So
    INCLUDED had to be implemented without locals.

    Not just that, but INCLUDED is also implemented in the cross-compiled
    part of Gforth. If we wanted to use locals for implementing INCLUDED,
    we would need to teach the cross-compiler about locals.

    - 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 2025 proceedings: http://www.euroforth.org/ef25/papers/
    --- Synchronet 3.21d-Linux NewsLink 1.2
  • From albert@albert@spenarnc.xs4all.nl to comp.lang.forth on Sat Mar 14 15:33:57 2026
    From Newsgroup: comp.lang.forth

    In article <87bjgre5yy.fsf@nightsong.com>,
    Paul Rubin <no.email@nospam.invalid> wrote:
    They can really be nested, right? So there's a REPL that can load files
    that can load other files, there is EVALUATE, there are parsing words
    that intercept the input stream from when they are invoked, etc. So the >current input source has to at least conceptually be maintained on a
    stack.

    Is there typically an explicit stack for this inside a text interpreter?
    Is it normally just done with recursion and the usual D and R stacks?
    Using stack juggling in the implementations where the person doesn't
    want to use local variables?

    Wondering what is usual in this.

    Anton comments that there are several approaches, following from the
    fact that this is properly specified, not forcing implementors hand.

    ciforth prioritize simplicity.
    The core ciforth always slurps the whole file. All text currently
    interpreted is present. Three pointers identify the input source,
    easily stored on the return stack ( SAVE RESTORE ).
    The only thing that is actually a stream is standard input.
    There is no REFILl only a REFILL-TIB (!) that accommodates redirection.

    Then there were complaints by people that wanted to use REFILL
    to skip to the next line. If INCLUDE must accommodate nesting you
    have to have a buffer for each file.
    Fortunately ciforth contains a buffering mechanism for blocks,
    that can be reused. The old fashioned restriction that every
    input should check whether a block is still valid has long been
    abandoned. Instead I have a lock mechanism for buffers.
    It is strict ISO, but the consequence is that UPDATE ing is
    immediately writing to disk, killing tape performance,
    inconsequential for disk based systems.

    On terminating an include, or in case of throws the buffer is
    unlocked.

    Groetjes Albert
    --
    The Chinese government is satisfied with its military superiority over USA.
    The next 5 year plan has as primary goal to advance life expectancy
    over 80 years, like Western Europe.
    --- Synchronet 3.21d-Linux NewsLink 1.2
  • From anton@anton@mips.complang.tuwien.ac.at (Anton Ertl) to comp.lang.forth on Sat Mar 14 15:09:24 2026
    From Newsgroup: comp.lang.forth

    peter <peter.noreply@tin.it> writes:
    On Fri, 13 Mar 2026 15:10:13 -0700
    Paul Rubin <no.email@nospam.invalid> wrote:

    They can really be nested, right?
    [...]
    Check out the standard words SAVE-INPUT and RESTORE-INPUT!

    I don't think there is anything to check out:

    1) If you want to treat RESTORE-INPUT a reliable component (i.e.,
    whenever you give it an input produced by SAVE-INPUT, it restores
    the input source specification and returns false), I don't see how
    to reconcile this with the nesting of INCLUDED, EVALUATE and LOAD.
    E.g., consider:

    File a.4th:
    --------------
    .( a)
    include b.4th
    .( b)
    restore-input abort" RESTORE-INPUT cannot restore input source specification"
    .( c)
    --------------

    File b.4th:
    -------------
    .( d)
    save-input
    .( e)

    what should this code output?

    2) OTOH, if you consider the allowance for systems to let
    RESTORE-INPUT return true, it is certainly not useful for
    implementing INCLUDED and friends, unless you have extra knowledge
    about the concrete implementation of SAVE-INPUT and RESTORE-INPUT,
    in which case Paul Rubin would have to check out that particular
    implementation, not the standard words.

    E.g., in Gforth RESTORE-INPUT returns false only if the source-id
    is the same as on SAVE-INPUT, so in Gforth SAVE-INPUT and
    RESTORE-INPUT are completely useless for implementing INCLUDED and
    friends.

    In the extreme, the following implementation of these words
    satisfies the requirements of the standard, but is absolutely
    useless:
    : SAVE-INPUT ( -- ) ;
    : RESTORE-INPUT ( -- f ) true ;

    Actually, looking at <https://forth-standard.org/standard/rationale#rat:core:SAVE-INPUT>, I
    find that the committee intended the usage that Gforth supports, and
    nothing more. This rationale even claims that a usage that tries to
    unnest the input stream using RESTORE-INPUT is non-standard (but I
    don't read that out of the normative text).

    Here is Evaluate from ntf64 as an example

    : EVALUATE ( addr u -- )
    save-input 2>r
    (#src) ! (src) ! 0 >in ! -1 sid ! 0 blk ! ['] refill-evaluate [refill] !
    s" Evaluate:" sourcename place
    ['] interpret catch
    dup -1 < if .source then
    restore-input drop
    throw ;

    It looks like you make use of carnal knowledge about how your
    SAVE-INPUT and RESTORE-INPUT is implemented, including knowledge of
    the number of stack items pushed by SAVE-INPUT, and DROPping the flag
    that indicates the success or failure of RESTORE-INPUT.

    - 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 2025 proceedings: http://www.euroforth.org/ef25/papers/
    --- Synchronet 3.21d-Linux NewsLink 1.2
  • From peter@peter.noreply@tin.it to comp.lang.forth on Sat Mar 14 23:30:10 2026
    From Newsgroup: comp.lang.forth

    On Sat, 14 Mar 2026 15:09:24 GMT
    anton@mips.complang.tuwien.ac.at (Anton Ertl) wrote:

    peter <peter.noreply@tin.it> writes:
    On Fri, 13 Mar 2026 15:10:13 -0700
    Paul Rubin <no.email@nospam.invalid> wrote:

    They can really be nested, right?
    [...]
    Check out the standard words SAVE-INPUT and RESTORE-INPUT!

    I don't think there is anything to check out:

    1) If you want to treat RESTORE-INPUT a reliable component (i.e.,
    whenever you give it an input produced by SAVE-INPUT, it restores
    the input source specification and returns false), I don't see how
    to reconcile this with the nesting of INCLUDED, EVALUATE and LOAD.
    E.g., consider:

    File a.4th:
    --------------
    .( a)
    include b.4th
    .( b)
    restore-input abort" RESTORE-INPUT cannot restore input source specification"
    .( c)
    --------------

    File b.4th:
    -------------
    .( d)
    save-input
    .( e)

    what should this code output?
    on LXF64 it outputs adeb and then crashes!
    I think that is expected. It crashes as save-input save the input for b.4th
    but include b.4th does a restore input and also closes the b.4th file-mapping as it is ready using it. when the next restore-input comes it restores again the input but now the file-mapping is gone and it crashes when reading from
    non existing memory.


    2) OTOH, if you consider the allowance for systems to let
    RESTORE-INPUT return true, it is certainly not useful for
    implementing INCLUDED and friends, unless you have extra knowledge
    about the concrete implementation of SAVE-INPUT and RESTORE-INPUT,
    in which case Paul Rubin would have to check out that particular
    implementation, not the standard words.

    E.g., in Gforth RESTORE-INPUT returns false only if the source-id
    is the same as on SAVE-INPUT, so in Gforth SAVE-INPUT and
    RESTORE-INPUT are completely useless for implementing INCLUDED and
    friends.

    In the extreme, the following implementation of these words
    satisfies the requirements of the standard, but is absolutely
    useless:
    : SAVE-INPUT ( -- ) ;
    : RESTORE-INPUT ( -- f ) true ;

    Actually, looking at <https://forth-standard.org/standard/rationale#rat:core:SAVE-INPUT>, I
    find that the committee intended the usage that Gforth supports, and
    nothing more. This rationale even claims that a usage that tries to
    unnest the input stream using RESTORE-INPUT is non-standard (but I
    don't read that out of the normative text).

    Here is Evaluate from ntf64 as an example

    : EVALUATE ( addr u -- )
    save-input 2>r
    (#src) ! (src) ! 0 >in ! -1 sid ! 0 blk ! ['] refill-evaluate [refill] !
    s" Evaluate:" sourcename place
    ['] interpret catch
    dup -1 < if .source then
    restore-input drop
    throw ;

    It looks like you make use of carnal knowledge about how your
    SAVE-INPUT and RESTORE-INPUT is implemented, including knowledge of
    the number of stack items pushed by SAVE-INPUT, and DROPping the flag
    that indicates the success or failure of RESTORE-INPUT.

    Yes SAVE-INPUT and RESTORE-INPUT is coded to work in INCLUDE EVALUATE etc.
    And for sure I use that fully.

    I have always thought that that was the main use for them!

    Thanks to the way input variables are organized they are very simple

    : SAVE-INPUT ( -- addr 1 )
    input-source @
    include-buffer dup input-source !
    over swap icb-len move
    1 ;

    : RESTORE-INPUT ( addr n -- f )
    1 <> abort" Bad restore-input"
    input-source @ free throw
    input-source !
    blk-fix
    0 ;

    include-buffer just allocates icb-len of space

    This works for INCLUDE etc and also passes Garry Jackssons test suit

    BR
    Peter


    - anton


    --- Synchronet 3.21d-Linux NewsLink 1.2
  • From Paul Rubin@no.email@nospam.invalid to comp.lang.forth on Sat Mar 14 23:34:12 2026
    From Newsgroup: comp.lang.forth

    anton@mips.complang.tuwien.ac.at (Anton Ertl) writes:
    I don't think there is anything typical here, because INCLUDED and
    EVALUATE were introduced after the great increase in the number of
    Forth systems in the 1980s; so everybody came up with their own implementation.

    Ah thanks, I had wondered if there was a traditional approach. But was
    there a similar situation with blocks from the very beginning? You'd
    LOAD an initialization block for your application, which in turn would
    use LOAD and THRU, maybe nested through multiple levels, to load the
    rest of your program as e.g. a tree of subsystems.

    Gforth currently... forming a stack implemented as a linked list.

    Thanks, the above is helpful.

    while INCLUDED is already running. If you look at the stack effect of INCLUDED, LOAD, and EVALUATE, you will find that they are not allowed
    to use the data stack for their storage needs, The return stack is
    available for such purposes, however.

    I didn't know about this restriction. It's not mentioned in Docs-html/Forth-source-files.html for gforth 0.7.0 or 0.7.9 at the
    moment fwiw. It sounds inconvenient.
    --- Synchronet 3.21d-Linux NewsLink 1.2
  • From dxf@dxforth@gmail.com to comp.lang.forth on Sun Mar 15 18:26:45 2026
    From Newsgroup: comp.lang.forth

    On 15/03/2026 5:34 pm, Paul Rubin wrote:
    anton@mips.complang.tuwien.ac.at (Anton Ertl) writes:
    ...
    while INCLUDED is already running. If you look at the stack effect of
    INCLUDED, LOAD, and EVALUATE, you will find that they are not allowed
    to use the data stack for their storage needs, The return stack is
    available for such purposes, however.

    I didn't know about this restriction. It's not mentioned in Docs-html/Forth-source-files.html for gforth 0.7.0 or 0.7.9 at the
    moment fwiw. It sounds inconvenient.

    DX-Forth uses a 256 byte return stack. The consequence of that is only
    about 6 files can be included before it runs out. Were my DO LOOPs
    three items on the return stack instead of two, even less files could
    be included. Of course I could increase return stack size (it's even a run-time option) but it's fine as it is.

    --- Synchronet 3.21d-Linux NewsLink 1.2
  • From anton@anton@mips.complang.tuwien.ac.at (Anton Ertl) to comp.lang.forth on Sun Mar 15 14:02:42 2026
    From Newsgroup: comp.lang.forth

    peter <peter.noreply@tin.it> writes:
    On Sat, 14 Mar 2026 15:09:24 GMT
    anton@mips.complang.tuwien.ac.at (Anton Ertl) wrote:
    E.g., consider:

    File a.4th:
    --------------
    .( a)
    include b.4th
    .( b)
    restore-input abort" RESTORE-INPUT cannot restore input source specification"
    .( c)
    --------------

    File b.4th:
    -------------
    .( d)
    save-input
    .( e)

    what should this code output?
    on LXF64 it outputs adeb and then crashes!
    I think that is expected. It crashes as save-input save the input for b.4th >but include b.4th does a restore input and also closes the b.4th file-mapping >as it is ready using it. when the next restore-input comes it restores again >the input but now the file-mapping is gone and it crashes when reading from >non existing memory.

    You expect it because you know your implementation.

    In Gforth it prints "adeb", then some complaints because abort" is compile-only, then "c".

    After changing the abort" into code that throws if the flag is true, I
    get

    adeb
    in file included from *args*:1:1:
    a.4th:4:21: error: error #1
    restore-input 1 and >>>throw<<<

    I can also imagine an implementation SAVE-INPUT puts some permanent
    reference to the file on the stack (say filesystem number and inode
    number), plus a position within the file, and RESTORE-INPUT recreates
    the position within b.4th from that. The interesting thing then is
    what happens when the second coming of b.4th tries to unnest at the
    file end. What if the RESTORE-INPUT did not happen from another file,
    but from an EVALUATE or a LOAD?

    Given that the intention of SAVE-INPUT and RESTORE-INPUT was to work
    within a single input source, I think the better approach would have
    been that RESTORE-INPUT produces no flag, but guarantees restoration
    as long as you are in the same file, EVALUATE, or LOAD as the
    SAVE-INPUT, and throws otherwise (admittedly, exceptions were not
    guaranteed in Forth-94).

    - 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 2025 proceedings: http://www.euroforth.org/ef25/papers/
    --- Synchronet 3.21d-Linux NewsLink 1.2
  • From anton@anton@mips.complang.tuwien.ac.at (Anton Ertl) to comp.lang.forth on Sun Mar 15 16:29:20 2026
    From Newsgroup: comp.lang.forth

    Paul Rubin <no.email@nospam.invalid> writes:
    anton@mips.complang.tuwien.ac.at (Anton Ertl) writes:
    I don't think there is anything typical here, because INCLUDED and
    EVALUATE were introduced after the great increase in the number of
    Forth systems in the 1980s; so everybody came up with their own
    implementation.

    Ah thanks, I had wondered if there was a traditional approach. But was
    there a similar situation with blocks from the very beginning?

    Forth had blocks already while it was Chuck Moore's language. The
    current LOADed block is stored in BLK, and LOAD of course to save BLK
    before changing it and restore BLK after the block has been
    text-interpreted. And BLK @ BLOCK has to be performed at appropriate
    places.

    If you look at the stack effect of
    INCLUDED, LOAD, and EVALUATE, you will find that they are not allowed
    to use the data stack for their storage needs, The return stack is
    available for such purposes, however.

    I didn't know about this restriction. It's not mentioned in >Docs-html/Forth-source-files.html for gforth 0.7.0 or 0.7.9 at the
    moment fwiw. It sounds inconvenient.

    It's a guarantee, not a restriction, to programmers. It allows them
    to pass data on the data stack into and out of an INCLUDED file, a
    LOADed block, or an EVALUATEd string.

    Where do you find this guarantee:

    https://forth-standard.org/standard/file/INCLUDED says:
    |( i * x c-addr u -- j * x )
    |
    |Remove c-addr u from the stack. ... Other stack effects are due to the
    |words included.

    EVALUATE and LOAD are similar, but are not explicit about removing the
    string descriptor or the block number first. This may be something we
    may want to fix at some point.

    - 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 2025 proceedings: http://www.euroforth.org/ef25/papers/
    --- Synchronet 3.21d-Linux NewsLink 1.2
  • From albert@albert@spenarnc.xs4all.nl to comp.lang.forth on Sun Mar 15 19:25:45 2026
    From Newsgroup: comp.lang.forth

    In article <2026Mar15.150242@mips.complang.tuwien.ac.at>,
    Anton Ertl <anton@mips.complang.tuwien.ac.at> wrote:
    <SNIP>
    Given that the intention of SAVE-INPUT and RESTORE-INPUT was to work
    within a single input source, I think the better approach would have
    been that RESTORE-INPUT produces no flag, but guarantees restoration
    as long as you are in the same file, EVALUATE, or LOAD as the
    SAVE-INPUT, and throws otherwise (admittedly, exceptions were not
    guaranteed in Forth-94).

    I had tested the transputer Forth including a file from loading a block
    called from evaluating a string. With throws and all.
    That succeeds, but I did not have have the idea that you could do
    RESTORE-INPUT while a SAVE-INPUT from another stream is hanging.
    That is insane, and honestly it is hard to think of a scenario that
    would be useful.
    "
    RESTORE-INPUT:
    An ambiguous condition exist if the latest SAVE-INPUT was not
    from the same stream as the input currently restored.
    "
    The flag could be useful to signal that this condition where not
    met.

    - anton


    Groetjes Albert
    --
    The Chinese government is satisfied with its military superiority over USA.
    The next 5 year plan has as primary goal to advance life expectancy
    over 80 years, like Western Europe.
    --- Synchronet 3.21d-Linux NewsLink 1.2
  • From albert@albert@spenarnc.xs4all.nl to comp.lang.forth on Sun Mar 15 19:48:48 2026
    From Newsgroup: comp.lang.forth

    In article <2026Mar15.172920@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 there is anything typical here, because INCLUDED and
    EVALUATE were introduced after the great increase in the number of
    Forth systems in the 1980s; so everybody came up with their own
    implementation.

    Ah thanks, I had wondered if there was a traditional approach. But was >>there a similar situation with blocks from the very beginning?

    Forth had blocks already while it was Chuck Moore's language. The
    current LOADed block is stored in BLK, and LOAD of course to save BLK
    before changing it and restore BLK after the block has been
    text-interpreted. And BLK @ BLOCK has to be performed at appropriate
    places.

    I recommend locking blocks in memory as long as they are being interpreted.
    BLK @ BLOCK has becomes superfluous.
    In modern system you can afford , say 16 block buffers and an extract
    flag. All legacy programs will still work, but the implementation can
    nest blocks without worry.

    - anton
    Groetjes Albert
    --
    The Chinese government is satisfied with its military superiority over USA.
    The next 5 year plan has as primary goal to advance life expectancy
    over 80 years, like Western Europe.
    --- Synchronet 3.21d-Linux NewsLink 1.2
  • From Paul Rubin@no.email@nospam.invalid to comp.lang.forth on Sun Mar 15 13:21:36 2026
    From Newsgroup: comp.lang.forth

    dxf <dxforth@gmail.com> writes:
    DX-Forth uses a 256 byte return stack. The consequence of that is only
    about 6 files can be included before it runs out.

    If you mean 6 levels of nesting, that seems sufficient for a small
    system. It's around 20 return stack cells for each level. Is that for
    a blocks system, or do you have files? I guess it's reasonable to set
    aside a chunk of dictionary or block space to use as an explicit stack,
    if you want to remember filenames.

    Do you use RPICK or anything like that, to get at the data for the
    current level?

    I still don't understand the issue with using the data stack. Maybe I
    haven't thought about it enough.
    --- Synchronet 3.21d-Linux NewsLink 1.2
  • From dxf@dxforth@gmail.com to comp.lang.forth on Mon Mar 16 10:46:53 2026
    From Newsgroup: comp.lang.forth

    On 16/03/2026 7:21 am, Paul Rubin wrote:
    dxf <dxforth@gmail.com> writes:
    DX-Forth uses a 256 byte return stack. The consequence of that is only
    about 6 files can be included before it runs out.

    If you mean 6 levels of nesting, that seems sufficient for a small
    system. It's around 20 return stack cells for each level. Is that for
    a blocks system, or do you have files?

    Blocks are mapped onto OS files. DX-Forth maintains a 'file descriptor
    block' in memory of which there are 6. A flag in the FDB determines
    whether it's a block file, text file or unused. Loading works on the
    principle of a 'current file' whose pointer is saved/restored during
    nesting.

    I guess it's reasonable to set
    aside a chunk of dictionary or block space to use as an explicit stack,
    if you want to remember filenames.

    A field in the file descriptor block holds the filename.

    Do you use RPICK or anything like that, to get at the data for the
    current level?

    Not sure what you mean, but no, I use nothing fancy.

    I still don't understand the issue with using the data stack. Maybe I haven't thought about it enough.

    It would prevent nested files from passing data on the stack.

    --- Synchronet 3.21d-Linux NewsLink 1.2
  • From Paul Rubin@no.email@nospam.invalid to comp.lang.forth on Sun Mar 15 18:09:28 2026
    From Newsgroup: comp.lang.forth

    dxf <dxforth@gmail.com> writes:
    It would prevent nested files from passing data on the stack.

    Oh I think I understand what you mean now. LOAD can't have extra stuff
    on the data stack when it transfers control to the newly loaded block or
    file. But, it can use the DS temporarily while getting the new block
    ready to run. It could even return after modifying the input stream
    pointer so execution would continue in the new block. Location in the
    old stream would have to be saved somewhere, and restored on reaching
    EOF in the new block or file.

    Loading works on the principle of a 'current file' whose pointer is saved/restored during nesting.

    Ok but in this case why is the return stack depth a limiting factor?
    The FDB pointer is just one cell, maybe even a static cell. Then you
    have an array of FDB's that is used as a stack with the FDB pointer as a
    stack pointer, if I understand what you mean.
    --- Synchronet 3.21d-Linux NewsLink 1.2
  • From dxf@dxforth@gmail.com to comp.lang.forth on Mon Mar 16 13:13:20 2026
    From Newsgroup: comp.lang.forth

    On 16/03/2026 12:09 pm, Paul Rubin wrote:
    dxf <dxforth@gmail.com> writes:
    ...
    Loading works on the principle of a 'current file' whose pointer is
    saved/restored during nesting.

    Ok but in this case why is the return stack depth a limiting factor?
    The FDB pointer is just one cell, maybe even a static cell. Then you
    have an array of FDB's that is used as a stack with the FDB pointer as a stack pointer, if I understand what you mean.

    For each nest there's state stuff that needs saving (loadline# source
    in blk etc). Then there's RS usage incurred during load/compile of
    the current file. It all adds up. My ?STACK does a RS check which is
    how I discovered 6 nested files was about the max.

    --- Synchronet 3.21d-Linux NewsLink 1.2
  • From Paul Rubin@no.email@nospam.invalid to comp.lang.forth on Mon Mar 16 15:14:33 2026
    From Newsgroup: comp.lang.forth

    dxf <dxforth@gmail.com> writes:
    For each nest there's state stuff that needs saving (loadline# source
    in blk etc).

    Oh I had figured that would be in the FDB. Does it have to be on the
    stack for some reason?

    Then there's RS usage incurred during load/compile of the current
    file. It all adds up.

    I wonder if moving the state to the FDB can get rid of the need for
    stack nesting. Then it's just a matter of how many FDB's you want to
    set aside space for. You could even put them in the ALLOCATE heap if
    you have that.
    --- Synchronet 3.21d-Linux NewsLink 1.2
  • From dxf@dxforth@gmail.com to comp.lang.forth on Tue Mar 17 10:37:23 2026
    From Newsgroup: comp.lang.forth

    On 17/03/2026 9:14 am, Paul Rubin wrote:
    dxf <dxforth@gmail.com> writes:
    For each nest there's state stuff that needs saving (loadline# source
    in blk etc).

    Oh I had figured that would be in the FDB. Does it have to be on the
    stack for some reason?

    Then there's RS usage incurred during load/compile of the current
    file. It all adds up.

    I wonder if moving the state to the FDB can get rid of the need for
    stack nesting. Then it's just a matter of how many FDB's you want to
    set aside space for. You could even put them in the ALLOCATE heap if
    you have that.

    I'd have to think how that could be made to work. OTOH RS exists and
    as its entire purpose is nesting, why wouldn't I use it? I don't have
    ALLOCATE for various reasons. It's always struck me as black magic.

    --- Synchronet 3.21d-Linux NewsLink 1.2
  • From Paul Rubin@no.email@nospam.invalid to comp.lang.forth on Mon Mar 16 17:27:03 2026
    From Newsgroup: comp.lang.forth

    dxf <dxforth@gmail.com> writes:
    I'd have to think how that could be made to work. OTOH RS exists and
    as its entire purpose is nesting, why wouldn't I use it?

    Do you have to do a bunch of painful juggling to get at the several
    relevant RS items? And as you say, it limits you to 6 levels.

    I don't have ALLOCATE for various reasons. It's always struck me as
    black magic.

    It gets worse. Don't ever let anyone tell you about garbage collection ;).
    --- Synchronet 3.21d-Linux NewsLink 1.2
  • From dxf@dxforth@gmail.com to comp.lang.forth on Tue Mar 17 12:48:52 2026
    From Newsgroup: comp.lang.forth

    On 17/03/2026 11:27 am, Paul Rubin wrote:
    dxf <dxforth@gmail.com> writes:
    I'd have to think how that could be made to work. OTOH RS exists and
    as its entire purpose is nesting, why wouldn't I use it?

    Do you have to do a bunch of painful juggling to get at the several
    relevant RS items? And as you say, it limits you to 6 levels.

    Nested files is the same as nested words with the exception there's
    more to save. There's nothing about the stacked word/file that needs accessing. The data stack is used for passing information between
    words/files if required.


    I don't have ALLOCATE for various reasons. It's always struck me as
    black magic.

    It gets worse. Don't ever let anyone tell you about garbage collection ;).

    --- Synchronet 3.21d-Linux NewsLink 1.2
  • From albert@albert@spenarnc.xs4all.nl to comp.lang.forth on Tue Mar 17 11:16:18 2026
    From Newsgroup: comp.lang.forth

    In article <87jyvbcth2.fsf@nightsong.com>,
    Paul Rubin <no.email@nospam.invalid> wrote:
    dxf <dxforth@gmail.com> writes:
    For each nest there's state stuff that needs saving (loadline# source
    in blk etc).

    Oh I had figured that would be in the FDB. Does it have to be on the
    stack for some reason?

    Then there's RS usage incurred during load/compile of the current
    file. It all adds up.

    I wonder if moving the state to the FDB can get rid of the need for
    stack nesting. Then it's just a matter of how many FDB's you want to
    set aside space for. You could even put them in the ALLOCATE heap if
    you have that.

    Somehow in addition to buffer information you must remember the
    file identification. For unix and linux that is a handle that you
    get back from OPEN-FILE. That is readily stored on the return stack,
    if you are not in a pinch (on a 64 bit system). If you store this in
    FDB still you have stack a reference to the FDB. I don't think you
    can use the data stack for that.
    Groetjes Albert
    --
    The Chinese government is satisfied with its military superiority over USA.
    The next 5 year plan has as primary goal to advance life expectancy
    over 80 years, like Western Europe.
    --- Synchronet 3.21d-Linux NewsLink 1.2
  • From Gerry Jackson@do-not-use@swldwa.uk to comp.lang.forth on Tue Mar 17 11:27:27 2026
    From Newsgroup: comp.lang.forth

    On 17/03/2026 10:16, albert@spenarnc.xs4all.nl wrote:
    In article <87jyvbcth2.fsf@nightsong.com>,
    Paul Rubin <no.email@nospam.invalid> wrote:
    dxf <dxforth@gmail.com> writes:
    For each nest there's state stuff that needs saving (loadline# source
    in blk etc).

    Oh I had figured that would be in the FDB. Does it have to be on the
    stack for some reason?

    Then there's RS usage incurred during load/compile of the current
    file. It all adds up.

    I wonder if moving the state to the FDB can get rid of the need for
    stack nesting. Then it's just a matter of how many FDB's you want to
    set aside space for. You could even put them in the ALLOCATE heap if
    you have that.

    Somehow in addition to buffer information you must remember the
    file identification. For unix and linux that is a handle that you
    get back from OPEN-FILE. That is readily stored on the return stack,
    if you are not in a pinch (on a 64 bit system). If you store this in
    FDB still you have stack a reference to the FDB. I don't think you
    can use the data stack for that.
    Groetjes Albert

    Presumably the file id has to be stored with the input source data as
    the specification for SOURCE-ID returns it when the source is a text
    file (see 11.6.1.2218 in the standard).
    --
    Gerry
    --- Synchronet 3.21d-Linux NewsLink 1.2