\section{Errors} \label{sec:errors} Errors are abnormalities that are detected during a programs execution. Errors may be caused by bugs in \product{}, bugs in the application program and finally by the application user making errors in operating the application (e.g. specifying a protected file). Errors may also be discriminated according to their `seriousness': If a certain font cannot be found it can easily be substituted by another. If a method expects an integer argument but the actual argument is a graphical object it is impossible to carry-out the operation. In such cases \product{} will normally trap the tracer. If the user decides to continue execution the method will return failure to its caller. Finally, some problems are categorised as `fatal'. When such a problem is encountered \product{} does not know how execution can be continued. All errors (except for some that may result from \product{} bugs during the boot phase of \product{}) are represented by an \class{error} object. An error object has the following properties: \begin{itemize} \tick{id} Unique identifier name of the error. It may be used to generate errors; look-up error objects in the @errors database or catch errors (see pce_catch_error/2). \tick{kind} The kind describes how serious the error is considered to be. The possible values are: {\em ignored} if the error is (currently) not regarded an error at all; {\em warning} if the error is to be reported, but no further action is required; {\em error} if the error is to be fixed. After printing the error the system will start the tracer, allowing a programmer to examine the problem context. Finally, {\em fatal} errors do not allow execution to be continued. The system will print context information and request Prolog to abort back to the Prolog interactive top level. \tick{feedback} Determines how the error is to be reported. If \const{print} the error is printed in the Prolog window. If \const{report} the error is reported using the report mechanism described in \secref{report}. The `report' mechanism is for errors that may be caused by application users, for example file errors. If \const{throw} and there is a Prolog goal on the stack, the error is mapped to a Prolog exception. See below. In the \idx{runtime-system}, all errors use feedback `report'. \tick{format} A format specification to construct a message text from the context arguments provided by the generator of the error. \end{itemize} \index{error,description of}% The online manual ``Errors Browser'' may be used to examine the defined errors; change attributes of errors and get precise description of errors. \subsection{Handling errors in the application} \index{errors,catching}\index{catch,errors}% Sometimes the application wants to anticipate on certain errors. Explicit testing of all conditions is a cumbersome solution to this problem. Therefore \product{} allows catching of errors by the application. There are two mechanism available to do this. Regardless of the `error<-feedback' type of the error, all except fatal errors can be silenced using pce_catch_error/2: \begin{description} \predicate{pce_catch_error}{2}{+ErrorSpec, :Goal} Run \arg{Goal} like once/1. It an error matching \arg{ErrorSpec} is raised, this error is not reported, but stored in `@pce<-last_error'. \arg{ErrorSpec} is the <-id of an error, a chain holding error-ids or @default. The latter implies none but fatal errors are reported. The example below silently ignores errors from creating a backup of \arg{File}. Note that the call does fail if backup raises an error. \begin{code} ..., pce_catch_error(backup_file, send(File, backup)), ... \end{code} \end{description} If the <-feedback of the error is \const{throw} and the error is not silenced with pce_catch_error/2 it is mapped to a Prolog exception of the form \begin{quote} \term{error}{\term{pce}{Id, ContextArgs}, Goal} \end{quote} For example: \begin{code} ?- catch(send(@pce, foobar), E, true). E = error(pce(no_behaviour, [@pce/pce, (->), foobar]), send(@pce/pce, foobar)) \end{code} \subsection{Raising errors} The application programmer may define new (application specific) errors. The error object is a normal \product{} object and may thus be created using new/2. An error is raised by invoking `object ->error'. The example below illustrates this: \begin{code} :- new(_, error(no_user, '%N: Unknown user: %s', warning, report)). ..., ( get(UserDatabase, user, Name) -> ... ; send(UserDatabase, error, no_user, Name) ), ... \end{code} Note that the names of errors should be unique. It is advised to reuse existing error-id's if possible. \subsection{Repairable errors} \index{exception}% On trapping certain `repairable` errors, \product{} will first raise an {\em exception}. Exceptions may be trapped by an {\em exception handler} which may solve the problem. If the exception-handler fails to solve the problem, \product{} will raise an {\em error}. See \secref{errors}. Exceptions are raised by invoking `@pce ->exception: id, arg ...'. Exception handlers are registered in the sheet `@pce ->exception_handlers', which maps an exception-id onto a code object that handles the exception. The following illustrates this: \begin{code} 1 ?- [user]. |: add_user(Name) :- write(Name), nl. ^D 2 ?- send(@pce?exception_handlers, value, no_user, message(@prolog, add_user, @arg1)). 3 ?- send(@pce, exception, no_user, fred). fred \end{code} The {\em context arguments} passed with an exception are defined by the code raising the exception. The currently defined exceptions are listed below. See also the online manual: `pce->exception' and `pce <-exception_handlers'. \begin{itemize} \tick{undefined_class} \index{class,undefined}\index{undefined,class}% An attempt is made to reference a non-existing class while doing one of the following: create an object; load an object from file using `File <-object'; create a subclass. @arg1 is bound to the class-name. This trap is used by pce_autoload/2, as well as by the code that realises compiled classes. \tick{undefined_assoc} \index{assoc,undefined}\index{undefined,object reference}% An attempt is made to resolve a symbolic reference (i.e. @pce), but the reference is unknown. @arg1 is bound to the missing reference name. This trap is used by pce_global/2. \tick{redefined_assoc} \index{assoc,redefined}\index{redefined,object reference}% An attempt is made to create an object with the same symbolic reference as an already existing object. @arg1 is bound to the already existing reference name. This trap is used by \pllib{pce_renew}. \tick{initialisation_failed} \index{new,failed}\index{initialisation,failed}% The ->initialisation method for some instance failed. @arg1 is bound to the (partial) instance; @arg2, ... are bound to the arguments given to the new-operation. \end{itemize}