umouse

umouse.git
git clone git://git.lenczewski.org/umouse.git
Log | Files | Refs | Submodules | README

DPANSA9.HTM (8710B)


      1 <HTML><HEAD>
      2 <TITLE>DPANS94</TITLE>
      3 <link disabled rel="stylesheet" href="mpexc6.css">
      4 <style>@import url(mpexc6.css);</style>
      5 </head>
      6 
      7 <BODY>
      8 <table width=100%>
      9 <tr>
     10 <td align=left>
     11 <a href=dpansa8.htm><img src=left.gif
     12  width=26 height=26 align=ALIGN border=0></a>
     13 <a href=dpansa10.htm><img src=right.gif
     14  width=26 height=26 align=ALIGN border=0></a>
     15 </td>
     16 <td align=right>
     17 <a href=dpans.htm#toc><img src=up.gif 
     18  width=26 height=26 align=ALIGN border=0></a>
     19 <a name=A.9>Table of Contents</a>
     20 </td>
     21 </tr>
     22 </table>
     23 <p>
     24 <hr size=4>
     25 
     26 <H2>A.9 The optional Exception word set</H2>
     27 
     28 <a href=dpans9.htm#9.6.1.0875>CATCH</a> and 
     29 <a href=dpans9.htm#9.6.1.2275>THROW</a> 
     30 provide a reliable mechanism for handling exceptions,
     31 without having to propagate exception flags through multiple levels of
     32 word nesting.  It is similar in spirit to the <B>non-local return</B>
     33 mechanisms of many other languages, such as C's setjmp() and longjmp(),
     34 and LISP's CATCH and THROW.  In the Forth context, THROW may be
     35 described as a <B>multi-level</b> 
     36 <a href=dpans6.htm#6.1.1380>EXIT</a>, 
     37 with CATCH marking a location to
     38 which a THROW may return.
     39 
     40 <P>
     41 
     42 Several similar Forth <B>multi-level EXIT</B> exception-handling schemes
     43 have been described and used in past years.  It is not possible to
     44 implement such a scheme using only standard words (other than CATCH and
     45 THROW), because there is no portable way to <B>unwind</B> the return
     46 stack to a predetermined place.
     47 
     48 <P>
     49 
     50 THROW also provides a convenient implementation technique for the
     51 standard words 
     52 <a href=dpans6.htm#6.1.0670>ABORT</a> and 
     53 <a href=dpans6.htm#6.1.0680>ABORT"</a>, 
     54 allowing an application to define,
     55 through the use of CATCH, the behavior in the event of a system ABORT.
     56 
     57 <P>
     58 
     59 This sample implementation of CATCH and THROW uses the non-standard
     60 words described below.  They or their equivalents are available in many
     61 systems.  Other implementation strategies, including directly saving the
     62 value of 
     63 <a href=dpans6.htm#6.1.1200>DEPTH</a>, 
     64 are possible if such words are not available.
     65 
     66 <P>
     67 
     68 SP@  ( -- addr )  returns the
     69 address corresponding to the top of data stack.
     70 
     71 <P>
     72 
     73 SP!  ( addr -- )  sets the stack pointer to addr, thus restoring the stack
     74 depth to the same depth that existed just before addr was acquired by
     75 executing SP@.
     76 
     77 <P>
     78 
     79 RP@  ( -- addr )  returns the address corresponding to the top of return
     80 stack.
     81 
     82 <P>
     83 
     84 RP!  ( addr -- )  sets the return stack pointer to addr, thus restoring the
     85 return stack depth to the same depth that existed just before addr was
     86 acquired by executing RP@.
     87 
     88 <PRE>
     89 VARIABLE HANDLER   0 HANDLER !  \ last exception handler
     90 
     91 : CATCH  ( xt -- exception# | 0 ) \ return addr on stack
     92     SP@ >R         ( xt ) \ save data stack pointer
     93     HANDLER @ >R   ( xt ) \ and previous handler
     94     RP@ HANDLER !  ( xt ) \ set current handler
     95     EXECUTE        ( )    \ execute returns if no THROW
     96     R> HANDLER !   ( )    \ restore previous handler
     97     R> DROP        ( )    \ discard saved stack ptr
     98     0              ( 0 )  \ normal completion
     99 ;
    100 
    101 : THROW  ( ??? exception# -- ??? exception# )
    102     ?DUP IF          ( exc# ) \ 0 THROW is no-op
    103     HANDLER @ RP!  ( exc# ) \ restore prev return stack
    104     R> HANDLER !   ( exc# ) \ restore prev handler
    105     R> SWAP >R     ( saved-sp ) \ exc# on return stack
    106     SP! DROP R>    ( exc# ) \ restore stack
    107         \  Return to the caller of CATCH because return
    108         \  stack is restored to the state that existed
    109         \  when CATCH began execution
    110 THEN
    111 ;
    112 </PRE>
    113 
    114 <P>
    115 
    116 In a multi-tasking system, the HANDLER variable should be in the
    117 per-task variable area (i.e., a user variable).
    118 
    119 <P>
    120 
    121 This sample implementation does not explicitly handle the case in which
    122 CATCH has never been called (i.e., the ABORT behavior).  One solution is
    123 to add the following code after the IF in THROW:
    124 
    125 
    126 <PRE>
    127 	HANDLER @ 0= IF ( empty the stack ) QUIT THEN
    128 </PRE>
    129 
    130 <P>
    131 
    132 Another solution is to execute CATCH within 
    133 <a href=dpans6.htm#6.1.2050>QUIT</a>, so that there is
    134 always an <B>exception handler of last resort</B> present.  For example:
    135 
    136 <PRE>
    137 : QUIT      ( empty the return stack and )
    138             ( set the input source to the user input device )
    139     POSTPONE [
    140     BEGIN
    141       REFILL
    142     WHILE
    143       ['] INTERPRET CATCH
    144       CASE
    145       0 OF STATE @ 0= IF ." OK" THEN CR  ENDOF
    146      -1 OF ( Aborted) ENDOF
    147      -2 OF ( display  message from ABORT" ) ENDOF
    148       ( default ) DUP ." Exception # "  .
    149       ENDCASE
    150     REPEAT BYE
    151 ;
    152 </PRE>
    153 
    154 <P>
    155 
    156 This example assumes the existance of a system-implementation word
    157 INTERPRET that embodies the text interpreter semantics described in 
    158 <a href=dpans3.htm#3.4>3.4</a>
    159 The Forth text interpreter.  Note that this implementation of QUIT
    160 automatically handles the emptying of the stack and return stack, due to
    161 THROW's inherent restoration of the data and return stacks.  Given this
    162 definition of QUIT, it's easy to define:
    163 
    164 
    165 <PRE>
    166 	: ABORT  -1 THROW ;
    167 </PRE>
    168 
    169 <P>
    170 
    171 In systems with other stacks in addition to the data and return stacks,
    172 the implementation of CATCH and THROW must save and restore those stack
    173 pointers as well.  Such an <B>extended version</B> can be built on top
    174 of this basic implementation.  For example, with another stack pointer
    175 accessed with FP@ and FP! only CATCH needs to be redefined:
    176 
    177 <PRE>
    178 : CATCH  ( xt -- exception# | 0 )
    179     FP@ >R  CATCH  R> OVER IF FP! ELSE DROP THEN ;
    180 </PRE>
    181 
    182 <P>
    183 
    184 No change to THROW is necessary in this case.  Note that, as with all
    185 redefinitions, the redefined version of CATCH will only be available to
    186 definitions compiled after the redefinition of CATCH.
    187 
    188 <P>
    189 
    190 CATCH and THROW provide a convenient way for an implementation to
    191 <B>clean up</B> the state of open files if an exception occurs during
    192 the text interpretation of a file with 
    193 <a href=dpans11.htm#11.6.1.1717>INCLUDE-FILE</a>.  The implementation
    194 of INCLUDE-FILE may guard (with CATCH) the word that performs the text
    195 interpretation, and if CATCH returns an exception code, the file may be
    196 closed and the exception reTHROWn so that the files being included at an
    197 outer nesting level may be closed also.  Note that the Standard allows,
    198 but does not require, INCLUDE-FILE to close its open files if an
    199 exception occurs.  However, it does require INCLUDE-FILE to unnest the
    200 input source specification if an exception is THROWn.
    201 
    202 <P>
    203 
    204 <hr>
    205 <a name=A.9.3>
    206 <H3>A.9.3 Additional usage requirements</H3>
    207 </a>
    208 
    209 One important use of an exception handler is to maintain program control
    210 under many conditions which 
    211 <a href=dpans6.htm#6.1.0670>ABORT</a>.  This is practicable only if a range
    212 of codes is reserved.  Note that an application may overload many
    213 standard words in such a way as to 
    214 <a href=dpans9.htm#9.6.1.2275>THROW</a> ambiguous conditions not
    215 normally THROWn by a particular system.
    216 
    217 <P>
    218 
    219 <hr>
    220 <a name=A.9.3.6>
    221 <H4>A.9.3.6 Exception handling</H4>
    222 </a>
    223 
    224 The method of accomplishing this coupling is implementation dependent.
    225 For example, 
    226 <a href=dpans7.htm#7.6.1.1790>LOAD</a> 
    227 could <B>know</B> about 
    228 <a href=dpans9.htm#9.6.1.0875>CATCH</a> and 
    229 <a href=dpans9.htm#9.6.1.2275>THROW</a> (by using
    230 CATCH itself, for example), or CATCH and THROW could <B>know</B> about
    231 LOAD (by maintaining input source nesting information in a data
    232 structure known to THROW, for example).  Under these circumstances it is
    233 not possible for a Standard Program to define words such as LOAD in a
    234 completely portable way.
    235 
    236 <P>
    237 
    238 <hr>
    239 <a name=A.9.6>
    240 <H3>A.9.6 Glossary</H3>
    241 </a>
    242 
    243 
    244 <hr>
    245 <a name=A.9.6.1.2275>A.9.6.1.2275 THROW</A>
    246 <P>
    247 
    248 If THROW is executed with a non zero argument, the effect is as if the
    249 corresponding 
    250 <a href=dpans9.htm#9.6.1.0875>CATCH</a> 
    251 had returned it.  In that case, the stack depth is
    252 the same as it was just before CATCH began execution.  The values of the
    253 i*x stack arguments could have been modified arbitrarily during the
    254 execution of xt.  In general, nothing useful may be done with those
    255 stack items, but since their number is known (because the stack depth is
    256 deterministic), the application may 
    257 <a href=dpans6.htm#6.1.1260>DROP</a> them to return to a predictable
    258 stack state.
    259 
    260 <P>
    261 
    262 Typical use:
    263 
    264 <PRE>
    265 : could-fail ( -- char )
    266     KEY DUP [CHAR] Q =  IF  1 THROW THEN ;
    267 
    268 : do-it ( a b -- c)   2DROP could-fail ;
    269 
    270 : try-it ( --)
    271     1 2 ['] do-it  CATCH  IF ( x1 x2 )
    272         2DROP ." There was an exception" CR
    273     ELSE ." The character was " EMIT CR
    274     THEN
    275 ;
    276 
    277 : retry-it ( -- )
    278     BEGIN  1 2 ['] do-it CATCH  WHILE
    279        ( x1 x2) 2DROP  ." Exception, keep trying" CR
    280     REPEAT ( char )
    281     ." The character was " EMIT CR
    282 ;
    283 </PRE>
    284 
    285 <P>
    286 
    287 <hr>
    288 <a href=dpans.htm#toc><IMG   src="up.gif" ></A>    Table of Contents 
    289 <BR>
    290 <a href=dpansa10.htm><IMG   src="right.gif" ></A>
    291 Next Section
    292 <P>
    293 </BODY>
    294 </HTML>