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>