Proposal: [291] Obsolescence for SAVE-INPUT and RESTORE-INPUT


This page is dedicated to discussing this specific proposal


ruvavatar of ruv [291] Obsolescence for SAVE-INPUT and RESTORE-INPUTProposal2023-03-02 19:04:49



Change Log

  • 2023-03-02 Initial version


The words SAVE-INPUT and RESTORE-INPUT almost don't bear any usefulness to programs, and they only burden implementers.

These words have the following problems:

  • Too few guarantees to programs: RESTORE-INPUT may work or fail depending on on the input source kind (file, pipe, string, keyboard).
  • The returned flag of RESTORE-INPUT is inconsistent with other words: true means fail, false means success. A better variant could be a throwable ior.
  • In some systems RESTORE-INPUT works incorrectly in some cases: it restores the position in the input buffer and returns success, but doesn't restore the content of the input buffer.

These words are almost not used in programs. I asked in comp.lang.forth and ForthHub. Only one program was mentioned: "Lambda Expressions in ANS Forth" by Gerry Jackson (sources), and in this case the problem can be also solved without these words.

What is sometimes required in programs is an ability to parse (extract) a text fragment from the input stream, and later translate (evaluate) this fragment in the current context, regardless whether the input stream was switched or not. Such an API should be designed separately. The words SAVE-INPUT and RESTORE-INPUT cannot help on that.


Declare the words SAVE-INPUT and RESTORE-INPUTas obsolescent, to destandardize (remove from the standard) them on the next iteration.


This change doesn't affect the standard systems. The new (or updated) standard systems can be made slightly simpler by not providing an implementation and documentation for these words (if they are not used internally).

The standard programs that employ these words gain a new environmental dependency, and later they become non compliant to the new versions of the standard.


In the section 1.4.2 Obsolescent features, after the phrase "This standard designates the following word as obsolescent:", add:

  • 6.2.2182 SAVE-INPUT
  • 6.2.2148 RESTORE-INPUT

In each of the glossary entries 6.2.2182 SAVE-INPUT and 6.2.2148 RESTORE-INPUT add the following note:


This word is obsolescent and is included as a concession to existing implementations.

JohanKotlinskiavatar of JohanKotlinski

SAVE-INPUT/RESTORE-INPUT are used in some user-space code, for example in Gforth assemblers + cross-compilers. Example:

: .times{  ( n -- input n )
  dup >r 1 > IF  save-input  THEN  r> ;
: .}times  ( input n -- input n-1 / 1 / )
  1- dup 0>
  IF  >r restore-input throw r@ 1 >
      IF  save-input  THEN  r>
  THEN ;

I can only imagine one workaround, which is to copy input to a buffer, and EXECUTE it from there. Obviously, such a workaround increases CPU+RAM usage.

ruvavatar of ruv

SAVE-INPUT/RESTORE-INPUT are used in some user-space code, for example in Gforth assemblers + cross-compilers.

It's a good finding. The words .times{ and .}times are formally defined in the standard Forth. Although, as I can see, they are not used anywhere.

One problem with this construct is that it can work or fail without any explanation, — since the standard does not guarantee any conditions in which restore-input shall work. So the construct .times{ ... .}times is actually a system-specific means (or it has an environmental dependency concerning behavior of restore-input).

Another problem with this construct is that the body is performed at least once regardless of n. To correctly implement the case of n=0, we need to parse the input stream till the corresponding closing .}times (with possible nesting). But if we parse the input stream in this way, we can save the extracted text into a buffer and just translate (evaluate) it the given number of times, without employing save-input/restore-input.

I believe, we should have an API that helps in such tasks. Under the hood it can save a content or position (depending on the input source kind), and provides a uniform interface. Actually, such an API can be even implemented in a portable way if we standardize two things:

  1. When the input stream is a string, the line comment shall skip up to the nearest line terminator or to the end of the input buffer (what is encountered first) (see a comment).
  2. A program should not depend on the input source kind from which it's translated. It means, it should not rely that the input buffer contains a single line, and that refill reads a single line (see Portable line-oriented parsing). Probably, some helper words should be standardized for that.

Obviously, such a workaround increases CPU+RAM usage.

It depends on how save-input is implemented. A reliable implementation can also save a fragment of the input stream into the memory. OTOH, repeating reading from the file can take more CPU than reading from memory.

Reply New Version