18 Signal QuerySignal |
20 Signal QuerySignal |
19 " |
21 " |
20 |
22 |
21 ! |
23 ! |
22 |
24 |
23 examples |
25 examples |
24 " |
26 " |
25 examples to be added. |
27 an up-query from a deeply nested operation to a higher level: |
26 [exBegin] |
28 [exBegin] |
27 ... add code fragment for |
29 |zero| |
28 ... executable example here ... |
30 |
29 [exEnd] |
31 zero := 0. |
|
32 Query handle:[:ex | |
|
33 Transcript showCR:'query'. |
|
34 ex proceedWith:true |
|
35 ] do:[ |
|
36 'nesting'. |
|
37 [ |
|
38 [ |
|
39 Object errorSignal handle:[:ex | |
|
40 Transcript showCR:'some error: ' , ex errorString. |
|
41 ex proceed |
|
42 ] do:[ |
|
43 [ |
|
44 1 // zero. 'an error which is caught in the handler'. |
|
45 (Query query) == true ifTrue:[ |
|
46 Transcript showCR:'query says: ok'. |
|
47 ] ifFalse:[ |
|
48 Transcript showCR:'query says: no' |
|
49 ] |
|
50 ] value |
|
51 ] |
|
52 ] value |
|
53 ] value |
|
54 ] |
|
55 [exEnd] |
|
56 for lazy typists, a more compact interface is also provided |
|
57 (which is also easier to read): |
|
58 [exBegin] |
|
59 Query answer:true do:[ |
|
60 'nesting'. |
|
61 [ |
|
62 [ |
|
63 (Query query) == true ifTrue:[ |
|
64 Transcript showCR:'query says: ok'. |
|
65 ] ifFalse:[ |
|
66 Transcript showCR:'query says: no' |
|
67 ] |
|
68 ] value |
|
69 ] value |
|
70 ] |
|
71 [exEnd] |
|
72 an up-query from a deeply nested operation, for which there |
|
73 is no handler: |
|
74 (notice, this would not work with normal signals, which would raise |
|
75 another unhandled exception-exception; |
|
76 also notice the == check #raise's return value being true, |
|
77 instead of a simple ifTrue; this handles a nil-value from |
|
78 the unhandled query) |
|
79 [exBegin] |
|
80 |zero| |
|
81 |
|
82 zero := 0. |
|
83 [ |
|
84 'nesting'. |
|
85 [ |
|
86 [ |
|
87 Object errorSignal handle:[:ex | |
|
88 Transcript showCR:'some error: ' , ex errorString. |
|
89 ex proceed |
|
90 ] do:[ |
|
91 [ |
|
92 1 // zero. 'an error which is caught in the handler'. |
|
93 (Query raise) == true ifTrue:[ |
|
94 Transcript showCR:'query says: ok'. |
|
95 ] ifFalse:[ |
|
96 Transcript showCR:'query says: no' |
|
97 ] |
|
98 ] value |
|
99 ] |
|
100 ] value |
|
101 ] value |
|
102 ] value |
|
103 [exEnd] |
|
104 counter-example, just to show that things would not work this way |
|
105 with regular signals: |
|
106 [exBegin] |
|
107 |signal| |
|
108 |
|
109 signal := Signal new. |
|
110 'nesting deeply'. |
|
111 [ |
|
112 [ |
|
113 [ |
|
114 [ |
|
115 [ |
|
116 (signal raise) == true ifTrue:[ |
|
117 Transcript showCR:'query says: ok'. |
|
118 ] ifFalse:[ |
|
119 Transcript showCR:'query says: no' |
|
120 ] |
|
121 ] value |
|
122 ] value |
|
123 ] value |
|
124 ] value |
|
125 ] value |
|
126 [exEnd] |
|
127 |
|
128 except, by handling the unhandled exception |
|
129 (but we think, that querySignals are easier to use and |
|
130 better document the intent): |
|
131 [exBegin] |
|
132 |signal| |
|
133 |
|
134 signal := Signal new. |
|
135 'nesting deeply'. |
|
136 [ |
|
137 [ |
|
138 [ |
|
139 [ |
|
140 [ |
|
141 Signal noHandlerSignal handle:[:ex | |
|
142 ex proceedWith:nil |
|
143 ] do:[ |
|
144 (signal raise) == true ifTrue:[ |
|
145 Transcript showCR:'query says: ok'. |
|
146 ] ifFalse:[ |
|
147 Transcript showCR:'query says: no' |
|
148 ] |
|
149 ] |
|
150 ] value |
|
151 ] value |
|
152 ] value |
|
153 ] value |
|
154 ] value |
|
155 [exEnd] |
30 " |
156 " |
|
157 |
31 ! |
158 ! |
32 |
159 |
33 history |
160 history |
34 "Created: / 23.7.1999 / 14:16:16 / stefan" |
161 "Created: / 23.7.1999 / 14:16:16 / stefan" |
35 ! ! |
162 ! ! |
39 answer:someAnswer do:aBlock |
166 answer:someAnswer do:aBlock |
40 "evaluate the argument, aBlock. |
167 "evaluate the argument, aBlock. |
41 If the receiver is queried during evaluation, answer with someAnswer. |
168 If the receiver is queried during evaluation, answer with someAnswer. |
42 This is a wrapper for #handle:do: for lazy typists; no new functionality." |
169 This is a wrapper for #handle:do: for lazy typists; no new functionality." |
43 |
170 |
44 ^ self handle:[:ex | ex proceedWith:someAnswer] do:aBlock. |
171 thisContext markForHandle. |
|
172 aBlock value. |
45 |
173 |
46 " |
174 " |
47 Query answer:true do:[ |
175 Query answer:true do:[ |
48 Transcript showCR:'query answers: ' , (Query query printString). |
176 Transcript showCR:'query answers: ' , (Query query printString). |
49 ] |
177 ] |
95 ^ super raiseRequest |
223 ^ super raiseRequest |
96 |
224 |
97 "Created: / 23.7.1999 / 15:16:03 / stefan" |
225 "Created: / 23.7.1999 / 15:16:03 / stefan" |
98 ! |
226 ! |
99 |
227 |
|
228 handlerForSignal:signal context:theContext originator:originator |
|
229 "answer the handler block for the signal from originator. |
|
230 The block is retrieved from aContext. |
|
231 Answer nil if the signal is not handled" |
|
232 |
|
233 |arg| |
|
234 |
|
235 theContext selector == #'answer:do:' ifTrue:[ |
|
236 (self accepts:signal) ifTrue:[ |
|
237 arg := theContext argAt:1. |
|
238 ^ [:ex| ex proceedWith:arg]. |
|
239 ] |
|
240 ] ifFalse:[ |
|
241 ^ super handlerForSignal:signal context:theContext originator:originator. |
|
242 ]. |
|
243 |
|
244 ^ nil |
|
245 |
|
246 "Created: / 25.7.1999 / 23:11:55 / stefan" |
|
247 ! |
|
248 |
100 isQuerySignal |
249 isQuerySignal |
101 |
250 |
102 ^ true |
251 ^ true |
103 |
252 |
104 "Created: / 23.7.1999 / 14:59:50 / stefan" |
253 "Created: / 23.7.1999 / 14:59:50 / stefan" |
105 ! |
254 ! |
106 |
|
107 raise |
|
108 "QuerySignals are proceedable by definition, |
|
109 so they should be raised with #query or #raiseRequest" |
|
110 |
|
111 ^ self shouldNotImplement |
|
112 |
|
113 "Created: / 23.7.1999 / 15:19:17 / stefan" |
|
114 ! |
|
115 |
|
116 raiseRequest |
|
117 "redefined to use #query" |
|
118 |
|
119 ^ self query |
|
120 |
|
121 "Created: / 23.7.1999 / 15:19:35 / stefan" |
|
122 ! ! |
|
123 |
|
124 !Query class methodsFor:'query'! |
|
125 |
255 |
126 query |
256 query |
127 "raise the query - return the handlers value, or the default |
257 "raise the query - return the handlers value, or the default |
128 value, if there is no handler. |
258 value, if there is no handler. |
129 Invoking the handler is exactly the functionality of Signal>>raiseRequest, |
259 Invoking the handler is exactly the functionality of Signal>>raiseRequest, |
131 |
261 |
132 |con s| |
262 |con s| |
133 |
263 |
134 con := thisContext sender. |
264 con := thisContext sender. |
135 [con notNil] whileTrue:[ |
265 [con notNil] whileTrue:[ |
136 con := con findNextContextWithSelector:#doRaise |
266 con := con findSpecialHandle:true raise:true. |
137 or:#handle:do: |
|
138 or:#handle:from:do:. |
|
139 con notNil ifTrue:[ |
267 con notNil ifTrue:[ |
140 (con selector == #handle:do:) ifFalse:[ |
268 (con selector == #answer:do:) ifFalse:[ |
141 ^ super raiseRequest |
269 ^ super raiseRequest |
142 ]. |
270 ]. |
143 (s := con receiver) == self ifTrue:[ |
271 (s := con receiver) == self ifTrue:[ |
144 "/ found a non-busy handler ... |
|
145 "/ if its sender is a #answer context, |
|
146 "/ fetch its value quickly from it. |
|
147 con := con sender. |
|
148 con selector == #answer:do: ifFalse:[ |
|
149 con receiver == self ifFalse:[ |
|
150 ^ super raiseRequest |
|
151 ] |
|
152 ]. |
|
153 ^ con argAt:1 |
272 ^ con argAt:1 |
154 ] ifFalse:[ |
273 ] ifFalse:[ |
155 (s accepts:self) ifTrue:[ |
274 (s accepts:self) ifTrue:[ |
156 ^ super raiseRequest |
275 ^ super raiseRequest |
157 ] |
276 ] |
160 ]. |
279 ]. |
161 "/ no handler found - return the default value |
280 "/ no handler found - return the default value |
162 ^ self defaultAnswer |
281 ^ self defaultAnswer |
163 |
282 |
164 "Modified: / 15.6.1998 / 21:27:37 / cg" |
283 "Modified: / 15.6.1998 / 21:27:37 / cg" |
165 "Modified: / 23.7.1999 / 15:19:59 / stefan" |
284 "Modified: / 25.7.1999 / 23:15:16 / stefan" |
|
285 ! |
|
286 |
|
287 raise |
|
288 "QuerySignals are proceedable by definition, |
|
289 so they should be raised with #query or #raiseRequest" |
|
290 |
|
291 ^ self shouldNotImplement |
|
292 |
|
293 "Created: / 23.7.1999 / 15:19:17 / stefan" |
|
294 ! |
|
295 |
|
296 raiseRequest |
|
297 "redefined to use #query" |
|
298 |
|
299 ^ self query |
|
300 |
|
301 "Created: / 25.7.1999 / 23:25:59 / stefan" |
166 ! ! |
302 ! ! |
167 |
303 |
168 !Query methodsFor:'default actions'! |
304 !Query methodsFor:'default actions'! |
169 |
305 |
170 action |
306 action |