Exception Handling
The THROW and CATCH mechanism was first introduced in KCML 6.20. In KCML 6.40 and KCML 6.60 it has been enhanced to allow compiler checking of the range of a THROW. This provides safety for an application from unexpected THROWS occuring that the application fails to catch. THROW and CATCH are normally associated with error handling but they are useful for non-error situations as well so are more correctly described as implementing exception handling.
The mechanism consists of throwing an error through the THROW ERR statement and catching it with a TRY CATCH block. Often the CATCH will be in the same function as the THROW, but it is possible to declare a function as permitted to throw certain errors and then the CATCH may be located in a calling function.
Run-time error may also be caught using a TRY block. However, they are not subject to any of the restrictions presented here about the range of the error.
THROW ERR
The THROW ERR statement transfers program control from the statement to the appropriate CATCH or CATCH ERR statement. A value is specified for THROW ERR allowing code to throw several different errors which are then processed differently.
The THROW ERR statement should only throw constants that are members of an enumeration. This provides for future compatibility. The built in user error _KCML_USER_ERROR is a member of an enumeration. For example:
DEF ENUM MyExceptions DIM _Exception1 = _KCML_USER_ERROR + 1 DIM _Exception2 = _KCML_USER_ERROR + 2 END ENUM DIM _JustAConstant = _KCML_USER_ERROR + 1 THROW ERR _Exception1 // This is a member of an enumeration THROW ERR _JustAConstant // This will cause a compilation error
CATCH
One or more CATCH statements may appear in a TRY block. A CATCH statement may either contain one or more exceptions to catch or may be empty to catch all exceptions. After a THROW exception, KCML will look at the context of the THROW and if it is inside a TRY block will examine all the CATCH statements of the TRY block to see if any match the THROW. If there is a match then program control will transfer to the CATCH. If there is no match then KCML will examine any outer TRY block the THROW is contained in. If there is still no match then the function itself will pass on the THROW. It can only do this if the function is declared as being able to pass on the throw. This means that the function is called from other code that can itslef handle the throw or can itself pass it on. Thus there is a guarantee that there will be a CATCH to handle the THROW.
DEFSUB
A function that may provoke a THROW exception must either handle it or pass it on. If it passes it on it must say so on the DEFSUB line, using THROW at the end of the declaration. The THROW clause may either be a list of exceptions or empty meaning that the function can pass on any exception.
DEFSUB 'Fn1() THROW DEFSUB 'Fn1() AS _KDB_ERROR_ENUM THROW _Exception1, _Exception2
DEFSUB 'Throw1() TRY THROW ERR _Exception1 CATCH // Catch all. Program control will transfer here END TRY END SUB
DEFSUB 'Throw2() TRY THROW ERR _Exception1 CATCH ERR _Exception2 // Wrong exception CATCH ERR _Exception1 // Program control will transfer here END TRY END SUB
DEFSUB 'Throw3() TRY TRY THROW ERR _Exception1 CATCH ERR _Exception2 // Wrong exception END TRY CATCH ERR _Exception1 // Program control will transfer here END TRY END SUB
DEFSUB 'Throw4() // This will be a compilation error. The exception is not handled // here and the function is not allowed to pass it on. THROW ERR _Exception1 END SUB
DEFSUB 'Throw5() THROW _Exception1 // This function is permitted to THROW ERR _Exception1 THROW ERR _Exception1 END SUB DEFSUB 'Catch5() TRY // Call a function that may throw 'Throw5() CATCH ERR _Exception1 // Program control will transfer here END TRY END SUB
DEFSUB 'Throw5() THROW _Exception1 // This function is permitted to THROW ERR _Exception1 THROW ERR _Exception1 END SUB DEFSUB 'Intermediate5() THROW // This function can call anything and any throw will past through 'Throw5() END SUB DEFSUB 'Catch5() TRY // Call a function that may throw 'Intermediate5() CATCH ERR _Exception1 // Program control will transfer here END TRY END SUB
PROTOTYPE and CALLBACK
CALLBACK and PROTOTYPE declarations have the same syntax as DEFSUB. The same rules about passing on exceptions apply to CALLBACK and PROTOTYPE. For a CALLBACK to be compatible with a PROTOTYPE, any exception the CALLBACK may throw must also be permitted to be thrown by the PROTOTYPE.
WHILE TRANS
It is a compilation error if it is possible for an exception to reach a WHILE TRANS loop.
KCML 6
DEF ENUM is syntactically supported in KCML6 but has no run time effect. Enumerated values are treated as constant values and it is not possible to distinguish two enumerated values with different names but the same numerical value. The compiler will spot where a conflict may occur between a throw and a catch.
See also:
TRY, THROW, ON ERROR, SELECT ERROR, ERR, ERROR, ERR$( DEF ENUM