Conditions
The defined name of this module is condition.
The condition system was influenced by the Common Lisp error system [?]
and the Standard ML exception mechanism. It is a simplification of the former
and an extension of the latter. Following standard practice, this text defines
the actions of functions in terms of their normal behaviour. Where an
exceptional behaviour might arise, this has been defined in terms of a
condition. However, not all exceptional situations are errors. Following
Pitman, we use condition to be a kind of occasion in a program
when an exceptional situation has been signalled. An error is a kind of
condition|error and condition are also used as terms for the objects that
represent exceptional situations. A condition can be signalled continuably by
passing a continuation for the resumption to signal. If a continuation is not
supplied then the condition cannot be continued.
These two categories are characterized as follows:
- A condition might be signalled when some limit has been transgressed
and some corrective action is needed before processing can resume. For
example, memory zone exhaustion on attempting to heap-allocate an
item can be corrected by calling the memory management scheme to
recover dead space. However, if no space was recovered a new kind of
condition has arisen. Another example arises in the use of IEEE floating
point arithmetic, where a condition might be signalled to indicate
divergence of an operation. A condition should be signalled continuably
when there is a strategy for recovery from the condition.
- Alternatively, a condition might be signalled when some catastrophic
situation is recognized, such as the memory manager being unable to
allocate more memory or unable to recover sufficient memory from that
already allocated. A condition should be signalled non-continuably when
there is no reasonable way to resume processing.
A condition class is defined using defcondition (see Section ).
The definition of a condition causes the creation of a new class of condition. A
condition is signalled using the function signal, which has
two required arguments and one optional argument: an instance of a
condition, a resume continuation or the empty list, the latter signifying a
non-continuable signal, and a thread. A condition can be handled using the
special form with-handler, which takes a function, the
handler function, and a sequence of forms to be protected. The initial
condition class hierarchy is as follows:
<condition>
<execution-condition>
<invalid-operator>
<cannot-update-setter>
<no-setter>
<domain-condition>
<range-condition>
<environment-condition>
<arithmetic-condition>
<division-by-zero>
<conversion-condition>
<no-converter>
<stream-condition>
<syntax-error>
<thread-condition>
<thread-already-started>
<wrong-thread-continuation>
<wrong-condition-class>
<telos-condition>
<no-next-method>
<generic-function-condition>
<non-congruent-lambda-lists>
<incompatible-method-domain>
<no-applicable-method>
<method-domain-clash>
Condition Classes
defcondition :
defining form
Syntax
defcondition form
= '(', 'defcondition',
condition class name,
condition superclass name,
{slot name}, ')';
Remarks
Arguments
- condition class name
- An identifier naming a binding to
be initialized with the new condition class.
- condition superclass name
- An indentifier naming a
binding of a class to be used as the superclass of the new condition class.
- slot names
- A sequence of keywords used to name and to
identify additional slots begin defined for this condition class.
Remarks
This defining form defines a new condition class. The first
argument is the identifier to which the new condition class will be bound. The
second is the identifier of the superclass of the new condition class and an
init-option is an identifier followed by its (default) initial value. If
superclass-name is (), the superclass is taken to
be <condition>. Otherwise superclass-name must
be <condition> or the name of one of its subclasses.
<condition>
: class
Initialization options
- message : <string>
- A
string, which may contain format directives which will be filled in with
the corresponding message arguments.
- message-arguments : <list>
-
A list of objects to be used in processing the message format string.
Remarks
The class which is the superclass of all condition classes.
conditionp :
function
Arguments
- object
- An object to examine.
Result
Returns object if it is a condition, otherwise
().
initialize :
method
Specialized arguments
- (condition <condition>)
- A
condition.
- initlist
- A list of initialization options as follows:
- message : <string>
- A
string, which may contain format directives which will be filled in
with the corresponding message arguments.
- message-arguments : <list>
-
A list of objects to be used in processing the message format string.
Result
A new, initialized condition.
Remarks
First calls call-next-method to carry out
initialization specified by superclasses then does the condition
specific initialization.
<wrong-
condition-class> :
<thread-condition>
Initialization options
- condition : condition
- A condition.
Signalled by signal if the given condition is not an instance
of the condition class <thread-condition>.
Condition Signalling and Handling
Conditions are handled by a function called a handler. Handlers
are established dynamically and have dynamic scope and extent. Thus, when a
condition is signalled, the processor will call the nearest enclosing handler.
Handlers are established by the special form with-handler.
signal :
function
Arguments
- condition
- The condition to be signalled.
- [thread]
- If this argument is not supplied, the condition
is signalled on the thread which called
signal,
otherwise, thread indicates the thread on which
condition is to be signalled.
Remarks
Called to indicate that a specified condition has arisen
during the execution of a program.
If the third argument is not supplied, signal calls the nearest
enclosing handler with condition.
If the second argument is supplied, signal registers the
specified condition to be signalled on thread. The condition must
be an instance of the condition class <thread-condition>,
otherwise an error is signalled (condition class:
<wrong-condition-class>) on the thread calling
signal. A signal on a determined thread
has no effect on either the signalled or signalling thread except in the case of
the above error.
See also:
thread-reschedule,
thread-value, with-handler.
call-next-handler :
special form
Syntax
call next handler form
= '(', 'call-next-handler', ')';
Remarks
The call-next-handler special form calls
the next enclosing handler. It is an error to evaluate this form other than
within an established handler function.
The call-next-handler special form is normally used when a
handler function does not know how to deal with the class of condition.
However, it may also be used to combine handler function behaviour in a
similar but orthogonal way to call-next-method (assuming a
generic handler function).
with-handler :
special form
Syntax
with handler form
= '(', 'with-handler',
handler function,
{form}, ')';
handler function
= level 0 expression;
Arguments
- handler function
- The result of evaluating the handler
function expression must be either a function or a generic function. This
function will be called if a condition is signalled during the dynamic
extent of protected-forms and there are no intervening
handler functions which accept or resume the condition. A handler
function takes two arguments: a condition, and a resume
function/continuation. The condition is the condition object that was
passed to
signal as its first argument. The
resume continuation is the continuation (or
()) that was given to signal as its
second argument.
- forms
- The sequence of forms whose execution is
protected by the handler function specified above.
Result
The value of the last form in the sequence of
forms.
Remarks
A with-handler form is evaluated in three
steps:
- The new handler-function is evaluated. This now identifies
the nearest enclosing handler and shadows the previous nearest enclosing
handler.
- The sequence of forms is evaluated in order and the value of
the last one is returned as the result of the
with-handler expression.
- the handler function is disestablished as the nearest
enclosing handler, and the previous handler function is restored as the
nearest enclosing.
The above is the normal behaviour of with-handler. The
exceptional behaviour of with-handler happens when there is
a call to signal during the evaluation of
protected-form. signal calls the nearest enclosing
handler-function passing on the first two arguments given to
signal. The handler-function is executed in the
dynamic extent of the call to signal. However, any calls to
signals occurring during the execution of
handler-function are dealt with by the nearest enclosing handler
outside the extent of the form which established handler-function.
It is an error if there is no enclosing handler. In this circumstance the
identified error is delivered to the configuration to be dealt with in an
implementation-defined way. Errors arising in the dynamic extent of the
handler function are signalled in the dynamic extent of the original
signal but are handled in the enclosing dynamic extent of
the handler.
Examples
There are three ways in which a handler function can
respond:
- The error is very serious and the computation must be abandoned; this is
likely to be characterised by a non-local exit from the handler function.
- The situation can be corrected by the handler, so it does and then
returns. Thus the call to
signal returns with the result
passed back from the handler function.
- The handler function does not know how to deal with the class of
condition signalled; control is passed explicitly to the next enclosing
handler via the
call-next-handler special
form.
An illustration of the use of all three cases is given here:
(defgeneric error-handler (condition)
method: (((c <serious-error>)) ... abort thread ...)
method: (((c <fixable-situation>)) ...apply fix and return ... )
method: (((c <condition>) (call-next-handler))))
(with-handler error-handler
;; the protected expression
(something-which-might-signal-an-error))
See also:
signal.