例外処理までプリミティブじゃないのか
Forth では例外処理までプリミティブではなく、Forth 自身で書けてしまう。
リターンスタックをいじれるといろんなことができるのか。
普通の言語じゃ関数の戻り先なんていじれないもんな。
Forth は本当に自由な言語だ。
jonesforth.f より。
: EXCEPTION-MARKER RDROP ( drop the original parameter stack pointer ) 0 ( there was no exception, this is the normal return path ) ; : CATCH ( xt -- exn? ) DSP@ 4+ >R ( save parameter stack pointer (+4 because of xt) on the return stack ) ' EXCEPTION-MARKER 4+ ( push the address of the RDROP inside EXCEPTION-MARKER ... ) >R ( ... on to the return stack so it acts like a return address ) EXECUTE ( execute the nested function ) ; : THROW ( n -- ) ?DUP IF ( only act if the exception code <> 0 ) RSP@ ( get return stack pointer ) BEGIN DUP R0 4- < ( RSP < R0 ) WHILE DUP @ ( get the return stack entry ) ' EXCEPTION-MARKER 4+ = IF ( found the EXCEPTION-MARKER on the return stack ) 4+ ( skip the EXCEPTION-MARKER on the return stack ) RSP! ( restore the return stack pointer ) ( Restore the parameter stack. ) DUP DUP DUP ( reserve some working space so the stack for this word doesn't coincide with the part of the stack being restored ) R> ( get the saved parameter stack pointer | n dsp ) 4- ( reserve space on the stack to store n ) SWAP OVER ( dsp n dsp ) ! ( write n on the stack ) DSP! EXIT ( restore the parameter stack pointer, immediately exit ) THEN 4+ REPEAT ( No matching catch - print a message and restart the INTERPRETer. ) DROP CASE 0 1- OF ( ABORT ) ." ABORTED" CR ENDOF ( default case ) ." UNCAUGHT THROW " DUP . CR ENDCASE QUIT THEN ; : ABORT ( -- ) 0 1- THROW ;