Previous section: Overview

Dylan reference manual -- Specification

Specification

The following sections outline the classes and operations on conditions available in Dylan.

Format Strings

A "format string" is a string template into which values can be inserted to construct a message. The two-character sequences %d, %b, %o, %x, %c, %s, and %= are replaced by the next element of the associated sequence of "format arguments." Upper and lower case letters are equivalent in these format directives. The inserted value is formatted according to the following table:

    directive          argument type                  textual format          
       %d                <integer>         decimal number
       %b                <integer>         binary number
       %o                <integer>         octal number
       %x                <integer>         hexadecimal number
       %c                <character>       character (with no quotes)
       %s                <string>          string (with no quotes)
       %s                <condition>       error message (with no quotes)
       %=                <object>          unspecified but works for any object
       %%                none             literal %

The text printed by the %= format directive for any given object is implementation-defined. The behavior when a format argument is not of the type specified in the table above is implementation-defined. The behavior when too many or too few format arguments are supplied is implementation-defined.

The two-character sequence %% does not consume a format argument, but inserts a % character.

All other uses of the % character in a format string are implementation-defined. Extensions in the style of Common Lisp format or C printf might exist in some implementations but are not portable. This is not attempting to be a general text-formatting package, just a simple least common denominator for casual construction of error messages.

There is no standard way to get the "error message" from a condition, although it can be inserted into another message by using the %s directive in a format string. Debuggers get the error message using implementation-dependent mechanisms. When a streams library is present, it might include a function to get the "error message" from a condition.

There is no standard way for a user-defined condition class that does not inherit from <simple-error> <simple-restart>, or <simple-warning> to supply an "error message." Individual platforms, application frameworks, or user interfaces should specify a mechanism for this that is appropriate to their needs.

Classes

The classes described in this section are defined by Dylan. In addition, numerous condition classes specific to particular Dylan built-in functions or user functions will no doubt exist. Note that there can be other direct subclasses of <condition> besides the three specified ones. Also note that the subclass relationships shown below are not necessarily direct subclass relationships (i.e. implementation-specific classes can be inserted in the class hierarchy).

Abstract classes are shown in italics.


<condition>	[Abstract Class]
A condition is a general instance of the abstract class <condition>. It is an object that represents the occurrence of an exception. Conditions have indefinite extent and no special restrictions. A program that does not encounter any exceptional situations will not implicitly allocate any conditions.

There is a default handler for <condition> that returns #f.

<serious-condition>	[Abstract Class]
<serious-condition> is the abstract class of all conditions that cannot safely be ignored. There is a default handler for <serious-condition> that calls the debugger, using an unspecified mechanism.
<error>	[Abstract Class]
<error> is the abstract class of all conditions that represent something invalid about the program (as opposed to environmental conditions such as running out of memory or battery power, or inability to establish a network connection, for example). <error> is a subclass of <serious-condition>. <error> is distinct from <serious-condition> so one can establish a handler for errors that does not also trap unpredictable environmental exceptions such as network problems.
<simple-error>	[Instantiable Class]
<simple-error> is the concrete class of error conditions that consist of just an error message constructed from a format string and arguments; it is a subclass of <error>. The recovery protocol is empty. The initialization arguments format-string: and format-arguments: are accepted. The accessor functions condition-format-string and condition-format-arguments are applicable.
<type-error>	[Instantiable Class]
<type-error> is a concrete subclass of <error> used by check-type. The recovery protocol is empty. The initialization arguments value: and type: are accepted. The accessor functions type-error-value and type-error-expected-type are applicable.
<sealed-object-error>	[Instantiable Class]
<sealed-object-error> is a subclass of <error>
<warning>	[Abstract Class]
<warning> is an abstract subclass of <condition>. There is a default handler for <warning> that displays the warning in a user-interface dependent way and then returns #f. The recovery protocol is that any value can be returned and will be ignored.
<simple-warning>	[Instantiable Class]
<simple-warning> is a concrete subclass of <warning> used by signal. The recovery protocol is the same as for <warning>. The initialization arguments and accessor functions are the same as for <simple-error>.
<restart>	[Abstract Class]
A restart is a general instance of the abstract class <restart>. <restart> is a subclass of <condition>. There is a default handler for <restart> that signals an error reporting an attempt to use a restart for which no restart handler was established. The recovery protocol concept is not applicable to restarts. The initialization argument condition: is accepted and ignored by <restart>; some subclasses save the value of this initialization argument and use it to associate a restart with a particular condition from which the restart can recover. At present, none of these subclasses are defined as part of the language. Other restarts do not care; they can recover from any condition.
<simple-restart>	[Instantiable Class]
<simple-restart> is a concrete subclass of <restart> that is used by cerror. The initialization arguments format-string: and format-arguments: are accepted. The accessor functions condition-format-string and condition-format-arguments are applicable. Typical implementations will use the format string and format arguments to produce a description of the restart.
<abort>	[Instantiable Class]
<abort> is a concrete subclass of <restart> whose handlers are expected to terminate execution of the current application command, or similar unit of execution, and return control to something like an application command loop. This is comparable to command-period on the Macintosh. The exact details of this feature depend on the particular environment, of course, but signaling an instance of <abort> is a uniform way to "get out."

Basic Operator for Signaling

signal   condition   =>  values	[Function]
Signals the condition, trying each active dynamic handler, the most recent first. If all dynamic handlers decline, signal calls default-handler (condition). If a handler returns, all the values that it returned are returned from signal. If signal returns when condition's recovery protocol does not allow returning, some handler has violated protocol; signal does not check for this error. If condition is a restart, the caller of signal should always assume that it might return.

Additional operators for signaling, defined for convenience, are described in a later section.

Basic Operator for Handling Conditions

let handler condition = handler	[Local Declaration]
	
let handler establishes a condition handler during the dynamic extent of the evaluation of the rest of the enclosing body. It is scoped as in let.

condition should be of the form

type

or ( type [, test: test ] [, init-arguments: init-arguments ] )

type, handler, test, and init-arguments are evaluated before evaluation of the rest of the enclosing body begins.

type
The handler applies to conditions that are general instances of type.
test
A function called with a condition that is a general instance of type and that returns true if this handler applies to this condition. The default is a function that always returns true. An example usage is a restart handler for restarting only from a particular condition object, for example, restarting from an unbound-slot error by setting the slot and retrying the invocation of the accessor. The <set-and-continue> restart condition will have the signaled <unbound-slot> condition in a slot, and the handler's test will check for it. (These class names are invented for this example and are not part of the specification.)
handler
A function called to handle a condition that matches type and passes test. The values of the arguments are the condition being signaled and the next handler function. The function handles the condition by taking a non-local exit, returning values according to the condition's recovery protocol, or tail-recursively calling signal of a restart. The function can decline to handle the condition by tail-recursively calling next-handler with no arguments.[26]
init-arguments
A sequence of alternating keywords and objects which can be used as initialization arguments to construct an instance of type. It defaults to an empty sequence. This is probably used only in restart handlers.
test and handler are distinct so that handler applicability can be tested without actually handling (which might take a non-local exit). One use for this is constructing a list of available restart handlers.

There is no "condition wall," i.e., when executing handler the set of available handlers is not reset to the handlers that were in effect when the let handler was entered.[27]

The expansion of a let handler form is implementation-dependent. Implementations are encouraged to use an expansion that optimizes establishing a handler for both speed and space, even if that increases the cost of signaling. The assumption is that most of the time a handler will never be used, because the exception it is looking for will never occur.

Miscellaneous Condition Operations

Some condition classes define accessor functions. The accessor functions for the standardized classes are specified briefly with the class above. None of these are settable.

Full Set of Operators for Signaling

The first operator listed here is a repeat of the basic operator. The others all have straightforward implementations in terms of other primitives but are provided to enable concise code in simple, common cases.
signal   condition   =>  values	[Function]
signal   string argument1 argument2 ...   =>  values
Signals the condition, trying each active dynamic handler, the most recent first. If all dynamic handlers decline, signal calls default-handler(condition). If a handler returns, all the values that it returned are returned from signal. If signal returns when the condition's recovery protocol does not allow returning, some handler has violated protocol; signal does not check for this error. If the condition is a restart, the caller of signal should always assume that it might return.

The second form signals a condition of type <simple-warning>.

error   condition   =>  {will never return}	[Function]
error   string argument1 argument2 ...   =>  {will never return}
error is similar to signal but never returns; if a handler returns, error bombs directly to the debugger. error is used to make it clear that a program does not expect to receive control again after signaling a condition and might enable the compiler to generate slightly more compact code.

The second form signals a condition of type <simple-error>.

cerror   restart-description condition   =>  #f	[Function]
cerror   restart-description string argument1 argument2 ...  =>  #f
cerror is the same as error but first establishes a handler for <simple-restart>, with init-arguments: specifying format-string: restart-description and format-arguments: the sequence argument1, argument2, ... .

If the restart handler is invoked, cerror returns #f; otherwise, cerror never returns. If cerror returns, the program should take the corrective actions promised in the restart-description. cerror is the standard way to signal correctable errors when no special class of restart condition is required.

break   [condition]  =>  #f	[Function]
break   [string argument1 argument2...]   =>  #f
break obtains a condition in the same way as signal but then invokes the debugger immediately without signaling first. break establishes a <simple-restart> so the debugger can continue execution. This is useful for breakpoints. break always returns #f. With no arguments, a default message string is used.
check-type   value type   =>  value	[Function]
check-type signals a <type-error> if instance?(value , type) is false.
abort	[Function]
Performs error(make (<abort>)). This function is provided as a convenient shortcut.

The call is to error, rather than to signal, to guarantee that abort will never return.

Additional Operators for Handling

The optional exception clauses in Dylan's block statement establish exception handlers during the dynamic extent of the evaluation of the body of the block statement. Any number of cleanup-clauses (described under block in the chapter on Control Constructs) may be provided, and they may be arbitrarily interleaved with exception-clauses .The syntax of an exception clause is as follows:

exception ( type | name :: type #key test init-arguments )

exception-body [;]

If one of these handlers is invoked, it never declines, but immediately takes a non-local exit, executes the expressions in the exception-body , and returns the values of the last expression in the exception-body, or #f if the exception-body contains no expressions. If the exception handlers are never invoked, block returns the values of the last expression in the block body (or the the values of the last expression in the last cleanup-clause, if there are cleanup-clauses). Note that when the expressions in an exception-body are executed, the handler established by that exception clause is no longer active. type, test, and init-arguments are as for let handler. name, if present, is not evaluated but is the name of a variable that is bound to the condition around the expressions in the block body.

The exception clauses are checked in the order in which they appear. That is, the first handler will take precedence over the second, etc.

A very trivial use of an exception clause might look like:

block (return)
  open-files();
  ...
  result
exception (<error>) 
  return(#f);
cleanup
  close-files();
end block
default-handler   condition   =>  values	[Generic Function]
default-handler is called if no dynamic handler handles a condition. There are predefined methods for <condition>, which returns an empty sequence, <serious-condition>, which calls the debugger, <warning>, which prints the message and returns #f, and <restart>, which signals an error.

Operators for Interactive Handling

restart-query   restart	[Generic Function]
restart-query engages the interactive user in a dialog and stores the results in slots of restart. This function is designed to be called from a handler, after making a restart and before signaling it. The debugger uses restart-query, for example. There is a default method for <restart> which does nothing.
return-query   condition	[Generic Function]
If the recovery protocol of condition allows returning values, this engages the interactive user in a dialog and returns the results as any number of values, which the handler should return. return-query should not be called if return-allowed? returns #f. If you define your own condition class whose recovery protocol allows returning values, you need to define a method for return-query, unless the inherited method is suitable.

Operators for Introspection

do-handlers   funarg	[Function]
do-handlers applies funarg to all dynamically active handlers, the most recently established first. funarg receives four arguments: type, test, function, and init-arguments. The arguments describe a dynamically active handler. All arguments have dynamic extent and must not be modified. test is defaulted to a function that always returns #t. init-arguments is #f if unsupplied by the handler.
return-allowed?   condition   =>  boolean	[Generic Function]
This predicate returns #t if the recovery protocol of condition allows returning values, or #f if it does not. There is a default method for <condition> that returns #f. If you define your own condition class, you need to define a method for return-allowed? unless the inherited method is suitable.
return-description   condition  =>  description	[Generic Function]
If the recovery protocol of this condition allows returning values, return-description returns a description of the meaning of returning values. This description can be a restart, a string, or #f. return-description should not be called if return-allowed? returns #f. If you define your own condition class whose recovery protocol allows returning values, you need to define a method for return-description unless the inherited method is suitable.

Next section: 14. Modules