en:words:catch_throw
Table of Contents
catch throw
sp@ ( – addr )
returns the address corresponding to the top of data stack.
rp@ ( – addr )
returns the address corresponding to the top of return stack.
sp! ( addr – )
sets the stack pointer to addr, thus restoring the stack depth to
the same depth that existed just before addr was acquired by
executing sp@.
rp! ( addr – )
sets the return stack pointer to addr. thus restoring the return
stack depth to the same depth that existed just before addr was
acquired by executing rp@.
Legend:
- #exc = exeption number
- ix = any stack items underneath #exc * iadr = any returnstack items above last catchframe
- xt = execution address used inside of catch by EXECUTE
- RS: = Return Stack Picture
Step by step explanation of CATCH
variable handler \ Most recent exception handler \ Put catchframe on return stack. \ v v : CATCH ( xt -- exc# | 0 ) ( 1) ( 2) sp@ >r ( -- xt) ( RS: -- sp ) ( 3) handler @ >r ( -- xt) ( RS: -- sp hlr ) ( 4) rp@ handler ! ( -- xt) ( RS: -- sp hlr ) ( 5) execute ( -- ) ( RS: -- sp hlr ) ( 6) r> handler ! ( -- ) ( RS: -- sp ) ( 7) r> drop ( -- ) ( RS: -- ) ( 8) 0 ( -- 0 ) ( 9) ;
- Build a catchframe for throw. Pass the exception number of the word executeted.
- Execution token XT is already on the stack.
- Save data stack pointer; exclude current xt on data stack.
- Save previous handler.
- Set current handler to this one.
sp
,hlr
andhandler
are current catchframe now. - Now execute the word passed in on the stack. It is now wrapped by your own exception handler, created with the word where you put your catch in.
- Execution comes back without exception. So restore previous handler.
- Discard saved data stack pointer.
- Signify normal completion by 0 on data stack.
Step by step explanation of THROW
\ TROW exits to saved context if exc# <> 0 : THROW ( i*x exc# -- i*x exc# | i*x exc# ) ( RS: -- sp hlr i*adr ) ( 1) dup 0= ( -- i*x exc# f ) ( RS: -- sp hlr i*adr ) ( 2) if drop exit then ( -- i*x ) ( RS: -- sp hlr i*adr ) ( 3) handler @ rp! ( -- i*x exc# ) ( RS: -- sp hlr ) ( 4) r> handler ! ( -- i*x exc# ) ( RS: -- sp ) ( 5) r> ( -- i*x exc# sp ) ( RS: -- ) ( 6) swap ( -- i*x sp exc# ) ( RS: -- ) ( 7) >r ( -- i*x sp ) ( RS: -- exc# ) ( 8) sp! ( -- xt ) ( RS: -- exc# ) ( 9) drop r> ( -- exc# ) ( RS: -- ) ( 10) ;
throw
expects an exception numer on the stack, passing or dropping it, and its returnstack picture has a catchframe underneath the current returnaddresses.- Get flag.
- Noop, don't throw 0.
- Return to saved return stack context.
- Restore previous handler.
- Get saved stack pointer.
- Ready to save #exc on return stack for use in step ( 9).
- Now save it
- Return to saved data stack context; we can see XT again now, but it's no use, so drop it.
- Pass exception number. We are ready to proceed error handling words compiled behind CATCH in calling word. The caling word is that which has the CATCH phrase in its compilat.
Intended use is:
\ enable "spam" to THROW an exeption number in case of exeption. : spam ( -- ) ... #exc THROW ; \ put "spam" into exception handling frame using CATCH : sapm-exc ( i*x -- ) ... ['] spam CATCH ( -- #exc ) dup 0= IF drop exit then \ = NOOP dup #exc = IF ... \ known error code, do execption handling else ... throw \ unknown error code; re-throw system code then ;
( finis)
en/words/catch_throw.txt · Last modified: 2013-06-06 21:26 by 127.0.0.1