source: project/wiki/man/5/Module (chicken condition) @ 34267

Last change on this file since 34267 was 34267, checked in by sjamaan, 15 months ago

man/5: Move print-error-message to Module (chicken condition)

File size: 14.3 KB
Line 
1[[tags: manual]]
2[[toc:]]
3
4== Module (chicken condition)
5
6This module provides various procedures and special forms for raising
7and handling exceptions with "condition objects".  Condition objects
8provide a structured and composable way to encode the kind of
9exception that took place, and provide the necessary context.
10
11CHICKEN's exception handling is based on the
12[[http://srfi.schemers.org/srfi-12/srfi-12.html|SRFI-12]] exception
13system.  This document contains the core of the SRFI-12 spec as well
14as CHICKEN implementation specifics.
15
16There is also a {{srfi-12}} or {{(srfi 12)}} module which only
17includes the standard procedures and macros from the SRFI document,
18without the CHICKEN extensions.  {{(chicken condition)}} offers the
19complete set of procedures and macros, both CHICKEN-specific and
20standard SRFI-12.
21
22
23== CHICKEN implementation
24
25=== System conditions
26
27All error-conditions signaled by the system are of kind {{exn}}.
28The following composite conditions are additionally defined:
29
30<table>
31
32<tr><td> (exn arity) </td><td>
33
34Signaled when a procedure is called with the wrong number of arguments.
35
36</td></tr><tr><td> (exn type) </td><td>
37
38Signaled on type-mismatch errors, for example when an argument of the wrong
39type is passed to a built-in procedure.
40
41</td></tr><tr><td> (exn arithmetic) </td><td>
42
43Signaled on arithmetic errors, like division by zero.
44
45</td></tr><tr><td> (exn i/o) </td><td>
46
47Signaled on input/output errors.
48
49</td></tr><tr><td> (exn i/o file) </td><td>
50
51Signaled on file-related errors.
52
53</td></tr><tr><td> (exn i/o net) </td><td>
54
55Signaled on network errors.
56
57</td></tr><tr><td> (exn bounds) </td><td>
58
59Signaled on errors caused by accessing non-existent elements of a collection.
60
61</td></tr><tr><td> (exn runtime) </td><td>
62
63Signaled on low-level runtime-system error-situations.
64
65</td></tr><tr><td> (exn runtime limit) </td><td>
66
67Signaled when an internal limit is exceeded (like running out of memory).
68
69</td></tr><tr><td> (exn match) </td><td>
70
71Signaled on errors raised by failed matches (see the section on {{match}}).
72
73</td></tr><tr><td> (exn syntax) </td><td>
74
75Signaled on syntax errors.
76
77</td></tr>
78
79</table>
80
81=== Notes
82
83* All error-exceptions (of the kind {{exn}}) are non-continuable.
84
85* Error-exceptions of the {{exn}} kind have additional {{arguments}} and
86{{location}} properties that contain the arguments passed to the
87exception-handler and the name of the procedure where the error occurred (if
88available).
89
90* When the {{posix}} unit is available and used, then a user-interrupt
91({{signal/int}}) signals an exception of the kind {{user-interrupt}}.
92
93* The procedure {{condition-property-accessor}} accepts an optional third
94argument. If the condition does not have a value for the desired property and
95if the optional argument is given, no error is signaled and the accessor
96returns the third argument.
97
98* On platforms that support the {{sigprocmask(3)}} POSIX API function,
99the signals {{SIGSEGV}}, {{SIGFPE}}, {{SIGBUS}} and {{SIGILL}} will be
100caught and trigger an exception instead of aborting the process, if
101possible. If the unwinding and handling of the signal raises one of
102these signals once again, the process will abort with an error
103message.
104
105=== Additional API
106
107==== condition-case
108
109<macro>(condition-case EXPRESSION CLAUSE ...)</macro>
110
111Evaluates {{EXPRESSION}} and handles any exceptions that are covered by
112{{CLAUSE ...}}, where {{CLAUSE}} should be of the following form:
113
114  CLAUSE = ([VARIABLE] (KIND ...) BODY ...)
115
116If provided, {{VARIABLE}} will be bound to the signaled exception
117object. {{BODY ...}} is executed when the exception is a property-
118or composite condition with the kinds given {{KIND ...}} (unevaluated).
119If no clause applies, the exception is re-signaled in the same dynamic
120context as the {{condition-case}} form.
121
122<enscript highlight=scheme>
123(define (check thunk)
124  (condition-case (thunk)
125    [(exn file) (print "file error")]
126    [(exn) (print "other error")]
127    [var () (print "something else")] ) )
128
129(check (lambda () (open-input-file "")))   ; -> "file error"
130(check (lambda () some-unbound-variable))  ; -> "othererror"
131(check (lambda () (signal 99)))            ; -> "something else"
132
133(condition-case some-unbound-variable
134  ((exn file) (print "ignored")) )      ; -> signals error
135</enscript>
136
137==== get-condition-property
138
139<procedure>(get-condition-property CONDITION KIND PROPERTY [DEFAULT])</procedure>
140
141A slightly more convenient condition property accessor, equivalent to
142
143 ((condition-property-accessor KIND PROPERTY [DEFAULT]) CONDITION)
144
145==== condition
146
147<procedure>(condition LST1 LST2 ...)</procedure>
148
149This is a more convenient constructor for conditions.  Each of
150{{LST1}}, {{LST2}} etc is a list of the following form:
151
152  (KIND PROPERTY1 VALUE1 PROPERTY2 VALUE2 ...)
153
154In other words, the following:
155
156  (signal (condition '(exn location foo message "hi") '(file bar 1)))
157
158is equivalent to the SRFI-12 code:
159
160  (signal (make-composite-condition
161            (make-property-condition 'exn 'location 'foo 'message "hi")
162            (make-property-condition 'file 'bar 2)))
163
164
165==== condition->list
166
167<procedure>(condition->list CONDITION)</procedure>
168
169This procedure converts a condition object into a list holding all the
170conditions that are represented by the ''CONDITION'' object.  It is
171formatted as follows:
172
173 ((KIND1 PROPERTY1 VALUE1 PROPERTY2 VALUE2 ...) (KIND2 ... ) ... )
174
175There is no guaranteed order within the list.
176
177
178==== print-error-message
179
180<procedure>(print-error-message EXN [PORT [HEADER]])</procedure>
181
182Prints an appropriate error message to {{PORT}} (which defaults to the
183value of {{(current-output-port)}} for the object {{EXN}}. {{EXN}} may
184be a condition, a string or any other object. The output is prefixed
185by the {{HEADER}}, which defaults to {{"Error:"}}.
186
187
188
189== SRFI-12 specification
190
191A Scheme implementation ("the system") raises an exception whenever an
192error is to be signaled or whenever the system determines that evaluation
193cannot proceed in a manner consistent with the semantics of Scheme. A
194program may also explicitly raise an exception.
195
196Whenever the system raises an exception, it invokes the current exception
197handler with a condition object (encapsulating information about the
198exception) as its only argument. Any procedure accepting one argument
199may serve as an exception handler. When a program explicitly raises an
200exception, it may supply any object to the exception handler.
201
202An exception is either continuable or non-continuable. When the current
203exception handler is invoked for a continuable exception, the continuation
204uses the handler's result(s) in an exception-specific way to continue.
205When an exception handler is invoked for a non-continuable exception,
206the continuation raises a non-continuable exception indicating that the
207exception handler returned.  On CHICKEN, system error exceptions
208(of kind {{exn}}) are non-continuable.
209
210=== Exception Handlers
211
212==== current-exception-handler
213
214<parameter>(current-exception-handler [PROCEDURE])</parameter><br>
215
216Sets or returns the current exception handler, a procedure of one
217argument, the exception object.
218
219==== with-exception-handler
220
221<procedure>(with-exception-handler handler thunk)</procedure><br>
222
223Returns the result(s) of invoking ''thunk''. The ''handler'' procedure
224is installed as the current exception handler in the dynamic context of
225invoking ''thunk''.
226
227Example:
228
229<enscript highlight=scheme>
230(call-with-current-continuation
231 (lambda (k)
232  (with-exception-handler (lambda (x) (k '()))
233                          (lambda () (car '())))))
234;=> '()
235</enscript>
236
237Note that the handler procedure must somehow return non-locally out of
238the dynamic extent of the {{with-exception-handler}} form, because
239returning normally will signal yet another exception and thus result
240in non-termination.
241
242==== handle-exceptions
243
244<macro>(handle-exceptions var handle-expr expr1 expr2 ...)</macro><br>
245
246Evaluates the body expressions ''expr1'', ''expr2'', ... in sequence with
247an exception handler constructed from ''var'' and ''handle-expr''. Assuming
248no exception is raised, the result(s) of the last body expression is(are)
249the result(s) of the {{handle-exceptions}} expression.
250
251The exception handler created by {{handle-exceptions}} restores the dynamic
252context (continuation, exception handler, etc.) of the {{handle-exceptions}}
253expression, and then evaluates ''handle-expr'' with ''var'' bound to the
254value provided to the handler.
255
256Examples:
257
258<enscript highlight=scheme>
259(handle-exceptions exn
260                   (begin
261                     (display "Went wrong")
262                     (newline))
263 (car '()))
264; displays "Went wrong"
265 
266(handle-exceptions exn
267                   (cond
268                    ((eq? exn 'one) 1)
269                     (else (abort exn)))
270  (case (random 3)
271   [(0) 'zero]
272   [(1) (abort 'one)]
273   [else (abort "Something else")]))
274;=> 'zero, 1, or (abort "Something else")
275</enscript>
276
277=== Raising Exceptions
278
279==== abort
280
281<procedure>(abort obj)</procedure><br>
282
283Raises a non-continuable exception represented by ''obj''. The {{abort}}
284procedure can be implemented as follows:
285
286<enscript highlight=scheme>
287(define (abort obj)
288  ((current-exception-handler) obj)
289  (abort (make-property-condition
290           'exn
291           'message
292           "Exception handler returned")))
293</enscript>
294
295The {{abort}} procedure does not ensure that its argument is a condition.
296If its argument is a condition, {{abort}} does not ensure that the condition
297indicates a non-continuable exception.
298
299==== signal
300
301<procedure>(signal obj)</procedure><br>
302
303Raises a continuable exception represented by ''obj''. The {{signal}} procedure
304can be implemented as follows:
305
306<enscript highlight=scheme>
307(define (signal exn)
308 ((current-exception-handler) exn))
309</enscript>
310
311The {{signal}} procedure does not ensure that its argument is a condition.
312If its argument is a condition, {{signal}} does not ensure that the condition
313indicates a continuable exception.
314
315=== Condition Objects
316
317==== condition?
318
319<procedure>(condition? obj)</procedure><br>
320
321Returns #t if ''obj'' is a condition, otherwise returns #f. If any of
322the predicates listed in Section 3.2 of the R5RS is true of ''obj'', then
323{{condition?}} is false of ''obj''.
324
325Rationale: Any Scheme object may be passed to an exception handler. This
326would cause ambiguity if conditions were not disjoint from all of Scheme's
327standard types.
328
329==== make-property-condition
330
331<procedure>(make-property-condition kind-key prop-key value ...)</procedure><br>
332
333This procedure accepts any even number of arguments after ''kind-key'',
334which are regarded as a sequence of alternating ''prop-key'' and ''value''
335objects. Each ''prop-key'' is regarded as the name of a property, and
336each ''value'' is regarded as the value associated with the ''key'' that
337precedes it. Returns a ''kind-key'' condition that associates the given
338''prop-key''s with the given ''value''s.
339
340==== make-composite-condition
341
342<procedure>(make-composite-condition condition ...)</procedure><br>
343
344Returns a newly-allocated condition whose components correspond to the the
345given ''condition''s. A predicate created by {{condition-predicate}} returns
346true for the new condition if and only if it returns true for one or more
347of its component conditions.
348
349==== condition-predicate
350
351<procedure>(condition-predicate kind-key)</procedure><br>
352
353Returns a predicate that can be called with any object as its argument.
354Given a condition that was created by {{make-property-condition}}, the
355predicate returns #t if and only if ''kind-key'' is EQV? to the kind key
356that was passed to {{make-property-condition}}. Given a composite condition
357created with {{make-composite-condition}}, the predicate returns #t if and only
358if the predicate returns #t for at least one of its components.
359
360==== condition-property-accessor
361
362<procedure>(condition-property-accessor kind-key prop-key [default])</procedure><br>
363
364Returns a procedure that can be called with any condition that satisfies
365{{(condition-predicate ''kind-key'')}}. Given a condition that was created
366by {{make-property-condition}} and ''kind-key'', the procedure returns the
367value that is associated with ''prop-key''. Given a composite condition
368created with {{make-composite-condition}}, the procedure returns the value that
369is associated with ''prop-key'' in one of the components that satisfies
370{{(condition-predicate ''kind-key'')}}.
371
372On CHICKEN, this procedure accepts an optional third argument
373DEFAULT. If the condition does not have a value for the desired
374property and if the optional argument is given, no error is signaled
375and the accessor returns the third argument.
376
377When the system raises an exception, the condition it passes to the
378exception handler includes the {{'exn}} kind with the following
379properties:
380
381; message : the error message
382; arguments: the arguments passed to the exception handler
383; location: the name of the procedure where the error occurred (if available)
384
385Thus, if ''exn'' is a condition representing a system exception,
386then
387
388<enscript highlight=scheme>
389 ((condition-property-accessor 'exn 'message) exn)
390</enscript>
391
392extracts the error message from ''exn''. Example:
393
394<enscript highlight=scheme>
395(handle-exceptions exn
396                   (begin
397                     (display "Went wrong: ")
398                     (display
399                      ((condition-property-accessor 'exn 'message) exn))
400                     (newline))
401 (car '()))
402; displays something like "Went wrong: can't take car of nil"
403</enscript>
404
405=== More Examples
406
407<enscript highlight=scheme>
408(define (try-car v)
409 (let ((orig (current-exception-handler)))
410   (with-exception-handler
411    (lambda (exn)
412      (orig (make-composite-condition
413             (make-property-condition
414              'not-a-pair
415              'value
416              v)
417             exn)))
418    (lambda () (car v)))))
419 
420(try-car '(1))
421;=> 1
422
423(handle-exceptions exn
424                   (if ((condition-predicate 'not-a-pair) exn)
425                       (begin
426                        (display "Not a pair: ")
427                        (display
428                         ((condition-property-accessor 'not-a-pair 'value) exn))
429                        (newline))
430                       (abort exn))
431  (try-car 0))
432; displays "Not a pair: 0"
433
434(let* ((cs-key (list 'color-scheme))
435       (bg-key (list 'background))
436       (color-scheme? (condition-predicate cs-key))
437       (color-scheme-background
438        (condition-property-accessor cs-key bg-key))
439       (condition1 (make-property-condition cs-key bg-key 'green))
440       (condition2 (make-property-condition cs-key bg-key 'blue))
441       (condition3 (make-composite-condition condition1 condition2)))
442  (and (color-scheme? condition1)
443       (color-scheme? condition2)
444       (color-scheme? condition3)
445       (color-scheme-background condition3)))
446; => 'green or 'blue
447</enscript>
448
449----
450Previous: [[Module (chicken blob)]]
451
452Next: [[Module (chicken continuation)]]
Note: See TracBrowser for help on using the repository browser.