TIP proposal: Try/Catch Exception Handling
Draft proposal by Twylite 2008-09-12.
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.
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.
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.
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.
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:
KD: What I'm missing in this is that Tcl has already a mechanism for throwing exceptions, namely special return codes. For example, the following throws an exception with return code 7:
return -code 7 "User provided incomplete input"
which can be catched somewhere on the call tree with:
switch [catch {do something} result] { 0 {do the next thing} 1 {return -code 1 -errorcode $::errorCode -errorinfo $::errorInfo $result} 7 {tk_messageBox -type ok -icon error -message $result} }
Tip 89 seems to use ::errorCode for everything, but exceptions are not errors, and currently ::errorCode in Tcl is used only for I/O and OS errors. To me it seems better to keep return code 1 for these errors, and use special return codes for user-defined exceptions.