Proposal: The value of STATE should be restored

Informal

This proposal has been moved into this section. Its former address was: /standard/exception/THROW

This page is dedicated to discussing this specific proposal

ContributeContributions

AlexDyachenkoavatar of AlexDyachenko The value of STATE should be restoredProposal2017-09-03 11:07:49

To meaningfully continue after a THROW/CATCH, the value of STATE should be captured during CATCH and restored during THROW.

LeonWagneravatar of LeonWagner

What is your use case for this? Could you show us an example?

AntonErtlavatar of AntonErtl

We discussed this at the standards meeting, but do not have an answer for this proposal yet. Anyway, here is my personal answer:

It is a common problem to have a global variable that you want to restore on exiting a word, whether the exit is regular, or through THROW. This problem exists not just for system variables like STATE or BASE, but also for application variables. The general approach that I recommend is to have wrappers around the code that changes the variables. The wrapper catches any exception coming through, restores the old value of the variable, and then THROWs the exception (if any) on. For STATE, this can be done as follows:

: state! ( f -- )
  if ] else postpone [ then ;
: state-wrapper ( xt -- )
  state @ >r catch r> state! throw ;

\ usage example
s" ] non-existent-word" ' evaluate ' state-wrapper catch .

AlexDyachenkoavatar of AlexDyachenko

My main use case was trying to handle any errors that may occur when including another file, e.g.

S" somefile.4th" ' INCLUDED CATCH ...

This code could be interpreted or compiled, and of course inside somefile.4th the STATE can change arbitrarily prior to a THROW. So anything following CATCH would only work as intended if STATE had not changed. Your example is certainly one way to work around this, but it requires every use of CATCH to be wrapped. In my opinion, if CATCH does not restore STATE, it falls short of satisfying this from the THROW Rationale: "If THROW is executed with a non zero argument, the effect is as if the corresponding CATCH had returned it." The application variables are certainly the application's responsibility, but system variables should be the system's.

If an otherwise standard system chose to restore STATE and BASE as part of the CATCH semantics, would this still be a standard system?

AntonErtlavatar of AntonErtl

Not every CATCH needs to be wrapped, only code that changes STATE. If you have a word that changes and has to restore STATE, use a STATE-wrapper. All other CATCHes are unaffected. Because the INCLUDED can change STATE, use a STATE-wrapper for the INCLUDED in your example.

The cited statement from the rationale is about what happens on the stack, and is unrelated to other state.

A system that saves and restores STATE on a CATCH would not be standard, because it would do programmer-visible things that are not specified in the standard.

StephenPelcavatar of StephenPelc

The current definition of CATCH and THROW is deliberately minimal. I believe that it should stay minimal. An embedded system may use CATCH/THROW but not have STATE or BASE.

We (MPE) have attempted in the past to cope with customer wishes for extended facilities. 30 years later we regret all these concessions. The best that we could do now is to DEFER CATCH and THROW.

In the given use case (INCLUDED and friends), the most likely action of the final error handler is to leave compilation and perform some form of restart. We also have plenty of instances in which errors are rethrown because the CATCH/THROW mechanism itself is used to ensure state recovery at several levels. In this case, putting a CATCH inside INCLUDED and then throwing again permits STATE restoration, and no specification change for CATCH is required.

Reply New Version