;;; -*- Mode:gate; Fonts:(HL12 HL12I HL12B CPTFONTB HL12BI HL12B HL12I ) -*-

=Node: Introduction

=Text:
3INTRODUCTION*

     The first portion of this chapter explains how programs can handle errors, by means of condition
handlers.  It also explains how a program can signal an error if it detects something it doesn't like.

     The second explains how users can handle errors, by means of an interactive debugger; that is,
it explains how to recover if you do something wrong.  A new user of the Lisp Machine, or someone
who just wants to know how to deal with errors and not how to cause them, should ignore the first
sections and skip ahead to 4(DEBUGGING-4)The Debugger*.

     The remaining sections describe some other debugging facilities.  Anyone who is going to be
writing programs for the Lisp Machine should familiarize himself with these.

     The 1trace* facility provides the ability to perform certain actions at the time a function is called
or at the time it returns.  The actions may be simple typeout, or more sophisticated debugging
functions.

     The 1advise* facility is a somewhat similar facility for modifying the behavior of a function.

     The 1breakon* facility allows you to cause the debugger to be entered when a certain function is
called.  You can then use the debugger's stepping commands to step to the next function call or
return.

     The 1step* facility allows the evaluation of a form to be intercepted at every step so that the
user may examine just what is happening throughout the execution of the form.  Stepping works only
on interpreted code.

     The 1MAR* facility provides the ability to cause a trap on any memory reference to a word (or a
set of words) in memory.  If something is getting clobbered by agents unknown, this can help track
down the source of the clobberage.

=Node: 4Conditions*

=Text:
3CONDITIONS*

     Programmers often want to control what action is taken by their programs when errors or other
exceptional situations occur.  Usually different situations are handled in different ways, and in order
to express what kind of handling each situation should have, each situation must have an associated
name.  In Zetalisp, noteworthy events are represented by objects called 1condition instances*.  When
an event occurs, a condition instance is created; it is then 1signaled*, and a 1handler* for that condition
may be invoked.

     When a condition is signaled, the system (essentially) searches up the stack of nested function
invocations looking for a handler established to handle that condition.  The handler is a function that
gets called to deal with the condition.  The condition mechanism itself is just a convenient way for
finding an appropriate handler function for a particular exceptional situation.

     When a condition is signaled, a 1condition instance* is created to represent the event and hold
information about it.  This information includes 1condition names* then classify the condition and any
other data that is likely to be of interest to condition handlers.  A condition instance is immutable
once it has been created.  Some conditions are 1errors*, which means that the debugger is invoked if
they are signaled and not handled.

     Condition instances are flavor instances.  The flavor 2condition* is the base flavor from which all
flavors of condition are built.  Several operations that are defined on condition instances are
described below.  The flavor 2error*, which is built on 2condition*, is the base flavor for all kinds of
conditions which are errors.  A 1condition name* is a symbol then is used to identify a category of
conditions.  Each condition instance possesses one or more condition names.  Each condition handler
specifies one or more condition names that it should apply to.  A handler applies to a condition if
they have any condition names in common.  This is the sole purpose of condition names:  to match
condition instances with their handlers.  The meaning of every condition name signaled by the
system is described in this manual.  The condition name index is a directory for them.  Conditions
that are errors possess the condition name 2error*.

     In PL/I, CLU, ADA and most other systems that provide named conditions, each condition has
only one name.  That is to say, the categories identified by condition names are disjoint.  In Zetalisp,
each condition instance can have multiple condition names, which means that the categories identified
by condition names can overlap and be subdivided.

     For example, among the condition names defined by the system are 2condition*, 2error*,
2sys:arithmetic-error*, 2sys:floating-exponent-underflow* and 2sys:divide-by-zero*.  2condition* is a
condition name that all condition instances possess.  2error* identifies the category of conditions that
are considered errors.  2sys:arithmetic-error* identifies the category of errors that pertain to arithmetic
operations.  2sys:floating-exponent-underflow* and 2sys:divide-by-zero* are the most specific level of
categorization.  So, the condition signaled when you evaluate 2(* 1s-30 1s-30 1s-30 1s-30)*
possesses condition names 2sys:floating-exponent-underflow*, 2sys:arithmetic-error*, 2error* and
2condition*, while the one signaled if you evaluate 2(// 1 0)* possesses condition names
2sys:divide-by-zero*, 2sys:arithmetic-error*, 2error* and 2condition*.  In this example, the categories fall into
a strict hierarchy, but this does not need to be the case.

     Condition names are documented throughout the manual, with definitions like this:

3sys:divide-by-zero* (3sys:arithmetic-error* 3error*)                               1Condition*        
        The condition name 2sys:divide-by-zero* is always accompanied by 2sys:arithmetic-error* and
        2error* (that is, it categorizes a subset of those categories).  The presence of 2error* implies that
        all 2sys:divide-by-zero* conditions are errors.  

     The condition instance also records additional information about the event.  For example, the
condition instance signaled by dividing by zero handles the 2:function* operation by returning the
function that did the division (it might be 2truncate*, 2floor*, 2ceiling* or 2round*, as well as 2//*).  In general,
for each condition name there are conventions saying what additional information is provided and
what operations to use to obtain it.

     The flavor of the condition instance is always one of the condition names, and so are its
component flavors (with a few exceptions; 2si:vanilla-flavor* and some other flavor components are
omitted, since they are not useful categories for condition handlers to specify).  In our example, the
flavor of the condition is 2sys:arithmetic-error*, and its components include 2error* and 2condition*.
Condition names require new flavors only when they require significantly different handling by the
error system; you will understand in detail after finishing this section.

3condition-typep* 1condition-instance* 1condition-name*                                                     
        Returns 2t* if 1condition-instance* possesses condition name 1condition-name*.  1condition-name*
        can also be a combination of condition names using 2and*, 2or* and 2not*; then the condition tested
        for is a boolean combination of the presence or absence of various condition names.
        Example:  

                3(condition-typep error 'fs:file-not-found)*
                3(condition-typep error *
                3   '(or fs:file-not-found fs:directory-not-found))

errorp* 1object*                                                                                                   
        Returns 2t* if 1object* is a condition instance and its flavor incorporates 2error*.  This is normally
        equivalent to 2(typep 1object* 'error)*.  Some functions such as 2open* optionally return the
        condition instance rather than signaling it, if an error occurs.  2errorp* is useful in testing the
        value returned.  

3:condition-names*                                                           1Operation on 2condition**        
        Returns a list of all the condition names possesses by this condition instance.  

=Node: 4Handling Conditions*

=Text:
3HANDLING CONDITIONS*

     A condition handler is a function that is associated with certain condition names (categories of
conditions).  The variable 2eh:condition-handlers* contains a list of the handlers that are current;
handlers are established using macros which bind this variable.  When a condition is signaled, this list
is scanned and all the handlers which apply are called, one by one, until one of the handlers either
throws or returns non-2nil*.

     Since each new handler is pushed onto the front of 2eh:condition-handlers*, the
innermost-established handler gets the first chance to handle the condition.  When the handler is run,
2eh:condition-handlers* is bound so that the running handler (and all the ones that were established
farther in) are not in effect.  This avoids the danger of infinite recursion due to an error in a handler
invoking the same handler.

     One thing a handler can do is throw to a tag.  Often the 2catch* for this tag is right next to the
place where the handler is established, but this does not have to be so.  A simple handler that
applies to all errors and just throws to a tag is established using 2ignore-errors*.

3ignore-errors* 1body...*                                                                          1Macro*        
        An error within the execution of 1body* causes control to return from the 2ignore-errors* form.  In
        this case, the values are 2nil*, 2t*.  If there is no error inside 1body*, the first value is that of the
        last form in the 1body* and the second is 2nil*.

        Errors whose condition instances return true for the 2:dangerous-condition-p* operation are not
        handled.  These include such things as running out of virtual memory.  

     A handler can also signal another condition.  For example, signaling 2sys:abort* has the effect of
pretending that the user typed the 2Abort* key.  The following function creates a handler which signals
2sys:abort*.

3si:eval-abort-trivial-errors* 1form*                                                                    
        Evaluates 1form* with a condition handler for many common error conditions such as
        2:wrong-type-argument*, 2:unbound-variable* and 2:unclaimed-message*.  The handler asks the
        user whether to allow the debugger to be entered.  If the user says `no', the handler signals
        the 2sys:abort* condition.  If the user says `yes', the handler does not handle the condition,
        allowing the debugger to do so.

        In some cases the handler attempts to determine whether the incorrect variable, operation, or
        argument appeared in 1form*; if it did not, the debugger is always allowed to run.  The
        assumption is that 1form* was typed in by the user, and the intention is to distinguish trivial
        mistakes from program bugs.  

     The handler can also ask to proceed from the condition.  This is done by returning a non-2nil*
value.  See the section on proceeding, 4(DEBUGGING-3)Proceeding*, for more information.

     The handler can also decline to handle the condition, by returning 2nil*.  Then the next applicable
handler is called, and so on until either some handler does handle the condition or there are no more
handlers.

     The handler function is called in the environment where the condition was signaled, and in the
same stack group.  All special variables have the values they had at the place where the signaling
was done, and all catch tags that were available at the point of signaling may be thrown to.

     The handler receives the condition instance as its first argument.  When establishing the handler,
you can also provide additional arguments to pass to the handler when it is called.  This allows the
same function to be used in varying circumstances.

     The fundamental means of establishing a condition handler is the macro 2condition-bind*.

3condition-bind* 1(handlers...)* 1body...*                                                          1Macro*        
3condition-bind-default* 1(handlers...)* 1body...*                                                              
        A 2condition-bind* form looks like this:  

                3(condition-bind ((1conditions* 1handler-form* 1additional-arg-forms*...)*
                3                 (1conditions* 1handler-form* 1additional-arg-forms*...))*
                3  1body*...)*

        The purpose is to execute 1body* with one or more condition handlers established.

        Each list of conditions and handler-form establishes one handler.  1conditions* is a condition
        name or a list of condition names to which the handler should apply.  It is 1not* evaluated.
        1handler-form* is evaluated to produce the function that is the actual handler.  The
        1additional-arg-forms* are evaluated, on entry to the 2condition-bind*, to produce additional
        arguments that are passed to the handler function when it is called.  The arguments to the
        handler function are the condition instance being signaled, followed by the values of any
        1additional-arg-forms*.

        1conditions* can be 2nil*; then the handler applies to all conditions that are signaled.  In this case
        it is up to the handler function to decide whether to do anything.  It is important for the
        handler to refrain from handling certain conditions that are used for debugging, such as 2break*
        and 2eh:call-trap*.  The 2:debugging-condition-p* operation on condition instances returns non-2nil*
        for these conditions.  Certain other conditions such as 2sys:virtual-memory-overflow* should
        be handled only with great care.  The 2:dangerous-condition-p* operation returns non-2nil* for
        these conditions.  Example:

                3(condition-bind ((nil 'myhandler "it happened here" 45))*
                3  (catch 'x*
                3    ...))*

                3(defun myhandler (condition string value)*
                3  (unless (or (condition-typep condition 'fs:file-error)*
                3              (send condition :dangerous-condition-p)*
                3              (send condition :debugging-condition-p))*
                3    (format error-output "~&~A:~%~A~%" string condition)*
                3    (throw 'x value)))*

        2myhandler* declines to handle file errors, and all debugging conditions and dangerous errors.
        For all other conditions, it prints the string specified in the condition bind and throws to the
        tag 2x* the value specified there (45).

        2condition-bind-default* is like 2condition-bind* but establishes a 1default* 1handler* instead of an
        ordinary handler.  Default handlers work like ordinary handlers, but they are tried in a different
        order:  first all the applicable ordinary handlers are given a chance to handle the condition, and
        then the default handlers get their chance.  A more flexible way of doing things like this is
        described under 2signal-condition* (4(DEBUGGING-2)Signaling a Condition Instance*).  

     Condition handlers that simply throw to the function that established them are very common, so
there are special constructs provided for defining them.

3condition-case* 1(variables...)* 1body-form* 1clauses...*                                          1Macro*        

                3(condition-case (1variable*)*
                3    1body-form**
                3  (1condition-names* 1forms*...)*
                3  (1condition-names* 1forms*...)*
                3  ...)*

        1body-form* is executed with a condition handler established that will throw back to the
        2condition-case* if any of the specified condition names is signaled.

        Each list starting with some condition names is a 1clause*, and specifies what to do if one of
        those condition names is signaled.  1condition-names* is either a condition name or a list of
        condition names; it is not evaluated.

        Once the handler per se has done the throw, the clauses are tested in order until one is
        found that applies.  This is almost like a 2selectq*, except that the signaled condition can have
        several condition names, so the first clause that matches any of them gets to run.  The
        forms in the clause are executed with 1variable* bound to the condition instance that was
        signaled.  The values of the last form in the clause are returned from the 2condition-case* form.

        If none of the specified conditions is signaled during the execution of 1body-form* (or if other
        handlers, established within 1body-form*, handle them) then the values of 1body-form* are
        returned from the 2condition-case* form.

        1variable* may be omitted if it is not used.

        It is also possible to have a clause starting with 2:no-error* in place of a condition name.  This
        clause is executed if 1body-form* finishes normally.  Instead of just one 1variable* there can be
        several variables; during the execution of the 2:no-error* clause, these are bound to the values
        returned by 1body-form*.  The values of the last form in the clause become the values of the
        2condition-case* form.

        Here is an example:  

                3(condition-case ()*
                3    (print foo)*
                3  (error (format t " <<Error in printing>>")))

condition-call* 1(variables...)* 1body-form* 1clauses...*                                          1Macro*        
        2condition-call* is an extension of 2condition-case* that allows you to give each clause an
        arbitrary conditional expression instead of just a list of condition names.  It looks like this:  

                3(condition-call (1variables*...)*
                3    1body-form**
                3  (1test* 1forms*...)*
                3  (1test* 1forms*...)*
                3  ...)*

        The difference between this and 2condition-case* is the 1test* in each clause.  The clauses in a
        2condition-call* resemble the clauses of a 2cond* rather than those of a 2selectq*.

        When a condition is signaled, each 1test* is executed while still within the environment of the
        signaling (that is, within the actual handler function).  The condition instance can be found in
        the first 1variable*.  If any 1test* returns non-2nil*, then the handler throws to the 2condition-call*
        and the corresponding clause's 1forms* are executed.  If every 1test* returns 2nil*, the condition is
        not handled by this handler.

        In fact, each 1test* is computed a second time after the throw has occurred in order to decide
        which clause to execute.  The code for the 1test* is copied in two different places, once into
        the handler function to decide whether to throw, and once in a 2cond* which follows the catch.

        The last clause can be a 2:no-error* clause just as in 2condition-case*.  It is executed if the
        body returns without error.  The values returned by the body are stored in the 1variables*.
        The values of the last form in the 2:no-error* clause are returned by the 2condition-call*.

        Only the first of 1variables* is used if there is no 2:no-error* clause.  The 1variables* may be
        omitted entirely in the unlikely event that none is used.  Example:  

                3(condition-call (instance)*
                3    (do-it)*
                3  ((condition-typep instance*
                3     '(and fs:file-error (not fs:no-more-room)))*
                3   (compute-what-to-return)))*

        The condition name 2fs:no-more-room* is a subcategory of 2fs:file-error*; therefore, this handles
        all file errors 1except* for 2fs:no-more-room*.  

     Each of the four condition handler establishing constructs has a conditional version that decides
at run time whether to establish the handlers.

3condition-bind-if* 1cond-form* 1(handlers...)* 1body...*                                         1Macro*        

                3(condition-bind-if 1cond-form**
                3                   ((1conditions* 1handler-form* 1additional-arg-forms*...)*
                3                    (1conditions* 1handler-form* 1additional-arg-forms*...))*
                3  1body*...)*

        begins by executing 1cond-form*.  If it returns non-2nil*, then all proceeds as for a regular
        2condition-bind*.  If 1cond-form* returns 2nil*, then the 1body* is still executed but without the
        condition handler.  

3condition-case-if* 1cond-form* 1(variables...)* 1body-form* 1clauses...*                         1Macro*        

                3(condition-case-if 1cond-form* (1variables*...)*
                3    1body-form**
                3  (1condition-names* 1forms*...)*
                3  (1condition-names* 1forms*...)*
                3  ...)*

        begins by executing 1cond-form*.  If it returns non-2nil*, then all proceeds as for a regular
        2condition-case*.  If 1cond-form* returns 2nil*, then the 1body-form* is still executed but without the
        condition handler.  1body-form*'s values are returned, or, if there is a 2:no-error* clause, it is
        executed and its values returned.  

3condition-call-if* 1cond-form* 1([variable])* 1body-form* 1clauses...*                         1Macro*        

                3(condition-call-if 1cond-form* (1variables*...)*
                3    1body-form**
                3  (1test* 1forms*...)*
                3  (1test* 1forms*...)*
                3  ...)*

        begins by executing 1cond-form*.  If it returns non-2nil*, then everything proceeds as for a
        regular 2condition-call*.  If 1cond-form* returns 2nil*, then the 1body-form* is still executed but without
        the condition handler.  In that case, 1body-form*'s values are returned, or, if there is a 2:no-error*
        clause, it is executed and its values returned.  

3condition-bind-default-if* 1cond-form* 1(handlers...)* 1body...*                             1Macro*        
        This is used just like 2condition-bind-if*, but establishes a default handler instead of an
        ordinary handler.  

3eh:condition-handlers*                                                                    1Variable*        
        This is the list of established condition handlers.  Each element looks like this:  

                3(1condition-names* 1function* 1additional-arg-values*...)*

        1condition-names* is a condition name or a list of condition names, or 2nil* which means all
        conditions.

        1function* is the actual handler function.

        1additional-arg-values* are additional arguments to be passed to the 1function* when it is called.
        1function*'s first argument is always the condition instance.

        Both the links of the value of 2eh:condition-handlers* and the elements are usually created with
        2with-stack-list*, so copy them if you want to save them for any period of time.  

3eh:condition-default-handlers*                                                        1Variable*        
        This is the list of established default condition handlers.  The data format is the same as that
        of 2eh:condition-handlers*.  

=Node: 4Standard Condition Flavors*

=Text:
3STANDARD CONDITION FLAVORS

condition*                                                                                        1Flavor*        
        The flavor 2condition* is the base flavor of all conditions, and provides default definitions for
        all the operations described in this chapter.

        2condition* incorporates 2si:property-list-mixin*, which defines operations 2:get* and 2:plist*.  Each
        property name on the property list is also an operation name, so that sending the 2:foo*
        message is equivalent to 2(send instance :get :foo)*.  In addition, 2(send instance :set :foo*
        1value2)** is equivalent to 2(send instance :set :get :foo 1value*)*.

        2condition* also provides two instance variables, 2eh:format-string* and 2eh:format-args*.
        2condition*'s method for the the 2:report* operation passes these to 2format* to print the error
        message.  

3error*                                                                                              1Flavor*        
        The flavor 2error* makes a condition an error condition.  2errorp* returns 2t* for such conditions,
        and the debugger is entered if they are signaled and not otherwise handled.  

3sys:no-action-mixin*                                                                         1Flavor*        
        This mixin provides a definition of the proceed type 2:no-action*.  

3sys:proceed-with-value-mixin*                                                            1Flavor*        
        This mixin provides a definition of the proceed type 2:new-value*.  

3ferror*                                                                                             1Flavor*        
        This flavor is a mixture of 2error*, 2sys:no-action-mixin* and 2sys:proceed-with-value-mixin*.  It is
        the flavor used by default by the functions 2ferror* and 2cerror*, and is often convenient for
        users to instantiate.  

3sys:warning*                                                                                     1Flavor*        
        This flavor is a mixture of 2sys:no-action-mixin* and 2condition*.  

3sys:bad-array-mixin*                                                                         1Flavor*        
        This mixin provides a definition of the proceed type 2:new-array*.  

