implementationforth

How is SAVE-INPUT/RESTORE-INPUT implemented?


SAVE-INPUT should save the current state of the input source specification, but where?

It can't be saved to a fixed location, as SAVE-INPUT can be called multiple times before calling RESTORE-INPUT.

It can't be saved to the data stack, as it can grow later as a result of other words being executed.

It seems like it can be saved to the return stack, below the current return address, as SAVE-INPUT and RESTORE-INPUT are both executed in the same level (word), but that doesn't seem right.

EDIT

I was fooled by the doc; SAVE-SOURCE doesn't "save" anything in the sense of storing something somewhere for later retrieval.

These words should be called "GET-SOURCE/SET-SOURCE." to better reflect their operation.

But the problem of where to save SOURCE persists, since EVALUATE can be called recursively, and saving the information in a fixed memory location is useless.


Solution

  • SAVE-INPUT ( -- x.n ... x.1 n ) leaves a tuple of items on the data stack (see 6.2.2148). This tuple describes the current state of the input source specification; this tuple shall be valid until interpretation of this input source is complete.

    The program can move this tuple into memory (see nmem.fth) or onto the return stack (e.g., using N>R).

    When the program applies RESTORE-INPUT to this tuple, the current input source must be the same as the input source whose state is described by the tuple. The program may apply RESTORE-INPUT to the same tuple many times.

    SAVE-INPUT and RESTORE-INPUT work for the input source similarly to FILE-POSITION and REPOSITION-FILE for a file.

    as SAVE-INPUT and RESTORE-INPUT are both executed in the same level (word)

    This is not necessary. They can be executed at different levels of word nesting.

    A common problems in implementations of these words are:

    These words are almost not used by programs.


    An example implementation for cases where the input source is a string from evaluate or a block:

    : save-input ( -- input-sys )
      blk @ if \ the input source is a block
        >in @  blk @  2 exit
      then
      source-id -1 = if \ the input source is a string from `evaluate`
        >in @ source 3 exit
      then
      \ In other cases it's impossible to obtain the state of the input source
      \ without carnal knowledge
      source-id 1 
    ;
    : restore-input ( input-sys -- flag )
      case
        1 of source-id =  blk @ 0=  and  if -1 exit then endof
        2 of blk @ if blk ! >in ! 0 exit then endof \ this depends on implementation
        3 of source d=  source-id -1 =  and  blk @ 0=  and  if >in ! 0 exit then endof
        -12 throw \ "argument type mismatch"
      endcase ( i*x )
      true abort" invalid input source for `restore-input`"
    ;