TIP proposal: Try/Catch Exception Handling Draft proposal by [Twylite] 2008-09-12. **Abstract** This TIP proposes the addition of new core commands to improve the exception handling mechanism. It supercedes TIP #89 by providing support for the error options dict introduced in Tcl 8.5 by TIP #90. **Rationale** See TIP #89 for general rationale for enhancing exception handling. In Tcl 8.4 exceptions could be caught using [[catch]], and exception information was available via the [[catch]] return value and resultvar. If the return value was TCL_ERROR (1) then the globals ::errorCode and ::errorInfo would be set according to the exception raised. TIP #89 was written to work with this model, such that a catch handler (in a try...catch) would be able to capture the resultvar, errorCode and errorInfo. Tcl 8.5 implements TIP #90 which extends [[catch]] to allow an additional dict of options (error information) to be captured. These options supercede the ::errorInfo and ::errorCode globals. It it logical to extend/correct the syntax of TIP #89 to support the options dict in preference to the older mechanism for capturing exception information. **Specification** * '''throw''' ''type message'' Since the catch handlers in the try...catch control structure will filter based on the exception's errorcode, it makes sense to have a command that will encourage the use of error codes when throwing an exception. [[throw]] is merely a reordering of the arguments of the [[error]] command. * '''rethrow''' ?''type''? ?''message''? TBD Use within a catch handler to rethrow the existing exception, possibly with translation of the errocode and message. The intent is to allow exception translation/chaining without losing the context of the original error. * '''try''' ''body'' ?'''catch''' {''type'' ?''emvar''? ?''optvar''?} ''body''? ?...? ?'''finally''' ''body''? The try body is evaluated in the caller's scope. If the result is TCL_ERROR then each catch handler is considered in order until one is found with a type that matches the exception's errorcode, then the body of that handler is executed. Rules: * The type is a glob that is used to match against the exception's errorcode. * Only one catch handler will be executed. If the type matches for more than one handler then on the first handler (reading left-to-right in the command) will be executed. * If no matching handler is found then the exception will propagate up the stack. * If the catch body is a "-" then the body of the following catch block will be executed instead. * When the handler body is executed the error message will be stored in the emvar (if specified) and the error options in the optvar (if specified). * If an exception occurs in a catch block and the errorcode is "RETHROW" then the existing exception is re-raised at this point. (TBD FIXME - this prevents errorcode translation) * If an exception other than a rethrow occurs in a catch block then the new exception takes precedence and will propagate upwards, but the existing error stack will be maintained (with an indication that the cause of the error has changed, e.g. "new error X WHILE old error Y" **For consideration** * Execute ALL matching catch handlers (use [break] or [continue] for control?) * If there is an exception in a catch handler it takes precedence, but keep looking for other matching handlers * If the last handler has type {*} and at least one handler has been executed then don't run the last (catchall) handler * Alternative syntax for [[finally]] * What should [[try]] return? Nothing (like [for], [while], [foreach]) or the result of the body (like [if] and [switch])? **References** * TIP #89 [http://www.tcl.tk/cgi-bin/tct/tip/89.html] * TIP #90 [http://www.tcl.tk/cgi-bin/tct/tip/90.html] * Tcl 8.4 catch [http://www.tcl.tk/man/tcl8.4/TclCmd/catch.htm] ---- !!!!!! %| [Category Control Structure] | [Category Suggestions] |% !!!!!!