Heading:
IDL DESIGN: Page heading
Page Numbers: Yes X: 527 Y: 10.5"
XEROX Palo Alto Research Center 15 May 1977
Inter-Office Memorandum
ToIDL GroupIDL Design Note Number: 11
FromBeau SheilFile:<IDL>Design.ErrorHandling
Subject The Handling of User Errors
This memo outlines the techniques we will use in the IDL code to handle errors that should be redirected to the user.
Error handling can be divided into two parts - the signalling of the error condition, and the interception and handling of the signal. The handling, in turn, can be divided into deciding what message to print and where the eventual break is to take place. The general principles that underlie what follows are (a) exactly one error message will be printed, (b) the decision as to which error message to print will be decided dynamically by a system of overrides, and (c) the final break will occur "close" (in a sense that no system code other than the error handler will depend on) to the point at which the user (code) turned control over to IDL.
The method for signalling the occurrence of a user error is
(UERROR PRINTOUT-command-list)
which, unless overridden (see below), will call PRINTOUT on its argument list and return directly to the enclosing UENTRY or UERRORGUARD for further action. In terms of what is to be written in the system code, this does not differ from the current procedure.
The method for altering the response to a user error is
(UERRORGUARD form {PRINTOUT-command-list})
which evaluates form with printout from resulting UERRORs suppressed. Its subsequent action depends on the presence of a PRINTOUT command list. If one exists, then it is presumed that the desired effect is to redefine the error message for errors produced by the evaluation of form to be that produced by the new PRINTOUT command list. Thus,
(UERRORGUARD A←(CONV.ARITH FOO) "GASP: BAD FOO!")
has the effect of replacing the error message produced by CONV.ARITH with a message that is more appropriate given the higher level context. Note that the printing of the new message will be done (effectively) by calling UERROR on the PRINTOUT command list. Consequently, if the UERRORGUARD is in the scope of another (higher) UERRORGUARD, the higher UERRORGUARD will override the lower just as the lower overrode the UERROR. The multiple levels of error handling thus provided allow each function to construct an error message which takes advantage of its context, without concerning itself with the error messages produced in lower functions.
If, on the other hand, there is no PRINTOUT command list in a "call" on UERRORGUARD, it is assumed that the caller is interested in keeping control regardless of the result of the computation. Consequently, UERROR is not reinvoked, but the answer to the question "Did a UERROR occur?" is returned as the value of the UERRORGUARD. Using this mechanism, the protected evaluation of RESHAPE can be written
if (UERRORGUARD (SETQ TMP (CONV.SCALAR A)) )
then... A could not be converted to a scalar ...
else... it could! (and the result is in TMP) ...
The climb back up the chain of UERRORs and UERRORGUARDs ends when we get to the function at which the user gave us control (at which some unspecified thing happens). This point is specified by requiring the body of any function which can be called directly by the user to be of the form
(DLAMBDA argument-list (UENTRY function-body) )
This will cause (effectively) a special UERRORGUARD to be wrapped around the function body so that the error signal will be caught and redirected to the user in some way that bears on his context.
As the redirection to the user may involve showing him both the arguments he presented and the names to which they were bound, we will observe the following conventions
1.User entry functions will use moderately descriptive names for their arguments (e.g. from RESHAPE - NEWSHAPE is ok; A is not).
2.No user entry function will reset the variables to which it binds the arguments presented by the user.
For convenience during debugging, the absence of a containing UERRORGUARD or UENTRY will cause UERROR to call BREAK1 after printing its message. This may, however, be a fatal system error in the production version.