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>] endwhere
<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.
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.
begin p(q( )) except when e1: % handle e1 when e3(x:int): % handle e3 end end except when others: % handle e2 and e4 here endThe 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.
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:
begin % routine_body end except when failure (s: string): signal failure(s) others (s: string): signal failure ("unhandled exception: " || s) end