Author: lwall
Date: 2010-07-15 01:32:07 +0200 (Thu, 15 Jul 2010)
New Revision: 31690

[S04] revise catcher semantics semantics to allow $!.handled = 1 to work as 
well as case match

Modified: docs/Perl6/Spec/S04-control.pod
--- docs/Perl6/Spec/S04-control.pod     2010-07-14 21:18:42 UTC (rev 31689)
+++ docs/Perl6/Spec/S04-control.pod     2010-07-14 23:32:07 UTC (rev 31690)
@@ -13,8 +13,8 @@
     Created: 19 Aug 2004
-    Last Modified: 12 Jul 2010
-    Version: 101
+    Last Modified: 14 Jul 2010
+    Version: 102
 This document summarizes Apocalypse 4, which covers the block and
 statement syntax of Perl.
@@ -993,18 +993,46 @@
         default {...}
-you're really getting something more like:
+you're really calling into a I<catch lambda> that looks like:
-    CATCH {
-        when Mumble {...}
-        default {...}
+    -> $! {
+        my $SUCCEEDED = 1;     # assume we will handle it
-        leave(Failure);
+        given $! {
+            when Mumble {...}
+            default {...}
+            $SUCCEEDED = 0;    # unassume we handled it
+        }
-        KEEP (die("Pending exceptions not handled in $!") unless 
all($!.pendingĀ».handled); $!.handled = 1);
-        UNDO die $!;
+        # the user may handle exception either by
+        #      1. pattern matching in the given
+        #      2. explicitly setting $!.handled = 1
+        $!.handled = 1 if $SUCCEEDED;
+        # conjecture: this might be enforced by the exception thrower instead
+        if $!.handled {
+            $!.wrap-die("Pending exceptions not handled") unless 
+        }
+        $!;
+The exception thrower looks up the call stack for a catch lambda
+that returns the exception object as handled, and then it is happy,
+and unwinds the stack to that point.  If the exception is returned
+as not handled. the exception thrower keeps looking for a higher
+dynamic scope for a spot to unwind to.  Note that any C<die> in the
+catch lambda rethrows outside the lambda as a new exception, wrapping
+up the old exception in its new pending list.  In this case the lambda
+never finishes executing.  Resumable exceptions may or may not leave
+normally depending on the implementation.  If continuations are used,
+the C<$!.resume> call will simply goto the continuation in question,
+and the lambda's callframe is abandoned.  Resumable exceptions may also
+be implemented by simply marking the C<$!> exception as "resumed",
+in which case the original exception thrower simply returns to
+the code that threw the resumable exception, rather than unwinding
+before returning.
 A C<CATCH> block sees the lexical scope in which it was defined, but
 its caller is the dynamic location that threw the exception.  That is,
 the stack is not unwound until some exception handler chooses to
@@ -1013,7 +1041,7 @@
 C<CATCH> block to catch its own exception recursively forever.  However,
 a C<CATCH> must not behave that way, so we say that a C<CATCH> block
 never attempts to handle any exception thrown within its own dynamic scope.
-(Otherwise the C<die> in the previous paragraph would never work.)
+(Otherwise any C<die> would cause an infinite loop.)
 =head1 Control Exceptions
@@ -1132,7 +1160,11 @@
 that the semantics would be preserved by merely printing out the
 error and going on.  Since all exception handlers run in the dynamic
 scope of the throw, that reduces to simply returning from the C<warn>
-function most of the time.
+function most of the time.  See previous section for discussion of
+ways to return from catch lambdas.  The control lambda is logically
+separate from the catch lambda, though an implementation is allowed
+to combine them if it is careful to retain separate semantics for
+catch and control exceptions.
 =head1 The goto statement

Reply via email to