Exception.st
changeset 3066 eb7489e8275a
parent 3017 cdd87208ae2f
child 3068 e022c6c4e588
--- a/Exception.st	Tue Oct 28 21:15:01 1997 +0100
+++ b/Exception.st	Wed Oct 29 15:12:43 1997 +0100
@@ -10,6 +10,8 @@
  hereby transferred.
 "
 
+'From Smalltalk/X, Version:3.2.1 on 25-oct-1997 at 11:48:51 pm'                 !
+
 Object subclass:#Exception
 	instanceVariableNames:'signal parameter errorString suspendedContext handlerContext
 		rejected originator resumeBlock rejectBlock'
@@ -699,7 +701,7 @@
 
     |theContext block noHandlerSignal any msg conArg1
      theSignal c ex1 activeHandlers inHandler rejected
-     lastHandler h raiseReceiver r|
+     lastHandler h raiseReceiver r firstHandler|
 
     theContext := thisContext sender sender.  "the raise/raiseRequest-context"
                                               "the signal raise context"
@@ -721,102 +723,126 @@
     "/ same handler)
     "/ the code below collects active handlers ...
 
-    [c notNil] whileTrue:[
-        c := c findNextContextWithSelector:#doRaise or:nil or:nil.
-        c notNil ifTrue:[
-
-            ex1 := c receiver.
+    "/ on the fly, look for the first #handle:do: - context,
+    "/ and remember it (as firstHandler) to avoid walking the context chain twice
+    "/ in most cases ...
 
-            ((ex1 class == self class)
-            or:[ex1 species == self species]) ifTrue:[
-                c := c sender.
-                (c notNil and:[c receiver == ex1]) ifTrue:[
-                    c := c sender.
-                    c notNil ifTrue:[
+    firstHandler := nil.
 
-                        "/ the common case (really ?) first
-                        ((raiseReceiver := c receiver) == theSignal) ifTrue:[
-                            (c selector startsWith:'raise') ifTrue:[
-                                h := ex1 handlerContext.
-                                h notNil ifTrue:[
-                                    activeHandlers isNil ifTrue:[
-                                        activeHandlers := OrderedCollection new
-                                    ].
+    [c notNil] whileTrue:[
+        firstHandler isNil ifTrue:[
+            c := c findNextContextWithSelector:#doRaise or:#'handle:do:' or:#'handle:from:do:'.
+        ] ifFalse:[
+            c := c findNextContextWithSelector:#doRaise or:nil or:nil.
+        ].
+        c notNil ifTrue:[
+            (c selector == #doRaise) ifTrue:[
 
-                                    lastHandler := h.
-                                    activeHandlers add:lastHandler.
-                                    inHandler := true.
-                                    c := lastHandler.
-                                ]
-                            ]
-                        ] ifFalse:[
-                            raiseReceiver isSignal ifTrue:[
+                ex1 := c receiver.
+
+                ((ex1 class == self class)
+                or:[ex1 species == self species]) ifTrue:[
+                    c := c sender.
+                    (c notNil and:[c receiver == ex1]) ifTrue:[
+                        c := c sender.
+                        c notNil ifTrue:[
+
+                            "/ the common case (really ?) first
+                            ((raiseReceiver := c receiver) == theSignal) ifTrue:[
                                 (c selector startsWith:'raise') ifTrue:[
                                     h := ex1 handlerContext.
                                     h notNil ifTrue:[
-					r := h receiver.
-                                        (r notNil and:[r accepts:theSignal]) ifTrue:[
+                                        activeHandlers isNil ifTrue:[
+                                            activeHandlers := OrderedCollection new
+                                        ].
 
-                                            activeHandlers isNil ifTrue:[
-                                                activeHandlers := OrderedCollection new
-                                            ].
-                                            lastHandler := h.
-                                            activeHandlers add:lastHandler.
-                                            inHandler := true.
-                                            c := lastHandler.
-                                        ]
+                                        lastHandler := h.
+                                        activeHandlers add:lastHandler.
+                                        inHandler := true.
+                                        c := lastHandler.
+                                    ]
+                                ]
+                            ] ifFalse:[
+                                raiseReceiver isSignal ifTrue:[
+                                    (c selector startsWith:'raise') ifTrue:[
+                                        h := ex1 handlerContext.
+                                        h notNil ifTrue:[
+                                            r := h receiver.
+                                            (r notNil and:[r accepts:theSignal]) ifTrue:[
+
+                                                activeHandlers isNil ifTrue:[
+                                                    activeHandlers := OrderedCollection new
+                                                ].
+                                                lastHandler := h.
+                                                activeHandlers add:lastHandler.
+                                                inHandler := true.
+                                                c := lastHandler.
+                                            ]
+                                        ]    
                                     ]    
                                 ]    
-                            ]    
+                            ]
                         ]
                     ]
                 ]
+            ] ifFalse:[
+                "/ must be a #handle:do context ...
+                firstHandler := c.
             ]
         ]
     ].
 
     "/ now, start searching for a handler,
-    "/ start search above the last active handler
+    "/ start search above the last active handler.
+    "/ Or start with the first handle:do: context, if one
+    "/ was found as a side effect of the previous handler search.
+    "/ If nil, then there is no handler and we can directly proceed
+    "/ to the unhandled code below.
 
     lastHandler notNil ifTrue:[
         theContext := lastHandler.
+        theContext := lastHandler findNextContextWithSelector:#'handle:do:' or:#'handle:from:do:' or:nil.
+    ] ifFalse:[
+        theContext := firstHandler
     ].
 
+    "/ remember if there was any handler
+    "/ for the better errorString (unhandled vs. rejected exception)
+
     any := false.
     [theContext notNil] whileTrue:[
-        theContext := theContext findNextContextWithSelector:#'handle:do:' or:#'handle:from:do:' or:nil.
-        theContext notNil ifTrue:[
-            (theContext selector == #'handle:do:'
-            or:[(theContext argAt:2) == originator]) 
-	    ifTrue:[
-                (activeHandlers notNil
-                 and:[activeHandlers includesIdentical:theContext]) ifTrue:[
-                    'skip activeHandler: ' print. theContext displayString printCR.
+        (theContext selector == #'handle:do:'
+        or:[(theContext argAt:2) == originator]) 
+        ifTrue:[
+            (activeHandlers notNil
+             and:[activeHandlers includesIdentical:theContext]) ifTrue:[
+                'skip activeHandler: ' print. theContext displayString printCR.
 
-                ] ifFalse:[
-                    "
-                     if this is the Signal>>handle:do: context
-                     or a SignalSet>>handle:do: context with self in it,
-                     call the handler
-                    "
-		    r := theContext receiver.
-                    (r notNil and:[r accepts:signal]) ifTrue:[
-                        "call the handler"
+            ] ifFalse:[
+                "
+                 if this is the Signal>>handle:do: context
+                 or a SignalSet>>handle:do: context with self in it,
+                 call the handler
+                "
+                r := theContext receiver.
+                (r notNil and:[r accepts:signal]) ifTrue:[
+                    "call the handler"
 
-                        conArg1 := theContext argAt:1.
+                    conArg1 := theContext argAt:1.
 
-                        handlerContext := theContext.
-                        any := true.
+                    handlerContext := theContext.
+                    any := true.
 
-                        self doCallHandler:conArg1.
+                    self doCallHandler:conArg1.
 
-                        "if the handler rejects, we arrive here"
-                        "continue search for another handler"
-                        rejected := true.
-                    ].
-                ]
+                    "/ if the handler rejects, we arrive here
+                    "/ continue search for another handler
+
+                    rejected := true.
+                ].
             ]
-        ]
+        ].
+        theContext := theContext findNextContextWithSelector:#'handle:do:' or:#'handle:from:do:' or:nil.
     ].
 
     activeHandlers := nil.
@@ -879,8 +905,8 @@
     "... and call it"
     ^ block value:self.
 
-    "Created: 12.5.1996 / 15:09:39 / cg"
-    "Modified: 1.3.1997 / 23:53:14 / cg"
+    "Created: / 12.5.1996 / 15:09:39 / cg"
+    "Modified: / 25.10.1997 / 11:44:35 / cg"
 !
 
 raise
@@ -919,6 +945,6 @@
 !Exception class methodsFor:'documentation'!
 
 version
-    ^ '$Header: /cvs/stx/stx/libbasic/Exception.st,v 1.56 1997-10-10 17:51:02 cg Exp $'
+    ^ '$Header: /cvs/stx/stx/libbasic/Exception.st,v 1.57 1997-10-29 14:12:40 cg Exp $'
 ! !
 Exception initialize!