Except Statement

next up previous contents index
Next: Resignal Statement Up: Statements Previous: Begin Statement

Except Statement

By attaching handlers to a statement, the caller can specify the action to be taken when an exception is signaled by an invocation contained within that statement. (Except statements also handle signals raised by contained exit statements (8.16).) A statement with handlers attached is called an except statement and has the form

<statement> except [<handler>]* [others ["(" <idn> ":" string ")"] ":" <body>] end
        <handler> -> when <name> ["," <name>]* ["(" <decl> ["," <decl>]* ")"] ":" <body>
Let S be the statement to which the handlers are attached, and let X be the entire except statement. Each handler arm specifies one or more exception names and a body. The body is executed if an exception with one of those names is signaled by an invocation in S. All the names listed in the arms must be distinct. The optional others arm is used to handle all exceptions not explicitly named in a handler arm. S can be any form of statement, even another except statement.

If, during the execution of S, some invocation in S signals an exception E, control immediately transfers to the closest applicable handler: that is, the closest handler for E that is attached to a statement containing the invocation. When execution of the handler is complete, control passes to the statement following the one to which the handler is attached. Thus if the closest handler is attached to S, the statement following S is executed next. If execution of S completes without signaling an exception, the attached handlers are not executed.

An exception raised by an invocation inside a handler is treated the same as any other exception: Control passes to the closest handler attached to a statement containing the invocation. Note that if handlers H1 and H2 are attached to the same statement S, and H1 makes an invocation that raises an exception, H2 cannot handle this exception since H2 is not attached to a statement that encloses H1. Either H1 must handle the exception itself, or a handler attached to a statement that contains H1 must handle the exception.

Handlers without Declarations

If a handler for exception E has no declarations, then if it is selected to handle E, any results raised with E are simply ignored. Such a handler can be used to handle exceptions that are raised without results, or in cases where the results are not of interest.

Handlers with Declarations

A handler with declarations is used to handle exceptions with the given names when the exception results are of interest. The declared variables, which are local to the handler, are assigned the exception results before the body is executed.

When matching exceptions to handlers, only the exception names are used. If a handler for exception E includes declarations, it must be able to handle all possible exceptional results that can be raised with E. For example, suppose in the same statement there are two routine invocations, where one has "`signals`(foo(int))" in its signature, and the other has "`signals` (foo(string,real))". In this case it is impossible to use a handler with declarations to handle exception "foo"; no single handler with declarations could cover both cases. (The solution is to use a handler without declarations, or to split the statement up into two different except statements, so that different handlers can be used.)

Stated more formally: If a handler H for exception E has [tex2html_wrap2938] variable declarations, and is attached to statement S, then for each invocation in S that can raise E so that it is handled by H, E must be raised with [tex2html_wrap2940] results and the [tex2html_wrap2942]th result type must be a subtype of the [tex2html_wrap2944]th variable declared by H; otherwise there is a compile-time error.

Others Handler

The others arm is optional and must appear last in a handler list. This form handles any exception not handled by other handlers in the list. If a variable is declared, it must be of type "string". The variable, which is local to the handler, is assigned a lower-case string representing the actual exception name; any results of the exception are discarded.


The following example assumes that procedure p raises exceptions e1, e2, and e3, and that e1 and e2 have no results, while e3 has an int result. It also assumes that procedure q raises e1 (with no results) and e4 (also with no results).
            p(q( ))  except  when e1:  % handle e1 
                             when e3(x:int):  % handle e3
        end except  when others:  % handle e2 and e4 here
The first arm handles exception e1, which might have been raised by either the call of q or the call of p. Exceptions e2 and e4 aren't handled by the inner except statement, but are handled by the outer one.

The Failure Exception

The exception "failure(string)" is implicitly included in every routine interface; it is illegal to list a "failure" exception explicitly in an interface.

If a routine performs an invocation that raises an exception not handled by any except statements in the routine body, the routine will terminate automatically with the "failure" exception. If the unhandled exception is not "failure", the "failure" exception will have as a result a string naming the unhandled exception; otherwise its result will be the string argument of the unhandled "failure" exception. The semantics is the same as if every routine body were placed in an except statement of this form:

     % routine_body 
  except  when failure (s: string): signal failure(s) 
          others (s: string): signal failure ("unhandled exception: " || s)

next up previous contents index
Next: Resignal Statement Up: Statements Previous: Begin Statement