Core Condition code fixes.
[cslatevm.git] / src / core / condition.slate
blobcda62b622d3dbbdce2f86ad25e2710614697722f
1 prototypes ensureNamespace: #conditions &delegate: True.
3 conditions addSlot: #conditionStack valued: Stack new.
4 "The current active condition stack. This assumes that no concurrency is
5 present."
7 conditions define: #Condition &parents: {Cloneable} &slots: {
8 "A situation in the call context which is not handled in normal program logic,
9 and may require investigative or other special handling."
10 #handlers -> {}.
11 "The ordered group of handlers for the condition."
12 #exitContinuation -> [| :result |].
13 "A continuation which when invoked will exit from the handler."
14 #returnContinuation -> [| :result |].
15 "A continuation which when invoked will return from the point where the condition was signaled."
18 c@(Condition traits) new
19 "Create and initialize a new condition."
20 [c clone].
22 c@(Condition traits) defaultHandler
23 "Do nothing, and return nothing by default."
24 [Nil].
26 c@(Condition traits) isRestartAvailable
27 "Answer whether there is an available Restart for the Condition."
31 c@(Condition traits) signal
32 "Signalling a Condition."
34   c tryHandlers
37 _@(Condition traits) describeOn: console
38 "The default description for a Condition."
40   console ; 'Undescribed condition\n'
43 block@(Method traits) on: c@(Condition traits) do: handler
44 "Establishes a handler to be executed when the Condition is signaled within the block."
45 [| context |
46   context := c clone `>>
47     [handlers := {handler}.
48      exitContinuation := [| :result | ^ result]. ].
49   conditionStack push: context.
50   block ensure: [conditionStack pop]
53 block@(Method traits) on: col@(Collection traits) do: handler
54 "Establishes the handlers to be executed when the Condition is signaled within the block."
56   col do:
57     [| :c context |
58      context := c clone `>>
59        [handlers := {handler}.
60         exitContinuation := [| :result | ^ result]. ].
61      conditionStack push: context].
62   block ensure: [conditionStack pop: col size]
65 block@(Method traits) handlingCases: handlers
66 "Establishes handlers to be executed when their associated Conditions are
67 signaled within the block."
68 [| context pos |
69   pos := conditionStack position.
70   handlers
71     reverseDo:
72       [| :handler |
73        context := handler key clone `>>
74          [handlers := {handler value}.
75           exitContinuation := [| :result | ^ result]. ].
76        conditionStack push: context].
77   block ensure: [conditionStack position := pos]
80 c@(Condition traits) tryHandlers
81 [| delegates |
82    c returnContinuation := [| :result | ^ result].
83    delegates := c allDelegates.
84    conditionStack
85      reverseDoWithIndex:
86        [| :context :index |
87         (delegates includes: context traits)
88           ifTrue:
89             [[(index -= 1) >= 0
90                 /\ [(conditionStack at: index) exitContinuation == context exitContinuation]]
91                whileTrue.
92              c exitContinuation := context exitContinuation.
93              context handlers do: #(applyWith: c) `er]].
94    c defaultHandler 
98 c@(Condition traits) tryHandlers
100    c returnContinuation := [| :result | ^ result].
101    conditionStack
102      reverseDo:
103        [| :context |
104         c == context
105           ifTrue:
106             [c exitContinuation := context exitContinuation.
107              context handlers do: #(applyWith: c) `er]].
108    c defaultHandler 
112 c@(Condition traits) return: result
114   c returnContinuation applyWith: result
117 c@(Condition traits) return
119   c return: Nil
122 c@(Condition traits) exit: result
124   c exitContinuation applyWith: result
127 c@(Condition traits) exit
129   c exit: Nil
132 block@(Method traits) breakOn: c
133 "Breaks execution in case the given Condition is signaled within the block."
135   block on: c do: #exit `er.
138 block@(Method traits) ignoring: c
140   block on: c do: #return `er
143 conditions define: #Restart &parents: {Condition} &slots: {#condition}.
144 "A Restart is a Condition which is signaled by another Condition for the
145 purpose of handling it."
146 "The actual signaled condition that invoked this restart."
148 r@(Restart traits) newCondition: c
149 [r new `>> [condition := c. ]].
151 r@(Restart traits) appliesTo: c@(Condition traits)
152 "Answers whether the Restart applies to the Condition. The default is to
153 return True."
154 [True].
156 r@(Restart traits) describeOn: console
158   console ; 'Undescribed restart\n'
161 r@(Restart traits) queryFrom: d
165 block handleWith: r@(Restart traits)
167   block on: r do: [| :_ |]
170 conditions define: #Abort &parents: {Restart}.
171 "An Abort is a Restart which exits the computation, unwinding the stack."
173 _@(Root traits) abort
175   Abort signal
178 _@(Abort traits) describeOn: console
180   console ; 'Abort evaluation of expression\n'
183 conditions define: #Retry &parents: {Restart}.
184 "A retry is where you try doing it again."
186 _@(Retry traits) describeOn: console
188   console ; 'Retry evaluation of expression\n'
191 conditions define: #Quit &parents: {Restart}.
192 "Quit is a Restart which exits the Slate environment, noting an error."
194 _@(Quit traits) describeOn: console
196   console ; 'Quit Slate\n'
199 _@(Quit traits) defaultHandler
200 "Cause Slate to exit with an error code to the underlying system."
201 [lobby exit: 1].
203 conditions define: #DescriptiveConditionMixin &parents: {Cloneable} &slots: {#description -> 'Undescribed condition'}.
204 "Conditions which bear a description."
206 c@(DescriptiveConditionMixin traits) newDescription: description
207 [c new `>> [description := description. ]].
209 c@(DescriptiveConditionMixin traits) signalSaying: description
211   (c newDescription: description) signal
214 c@(DescriptiveConditionMixin traits) describeOn: console
216   (c description is: String)
217     ifTrue: [console ; c description ; '\n']
218     ifFalse: [console ; c description printString ; '\n']
221 conditions define: #Warning &parents: {DescriptiveConditionMixin. Condition}.
222 "Warnings are Conditions which should generate notifications, but do not need
223 to be raised for handling, i.e. no action needs to be taken."
225 _@(Root traits) warn: message
227   Warning signalSaying: message
230 warn@(Warning traits) describeOn: console
232   console ; 'Warning: ' ; warn description ; '\n'
235 warn@(Warning traits) defaultHandler
237   warn describeOn: DebugConsole
240 m@(Method traits) ignoringWarnings
242   m ignoring: Warning
245 conditions define: #SimpleWarning &parents: {Warning}.
246 "A SimpleWarning is a Warning."
248 conditions define: #StyleWarning &parents: {SimpleWarning}.
249 "A StyleWarning is a Warning that certain conventions set up by the library
250 author have not been followed, which could lead to problems."
252 _@(Root traits) deprecated
254   StyleWarning signalSaying: 'This method has been deprecated.'
257 conditions define: #BreakPoint &parents: {Condition}.
258 "A BreakPoint is a Condition raised when instrumenting code for
259 debugging from a particular place in the code. It may restarted."
261 _@(Root traits) break
263   (BreakPoint new) signal
266 _@(BreakPoint traits) describeOn: console
268   console ; 'Break point\n'.
271 bp@(BreakPoint traits) defaultHandler
272 "Invoke the debugger after setting up a Restart for the BreakPoint."
274   [bp invokeDebugger]
275     on: (BreakPoint Restart newCondition: bp)
276     do: [| :bpr | ^ Nil]
279 BreakPoint traits define: #Restart &parents: {Restart}.
280 "A BreakPoint Restart is a Restart used to restart from a BreakPoint."
282 bpr@(BreakPoint Restart traits) describeOn: console
284   console ; 'Restart break point\n'
287 bpr@(BreakPoint Restart traits) appliesTo: bp
289   bpr condition == bp
292 conditions define: #SeriousCondition &parents: {Condition}.
293 "A SeriousCondition is a Condition that requires handling, but is not a
294 semantic Error of the program. Rather, it's due to some incidental or
295 pragmatic consideration."
297 c@(SeriousCondition traits) defaultHandler
298 "Just raise a debugger if no handler is provided."
300   c invokeDebugger
303 conditions define: #Error &parents: {SeriousCondition}.
304 "An Error is a SeriousCondition which involves some misstep in program logic,
305 and raises the need for handlers."
307 m@(Method traits) ignoringErrors
308 [m ignoring: Error].
310 conditions define: #DescriptiveError &parents: {DescriptiveConditionMixin. Error}.
311 "A DescriptiveError is an Error which carries a description.
312 It is usually not recoverable."
314 _@(DescriptiveError traits) describeOn: console
316   console ; 'Error: '.
317   resend
320 _@(Root traits) error: message
322   DescriptiveError signalSaying: message