PSL Manual 7 February 1983 Error Handling and Recovery
section 14.0 page 14.1
CHAPTER 14
CHAPTER 14
CHAPTER 14
ERROR HANDLING
ERROR HANDLING
ERROR HANDLING
14.1. Introduction . . . . . . . . . . . . . . . 14.1
14.2. The Basic Error Functions. . . . . . . . . . . 14.1
14.3. Break Loop. . . . . . . . . . . . . . . . 14.4
14.4. Interrupt Keys . . . . . . . . . . . . . . 14.7
14.5. Details on the Break Loop. . . . . . . . . . . 14.7
14.6. Some Convenient Error Calls . . . . . . . . . . 14.7
14.7. Special Purpose Error Handlers . . . . . . . . . 14.9
14.1. Introduction
14.1. Introduction
14.1. Introduction
In PSL, as in most LISP systems, various kinds of errors are detected by
functions in the process of checking the validity of their argument types
and other conditions. Errors are then "signalled" to a currently active
ErrorSet Error
ErrorSet Error
error handler (called ErrorSet) by a call on an Error function. In PSL,
Break
Break
the error handler typically calls an interactive Break loop, which permits
the user to examine the context of the error and optionally make some
corrections and continue the computation, or to abort the computation.
Break
Break
While in the Break loop, the user remains in the binding context of the
function that detected the error; the user sees the value of FLUID
variables as they are in the function itself. If the user aborts the
Throw
Throw
computation, a call on Throw with a tag of !$ERROR!$ is done, and fluids
are unbound.
[??? What about errors signalled to the Interrupt Handler ???]
[??? What about errors signalled to the Interrupt Handler ???]
[??? What about errors signalled to the Interrupt Handler ???]
14.2. The Basic Error Functions
14.2. The Basic Error Functions
14.2. The Basic Error Functions
The following two switches and one global variable are used by the
functions in this section.
__________ ______
!*BACKTRACE [Initially: T] switch
ErrorSet
ErrorSet
Set in ErrorSet. Controls whether an unwind backtrace is
requested.
Error Handling and Recovery 7 February 1983 PSL Manual
page 14.2 section 14.2
__________ ______
!*MSGP [Initially: T] switch
ErrorSet
ErrorSet
Set in ErrorSet. Controls error message printing during call on
error.
__________ ______
EMSG!* [Initially: NIL] global
Contains the message generated by the last error call.
ErrorSet
ErrorSet _ ___ ____ _______ _________ _______ ___ ____
(ErrorSet U:any !*MSGP:boolean !*BACKTRACE:boolean): any expr
_
If an uncorrected error occurs during the evaluation of U, the
______
value of NUMBER from the associated error call is returned as the
____
____
____
ErrorSet ErrorSet expr
ErrorSet ErrorSet expr _
value of ErrorSet. Note that ErrorSet is an expr, so U gets
evaluated twice, once as the parameter is passed and once inside
ErrorSet ErrorSet Catch
ErrorSet ErrorSet Catch
ErrorSet. [Actually, ErrorSet executes a Catch with tag
Throw
Throw
!$ERROR!$, and so intercepts any Throw with this tag.] In
addition, if the value of !*MSGP is non-NIL, the message from the
error call is displayed upon both the standard output device and
the currently selected output device unless the standard output
device is not open. The message appears prefixed with 5
asterisks. The message list is displayed without top level
parentheses. The message from the error call is available in the
GLOBAL variable EMSG!*. The exact format of error messages
generated by PSL functions described in this document may not be
exactly as given and should not be relied upon to be in any
particular form. Likewise, error numbers generated by PSL
functions are not fixed. Currently, a number of different calls
Error
Error
on Error result in the same error message, since the cause of the
error is the same and the information to the user is the same.
The error number is then used to indicate which function actually
detected the error.
[??? Describe Error # ranges here, or have in a file on
[??? Describe Error # ranges here, or have in a file on
[??? Describe Error # ranges here, or have in a file on
machine ???]
machine ???]
machine ???]
_
If no error occurs during the evaluation of U, the value of
List Eval
List Eval _
(List (Eval U)) is returned.
If an error has been signalled and the value of !*BACKTRACE is
non-NIL, a traceback sequence is initiated on the selected output
device. The traceback displays information such as unbindings of
FLUID variables, argument lists and so on in an implementation--
dependent format.
Error
Error ______ _______ _______ ___ ____ ________ ____
(Error NUMBER:integer MESSAGE:any): None Returned expr
_______
MESSAGE is placed in the GLOBAL variable EMSG!* and the error
ErrorSet
ErrorSet
number becomes the value of the surrounding ErrorSet (if any
PSL Manual 7 February 1983 Error Handling and Recovery
section 14.2 page 14.3
Break
Break
intervening Break loop is exited). FLUID variables and LOCAL
bindings are unbound to return to the environment of the
ErrorSet
ErrorSet
ErrorSet. GLOBAL variables are not affected by the process.
Error Break
Error Break
Error actually signals a non-continuable error to the Break loop,
and it subsequently does a throw with tag !$ERROR!$.
ContinuableError
ContinuableError ______ _______ _______ ___ ____ ____ ___ ____
(ContinuableError NUMBER:integer MESSAGE:any FORM:form): any expr
_______
MESSAGE is placed in the GLOBAL variable EMSG!* and the error
ErrorSet
ErrorSet
number becomes the value of the surrounding ErrorSet if the
Break
Break
intervening Break loop is "QUIT" rather than "Continued" or
"Retried". FLUID variables and LOCAL bindings are unbound to
ErrorSet
ErrorSet
return to the environment of the ErrorSet. GLOBAL variables are
Error
Error
not affected by the process. Error actually signals a
Break
Break
continuable error to the Break loop, and it subsequently does a
throw with tag !$ERROR!$.
The FORM is stored in the GLOBAL variable ERRORFORM!*, for
examination, editing or possible reevaluation after defining
missing functions, etc. Setting up the ERRORFORM!* can get a bit
MkQuote
MkQuote
tricky, often involving MkQuoteing of already evaluated
arguments. The following MACRO may be useful.
ContError
ContError ____ ___ ___ _____
(ContError [ARGS:any]): any macro
____
The format of ARGS is (ErrorNumber, FormatString, {arguments to
____________
PrintF}, ReEvalForm). The FORMATSTRING is used with the
BldMsg
BldMsg
following arguments in a call on BldMsg to build an error
PrintF
PrintF
message. If the only argument to PrintF is a string, the
BldMsg
____________ BldMsg
FORMATSTRING may be omitted, and no call to BldMsg is made. The
ReEvalForm is something like Foo(X, Y) which becomes list('Foo,
MkQuote X, MkQuote Y) to be passed to the function
ContinuableError
ContinuableError
ContinuableError.
(DE DIVIDE (U, V)
(COND((ZEROP V)
(CONTERROR 99 "Attempt to divide by 0 in DIVIDE
(DIVIDE U V
(T (CONS (QUOTIENT U V) (REMAINDER U V)))))
__________ ______
!*CONTINUABLEERROR [Initially: NIL] switch
________________
If !*CONTINUABLEERROR is T, then one is inside a continuable
error.
Error Handling and Recovery 7 February 1983 PSL Manual
page 14.4 section 14.3
14.3. Break Loop
14.3. Break Loop
14.3. Break Loop
Read/Eval/Print
Read/Eval/Print
On detecting an error, PSL normally enters a Read/Eval/Print loop called
Break
Break
a Break loop. Here the user can examine the state of his computation,
change the values of FLUIDs, or define missing functions. He can then
ErrorSet
ErrorSet
dismiss the error call to the normal error handling mechanism (the ErrorSet
above) or (in some situations) continue the computation. By setting the
Break
Break
switch !*BREAK to NIL, all Break loops can be suppressed, and just an error
message is displayed.
__________ ______
!*BREAK [Initially: T] switch
Break
Break
Controls whether the Break package is called before unwinding the
stack on error.
__________ ______
BREAKLEVEL!* [Initially: 0] global
The current number of nesting level of breaks.
__________ ______
MAXBREAKLEVEL!* [Initially: 5] global
The maximum number of nesting levels of breaks permitted.
Break
Break
The prompt "Break>" indicates that PSL has entered a Break loop. A
message of the form "Continuation requires a value for ..." may also be
printed, in which case the user is able to continue his computation by
Break
Break
repairing the offending expression. By default, a Break loop uses the
Read Eval Print
Read Eval Print
functions Read, Eval, and Print. This may be changed by setting
BREAKREADER!*, BREAKEVALUATOR!*, or BREAKPRINTER!* to the appropriate
function name.
__________ ______
ERRORFORM!* [Initially: NIL] global
Break
Break
Contains an expression to reevaluate inside a Break loop for
continuable errors. [Not enough errors set this yet]. Used as a
tag for various Error functions.
Break
__ Break
Several ids, if typed at top-level, are special in a Break loop. These
are used as commands, and are currently E, M, R, T, Q, A, I, and C. They
call functions stored on their property lists under the indicator
__
'BreakFunction. These ids are special only at top-level, and do not cause
any difficulty if used as variables inside expressions. However, they may
not be simply typed at top-level to see their values. This is not expected
to cause any difficulty. If it does, an escape command will be provided
for examining the relevant variables.
The meanings of these commands are:
PSL Manual 7 February 1983 Error Handling and Recovery
section 14.3 page 14.5
E Edit the value of ERRORFORM!*. This is the object printed in the
"Continuation requires a value for ..." message. The function
BreakEdit
BreakEdit
BreakEdit is the associated function called by this command. The
Retry
Retry
Retry command (below) uses the corrected version of ERRORFORM!*.
The currently available editors are described in Chapter 16.
BreakErrmsg
BreakErrmsg
M Show the modified ERRORFORM!*. Calls the function BreakErrmsg.
R Retry. This tries to evaluate the offending expression again,
and continue the computation. It evaluates the value of
ERRORFORM!*. This is often useful after defining a missing
Edit
Edit
function, assigning a value to a variable, or using the Edit
BreakRetry
BreakRetry
command, above. This command calls the function BreakRetry.
Break
Break
C This causes the expression last printed by the Break loop to be
returned as the value of the offending expression. This is often
useful as an automatic stub. If an expression containing an
Break
Break
undefined function is evaluated, a Break loop is entered, and
this may be used to return the value of the function call. This
BreakContinue
BreakContinue
command calls the function BreakContinue.
Break
Break
Q Quit. This exits the Break loop by throwing to the closest
ErrorSet BreakQuit
ErrorSet BreakQuit
surrounding ErrorSet. It calls the function BreakQuit.
A Abort. This aborts to the top level, i.e., restarts PSL. It
Reset
Reset
calls the function Reset.
T Trace. This prints a backtrace of function calls on the stack
except for those on the lists IGNOREDINBACKTRACE!* and
BackTrace
BackTrace
INTERPRETERFUNCTIONS!*. It calls the function BackTrace.
I Interpreter Trace. This prints a backtrace of only interpreted
functions call on the stack except for those on the list
InterpBackTrace
InterpBackTrace
INTERPRETERFUNCTIONS!*. It calls the function InterpBackTrace.
An attempt to continue a non-continuable error with R or C prints a message
and behaves as Q.
__________
IGNOREDINBACKTRACE!* [Initially: '(Eval Apply FastApply CodeApply
CodeEvalApply Catch ErrorSet EvProgN TopLoop BreakEval
______
BindEval Break Main)] global
A list of function names that will not be printed by the commands
Break
Break
I and T given within a Break loop.
__________ ______
INTERPRETERFUNCTIONS!* [Initially: '(Cond Prog And Or ProgN SetQ)] global
A list of function names that will not be printed by the command
Break
Break
I given within a Break loop.
Error Handling and Recovery 7 February 1983 PSL Manual
page 14.6 section 14.3
The above two globals can be reset in an init file if the programmer
desires to do so.
The following is a slightly edited transcript, showing some of the BREAK
options:
PSL Manual 7 February 1983 Error Handling and Recovery
section 14.3 page 14.7
% foo is an undefined function, so the following has two errors
% in it
1> (Plus2 (foo 1)(foo 2))
***** `FOO' is an undefined function {1001}
***** Continuation requires a value for `(FOO 1)'
Break loop
1 lisp break> (plus2 1 1) % We simply compute a value
2 % prints as 2
2 lisp break> c % continue with this value
% it returns to compute "(foo 2)"
***** `FOO' is an undefined function {1001}
***** Continuation requires a value for `(FOO 2)'
Break loop
1 lisp break> 3 % again compute a value
3
2 lisp break> c % and return
5 % finally complete
% Pretend that we had really meant to call "fee":
2> (de fee (x) (add1 x))
FEE
3> (plus2 (foo 1)(foo 2)) % now the bad expression
***** `FOO' is an undefined function {1001}
***** Continuation requires a value for `(FOO 1)'
Break loop
1 lisp break> e % lets edit it
Type HELP<CR> for a list of commands.
edit> p % print form
(FOO 1)
edit> (1 fee) % replace 1'st by "fee"
edit> p % print again
(FEE 1)
edit> ok % we like it
(FEE 1)
2 lisp break> m % show modified ErrorForm!*
ErrorForm!* : `(FEE 1)'
NIL
3 lisp break> r % Retry EVAL ErrorForm!*
***** `FOO' is an undefined function {1001}
***** Continuation requires a value for `(FOO 2)'
Break loop
1 lisp break> (de foo(x) (plus2 x 1)) % define foo
FOO
2 lisp break> r % and retry
5
Error Handling and Recovery 7 February 1983 PSL Manual
page 14.8 section 14.4
14.4. Interrupt Keys
14.4. Interrupt Keys
14.4. Interrupt Keys
Need to "LOAD INTERRUPT;" to enable. This applies only to the DEC20.
<Ctrl-T> indicates routine currently executing, gives the load average,
and gives the location counter in octal;
<Ctrl-G> returns you to the Top-Loop;
<Ctrl-B> takes you into a lower-level Break loop.
14.5. Details on the Break Loop
14.5. Details on the Break Loop
14.5. Details on the Break Loop
Break Error
Break Error
If the SWITCH !*BREAK is T, the function Break() is called by Error or
ContinuableError
ContinuableError
ContinuableError before unwinding the stacks, or printing a backtrace.
Break
Break
Input and output to/from Break loops is done from/to the values (channels)
of BREAKIN!* and BREAKOUT!*. The channels selected on entrance to the
Break
Break
Break loop are restored upon exit.
__________ ______
BREAKIN!* [Initially: NIL] global
Rds
Rds
So Rds chooses STDIN!*.
__________ ______
BREAKOUT!* [Initially: NIL] global
Similar to BREAKIN!*.
Break Read-Eval-Print
Break Read-Eval-Print
Break is essentially a Read-Eval-Print function, called in the error
context. Any FLUID may be printed or changed, function definitions
Break TopLoop
Break TopLoop
changed, etc. The Break uses the normal TopLoop mechanism (including
Catch TopLoop
Catch TopLoop
History), embedded in a Catch with tag !$BREAK!$. The TopLoop attempts to
use the parent loop's TOPLOOPREAD!*, TOPLOOPPRINT!* and TOPLOOPEVAL!*; the
BreakEval
BreakEval __
BreakEval function first checks top-level ids to see if they have a special
BREAKFUNCTION on their property lists, stored under 'BREAKFUNCTION. This
is expected to be a function of no arguments, and is applied instead of
Eval
Eval
Eval.
14.6. Some Convenient Error Calls
14.6. Some Convenient Error Calls
14.6. Some Convenient Error Calls
The following functions may be useful in user packages:
FatalError
FatalError _ ___ ____ ________ ____
(FatalError S:any): None Returned expr
PSL Manual 7 February 1983 Error Handling and Recovery
section 14.6 page 14.9
(ProgN (ErrorPrintF "***** Fatal error: %s" S)
(While T Quit))
RangeError
RangeError ______ ___ _____ _______ __ ________ ____ ________ ____
(RangeError Object:any Index:integer Fn:function): None Returned expr
(StdError (BldMsg "Index %r out of range for %p in %p"
Index Object Fn))
StdError
StdError _______ ______ ____ ________ ____
(StdError Message:string): None Returned expr
(Error 99 Message)
TypeError
TypeError ________ ___ __ ________ ___ ___ ____ ________ ____
(TypeError Offender:any Fn:function Typ:any): None Returned expr
(StdError (BldMsg "An attempt was made to do %p on %r,
which is not %w" Fn Offender Typ))
UsageTypeError
UsageTypeError ___ ___ __ ________ ___ ___ _____ ___ ____ ________ ____
(UsageTypeError Off:any Fn:function Typ:any Usage:any): None Returned expr
(StdError
(BldMsg "An attempt was made to use %r as %w in %p,
where %w is needed" Offender Usage Fn Typ))
IndexError
IndexError ________ ___ __ ________ ____ ________ ____
(IndexError Offender:any Fn:function): None Returned expr
(UsageTypeError Offender Fn "an integer" "an index")
NonPairError
NonPairError ________ ___ __ ________ ____ ________ ____
(NonPairError Offender:any Fn:function): None Returned expr
(TypeError Offender Fn "a pair")
NonIDError
NonIDError ________ ___ __ ________ ____ ________ ____
(NonIDError Offender:any Fn:function): None Returned expr
(TypeError Offender Fn "an identifier")
NonNumberError
NonNumberError ________ ___ __ ________ ____ ________ ____
(NonNumberError Offender:any Fn:function): None Returned expr
(TypeError Offender Fn "a number")
NonIntegerError
NonIntegerError ________ ___ __ ________ ____ ________ ____
(NonIntegerError Offender:any Fn:function): None Returned expr
Error Handling and Recovery 7 February 1983 PSL Manual
page 14.10 section 14.6
(TypeError Offender Fn "an integer")
NonPositiveIntegerError
NonPositiveIntegerError ________ ___ __ ________ ____ ________ ____
(NonPositiveIntegerError Offender:any Fn:function): None Returned expr
(TypeError Offender Fn "a non-negative integer")
NonCharacterError
NonCharacterError ________ ___ __ ________ ____ ________ ____
(NonCharacterError Offender:any Fn:function): None Returned expr
(TypeError Offender Fn "a character")
NonStringError
NonStringError ________ ___ __ ________ ____ ________ ____
(NonStringError Offender:any Fn:function): None Returned expr
(TypeError Offender Fn "a string")
NonVectorError
NonVectorError ________ ___ __ ________ ____ ________ ____
(NonVectorError Offender:any Fn:function): None Returned expr
(TypeError Offender Fn "a vector")
NonSequenceError
NonSequenceError ________ ___ __ ________ ____ ________ ____
(NonSequenceError Offender:any Fn:function): None Returned expr
(TypeError Offender Fn "a sequence")
14.7. Special Purpose Error Handlers
14.7. Special Purpose Error Handlers
14.7. Special Purpose Error Handlers
[??? This needs to be rethought and reimplemented. Currently not
[??? This needs to be rethought and reimplemented. Currently not
[??? This needs to be rethought and reimplemented. Currently not
installed. ???]
installed. ???]
installed. ???]
It is possible to handle errors specially. The value of
Error
_ ____ ____ Error
ERRORHANDLERS!* is an a-list of error number/handler pairs. If Error is
Car
Car
called with a number which appears as the Car of an element of
Cdr
Cdr
ERRORHANDLERS!*, its Cdr is taken to be a function of two variables, the
error number and the error message, which is called instead. If called
ContinuableError
ContinuableError
from ContinuableError with a non-NIL third argument, any value returned by
the error handler is returned as the value of the function call.
Throw
Throw
Otherwise, normal termination of the handler Throws to the closest
ErrorSet
ErrorSet
surrounding ErrorSet.