Digest #25 2018-01-08
: FILL -ROT 0 ?DO 2DUP C! 1+ LOOP 2DROP ;
: 2DROP DROP DROP ;
: 2DUP OVER OVER ;
: 2SWAP >R -ROT R> -ROT ;
: 2OVER 2>R 2DUP 2R> 2SWAP ;
: OVER >R DUP R> SWAP ;
: TYPE 0 MAX 0 ?DO DUP C@ EMIT 1+ LOOP DROP ;
: ['] IMMEDIATE ' POSTPONE LITERAL ;
: [CHAR] IMMEDIATE CHAR POSTPONE LITERAL ;
: HEX 16 BASE !
: NIP SWAP DROP ;
: TUCK SWAP OVER ;
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.
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.
IMMEDIATE itself is not immediate, so Bernd Paysan's reference implementation is correct, and it contains a stack effect comment.
IMMEDIATE is not immediate, so this won't work. A working version is:
: ['] ( compilation: "name" --; run-time: -- xt ) ' POSTPONE literal ; immediate