If any bits of n are non-zero, pop the topmost exception frame from the exception stack, along with everything on the return stack above that frame. Then restore the input source specification in use before the corresponding CATCH and adjust the depths of all stacks defined by this standard so that they are the same as the depths saved in the exception frame (i is the same number as the i in the input arguments to the corresponding CATCH), put n on top of the data stack, and transfer control to a point just after the CATCH that pushed that exception frame.
If the top of the stack is non zero and there is no exception frame on the exception stack, the behavior is as follows:
Otherwise, the system may display an implementation-dependent message giving information about the condition associated with the THROW code n. Subsequently, the system shall perform the function of 6.1.0670 ABORT (the version of ABORT in the Core word set).
KEY DUP [CHAR] Q = IF 1 THROW THEN ;
?DUP IF ( exc# ) \ 0 THROW is no-op
HANDLER @ RP! ( exc# ) \ restore prev return stack
R> HANDLER ! ( exc# ) \ restore prev handler
R> SWAP >R ( saved-sp ) \ exc# on return stack
SP! DROP R> ( exc# ) \ restore stack
\ Return to the caller of CATCH because return
\ stack is restored to the state that existed
\ when CATCH began execution
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.
AndrewRead EXCEPTION LOCALsProposal2017-10-28 07:04:49
Disclaimer - my opinion is biased by the work I have already done on my hardware Forth machine
Conceptually I see BASE, and STATE (and some variables connected to the standard input / output) not as GLOBALs but as "EXCEPTION LOCALs". I.e. variables located on the exception stack. (My analogy here is with the more familiar "SUBROUTINE LOCALs" we are familiar with from the subroutine stack.)
When the Exception stack is PUSH_ed (by CATCH), then the current values of BASE etc. are pushed onto the Exception stack too.
When the Exception stack in POP_ed (by 1 THROW), then the current values of BASE etc. are discarded and the values from the exception layer above become current.
This is easy to implement if BASE etc. are located wherever the exception stack is located. I do it in hardware, but that's a detail.