PLOGHELP ERROR Simon Nichols, October 1990 A description of the kinds of errors which may arise while using Prolog. CONTENTS - (Use g to access required sections) -- Introduction -- Syntax Errors -- Run-time Errors -- Interrupts -- Raising an Error -- Handling Errors -- Related Documentation -- Introduction ------------------------------------------------------- There are two classes of error message which can arise while compiling or running a Prolog program: syntax errors and general run-time errors. Syntax errors occur when reading a clause, usually at compile time. Broadly speaking, other errors occur during the execution of a Prolog program. -- Syntax Errors ------------------------------------------------------ If a clause, directive or general term read-in by the Prolog system does not comply with the syntax of POPLOG Prolog (see PLOGHELP * SYNTAX), the system prints a syntax error message, either on the terminal or in the output buffer if Prolog is being used from within VED. This will be the case whether clauses are being read by the Prolog compiler as part of a consult or reconsult (see PLOGHELP * CONSULT, * RECONSULT) or by a user program by means of a call to the evaluable predicate read/1 (or vread/2: see PLOGHELP * READ). As an example, given the incorrectly formed clause: append([X|List1], List2, [X|List3) :- append(List1, List2, List3). Prolog will respond with the following message: ;;; PROLOG SYNTAX ERROR - OPERATOR OR ']' EXPECTED IN LIST ;;; FOUND : ) ;;; READING: append ( [ X | List1 ] , List2 , [ X | List3 <> ) As you can see, three pieces of information are printed: a message describing the problem, the token at which the error was detected (the closing parenthesis in the above example) and the sequence of tokens which comprise the offending clause (or in general, term) including a mark "<>" which indicates where the error occurred. Having reported the syntax error, the Prolog system attempts to skip past the erroneous term and resume reading (unless the term is in a file being loaded from VED: see below). It does this with a rather simple heuristic: if reading from the terminal, it skips to the end of the line and resumes reading with the next line of input. If reading from a file, it attempts to find the end of the offending term by discarding tokens up to a clause terminator, the atom '.'. This may sometimes lead the Prolog system to re-start reading from the middle of a term, which will in all probability produce a further syntax error. If a file is loaded from inside VED (for example, using l or l1) the Prolog system behaves differently: it will stop after the first syntax error, thereby leaving the cursor near the point at which the error occurred. This is not the case for files consulted or reconsulted from immediate mode (see HELP * IM), since this is treated the same as the Prolog top level. -- Run-time Errors ---------------------------------------------------- General run-time errors may have a wide variety of causes: calling an evaluable predicate with arguments of the wrong type (e.g. trying to perform arithmetic on symbolic atoms), attempting to assert a clause for a system predicate, and so on. They can also be generated from user programs by use of the evaluable predicate error/2 (see below). The error messages have a similar form to syntax error messages, except that instead of the tokens comprising the erroneous clause being printed, the names of predicates active when the error occurred are displayed. For example, the goal: ?- functor(Term, foo, N). will result in the error message: ;;; PROLOG ERROR - INSUFFICIENT INSTANTIATION OF GOAL ;;; INVOLVING: functor(_1, foo, _2) ;;; DOING : functor/3 functor/3 As with a syntax error, three pieces of information are displayed: a description of the error, the term(s) which were involved in the error (usually the immediate goal which resulted in the error or the arguments to that goal) and the name of the predicate which was executing when the error occurred together with the name of the predicate which called that (if any) and so on back up the calling chain: this is called a "backtrace", because it traces the sequence of calls back up the calling chain. Note that the most recently executing predicate (i.e. the one in which the error occurred) is the first predicate printed after the "DOING" part of the message. The example above shows an error raised by evaluable predicates when they are called with their arguments insufficiently instantiated. The predicate functor/3 (see PLOGHELP * FUNCTOR) requires both its second and third arguments to be instantiated when its first argument is uninstantiated, and in the above call the third argument is a variable. You may have noticed that the backtrace shows functor/3 twice: the first occurrence is the POP-11 procedure which actually does the work; the second is the Prolog predicate which invokes it. Both are called functor/3. Because of optimisations performed by the POPLOG Prolog compiler, the backtrace will often not show a complete calling chain. In general, only predicates with an outstanding choice point will still be active (i.e. have stack frames on the call stack), so only these will appear in the backtrace. In addition, non-Prolog procedures (such as low-level POPLOG system procedures) will not usually be printed. This may not be what you want if you are writing mixed language programs involving Prolog. This behaviour can be altered by assigning an integer value to the POP-11 variable -popsyscall- (see HELP * POPSYSCALL and REF * POPSYSCALL): ?- prolog_setq(popsyscall, 1). or from POP-11 : 1 -> popsyscall; See PLOGHELP * MIXED_LANGUAGES for an introduction to mixed language programming using Prolog. Some errors may not print the "INVOLVING" part of the message: messages resulting from running out of memory are like this. After printing out the error message, Prolog behaves as if you had interrupted it by typing the operating system interrupt character: see the next section. -- Interrupts --------------------------------------------------------- When you type the operating system interrupt character (usually CTRL-C), Prolog immediately terminates the currently executing goal and prints the message: ;;; [execution aborted] If you are interacting with the Prolog top level interpreter, either from the terminal or in a VED immediate mode window, you will be returned to the Prolog top level, thus: Setprolog ?- You will then be able to type in another goal. If, one the other hand, you are using LMR (load marked range) from VED, the standard VED interrupt routine is ultimately invoked and you will stay in VED, with error messages being sent to the output buffer (by default the file named "output.pl"). See PLOGHELP * VED for information on interacting with Prolog from within VED. -- Raising an Error --------------------------------------------------- You can raise an error from within a Prolog program by the use of the evaluable predicate error/2, which has the general form: ?- error(Message, ListOfCulprits). where Message is an atom and ListOfCulprits is list of terms. The effect is exactly the same as an error raised by the Prolog system: the current computation is aborted and an error message as described above is displayed. As an example, the predicate sum_sqr/3 calculates the sum of the squares of two numbers: sum_sqr(X,Y,Z) :- (integer(X); float(X)), (integer(Y); float(Y)), !, Z is X * X + Y * Y. sum_sqr(X,Y,_) :- error('Numbers needed', [X, Y]). When called by the following goal: ?- sum_sqr(2,X,Y). it raises the error: ;;; PROLOG ERROR - Numbers needed ;;; INVOLVING: 2 _1 ;;; DOING : pop_setpop_compiler Note that there are no outstanding choice points for sum_sqr/2, which is why the backtrace only mentions a procedure called -pop_setpop_compiler- (the compiler invoked by POPLOG when it starts up). -- Handling Errors ---------------------------------------------------- Run-time errors, whether generated by the Prolog system or from your program by means of error/2, may be handled (i.e. trapped) by asserting clauses for the Prolog error handler prolog_error/2. See PLOGHELP * PROLOG_ERROR for a description of the error handler and how to trap errors. It is possible to raise untrappable errors by calling the evaluable predicate prolog_syserror/2, which has the same format as error/2, i.e. ?- prolog_syserror(Message, ListOfCulprits). The only difference from error/2 is that such errors bypass the Prolog error handler. -- Related Documentation ---------------------------------------------- PLOGHELP * DEBUG Overview of the debugging facilities provided by POPLOG Prolog PLOGHELP * PROLOG_ERROR Description of the Prolog run-time error-handler --- C.all/plog/help/error --- Copyright University of Sussex 1990. All rights reserved. ----------