Error Handling

Error Implementation through error descriptors.

Top-level Prolog code to support error-handling.

  • The process is as follows:

  • Input the error from Prolog or C-code

  • Complete the descriptor with state information

  • Export the result either as a term or as a C-structure.

  • The key routines are:

  • Yap_ThrowError(): create an error descriptor and jump to the closest C longjmp handler.

  • ErrorFromProlog(): try to discriminate between a throw and an system error; if an error doThrowError().

Also included are exception manipulation routines and higher level error handlers, based on pl/error.yap. See include/YapError.h for a definition of data-strEuctures, and include/YapErrors.h for a list of implementation supported exceptions.

  • Exception LifeCycle

Exceptions are a dictionary that includee exception type, location, culprit, and user-defined. They start in the bottom stage, so that they: 1. complete the dictionary;

  1. force a throw to the exception handler;

  2. close the bottom-half and move to the top-half.

The top-half is Prolog code

The error handler is called when there is an execution error or a warning needs to be displayed. The handlers include a number of hooks to allow user-control.

Errors are terms of the form:

  • error( domain_error( Domain, Culprit )

  • error( evaluation_error( Expression, Culprit )

  • error( existence_error( Object, Culprit )

  • error( instantiation_error )

  • error( permission_error( Error, Permission, Culprit)

  • error( representation_error( Domain, Culprit )

  • error( resource_error( Resource, Culprit )

  • error( syntax_error( Error )

  • error( system_error( Domain, Culprit )

  • error( type_error( Type, Culprit )

  • error( uninstantiation_error( Culprit )`

Other types of terms result in a message.

Define:

1. set_key_b:

1. set_key_i:

1. set_key_s:

1. set_key_t:

1. query_key_b:

1. query_key_i:

1. query_key_s:

1. query_key_t:

1. YAP_BUF_SIZE:

1. BEGIN_ERROR_CLASSES:

1. BEGIN_ERROR_CLASSES:

1. BEGIN_ERROR_CLASSES:

1. END_ERROR_CLASSES:

1. END_ERROR_CLASSES:

1. END_ERROR_CLASSES:

1. ECLASS:

1. ECLASS:

1. ECLASS:

1. BEGIN_ERRORS:

1. BEGIN_ERRORS:

1. BEGIN_ERRORS:

1. END_ERRORS:

1. END_ERRORS:

1. END_ERRORS:

1. /0:

1. /0:

1. /0:

1. E:

1. E:

1. E:

1. /1:

1. /1:

1. /1:

1. ES:

1. ES:

1. ES:

1. /2:

1. /2:

1. /2:

Functions:

1. void Yap_RestartYap(int flag):

1. static bool setErr(const char q, yap_error_descriptor_t i, Term t):

1. static Term queryErr(const char q, yap_error_descriptor_t i):

1. static void print_key_b(FILE of, const char key, bool v):

1. static void print_key_i(FILE of, const char key, YAP_Int v):

1. static void print_key_s(FILE of, const char key, const char *v):

1. static void print_key_t(FILE of, const char key, YAP_Term v):

1. static void printErr(yap_error_descriptor_t i, FILE out):

1. static YAP_Term add_key_b(const char *key, bool v, YAP_Term o0):

1. static YAP_Term add_key_i(const char *key, YAP_Int v, YAP_Term o0):

1. static YAP_Term add_key_s(const char key, const char v, YAP_Term o0):

1. static YAP_Term add_key_t(const char *key, YAP_Term v, YAP_Term o0):

1. static Term err2list(yap_error_descriptor_t *i):

1. void Yap_do_warning__(const char file, const char function, int line, yap_error_number type, Term t, const char *fmt,...):

1. bool Yap_Warning(const char *s,...):

1. bool Yap_PrintWarning(Term twarning, Term level):

1. bool Yap_HandleError__(const char file, const char function, int lineno, const char *s,...):

1. int Yap_SWIHandleError(const char *s,...):

1. static void error_exit_yap(int value):

1. Term Yap_MkErrorTerm(yap_error_descriptor_t *i):

1. yap_error_descriptor_t * Yap_pushErrorContext(bool link, yap_error_descriptor_t new_error, yap_error_descriptor_t old_error): : add a new error descriptor, either to the top of the stack, or as the top;

1. yap_error_descriptor_t * Yap_popErrorContext(bool mdnew, bool pass, yap_error_descriptor_t *old_error):

1. void Yap_ThrowError__(const char file, const char function, int lineno, yap_error_number type, Term where, const char *msg,...): : Thow an error directly to the error handler.

filewhere functionwho linenowhen typewhat, error code wherehow, user information

1. void Yap_ThrowExistingError(void): : complete delayed error.

1. Term MkSysError(yap_error_descriptor_t *i): : Wrap the error descriptor as exception/2.

1. bool Yap_MkErrorRecord(yap_error_descriptor_t r, const char file, const char function, int lineno, yap_error_number type, Term where, Term extra, const char s):

1. Term Yap_MkFullError(yap_error_descriptor_t *i, yap_error_number type): : convert a C-error to a Prolog term:

  • fill text fields

  • wrap descriptor1240

1. yamop * Yap_Error__(bool throw, const char file, const char function, int lineno, yap_error_number type, Term where, const char *fmt,...): : Yap_Error() This function handles errors in the C code.

Check errors.yap for the corresponding Prolog code.

fileC source functionC function linenoC exact line typethe error ID (in YAP this is a single integer) wherethe culprit return:
usually FAILCODE

In a good day, the error handler's job is to generate a throw. This includes:

  • constructing an ISO style error term;

  • constructing a list with all available info on the bug

  • generating the throw

  • forcing backtracking in order to restart. 4 In a bad day, it has to deal with OOM, abort, and errors within errorts.

1. static Int close_error(USES_REGS1):

1. char * Yap_errorName(yap_error_number e):

1. char * Yap_errorNam/2(yap_error_number e):

1. yap_error_class_number Yap_errorClass(yap_error_number e):

1. yap_error_class_number Yap_errorClassNumber(const char *s):

1. char * Yap_errorClassName(yap_error_class_number e):

1. static Int reset_exception(USES_REGS1):

1. yap_error_descriptor_t * Yap_PeekException(void): : Notice that if the argument is an error descriptor, and you pass NULL, they always expect it to refer the current Active error descriptor.

is an error active?

1. yap_error_descriptor_t * Yap_GetException(void): : clone Active Error

1. void Yap_PrintException(yap_error_descriptor_t *i): : print descriptor to user_output/stdout

1. bool Yap_RaiseException(): : let's go.

1. bool Yap_ResetException(yap_error_descriptor_t *i): : v * clean up (notice that the code ensures ActiveError exists on exit.

1. bool Yap_RestartException(yap_error_descriptor_t *i): : clean up (notice that the code ensures ActiveError exists on exit.

1. static Int read_exception(USES_REGS1): : transform an exception into Prolog shape (dictionary or list)

1. static Int print_exception(USES_REGS1):

1. static Int query_exception(USES_REGS1):

1. static Int set_exception(USES_REGS1):

1. static Int drop_exception(USES_REGS1):

1. static Int new_exception(USES_REGS1):

1. static Int user_exception(USES_REGS1):

1. bool Yap_get_exception(void):

1. yap_error_number Yap_errorNumber(yap_error_class_number c, const char s, const char s2): : given a string(s, lookup for a corresponding error class r numbe

given a string(s) and class context, lookup for a corresponding error number

1. yap_error_descriptor_t * event(Term t, yap_error_descriptor_t *i):

1. Int is_nonvar__(const char file, const char function, int lineno, Term t USES_REGS):

1. static Int is_nonva/1(USES_REGS1): : "is_nonvar(T" )

@class is_nonvar_1

True if the term T has been instantiated, otherwise causs an exception. The same as must_be_bound_49 "must_be_bound/1".

1. bool is_boolean__(const char file, const char function, int lineno, Term t USES_REGS):

1. bool is_codes__(const char file, const char function, int lineno, Term t USES_REGS):

1. static Int is_boolea/1(USES_REGS1):

1. bool must_be_boolean__(const char file, const char function, int lineno, Term t USES_REGS):

1. static Int must_be_boolea/1(USES_REGS1):

1. bool is_atom__(const char file, const char function, int lineno, Term t USES_REGS):

1. static Int is_ato/1(USES_REGS1):

1. bool must_be_arity__(const char file, const char function, int lineno, Term t USES_REGS):

1. static Int must_be_arit/1(USES_REGS1):

1. bool must_be_atom__(const char file, const char function, int lineno, Term t USES_REGS):

1. static Int must_be_ato/1(USES_REGS1):

1. bool must_be_string__(const char file, const char function, int lineno, Term t USES_REGS):

1. static Int must_be_strin/1(USES_REGS1):

1. bool must_be_char__(const char file, const char function, int lineno, Term t USES_REGS):

1. static Int must_be_cha/1(USES_REGS1):

1. bool must_be_code__(const char file, const char function, int lineno, Term t USES_REGS):

1. static Int must_be_cod/1(USES_REGS1):

1. bool is_list__(const char file, const char function, int lineno, Term list USES_REGS):

1. static Int is_lis/1(USES_REGS1):

1. bool must_be_list__(const char file, const char function, int lineno, Term list USES_REGS):

1. static Int must_be_lis/1(USES_REGS1):

1. Int callable(USES_REGS1):

1. bool is_callable__(const char file, const char function, int lineno, Term t USES_REGS):

1. static Int is_callabl/1(USES_REGS1):

1. bool Yap_callable(Term t):

1. bool Yap_must_be_callable(Term G, Term mod):

1. static Int must_be_callabl/1(USES_REGS1):

1. void Yap_must_be_list(Term t): : Dereferenced term t must start as a list:

  • []

  • [_|_]

no effort is made to verify if a true list

1. static Int must_be_boun/1(USES_REGS1):

1. static Int must_be_groun/1(USES_REGS1):

1. static Int must_be_predicate_indicato/1(USES_REGS1): : "must_be_predicate_indicator( Term, Module, Name, Arity " )

@class must_be_predicate_indicator_4

This predicates can be used to verify if Term is a predicate indicator, that is of the form:

  • Name/Arity

  • Name//Arity-2

  • Module:Name/Arity

  • Module:Name//Arity-2

if it is, it will extract the predicate's module, name, and arity.

Note: this will now accept both mod:(a/n) and (mod:a)/n as valid.

1. void Yap_InitErrorPreds(void):

Var:

1. char tmpbuf[YAP_BUF_SIZE][YAP_BUF_SIZE]:

Typedef:

1. typedef struct c_error_info c_error_t: