Author: chip Date: Sat Jul 1 11:26:02 2006 New Revision: 13092 Modified: trunk/docs/pdds/pdd23_exceptions.pod
Log: * Exception handlers are now closures (or just plain subroutines), not continuations. * Eliminate the C<rethrow> opcode, as the handler returning is enough of a clue that the next handler should be called. (This change is at Allison & Patrick's request, and in accord with Audrey's not requesting otherwise. :-)) Modified: trunk/docs/pdds/pdd23_exceptions.pod ============================================================================== --- trunk/docs/pdds/pdd23_exceptions.pod (original) +++ trunk/docs/pdds/pdd23_exceptions.pod Sat Jul 1 11:26:02 2006 @@ -42,26 +42,29 @@ =over -=item B<< push_eh I<LABEL> >> {{FIXME - Not Available Yet}} +=item B<< push_eh I<SUB_LABEL> >> -=item B<< push_eh I<CONTINUATION> >> +=item B<< push_eh I<INVOCABLE_PMC> >> -The C<push_eh> opcode pushes a continuation onto the exception handler stack. +Push an invocable PMC -- usually a closure or, in rarer cases, a subroutine -- +onto the exception handler stack. -If a I<LABEL> is provided, Parrot automatically performs the equivalent of a -C<newcontinuation> operation on the given label, and pushes the resulting -continuation. - -{{FIXME - there is no "newcontinuation" opcode ... yet! In the meantime, you -have to create the continuations the old-fashioned way.}} +If a I<SUB_LABEL> is provided, Parrot automatically performs the equivalent of +a C<newclosure> operation on the given subroutine, and pushes the resulting +closure. When an exception is thrown, Parrot walks up the stack of active exception -handlers, invoking each one in turn. (See C<rethrow> and C<caught>.) +handlers, invoking each one in turn, but still in the dynamic context of the +exception (i.e. the call stack is I<not> unwound first). See below for more +detail. =item B<< pop_eh >> -The C<pop_eh> opcode removes the most recently pushed exception handler from -the control stack. +Pop the most recently pushed exception handler off the control stack. + +{{ TODO: should we provide a "pop_eh $P0" variant returning the address, since +it's easy and somebody might find it useful? Or is it more important to +provide generic control stack introspection? Probably the latter. }} =item B<< throw I<EXCEPTION> >> @@ -87,14 +90,15 @@ continuation at the next opcode. Active exception handlers (if any) will be invoked with I<EXCEPTION> and the given continuation as parameters. -Exception handlers can resume execution immediately after this opcode by -executing the C<caught> opcode, and then invoking the given continuation. - -{{TODO: May the continuation be invoked with values, or in other words, can -throwcc return a value?}} - -Except for the taking of a continuation which is passed to exception handlers, -C<throwcc> is just like C<throw>. +Except for its taking of a continuation which is then passed to exception +handlers, C<throwcc> is just like C<throw>. This opcode is useful for +exceptions that are more like warnings or notices than errors. + +Exception handlers can resume execution immediately after the C<throwcc> +opcode by executing the C<caught> opcode, and then invoking the given +continuation which they receive as a paremter. That continuation must be +invoked with no parameters; in other words, C<throwcc> may I<not> return a +value. =item B<die [ I<MESSAGE> ]> @@ -119,17 +123,12 @@ as a status to its embedded environment, or when running standalone, to execute the C function C<exit(I<EXITCODE>)>. -=item B<< rethrow >> - -While handling an exception, stop execution and move on to the next exception -handler, if any. This opcode is an exception handler's way of telling Parrot -that it cannot handle the exception. - =item B<< caught >> -While handling an exception, tell Parrot that the exception has been handled -and should be removed from the stack of active exceptions. This opcode is an -exception handler's way of telling Parrot that it has handled the exception. +While handling an exception, tell Parrot that the exception has been caught +(handled) and should be removed from the stack of active exceptions. This +opcode is an exception handler's way of telling Parrot that it has handled the +exception. =back @@ -146,20 +145,22 @@ containing pointer to exception handler block and exception PMC (and possibly a continuation) - invoke the handler's continuation + invoke the handler + (note: this is still in the thrower's dynamic context) -=item C<rethrow> +=item if the handler returns normally: find the "exception handling in progress" record find the next exception handler if found, - invoke its continuation - else if there is a continuation in the Exception Record (from C<throwcc>), - invoke it (i.e. resume execution) + invoke it + else if there is a continuation in the Exception Record + (because the throwing opcode was C<throwcc>), + invoke the ER's continuation (i.e. resume execution) else, terminate program a la C<die> -=item C<caught> +=item C<caught> opcode pop and destroy Exception Record @@ -321,11 +322,9 @@ C<store_lex> is likely to succeed every time, as creating new lexicals at runtime is OK in Tcl.) -[[ FIXME - Is it true that more opcodes throw exceptions? If so, they should -be listed here.]] +{{ FIXME - Is it true that more opcodes throw exceptions? If so, they should +be listed here. }} - -{{ FIXME }} Other opcodes respond to an C<errorson> setting to decide whether to throw an exception or return an error value. C<find_global> throws an exception (or returns a Null PMC) if the global name requested doesn't @@ -333,6 +332,9 @@ name requested doesn't exist in a lexical, current, global, or built-in namespace. +{{ FIXME - "erroron" as specified is dynamically rather than lexically +scoped; is this good? }} + It's a little odd that so few opcodes throw exceptions (these are the ones that are documented, but a few others throw exceptions internally even though they aren't documented as doing so). It's worth considering @@ -354,8 +356,8 @@ $P0 = new String $P0 = "something bad happened" - $P1 = new ['parrot';'exception'], $P0 # create new exception object - throw $P1 # throw it + $P1 = new ['exception'], $P0 # create new exception object + throw $P1 # throw it Exceptions are designed to work with the Parrot calling conventions. Since the return addresses of C<bsr> subroutine calls and exception