6.2.2182 SAVE-INPUT CORE EXT

( -- xn ... x1 n )

x1 through xn describe the current state of the input source specification for later use by RESTORE-INPUT.

See:

Rationale:

SAVE-INPUT and RESTORE-INPUT allow the same degree of input source repositioning within a text file as is available with BLOCK input. SAVE-INPUT and RESTORE-INPUT "hide the details" of the operations necessary to accomplish this repositioning, and are used the same way with all input sources. This makes it easier for programs to reposition the input source, because they do not have to inspect several variables and take different action depending on the values of those variables.

SAVE-INPUT and RESTORE-INPUT are intended for repositioning within a single input source; for example, the following scenario is NOT allowed for a Standard Program:

: XX
   SAVE-INPUT CREATE
   S" RESTORE-INPUT" EVALUATE
   ABORT" couldn't restore input"
;

This is incorrect because, at the time RESTORE-INPUT is executed, the input source is the string via EVALUATE, which is not the same input source that was in effect when SAVE-INPUT was executed.

The following code is allowed:

: XX
   SAVE-INPUT CREATE
   S" .( Hello)" EVALUATE
   RESTORE-INPUT ABORT" couldn't restore input"
;

After EVALUATE returns, the input source specification is restored to its previous state, thus SAVE- INPUT and RESTORE-INPUT are called with the same input source in effect.

In the above examples, the EVALUATE phrase could have been replaced by a phrase involving INCLUDE-FILE and the same rules would apply.

The standard does not specify what happens if a program violates the above rules. A Standard System might check for the violation and return an exception indication from RESTORE-INPUT, or it might fail in an unpredictable way.

The return value from RESTORE-INPUT is primarily intended to report the case where the program attempts to restore the position of an input source whose position cannot be restored. The keyboard might be such an input source.

Nesting of SAVE-INPUT and RESTORE-INPUT is allowed. For example, the following situation works as expected:

: XX
   SAVE-INPUT
   S" f1" INCLUDED
   \ The file "f1" includes:
   \ ... SAVE-INPUT ... RESTORE-INPUT ...
   \ End of file "f1"
   RESTORE-INPUT ABORT" couldn't restore input"
;

In principle, RESTORE-INPUT could be implemented to "always fail", e.g.:

: RESTORE-INPUT ( x1 ... xn n -- flag )
   0 ?DO DROP LOOP TRUE
;

Such an implementation would not be useful in most cases. It would be preferable for a system to leave SAVE-INPUT and RESTORE-INPUT undefined, rather than to create a useless implementation. In the absence of the words, the application programmer could choose whether or not to create "dummy" implementations or to work-around the problem in some other way.

Examples of how an implementation might use the return values from SAVE-INPUT to accomplish the save/restore function:


Input Source possible stack values

block >IN @ BLK @ 2
EVALUATE >IN @ 1
keyboard >IN @ 1
text file >IN @ lo-pos hi-pos 3

These are examples only; a Standard Program may not assume any particular meaning for the individual stack items returned by SAVE-INPUT.

Testing:

Testing with a file source
VARIABLE siv -1 siv !

: NeverExecuted
   ." This should never be executed" ABORT
;

11111 SAVE-INPUT

siv @

[IF]
   0 siv !
   RESTORE-INPUT
   NeverExecuted
[ELSE]
   \ Testing the ELSE part is executed
   22222
[THEN]

T{ -> 11111 0 22222 }T    \ 0 comes from RESTORE-INPUT

Testing with a string source
VARIABLE si_inc 0 si_inc !

: si1
   si_inc @ >IN +!
   15 si_inc !
;

: s$ S" SAVE-INPUT si1 RESTORE-INPUT 12345" ;

T{ s$ EVALUATE si_inc @ -> 0 2345 15 }T

Testing nesting
: read_a_line
   REFILL 0=
   ABORT" REFILL failed"
;

0 si_inc !
2VARIABLE 2res -1. 2res 2!

: si2
   read_a_line
   read_a_line
   SAVE-INPUT
   read_a_line
   read_a_line
   s$ EVALUATE 2res 2!
   RESTORE-INPUT
;

WARNING: do not delete or insert lines of text after si2 is called otherwise the next test will fail

si2
33333                  \ This line should be ignored
2res 2@ 44444        \ RESTORE-INPUT should return to this line

55555

T{ -> 0 0 2345 44444 55555 }T

ContributeContributions

FrancoisLaagelavatar of FrancoisLaagel [265] Bogus Test Case for SAVE-INPUTSuggested Testcase2022-09-06 14:36:57

In the "Testing" NeverExecuted obviously is executed and that's the end of it!

ruvavatar of ruv

Again, where have you tested the code?

RESTORE-INPUT changes the input source state, so after the next REFILL the parse area contains not " NeverExecuted" but " siv @" (that returns 0 in this time).

FrancoisLaagelavatar of FrancoisLaagel

Hello ruv,

I do apologize for the noise. Back when I published this, I was focusing on implementing EVALUATE without having a clearly defined SAVE-INPUT and RESTORE-INPUT process. The smoke has cleared up from my side since then and I have learned my lesson. I should always compare behaviour to what GNU Forth does, even though I will never support all the features of that beats.

Sorry about that.

    Francois
Closed
Reply New Version

JohanKotlinskiavatar of JohanKotlinski [282] Is data stack required?Request for clarification2023-02-14 20:17:30

Is it a requirement that SAVE-INPUT and RESTORE-INPUT saves the state on the data stack?

I would prefer if it was allowed to keep the state on some other stack. (my Forth has a very limited data stack space)

JohanKotlinskiavatar of JohanKotlinski

Umm... given that N>R R>N are listed as related. Is the intended workflow like this?

SAVE-INPUT N>R ... R>N RESTORE-INPUT ?

ruvavatar of ruv

I would prefer if it was allowed to keep the state on some other stack.

Probably, you need other (system-specific) words for that. The words save-input and restore-input are not what they appear on the first glance — see my other comment.

Is the intended workflow like this? SAVE-INPUT N>R ... R>N RESTORE-INPUT ?

It's a possible workflow, but in a single found program that uses these words ("Lambda Expressions in ANS Forth" by Gerry Jackson), they are used in a totally different manner. See a discussion on ForthHub.

AntonErtlavatar of AntonErtl

Yes, it's a requirement. However, given that the other requirements (guarantees to programs) are very weak, you do not need to put a lot of data on the data stack (at least for a minimal implementation of SAVE-INPUT).

Those who support N>R NR> told me that SAVE-INPUT N>R ... NR> RESTORE-INPUT is a usage that motivates N>R NR>. WHERE N>R on SwiftForth shows two uses, both after SAVE-INPUT and likewise both usese of NR> are before RESTORE-INPUT.

ruvavatar of ruv

N>R on SwiftForth shows two uses, both after SAVE-INPUT and likewise both usese of NR> are before RESTORE-INPUT.

BTW, in SwiftForth RESTORE-INPUT is used on a different input source. A standard program cannot use them in such a manner due to an ambiguous condition, which "exists if the input source represented by the arguments is not the same as the current input source".

Also, a SwiftForth version 3.11.6 peculiar (probably not only its) is that RESTORE-INPUT returns 0 (success) when it actually does not restore the state of the input source — e.g., in the case of keyboard. In this case it restores the position, but not the content of the input buffer. According to the specification, it shall restore nothing and return fail (-1), if it cannot restore the state of the input source.

UlrichHoffmannavatar of UlrichHoffmann

In my opinion, the ctual SAVE-INPUT values could be in a different memory area at some addrese ADDR and the stack effect of SAVE-INPUT might just be ( -- ADDR 1 ). This would be acceptable as a standard behaviour and would relieve the data stack on stack space limited systems.

AntonErtlavatar of AntonErtl

We discussed this question at the meeting on 2023-02-17, and our conclusion was that we do not recommend implementing SAVE-INPUT and RESTORE-INPUT on systems that are so memory constrained that the amount of data-stack memory is a problem.

Closed
Reply New Version

AbstractionFirstavatar of AbstractionFirst [437] A language standard should specify abstractions rather than mechanismsComment2026-07-18 19:38:23

I would like to raise a more general design question rather than the specific semantics of SAVE-INPUT itself.

One of the primary goals of a language standard is to specify observable semantics while leaving implementation details to implementors whenever possible.

This raises the following question:

Can a portable application express a requirement that naturally maps to SAVE-INPUT?

In practice, application programs manipulate data, define new words, parse text, compile code, evaluate strings, and process files. They naturally use words such as PARSE, EVALUATE, REFILL, and POSTPONE.

SAVE-INPUT and RESTORE-INPUTappear to belong to a different category. They expose and preserve the internal state of the input-processing mechanism rather than providing an application-level abstraction.

If these words are intended primarily for implementors of Forth systems rather than for portable application programs, should they really be part of the standard application interface?

More generally, should a language standard expose implementation mechanisms, or should it specify only the observable behavior required of a conforming system?

I believe this distinction deserves discussion because it directly affects implementation freedom without changing observable language semantics.

ruvavatar of ruv

We have a proposal to make the words save-input and restore-input obsolescent.

In any case, these words are optional and may be absent in a standard Forth system.


to specify observable semantics

Yes, sure. Note that in some cases, to observe semantics (behavior), we have to execute not just one word, but several words or even a program.

They expose and preserve the internal state of the input-processing mechanism rather than providing an application-level abstraction.

They do not expose internal state. They produce and consume an opaque data object and allow to restore internal state (withing specified constraints), without exposing its internal details. Beyond these operations, the user is only allowed to store and fetch this data object from memory.

Conceptually, these words could replace the functionality of >in. However, this did not happen because they are much less convenient to use.

I think the problem with these words isn't that they are not abstract enough, but that:

  • they don't provide sufficient guarantees (they might work with one input source kind but not another),
  • their flag of success is inverted,
  • they are not suitable for solving practical problems.

AntonErtlavatar of AntonErtl

Can a portable application express a requirement that naturally maps to SAVE-INPUT?

Given the lack of guarantees in restore-input, probably not. If restore-input was specified more tightly, yes. The usage would be a multi-line variant of what >in is used for (judging from the rationale).

My impression is that nobody uses save-input and restore-input in code that is intended to be portable, though. And while there are occasional questions about what these words are good for, nobody has actually pushed for a tightening of the specification.

My guess is that if these words are removed from the standard, no one who intends to write a standard program will miss them.

If these words are intended primarily for implementors of Forth systems rather than for portable application programs

Reading the rationale, the intention was to provide a feature for portable application programs. My dim memory of some of the discussions about these words is that some people have pointed out that some systems use them to implement some other words, such as IIRC included.

These words do not expose implementation mechanisms. I can think of many implementation approaches that support useful implementations of these words, and none that are incompatible with useful implementations of these words. And useless implementations do not care about the implementation of the input stream at all.

AbstractionFirstavatar of AbstractionFirst

I think my original point was not expressed clearly enough.

My intention was not to discuss whether SAVE-INPUT is useful, whether it should be specified more tightly, or how it can be implemented.

The question I was trying to raise is a different one:

Should facilities that manipulate the interpreter's own state belong to the application interface at all?

In other words, my concern is not the design of SAVE-INPUT itself, but the criteria used to decide whether such words belong in the standard programming interface for portable applications.

ruvavatar of ruv

Should facilities that manipulate the interpreter's own state belong to the application interface at all?

Your point was that save-input and restore-input are not in the same category as parse and refill. I didn't see any criteria by which these categories are distinguished. All of these words manipulate the state of the Forth system, namely, the state of the input source (in contrast, evaluate does not affect the state of the input source). Changing the value at >in also manipulates the state of the input source, as does its potential replacement, the word set-source-offset.

The Forth standard, at its core, defines an interface to the Forth system (an API). See 1.2 Scope, which says: "This standard specifies an interface between a Forth System and a Forth Program by defining the words provided by a Standard System". It's impossible to remove all words that affect the state of the Forth system.

AbstractionFirstavatar of AbstractionFirst

The distinction I am proposing is not based on whether a word manipulates the state of the Forth system.

It is about the language model.

The current standard mixes together words that are primarily needed by Forth implementors with words that are intended for general application programming.

My point is about the architecture of the language as a whole rather than the implementation of individual words.

ruvavatar of ruv

My point is about the architecture of the language as a whole rather than the implementation of individual words.

You should probably present your ideas as a new proposal with specific changes, rather than as comments on individual words.

AntonErtlavatar of AntonErtl

Should facilities that manipulate the interpreter's own state belong to the application interface at all?

I generally recommend to not write parsing words, but writing them is common practice, and until we have made the alternatives (such as recognizers or passing strings) compelling enough that people rewrite their code in terms of the alternatives, there is common practice, and the standard should include words for writing them.

The current standard mixes together words that are primarily needed by Forth implementors with words that are intended for general application programming.

There is no need to standardize words that are not useful outside the Forth system, and AFAICS, no such words have been standardized, certainly not those that you mentioned in your recent comments. These words are all intended for portable Forth programs; some people may consider not all of these programs to be "general application programs", but it's unclear what the criteria would be for this distinction.

pdaavatar of pda

About the question in the title " A language standard should specify abstractions rather than mechanisms" , even when I agree with the sentence a fundamental question arise in my brain: is this sentence compatible with the philosophy of Forth itself? as far as I know Forth has always been a language that do not hide implementation to the user and developer, it focuses in simplicity and hardware aware design , so I feel walking the path of abstraction is walking the opposite way of Forth pathway , even when I agree Forth classification of world into words is a powerful kind of abstraction

AntonErtlavatar of AntonErtl

is this sentence compatible with the philosophy of Forth itself?

That depends on what you mean with "the philosophy of Forth"? If you mean Chuck Moore's philosophy, standardization itself is not compatible with it, so he has bowed out of the standardization process many decades ago.

You can examine individual ideas that have been claimed to be part of the philosophy of Forth for compatibility with this sentence, but I think that it is a better use of your time to examine how well individual words or word groups satisfy goals like ease of use, ease of implementation, efficiency, portability between hardware platforms, portability between Forth systems, etc. I think that the Forth-94 committee generally did a good job in providing abstractions that satisfy many of these goals, with some exceptions.

Reply New Version