#FEATURE by sr
authorsr
Tue, 10 May 2016 15:04:58 +0200
changeset 19776 31fa179f48bf
parent 19775 cfffb072d9a3
child 19777 6e16198576c7
#FEATURE by sr class: GenericException added: #raiseAsQuery
GenericException.st
--- a/GenericException.st	Tue May 10 13:44:25 2016 +0200
+++ b/GenericException.st	Tue May 10 15:04:58 2016 +0200
@@ -1,3 +1,5 @@
+"{ Encoding: utf8 }"
+
 "
  COPYRIGHT (c) 1993 by Claus Gittinger
 	      All Rights Reserved
@@ -550,6 +552,62 @@
     "Modified: / 10-08-2010 / 09:30:42 / cg"
 !
 
+raiseAsQuery
+    "utility to avoid code duplication.
+     raise the exception as a query. This means, that if it is unhandled,
+     a default value is returned (i.e. an implicit resume).
+     Return the handler's value (if there is one), or the default value, if not.
+     Invoking the handler is exactly the functionality of Signal>>raiseRequest,
+     but we can do it faster here (avoiding the construction of an exception instance)."
+
+    |con signal ret|
+
+    self isQuerySignal ifFalse:[ self error:'this may only be used by queries' ].
+
+    con := Context findFirstSpecialHandle:true raise:false.
+    [con notNil] whileTrue:[
+        (con selector == #answer:do:) ifTrue:[ 
+            signal := con receiver.
+            signal == self ifTrue:[
+                ret := con argAt:1.
+                con := nil.
+                ^ ret
+            ].
+            signal isNil ifTrue:[
+                self error:'nil receiver in #answer:do: - send'.
+            ].
+            (signal accepts:self) ifTrue:[
+                ret := con argAt:1.
+                con := nil.
+                ^ ret
+            ].
+        ] ifFalse:[
+            "ask the the receiver of the #handle:do: or #on:do: or whatever- message for the handler.
+             nil is returned, if the signal is not accepted"
+            |r|
+            r := con receiver.     "receiver of #handle:do: or #on:do:"
+            (r notNil and:[(r handlerForSignal:self
+                                 context:con
+                                 originator:thisContext sender homeReceiver) notNil]
+            ) ifTrue:[
+                "there is another handler block, maybe it will return the answer.
+                 Call it via raiseRequest"
+                con := nil.
+                ^ here raiseRequest  "/ <- notice the here, to avoid recursion due
+                                     "/ to redefined raiseRequest in Query
+            ].
+        ].
+        con := con findSpecialHandle:true raise:false.
+    ].
+
+    "/ no handler found - return the default value
+    ^ self defaultAnswer
+
+    "Modified: / 15-06-1998 / 21:27:37 / cg"
+    "Modified: / 25-07-1999 / 23:15:16 / stefan"
+    "Modified: / 11-03-2015 / 11:26:45 / sr"
+!
+
 raiseErrorString:aString
     "raise a signal nonproceedable.
      The argument is used as messageText."