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.
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
andRESTORE-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:
RESTORE-INPUT
returns 0
(instead of -1
) when the input source state is not actually restored.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`"
;