diff --git a/C/errors.c b/C/errors.c index 824048465..dba801a01 100755 --- a/C/errors.c +++ b/C/errors.c @@ -266,7 +266,8 @@ static char tmpbuf[YAP_BUF_SIZE]; } #define END_ERROR_CLASSES() \ - } \ + } \ + return TermNil; \ } #define BEGIN_ERRORS() \ @@ -291,7 +292,7 @@ static char tmpbuf[YAP_BUF_SIZE]; return mkerrorct(B, ts); #define END_ERRORS() \ - } \ + } return TermNil; \ } #include "YapErrors.h" @@ -347,7 +348,9 @@ yamop *Yap_Error__(const char *file, const char *function, int lineno, Yap_RestartYap(1); } LOCAL_ActiveError.errorNo = type; - LOCAL_ActiveError.errorClass = Yap_errorClass(LOCAL_ActiveError.errorNo); + LOCAL_ActiveError.errorAsText = Yap_LookupAtom(Yap_errorName( type )); + LOCAL_ActiveError.errorClass = Yap_errorClass( type); + LOCAL_ActiveError.classAsText = Yap_LookupAtom(Yap_errorClassName( LOCAL_ActiveError.errorClass )); LOCAL_ActiveError.errorLine = lineno; LOCAL_ActiveError.errorFunction = function; LOCAL_ActiveError.errorFile = file; diff --git a/C/exec.c b/C/exec.c index a235a3ffa..41906519b 100755 --- a/C/exec.c +++ b/C/exec.c @@ -2074,8 +2074,18 @@ static Int jump_env(USES_REGS1) { Yap_Error(INSTANTIATION_ERROR, t, "throw ball must be bound"); return false; } else if (IsApplTerm(t) && FunctorOfTerm(t) == FunctorError) { + Term t2; + Yap_find_prolog_culprit(PASS_REGS1); - LOCAL_Error_TYPE = INSTANTIATION_ERROR; + LOCAL_Error_TYPE = ERROR_EVENT; + t = ArgOfTerm(1, t); + if (IsApplTerm(t) && IsAtomTerm((t2 = ArgOfTerm(1,t)))) { + LOCAL_ActiveError.errorAsText = AtomOfTerm(t2); + LOCAL_ActiveError.classAsText = NameOfFunctor(t); + } else if (IsAtomTerm(t)) { + LOCAL_ActiveError.errorAsText = AtomOfTerm(t); + LOCAL_ActiveError.classAsText = NULL; + } } else { LOCAL_Error_TYPE = THROW_EVENT; } diff --git a/CXX/yapi.cpp b/CXX/yapi.cpp index 10ebd22be..e74278ec0 100644 --- a/CXX/yapi.cpp +++ b/CXX/yapi.cpp @@ -1,6 +1,7 @@ #define YAP_CPP_INTERFACE 1 +#include #include "yapi.hh" extern "C" { @@ -947,30 +948,38 @@ void *YAPPrologPredicate::retractClause(YAPTerm skeleton, bool all) { void *YAPPrologPredicate::clause(YAPTerm skeleton, YAPTerm &body) { return 0; } const char *YAPError::text() { + + char buf[256]; std::string s = ""; - if (LOCAL_ActiveError.prologPredLine) { - s += LOCAL_ActiveError.prologPredFile->StrOfAE; - s += ":"; - s += LOCAL_ActiveError.prologPredLine; - s += ":0 error "; - s += Yap_errorClassName(getErrorClass()); - s += "."; - s += Yap_errorName(getID()); - s += " in "; - s += LOCAL_ActiveError.prologPredModule; - s += ":"; - s += (LOCAL_ActiveError.prologPredName)->StrOfAE; - s += "/"; - s += LOCAL_ActiveError.prologPredArity; - s += "\n"; - } if (LOCAL_ActiveError.errorFunction) { s += LOCAL_ActiveError.errorFile; s += ":"; - s += LOCAL_ActiveError.errorLine; - s += ":0 C-code for error."; - s += "\n"; + sprintf(buf, "%ld", (long int)LOCAL_ActiveError.errorLine); + s += buf; + s += ":0 in C-code"; } + if (LOCAL_ActiveError.prologPredLine) { + s += "\n" ; + s+= LOCAL_ActiveError.prologPredFile->StrOfAE ; + s+= ":" ; + sprintf(buf, "%ld", (long int)LOCAL_ActiveError.prologPredLine); + s+= buf; // std::to_string(LOCAL_ActiveError.prologPredLine) ; + // YAPIntegerTerm(LOCAL_ActiveError.prologPredLine).text(); + s+= ":0 " ; + s+= LOCAL_ActiveError.prologPredModule ; + s+= ":" ; + s+= (LOCAL_ActiveError.prologPredName)->StrOfAE ; + s+= "/" ; + sprintf(buf, "%ld", (long int)LOCAL_ActiveError.prologPredArity); + s+= // std::to_string(LOCAL_ActiveError.prologPredArity); + buf; + } + s += " error "; + if (LOCAL_ActiveError.classAsText != nullptr) + s += LOCAL_ActiveError.classAsText->StrOfAE; + s += "."; + s += LOCAL_ActiveError.errorAsText->StrOfAE; + s += ".\n"; if (LOCAL_ActiveError.errorTerm) { Term t = Yap_PopTermFromDB(LOCAL_ActiveError.errorTerm); if (t) { diff --git a/CXX/yapie.hh b/CXX/yapie.hh index 1a2374f39..f85723bb9 100644 --- a/CXX/yapie.hh +++ b/CXX/yapie.hh @@ -7,6 +7,8 @@ class YAPTerm; /// take information on a Prolog error: class YAPError { + std::string name, errorClass, info; + int swigcode; public: /// error handling when receiving the error term diff --git a/cmake/Config.cmake b/cmake/Config.cmake index b2f59a456..9c0abcae4 100644 --- a/cmake/Config.cmake +++ b/cmake/Config.cmake @@ -345,6 +345,7 @@ check_function_exists(strcasestr HAVE_STRCASESTR) check_function_exists(strchr HAVE_STRCHR) check_function_exists(strerror HAVE_STRERROR) check_function_exists(stricmp HAVE_STRICMP) +check_function_exists(strlcpy HAVE_STRLCPY) check_function_exists(strlwr HAVE_STRLWR) check_function_exists(strncasecmp HAVE_STRNCASECMP) check_function_exists(strncat HAVE_STRNCAT) diff --git a/config.h.cmake b/config.h.cmake index 02f74bf2b..baf479b92 100644 --- a/config.h.cmake +++ b/config.h.cmake @@ -2011,6 +2011,9 @@ calls it, or to nothing if 'inline' is not supported under any name. */ #endif #endif +#ifndef HAVE_STRLCPY +#define strlcpy(X,Y,Z) strcpy(X,Y) +#endif //#define DEBUG_MALLOC 1 #if DEBUG_MALLOC diff --git a/include/YapError.h b/include/YapError.h index 681c2ca6e..04e3351bf 100644 --- a/include/YapError.h +++ b/include/YapError.h @@ -178,6 +178,8 @@ INLINE_ONLY extern inline Term Yap_ensure_atom__(const char *fu, const char *fi, typedef struct yap_error_descriptor { enum yap_error_status status; yap_error_class_number errorClass; + YAP_Atom errorAsText; + YAP_Atom classAsText; yap_error_number errorNo; YAP_Int errorLine; const char *errorFunction; diff --git a/include/YapErrors.h b/include/YapErrors.h index 7c8fe2692..a7969e5ad 100644 --- a/include/YapErrors.h +++ b/include/YapErrors.h @@ -148,6 +148,7 @@ E(SYSTEM_ERROR_JIT_NOT_AVAILABLE, SYSTEM_ERROR_CLASS, "jit_not_available") E(SYSTEM_ERROR_OPERATING_SYSTEM, SYSTEM_ERROR_CLASS, "operating_system_error") E(SYSTEM_ERROR_SAVED_STATE, SYSTEM_ERROR_CLASS, "saved_state_error") +E(ERROR_EVENT, EVENT, "error") E(ABORT_EVENT, EVENT, "abort") E(THROW_EVENT, EVENT, "throw") E(CALL_COUNTER_UNDERFLOW_EVENT, EVENT, "call_counter_underflow") diff --git a/packages/python/yapex.py b/packages/python/yapex.py index f42c58a4e..6bb9fb92e 100644 --- a/packages/python/yapex.py +++ b/packages/python/yapex.py @@ -20,10 +20,19 @@ class T(tuple): return str(self.name) + str(self.tuple) + def query_prolog(engine, s): + + def answer( q ): +# try: + return q.next() +# except yap.YAPPythonException e: +# print e.text() +# return False + q = engine.query(s) ask = True - while q.next(): + while answer(q): vs = q.namedVarsCopy() if vs: i = 0 diff --git a/packages/swig/yap.i b/packages/swig/yap.i index 9e91ad369..6cee68b1d 100644 --- a/packages/swig/yap.i +++ b/packages/swig/yap.i @@ -85,20 +85,23 @@ return *new YAPTerm(); // Language independent exception handler -%exception { +%exception next { try { $action - } catch (YAPError e) { + } catch (YAPError &e) { + yap_error_number en = e.getID(); + PyObject *pyerr = PyExc_RuntimeError; + + LOCAL_Error_TYPE = YAP_NO_ERROR; switch (e.getErrorClass()) { case YAPC_NO_ERROR: break; /// bad domain, "first argument often is the predicate. case DOMAIN_ERROR: { - yap_error_number en = e.getID(); switch (en) { case DOMAIN_ERROR_OUT_OF_RANGE: case DOMAIN_ERROR_NOT_LESS_THAN_ZERO: - PyErr_SetString(PyExc_IndexError, e.text()); + pyerr = PyExc_IndexError; break; case DOMAIN_ERROR_CLOSE_OPTION: case DOMAIN_ERROR_ENCODING: @@ -106,47 +109,45 @@ return *new YAPTerm(); case DOMAIN_ERROR_ABSOLUTE_FILE_NAME_OPTION: case DOMAIN_ERROR_READ_OPTION: case DOMAIN_ERROR_SET_STREAM_OPTION: - PyErr_SetString(PyExc_KeyError, e.text()); + pyerr = PyExc_KeyError; break; case DOMAIN_ERROR_FILE_ERRORS: case DOMAIN_ERROR_FILE_TYPE: case DOMAIN_ERROR_IO_MODE: case DOMAIN_ERROR_SOURCE_SINK: case DOMAIN_ERROR_STREAM_POSITION: - PyErr_SetString(PyExc_IOError, e.text()); + pyerr = PyExc_IOError; break; default: - PyErr_SetString(PyExc_ValueError, e.text()); + pyerr = PyExc_ValueError; } } break; /// bad arithmetic case EVALUATION_ERROR: { - yap_error_number en = e.getID(); switch (en) { case EVALUATION_ERROR_FLOAT_OVERFLOW: case EVALUATION_ERROR_INT_OVERFLOW: - PyErr_SetString(PyExc_OverflowError, e.text()); + pyerr = PyExc_OverflowError; break; case EVALUATION_ERROR_FLOAT_UNDERFLOW: case EVALUATION_ERROR_UNDERFLOW: case EVALUATION_ERROR_ZERO_DIVISOR: - PyErr_SetString(PyExc_ArithmeticError, e.text()); + pyerr = PyExc_ArithmeticError; break; default: - PyErr_SetString(PyExc_RuntimeError, e.text()); + pyerr = PyExc_RuntimeError; } } break; /// missing object (I/O mostly) case EXISTENCE_ERROR: - PyErr_SetString(PyExc_NotImplementedError, e.text()); + pyerr = PyExc_NotImplementedError; break; /// should be bound case INSTANTIATION_ERROR_CLASS: - PyErr_SetString(PyExc_RuntimeError, e.text()); + pyerr = PyExc_RuntimeError; break; /// bad access, I/O case PERMISSION_ERROR: { - yap_error_number en = e.getID(); switch (en) { case PERMISSION_ERROR_INPUT_BINARY_STREAM: case PERMISSION_ERROR_INPUT_PAST_END_OF_STREAM: @@ -157,40 +158,42 @@ return *new YAPTerm(); case PERMISSION_ERROR_REPOSITION_STREAM: case PERMISSION_ERROR_OUTPUT_STREAM: case PERMISSION_ERROR_OUTPUT_TEXT_STREAM: - PyErr_SetString(PyExc_OverflowError, e.text()); + pyerr = PyExc_OverflowError; break; default: - PyErr_SetString(PyExc_RuntimeError, e.text()); + pyerr = PyExc_RuntimeError; } } break; /// something that could not be represented into a type case REPRESENTATION_ERROR: - PyErr_SetString(PyExc_RuntimeError, e.text()); + pyerr = PyExc_RuntimeError; break; /// not enough .... case RESOURCE_ERROR: - PyErr_SetString(PyExc_RuntimeError, e.text()); + pyerr = PyExc_RuntimeError; break; /// bad text case SYNTAX_ERROR_CLASS: - PyErr_SetString(PyExc_SyntaxError, e.text()); + pyerr = PyExc_SyntaxError; break; /// OS or internal case SYSTEM_ERROR_CLASS: - PyErr_SetString(PyExc_RuntimeError, e.text()); + pyerr = PyExc_RuntimeError; break; /// bad typing case TYPE_ERROR: - PyErr_SetString(PyExc_TypeError, e.text()); + pyerr = PyExc_TypeError; break; /// should be unbound case UNINSTANTIATION_ERROR_CLASS: - PyErr_SetString(PyExc_RuntimeError, e.text()); + pyerr = PyExc_RuntimeError; break; /// escape hatch default: break; } + PyErr_SetString(pyerr, e.text()); + return Py_False; } } @@ -203,12 +206,13 @@ return *new YAPTerm(); try { $action } catch (YAPError e) { +yap_error_number en = e.getID(); +LOCAL_ERROR_Type = YAP_NO_ERROR; switch (e.getErrorClass()) { case YAPC_NO_ERROR: break; /// bad domain, "first argument often is the predicate. case DOMAIN_ERROR: { - yap_error_number en = e.getID(); switch (en) { case DOMAIN_ERROR_OUT_OF_RANGE: case DOMAIN_ERROR_NOT_LESS_THAN_ZERO: @@ -235,7 +239,6 @@ return *new YAPTerm(); } break; /// bad arithmetic case EVALUATION_ERROR: { - yap_error_number en = e.getID(); switch (en) { case EVALUATION_ERROR_FLOAT_OVERFLOW: case EVALUATION_ERROR_FLOAT_UNDERFLOW: @@ -260,7 +263,6 @@ return *new YAPTerm(); break; /// bad access, I/O case PERMISSION_ERROR: { - yap_error_number en = e.getID(); switch (en) { case PERMISSION_ERROR_INPUT_BINARY_STREAM: case PERMISSION_ERROR_INPUT_PAST_END_OF_STREAM: