diff --git a/C/parser.c b/C/parser.c index b83ecb453..85a2ddb2b 100755 --- a/C/parser.c +++ b/C/parser.c @@ -58,14 +58,14 @@ extern const char *Yap_tokText(void *tokptr); static void syntax_msg(const char *msg, ...) { CACHE_REGS va_list ap; - if (!LOCAL_ErrorMessage || + if (!LOCAL_Error_TYPE || (LOCAL_Error_TYPE == SYNTAX_ERROR && - LOCAL_tokptr->TokPos < LOCAL_ActiveError->parserPos)) { + LOCAL_toktide->TokPos < LOCAL_ActiveError->parserPos)) { if (!LOCAL_ErrorMessage) { LOCAL_ErrorMessage = malloc(MAX_ERROR_MSG_SIZE + 1); } - LOCAL_ActiveError->parserLine = LOCAL_tokptr->TokLine; - LOCAL_ActiveError->parserPos = LOCAL_tokptr->TokPos; + LOCAL_ActiveError->parserLine = LOCAL_toktide->TokLine; + LOCAL_ActiveError->parserPos = LOCAL_toktide->TokPos; va_start(ap, msg); vsnprintf(LOCAL_ErrorMessage, MAX_ERROR_MSG_SIZE, msg, ap); va_end(ap); @@ -939,7 +939,7 @@ Term Yap_Parse(UInt prio, encoding_t enc, Term cmod) { Yap_CloseSlots(sls); } if (LOCAL_tokptr != NULL && LOCAL_tokptr->Tok != Ord(eot_tok)) { - LOCAL_Error_TYPE = SYNTAX_ERROR; + LOCAL_Error_TYPE =SYNTAX_ERROR; if (LOCAL_tokptr->TokNext) { size_t sz = strlen("bracket or operator expected."); LOCAL_ErrorMessage =malloc(sz+1); diff --git a/os/readterm.c b/os/readterm.c index 4a12db042..06bc2774a 100644 --- a/os/readterm.c +++ b/os/readterm.c @@ -402,15 +402,8 @@ static Term syntax_error(TokEntry *errtok, int sno, Term cmod, Int newpos, bool #endif if (GLOBAL_Stream[sno].status & Seekable_Stream_f) { - while (tok && tok->Tok != Error_tok && tok != errtok) - { - if (tok->TokNext) - tok = tok->TokNext; - else - break; - } - err_line = tok->TokLine; - errpos = tok->TokPos -1; + err_line = LOCAL_ActiveError->parserLine; + errpos = LOCAL_ActiveError->parserPos -1; if (errpos <= startpos) { o = malloc(1); @@ -457,7 +450,7 @@ static Term syntax_error(TokEntry *errtok, int sno, Term cmod, Int newpos, bool o[0] = '\0'; while (tok) { - if (tok->Tok == Error_tok) + if (tok->Tok == Error_tok || tok == LOCAL_toktide ) { o = realloc(o, strlen(o) + 1); Yap_local.ActiveError->parserTextA = o; @@ -488,15 +481,17 @@ static Term syntax_error(TokEntry *errtok, int sno, Term cmod, Int newpos, bool } } Yap_local.ActiveError->parserPos = errpos; - Yap_local.ActiveError->parserLine = err_line; - /* 0: strat, error, end line */ - /*2 msg */ - /* 1: file */ - if (!msg) - msg = "unspecified"; + Yap_local.ActiveError->parserLine = err_line; + /* 0: strat, error, end line */ + /*2 msg */ + /* 1: file */ Yap_local.ActiveError->culprit = + (char*)msg; + if (Yap_local.ActiveError->errorMsg) { Yap_local.ActiveError->errorMsg = (char*)msg; - Yap_local.ActiveError->errorMsgLen = strlen(msg); + Yap_local.ActiveError->errorMsgLen = strlen(Yap_local.ActiveError->errorMsg); + } + clean_vars(LOCAL_VarTable); clean_vars(LOCAL_AnonVarTable); if (Yap_ExecutionMode == YAP_BOOT_MODE) diff --git a/packages/python/pl2py.c b/packages/python/pl2py.c index 5cb964318..1ab854097 100644 --- a/packages/python/pl2py.c +++ b/packages/python/pl2py.c @@ -156,11 +156,10 @@ static bool entry_to_dictionary(PyObject *dict, Term targ, */ PyObject *term_to_python(term_t t, bool eval, PyObject *o, bool cvt) { // - YAP_Term yt = YAP_GetFromSlot(t); switch (PL_term_type(t)) { case PL_VARIABLE: { - if (yt == 0) { - Yap_ThrowError(SYSTEM_ERROR_INTERNAL, yt, "in term_to_python"); + if (t == 0) { + Yap_ThrowError(SYSTEM_ERROR_INTERNAL, t, "in term_to_python"); } PyObject *out = PyTuple_New(1); PyTuple_SET_ITEM(out, 0, PyLong_FromLong((YAP_Int)YAP_GetFromSlot(t))); @@ -169,6 +168,7 @@ PyObject *term_to_python(term_t t, bool eval, PyObject *o, bool cvt) { return term_to_nametuple("v", 1, out); }; case PL_ATOM: { + YAP_Term yt = YAP_GetFromSlot(t); YAP_Atom at = YAP_AtomOfTerm(yt); const char *s; @@ -189,6 +189,7 @@ PyObject *term_to_python(term_t t, bool eval, PyObject *o, bool cvt) { } } case PL_STRING: { + YAP_Term yt = YAP_GetFromSlot(t); const char *s = NULL; if (YAP_IsAtomTerm(yt)) { s = YAP_AtomName(YAP_AtomOfTerm(yt)); @@ -389,6 +390,9 @@ PyObject *term_to_python(term_t t, bool eval, PyObject *o, bool cvt) { else return Py_None; } + if (fun == FUNCTOR_var1) { + return Py_None; + } atom_t name; int arity; diff --git a/packages/python/py2pl.c b/packages/python/py2pl.c index 9b88d91cc..b8160d88c 100644 --- a/packages/python/py2pl.c +++ b/packages/python/py2pl.c @@ -155,6 +155,8 @@ else if (PyDict_Check(pVal)) { Py_ssize_t pos = 0, tot = PyDict_Size(pVal); PyObject *key, *value; Term f, *opt = &f, t, to; + if (tot == 0) + return MkAtomTerm( Yap_LookupAtom("{}")); while (PyDict_Next(pVal, &pos, &key, &value)) { Term t0[2]; t0[0] = python_to_term__(key); diff --git a/packages/python/py4yap.h b/packages/python/py4yap.h index 79c29543a..bae0be539 100644 --- a/packages/python/py4yap.h +++ b/packages/python/py4yap.h @@ -70,16 +70,16 @@ extern bool init_python_vfs(void); extern atom_t ATOM_true, ATOM_false, ATOM_colon, ATOM_dot, ATOM_none, ATOM_t, ATOM_comma, ATOM_builtin, ATOM_V, ATOM_A, ATOM_self, ATOM_nil, - ATOM_brackets, ATOM_curly_brackets; + ATOM_brackets, ATOM_curly_brackets; extern functor_t FUNCTOR_dollar1, FUNCTOR_abs1, FUNCTOR_all1, FUNCTOR_any1, FUNCTOR_as2, FUNCTOR_bin1, FUNCTOR_brackets1, FUNCTOR_comma2, FUNCTOR_dir1, - FUNCTOR_float1, FUNCTOR_int1, FUNCTOR_iter1, FUNCTOR_iter2, FUNCTOR_long1, + FUNCTOR_float1, FUNCTOR_int1, FUNCTOR_iter1, FUNCTOR_var1, FUNCTOR_iter2, FUNCTOR_long1, FUNCTOR_var1, FUNCTOR_len1, FUNCTOR_curly1, FUNCTOR_ord1, FUNCTOR_range1, FUNCTOR_range2, FUNCTOR_range3, FUNCTOR_sum1, FUNCTOR_pointer1, FUNCTOR_complex2, FUNCTOR_plus2, FUNCTOR_sub2, FUNCTOR_mul2, FUNCTOR_div2, FUNCTOR_hat2, FUNCTOR_colon2, FUNCTOR_comma2, FUNCTOR_equal2, FUNCTOR_sqbrackets2, - FUNCTOR_dot2; + FUNCTOR_dot2, FUNCTOR_var1; extern X_API PyObject *py_Main; extern X_API PyObject *py_Yapex; diff --git a/packages/python/pybips.c b/packages/python/pybips.c index ded76ada8..986162d01 100644 --- a/packages/python/pybips.c +++ b/packages/python/pybips.c @@ -591,7 +591,6 @@ static long get_len_of_range(long lo, long hi, long step) { } #if PY_MAJOR_VERSION >= 3 -/* static PyStructSequence_Field pnull[] = { {"A1", NULL}, {"A2", NULL}, {"A3", NULL}, {"A4", NULL}, {"A5", NULL}, {"A6", NULL}, {"A7", NULL}, {"A8", NULL}, {"A9", NULL}, {"A9", NULL}, @@ -601,17 +600,16 @@ static long get_len_of_range(long lo, long hi, long step) { {"A24", NULL}, {"A25", NULL}, {"A26", NULL}, {"A27", NULL}, {"A28", NULL}, {"A29", NULL}, {"A29", NULL}, {"A30", NULL}, {"A31", NULL}, {"A32", NULL}, {NULL, NULL}}; -*/ -static PyObject *structseq_str(PyObject *iobj) { + static PyObject *structseq_str(PyStructSequence *obj ) { /* buffer and type size were chosen well considered. */ #define REPR_BUFFER_SIZE 512 #define TYPE_MAXSIZE 100 - PyStructSequence *obj = (PyStructSequence *)iobj; - PyTypeObject *typ = Py_TYPE(obj); bool removelast = false; + PyTypeObject *typ = Py_TYPE(obj); + const char *type_name = typ->tp_name; Py_ssize_t len, i; char buf[REPR_BUFFER_SIZE]; char *endofbuf, *pbuf = buf; @@ -620,8 +618,8 @@ static PyObject *structseq_str(PyObject *iobj) { /* "typename(", limited to TYPE_MAXSIZE */ len = - strlen(typ->tp_name) > TYPE_MAXSIZE ? TYPE_MAXSIZE : strlen(typ->tp_name); - strncpy(pbuf, typ->tp_name, len); + strnlen(type_name, TYPE_MAXSIZE); + strncpy(pbuf, type_name, len); pbuf += len; *pbuf++ = '('; @@ -666,7 +664,7 @@ static PyObject *structseq_str(PyObject *iobj) { return PyUnicode_FromString(buf); } -static PyObject *structseq_repr(PyObject *iobj) { + static PyObject *structseq_repr(PyObject *iobj) { /* buffer and type size were chosen well considered. */ #define REPR_BUFFER_SIZE 512 @@ -674,6 +672,7 @@ static PyObject *structseq_repr(PyObject *iobj) { PyStructSequence *obj = (PyStructSequence *)iobj; PyTypeObject *typ = Py_TYPE(obj); + const char *type_name = typ->tp_name; bool removelast = false; Py_ssize_t len, i; char buf[REPR_BUFFER_SIZE]; @@ -683,8 +682,8 @@ static PyObject *structseq_repr(PyObject *iobj) { /* "typename(", limited to TYPE_MAXSIZE */ len = - strlen(typ->tp_name) > TYPE_MAXSIZE ? TYPE_MAXSIZE : strlen(typ->tp_name); - strncpy(pbuf, typ->tp_name, len); + strnlen(type_name, TYPE_MAXSIZE); + strncpy(pbuf, type_name, len); pbuf += len; *pbuf++ = '('; @@ -743,7 +742,7 @@ static bool legal_symbol(const char *s) { PyObject *term_to_nametuple(const char *s, arity_t arity, PyObject *tuple) { PyTypeObject *typp; PyObject *key = PyUnicode_FromString(s), *d; - if (!legal_symbol(s)) { + if (legal_symbol(s)) { if (!Py_f2p) { PyObject *o1; @@ -761,32 +760,42 @@ PyObject *term_to_nametuple(const char *s, arity_t arity, PyObject *tuple) { if ((d = PyList_GetItem(Py_f2p, arity - 1)) && PyDict_Contains(d, key)) { typp = (PyTypeObject *)d; } else { - typp = calloc(sizeof(PyTypeObject), 1); - PyStructSequence_Desc *desc = calloc(sizeof(PyStructSequence_Desc), 1); + PyStructSequence_Desc *desc = PyMem_Calloc(sizeof(PyStructSequence_Desc), 1); desc->name = PyMem_Malloc(strlen(s) + 1); + strcpy(desc->name, s); desc->doc = "YAPTerm"; - desc->fields = NULL; + desc->fields = pnull; desc->n_in_sequence = arity; + typp = PyStructSequence_NewType(desc); + typp->tp_name = desc->name; + if (PyStructSequence_InitType2(typp, desc) < 0) return NULL; - // typp->tp_flags &= ~Py_TPFLAGS_HEAPTYPE; - // typp->tp_flags &= ~Py_TPFLAGS_HAVE_GC; - // typp->tp_str = structseq_str; - typp->tp_repr = structseq_repr; - // typp = PyStructSequence_NewType(desc); + typp->tp_traverse = NULL; + typp->tp_flags |= + Py_TPFLAGS_TUPLE_SUBCLASS| + Py_TPFLAGS_BASETYPE| + Py_TPFLAGS_HEAPTYPE; // don't do this: we cannot add a type as an atribute. // PyModule_AddGObject(py_Main, s, (PyObject *)typp); - if (d && !PyDict_Contains(d, key)) - PyDict_SetItem(d, key, (PyObject*)typp); + if (d && !PyDict_Contains(d, key)) { + PyDict_SetItem(d, key, (void*)typp); + Py_INCREF(key); + Py_INCREF(typp); + } + typp->tp_repr = structseq_repr; + typp->tp_str = structseq_str; } PyObject *o = PyStructSequence_New(typp); Py_INCREF(typp); arity_t i; for (i = 0; i < arity; i++) { PyObject *pArg = PyTuple_GET_ITEM(tuple, i); + if (pArg) { Py_INCREF(pArg); - if (pArg) PyStructSequence_SET_ITEM(o, i, pArg); + + } // PyObject_Print(pArg,stderr,0);fputc('\n',stderr); } //((PyStructSequence *)o)->ob_base.ob_size = arity; @@ -860,6 +869,9 @@ PyObject *compound_to_pytree(term_t t, PyObject *context, bool cvt) { atom_t name; int arity; + if (PL_is_variable(t)) { + return term_to_python(t, false, context, cvt); + } o = find_obj(context, t, false); AOK(PL_get_name_arity(t, &name, &arity), NULL); if (arity == 0) @@ -876,27 +888,26 @@ PyObject *compound_to_pytree(term_t t, PyObject *context, bool cvt) { if (!(s = PL_atom_chars(name))) { return NULL; } - term_t tleft; + Term tleft; int i; PyObject *out = PyTuple_New(arity); - DebugPrintf("Tuple %p\n", o); - tleft = PL_new_term_ref(); + if (CHECKNULL(t, out) == NULL) { + PyErr_Print(); + return NULL; + } + //DebugPrintf("Tuple %s/%d = %p\n", name, arity, out); for (i = 0; i < arity; i++) { PyObject *pArg; - AOK(PL_get_arg(i + 1, t, tleft), NULL); - pArg = term_to_python(tleft, false, NULL, cvt); + tleft = ArgOfTerm(i + 1, Yap_GetFromSlot(t)); + pArg = yap_to_python(tleft, false, NULL, cvt); if (pArg) { /* pArg reference stolen here: */ PyTuple_SET_ITEM(out, i, pArg); Py_INCREF(pArg); } } - if (CHECKNULL(t, out) == NULL) { - PyErr_Print(); - return NULL; - } - PyObject *c = lookupPySymbol(s, o, NULL); + PyObject *c = lookupPySymbol(s, out, NULL); if (c && PyCallable_Check(c)) { PyObject *n = PyTuple_New(arity); diff --git a/packages/python/pyio.c b/packages/python/pyio.c index 8e16fa55d..e0a7813ce 100644 --- a/packages/python/pyio.c +++ b/packages/python/pyio.c @@ -8,9 +8,15 @@ YAP_Term TermErrStream, TermOutStream; -static void pyflush(StreamDesc *st) { +static void py_flush(int sno) { + StreamDesc *st = YAP_GetStreamFromId(sno); + PyObject *fl = + PyObject_GetAttrString(st->u.private_data, "flush"); + if (fl) { + PyObject_CallFunctionObjArgs(fl, + NULL); + } #if 0 - st->u.w_irl.ptr[0] = '\0'; // fprintf(stderr,"%s\n", st->u.w_irl.buf); term_t tg = python_acquire_GIL(); if (st->user_name == TermOutStream){ @@ -31,13 +37,13 @@ static int py_putc(int sno, int ch) { StreamDesc *st = YAP_GetStreamFromId(sno); #if 0 if (false && (st->user_name == TermOutStream || st->user_name == TermErrStream)) { - size_t sz = put_utf8(st->u.w_irl.ptr, ch); - if (sz > 0) { - st->u.w_irl.ptr += sz; - if (ch == '\n' || st->u.w_irl.ptr - st->u.w_irl.buf > 256) - {pyflush(st); } - } - return ch; + size_t sz = put_utf8(st->u.w_irl.ptr, ch); + if (sz > 0) { + st->u.w_irl.ptr += sz; + if ( st->u.w_irl.ptr - st->u.w_irl.buf > 256) + {py_flush(sno); } + } + return ch; } #endif unsigned char s[2]; @@ -50,8 +56,8 @@ static int py_putc(int sno, int ch) { python_release_GIL(g0); if ((err = PyErr_Occurred())) { PyErr_SetString( - err, - "Error in put\n"); // %s:%s:%d!\n", __FILE__, __FUNCTION__, __LINE__); + err, + "Error in put\n"); // %s:%s:%d!\n", __FILE__, __FUNCTION__, __LINE__); } return ch; } @@ -63,13 +69,13 @@ static int py_wputc(int sno, int ch) { StreamDesc *st = YAP_GetStreamFromId(sno); #if 0 if (false && (st->user_name == TermOutStream || st->user_name == TermErrStream)) { - size_t sz = put_utf8(st->u.w_irl.ptr, ch); - if (sz > 0) { - st->u.w_irl.ptr += sz; - if (ch == '\n' || st->u.w_irl.ptr - st->u.w_irl.buf > 256) - {pyflush(st); } - } - return ch; + size_t sz = put_utf8(st->u.w_irl.ptr, ch); + if (sz > 0) { + st->u.w_irl.ptr += sz; + if ( st->u.w_irl.ptr - st->u.w_irl.buf > 256) + {py_flush(sno); } + } + return ch; } #endif unsigned char s[8]; @@ -82,8 +88,8 @@ static int py_wputc(int sno, int ch) { python_release_GIL(g0); if ((err = PyErr_Occurred())) { PyErr_SetString( - err, - "Error in put\n"); // %s:%s:%d!\n", __FILE__, __FUNCTION__, __LINE__); + err, + "Error in put\n"); // %s:%s:%d!\n", __FILE__, __FUNCTION__, __LINE__); } return ch; } @@ -112,16 +118,16 @@ static void *py_open(VFS_t *me, const char *name, const char *io_mode, } /* if (!outbuf) - outbuf = ( unsigned char *)malloc(1024); + outbuf = ( unsigned char *)malloc(1024); st->u.w_irl.ptr = st->u.w_irl.buf = outbuf; -]\] + ]\] st->user_name = TermOutStream; - } else if (strcmp(name, "sys.stderr") == 0) { + } else if (strcmp(name, "sys.stderr") == 0) { st->user_name = TermErrStream; if (!errbuf) - errbuf = ( unsigned char *)malloc(1024); + errbuf = ( unsigned char *)malloc(1024); st->u.w_irl.ptr = st->u.w_irl.buf = errbuf; // } else if (strcmp(name, "input") == 0) { //pystream = PyObject_Call(pystream, PyTuple_New(0), NULL); @@ -131,18 +137,11 @@ static void *py_open(VFS_t *me, const char *name, const char *io_mode, st->vfs = me; st->file = NULL; python_release_GIL(ctk); + if (st->status & (Output_Stream_f | Append_Stream_f)) + py_flush(sno); return st; } -static void py_flush(int sno) { - StreamDesc *s = YAP_GetStreamFromId(sno); - term_t tg = python_acquire_GIL(); - PyObject *flush = PyObject_GetAttrString(s->u.private_data, "flush"); - pyflush(s); - PyObject_CallFunction(flush, NULL); - python_release_GIL(tg); -} - static bool py_close(int sno) { StreamDesc *st = YAP_RepStreamFromId(sno); if (st->status & (Output_Stream_f | Append_Stream_f)) @@ -158,49 +157,36 @@ static bool py_close(int sno) { } static bool pygetLine(StreamDesc *rl_iostream, int sno) { - // term_t ctk = python_acquire_GIL(); const char *myrl_line; - PyObject *user_line, *readl = NULL; + PyObject *user_line; PyObject *err; StreamDesc *s = YAP_GetStreamFromId(sno); - // term_t tg = python_acquire_GIL(); - PyObject_Print(s->u.private_data,stderr,0); + term_t tg = python_acquire_GIL(); + // PyObject_Print(s->u.private_data,stderr,0); if (PyFunction_Check( s->u.private_data )) { - readl = s->u.private_data; + user_line = PyObject_CallFunctionObjArgs( s->u.private_data , + NULL); + } else if ( s->u.private_data == NULL) { + PyObject *readl = + PyObject_GetAttrString(s->u.private_data, "readline"); + if (!readl) { + readl = + PyObject_GetAttrString(s->u.private_data, "read"); } - if (!strcmp(RepAtom(s->name)->StrOfAE, "user_input")) { - // note that input may change - readl = PythonLookupSpecial("input"); + if (readl) + user_line = PyObject_CallFunctionObjArgs(readl, + NULL); } - if (readl == NULL) { - readl = PythonLookup("readline", s->u.private_data); + python_release_GIL(tg); + if ((err = PyErr_Occurred())) { + if (PyErr_GivenExceptionMatches(err, PyExc_EOFError)) + return NULL; + PyErr_Print(); + Yap_ThrowError(SYSTEM_ERROR_GET_FAILED, YAP_MkIntTerm(sno), NULL); } - if (readl == NULL) { - readl = PythonLookup("read", s->u.private_data); - } - if (readl == NULL) { - if ((err = PyErr_Occurred())) { - PyErr_Print(); - Yap_ThrowError(SYSTEM_ERROR_GET_FAILED, YAP_MkIntTerm(sno), NULL); - } - } - user_line = PyObject_CallFunctionObjArgs(readl, - NULL); - if ((err = PyErr_Occurred())) { - PyErr_Print(); - Yap_ThrowError(SYSTEM_ERROR_GET_FAILED, YAP_MkIntTerm(sno), err); - } myrl_line = PyUnicode_AsUTF8(user_line); if (myrl_line == NULL) return NULL; - if ((err = PyErr_Occurred())) { - - if (PyErr_GivenExceptionMatches(err, PyExc_EOFError)) - return NULL; - PyErr_Print(); - Yap_ThrowError(SYSTEM_ERROR_GET_FAILED, YAP_MkIntTerm(sno), err); - - } rl_iostream->u.irl.ptr = rl_iostream->u.irl.buf = (unsigned char *)myrl_line; return true; } @@ -247,11 +233,11 @@ static int py_wgetc(int sno) { } /** - @brief Yap_ReadlinePeekChar peeks the next char from the - readline buffer, but does not actually grab it. + @brief Yap_ReadlinePeekChar peeks the next char from the + readline buffer, but does not actually grab it. - The idea is to take advantage of the buffering. Special care must be taken - with EOF, though. + The idea is to take advantage of the buffering. Special care must be taken + with EOF, though. */ static int py_peek(int sno) { @@ -280,7 +266,7 @@ static int py_peek(int sno) { static int64_t py_seek(int sno, int64_t where, int how) { StreamDesc *g0 = YAP_RepStreamFromId(sno); term_t s0 = python_acquire_GIL(); - PyObject *fseek = PyObject_GetAttrString(g0->u.private_data, "seek"); + PyObject *fseek = PyObject_GetAttrString(g0->u.private_data, "seek"); PyObject *pyr = PyObject_CallFunctionObjArgs(fseek, PyLong_FromLong(where), PyLong_FromLong(how), NULL); python_release_GIL(s0); @@ -311,7 +297,7 @@ bool init_python_vfs(void) { initialized = true; pystream.name = "python stream"; pystream.vflags = - VFS_CAN_WRITE | VFS_CAN_EXEC | VFS_CAN_READ | VFS_HAS_PREFIX; + VFS_CAN_WRITE | VFS_CAN_EXEC | VFS_CAN_READ | VFS_HAS_PREFIX; pystream.prefix = "/python/"; pystream.suffix = NULL; pystream.open = py_open; diff --git a/packages/python/pypreds.c b/packages/python/pypreds.c index 9dc6d4cbf..20cf338c8 100644 --- a/packages/python/pypreds.c +++ b/packages/python/pypreds.c @@ -26,6 +26,23 @@ static foreign_t python_len(term_t tobj, term_t tf) { len = PyObject_Length(o); pyErrorAndReturn(PL_unify_int64(tf, len)); } + +static foreign_t python_represent( term_t name, term_t tobj) { + term_t stackp = python_acquire_GIL(); + PyObject *e; + + e = term_to_python(tobj, false, NULL, true); + if (e == NULL) { + python_release_GIL(stackp); + pyErrorAndReturn(false); + } + bool b = python_assign(name, e, NULL); + python_release_GIL(stackp); + pyErrorAndReturn(b); +} + + + static foreign_t python_clear_errors(void) { PyErr_Clear(); return true; @@ -744,6 +761,7 @@ install_t install_pypreds(void) { PL_register_foreign("python_index", 3, python_index, 0); PL_register_foreign("python_field", 3, python_field, 0); PL_register_foreign("python_assign", 2, assign_python, 0); + PL_register_foreign("python_represents", 2, python_represent, 0); PL_register_foreign("python_export", 2, python_export, 0); PL_register_foreign("python_function", 1, python_function, 0); PL_register_foreign("python_slice", 4, python_slice, 0); diff --git a/packages/python/python.c b/packages/python/python.c index 7738d277b..e8b35ae9b 100644 --- a/packages/python/python.c +++ b/packages/python/python.c @@ -30,7 +30,7 @@ functor_t FUNCTOR_dollar1, FUNCTOR_abs1, FUNCTOR_all1, FUNCTOR_any1, FUNCTOR_as2 FUNCTOR_range3, FUNCTOR_sum1, FUNCTOR_pointer1, FUNCTOR_complex2, FUNCTOR_plus2, FUNCTOR_sub2, FUNCTOR_mul2, FUNCTOR_div2, FUNCTOR_hat2, FUNCTOR_colon2, FUNCTOR_comma2, FUNCTOR_equal2, FUNCTOR_sqbrackets2, - FUNCTOR_dot2, FUNCTOR_brackets1; + FUNCTOR_dot2, FUNCTOR_brackets1, FUNCTOR_var1; X_API PyObject *py_Atoms; X_API PyObject *py_Yapex; @@ -110,6 +110,7 @@ static void install_py_constants(void) { FUNCTOR_comma2 = PL_new_functor(PL_new_atom(","), 2); FUNCTOR_equal2 = PL_new_functor(PL_new_atom("="), 2); FUNCTOR_sqbrackets2 = PL_new_functor(PL_new_atom("[]"), 2); + FUNCTOR_var1 = PL_new_functor(PL_new_atom("$VAR"), 1); } foreign_t end_python(void) { diff --git a/packages/python/python.pl b/packages/python/python.pl index 7cf3cc275..85c94ef69 100644 --- a/packages/python/python.pl +++ b/packages/python/python.pl @@ -23,6 +23,7 @@ python_run_command/1, python_run_script/2, python_assign/3, + python_represents/2, python_import/1, array_to_python_list/4, array_to_python_tuple/4, diff --git a/packages/python/swig/CMakeLists.txt b/packages/python/swig/CMakeLists.txt index 6c607c007..551b6fea0 100644 --- a/packages/python/swig/CMakeLists.txt +++ b/packages/python/swig/CMakeLists.txt @@ -6,7 +6,9 @@ INCLUDE(UseSWIG) include(FindPythonModule) list (APPEND pl_library ${CMAKE_CURRENT_SOURCE_DIR}/prolog/yapi.yap ) -set (PYTHON_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/yap4py/yapi.py ${CMAKE_CURRENT_SOURCE_DIR}/yap4py/__main__.py) +set (PYTHON_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/yap4py/yapi.py + ${CMAKE_CURRENT_SOURCE_DIR}/yap4py/systuples.py + ${CMAKE_CURRENT_SOURCE_DIR}/yap4py/__main__.py) SET_SOURCE_FILES_PROPERTIES(../../swig/yap.i PROPERTIES CPLUSPLUS ON) diff --git a/packages/python/swig/prolog/yapi.yap b/packages/python/swig/prolog/yapi.yap index a540f0ad6..dbf909df0 100644 --- a/packages/python/swig/prolog/yapi.yap +++ b/packages/python/swig/prolog/yapi.yap @@ -25,18 +25,19 @@ :- python_import(yap4py.yapi). +:- python_import(json). %:- python_import(gc). :- meta_predicate( yapi_query(:,+) ). %:- start_low_level_trace. - %% @pred yapi_query( + VarList, - Dictionary) - %% - %% dictionary, Examples - %% - %% - yapi_query( VarNames, Self ) :- +%% @pred yapi_query( + VarList, - Dictionary) +%% +%% dictionary, Examples +%% +%% +yapi_query( VarNames, Self ) :- show_answer(VarNames, Dict), Self.bindings := Dict. @@ -47,6 +48,9 @@ set_preds :- fail, current_predicate(P, Q), functor(Q,P,A), + + current_predicate(P, Q), + functor(Q,P,A), atom_string(P,S), catch( := yap4py.yapi.named( S, A), @@ -72,27 +76,46 @@ python_query( Caller, String ) :- atomic_to_term( String, Goal, VarNames ), query_to_answer( Goal, VarNames, Status, Bindings), Caller.port := Status, - write_query_answer( Bindings ), - nl(user_error), - maplist(in_dict(Caller.answer, Bindings), Bindings). ->>>>>>> 37d5dcedc17b8c63cd9fa213454edb37816a130f + write_query_answer( Bindings ), + answer := {}, + foldl(ground_dict(answer), Bindings, [], Ts), + term_variables( Ts, Hidden), + foldl(bv, Hidden , 0, _), + maplist(into_dict(answer),Ts), + Caller.answer := json.dumps(answer), + S := Caller.answer, +format(user_error, '~nor ~s~n~n',S). + +bv(V,I,I1) :- + atomic_concat(['__',I],V), + I1 is I+1. + +into_dict(D,V0=T) :- + D[V0] := T. + /** * */ -in_dict(_Dict, _, var([_V0])) :- - !. -in_dict(Dict, Bindings, var([V0,V|Vs])) :- - !, - atom_to_string(V0,S0), - atom_to_string(V,S), - Dict[S] := S0, - in_dict( Dict, Bindings, var([V0|Vs])). -in_dict(Dict, Bindings, nonvar([V0|Vs], T)) :- - !, - atom_to_string(V0,S0), - term_to_string(T, S, _Bindings), - Dict[S0] := S, - in_dict( Dict, Bindings, var([V0|Vs])). -in_dict(_, _, _). +ground_dict(_Dict, var([V,V]), I, I) :- + !. +ground_dict(Dict, nonvar([V0|Vs], T),I0, [V0=T| I0]) :- + !, + ground_dict( Dict, var([V0|Vs]), I0, I0). +ground_dict(Dict, var([V0,V|Vs]), I, I) :- + !, + Dict[V]=V0, + ground_dict( Dict, var([V0|Vs]), I, I). +ground_dict(_, _, _, _). + + +bound_dict(Dict, nonvar([V0|Vs], T)) :- + !, + Dict[V0] := T, + bound_dict( Dict, var([V0|Vs])). +bound_dict(Dict, var([V0,V|Vs])) :- + !, + Dict[V] := V0, + bound_dict( Dict, var([V0|Vs])). +bound_dict(_, _). diff --git a/packages/python/swig/yap4py/yapi.py b/packages/python/swig/yap4py/yapi.py index 3763ad04b..c25157075 100644 --- a/packages/python/swig/yap4py/yapi.py +++ b/packages/python/swig/yap4py/yapi.py @@ -1,22 +1,12 @@ import readline from yap4py.yap import * +from yap4py.systuples import * from os.path import join, dirname -from collections import namedtuple + import sys yap_lib_path = dirname(__file__) -bindvars = namedtuple('bindvars', 'list') -compile = namedtuple('compile', 'file') -jupyter_query = namedtuple('jupyter_query', 'vars dict') -library = namedtuple('library', 'listfiles') -prolog_library = namedtuple('prolog_library', 'listfiles') -python_query = namedtuple('python_query', 'vars dict') -set_prolog_flag = namedtuple('set_prolog_flag', 'flag new_value') -show_answer = namedtuple('show_answer', 'vars dict') -v0 = namedtuple('v', 'slot') -yap_query = namedtuple('yap_query', 'query owner') -yapi_query = namedtuple('yapi_query', 'vars dict') class Engine( YAPEngine ): @@ -140,7 +130,7 @@ class YAPShell: # construct a query from a one-line string # q is opaque to Python # - #q = engine.query(python_query(self, s)) + # q = engine.query(python_query(self, s)) # # # vs is the list of variables # you can print it out, the left-side is the variable name, @@ -160,7 +150,7 @@ class YAPShell: q = Query( engine, python_query( engine, query) ) for answer in q: bindings += [answer] - if g.done(): + if q.done(): return bindings if loop: continue diff --git a/packages/python/yap_kernel/yap_ipython/prolog/jupyter.yap b/packages/python/yap_kernel/yap_ipython/prolog/jupyter.yap index 09f21f89b..4e1eab760 100644 --- a/packages/python/yap_kernel/yap_ipython/prolog/jupyter.yap +++ b/packages/python/yap_kernel/yap_ipython/prolog/jupyter.yap @@ -8,7 +8,7 @@ :- yap_flag(gc_trace,verbose). /* :- module( jupyter, - [jupyter_query/3, + [jupyter_queryl/3, blank/1, streams/2 ] @@ -27,6 +27,8 @@ :- python_import(sys). + + jupyter_query(Caller, Cell, Line ) :- jupyter_cell(Caller, Cell, Line). @@ -42,7 +44,7 @@ jupyter_cell(Caller, _, Line ) :- catch( python_query(Query,Line), error(A,B), - (writeln(A,B),system_error(A,B)) + system_error(A,B) ). restreams(call) :- diff --git a/packages/python/yap_kernel/yap_ipython/yapi.py b/packages/python/yap_kernel/yap_ipython/yapi.py index ad47d4818..bfd9af7e9 100644 --- a/packages/python/yap_kernel/yap_ipython/yapi.py +++ b/packages/python/yap_kernel/yap_ipython/yapi.py @@ -5,6 +5,7 @@ from typing import List from traitlets import Bool +from yap4py.systuples import * from yap4py.yapi import * from IPython.core.completer import Completer # import IPython.core @@ -18,23 +19,8 @@ from ipython_genutils.py3compat import builtin_mod from yap_kernel.displayhook import ZMQShellDisplayHook -from collections import namedtuple import traceback -use_module = namedtuple('use_module', 'file') -bindvars = namedtuple('bindvars', 'list') -library = namedtuple('library', 'list') -v = namedtuple('_', 'slot') -load_files = namedtuple('load_files', 'file ofile args') -python_query = namedtuple('python_query', 'query_mgr string') -jupyter_call = namedtuple('jupyter_call', 'self program query') -enter_cell = namedtuple('enter_cell', 'self' ) -exit_cell = namedtuple('exit_cell', 'self' ) -completions = namedtuple('completions', 'txt self' ) -errors = namedtuple('errors', 'self text' ) -streams = namedtuple('streams', 'text' ) -nostreams = namedtuple('nostreams', ' text' ) - global engine def tracefunc(frame, event, arg, indent=[0]): @@ -70,7 +56,7 @@ class YAPInputSplitter(InputSplitter): logical_line_transforms=None): self._buffer_raw = [] self._validate = True - self.yapeng = engine + self.engine = engine self.shell = shell if physical_line_transforms is not None: @@ -392,7 +378,7 @@ class YAPCompleter(Completer): return ( magic.startswith(bare_text) and magic not in global_matches ) else: - def matches(magic): + def matches(magic): return magic.startswith(bare_text) comp = [ pre2+m for m in cell_magics if matches(m)] @@ -503,7 +489,7 @@ class YAPCompleter(Completer): magic_res = self.magic_matches(text) return text, magic_res self.matches = [] - prolog_res = self.shell.yapeng.mgoal(completions(text, self), "user",True) + prolog_res = self.shell.engine.mgoal(completions(text, self), "user",True) return text, self.matches @@ -515,9 +501,9 @@ class YAPRun(InteractiveShell): def __init__(self, shell): self.shell = shell - self.yapeng = JupyterEngine() + self.engine = JupyterEngine() global engine - engine = self.yapeng + engine = self.engine self.errors = [] self.query = None self.os = None @@ -525,8 +511,9 @@ class YAPRun(InteractiveShell): self.port = "None" self.answers = None self.bindings = dicts = [] - self.shell.yapeng = self.yapeng + self.shell.engine = self.engine self._get_exc_info = shell._get_exc_info + self.iterations = 0 def showtraceback(self, exc_info): @@ -547,57 +534,46 @@ class YAPRun(InteractiveShell): return self.errors self.errors=[] (text,_,_,_) = self.clean_end(text) - self.yapeng.mgoal(errors(self,text),"user",True) + self.engine.mgoal(errors(self,text),"user",True) return self.errors - def prolog(self, s): + def prolog(self, s, result): # # construct a self.queryuery from a one-line string # self.query is opaque to Python try: - program,squery,stop,howmany = self.prolog_cell(s) - found = False + program,squery,_ ,howmany = self.prolog_cell(s) # sys.settrace(tracefunc) - if self.query and self.os == program+squery: + if self.query and self.os == (program,squery): howmany += self.iterations - found = howmany != 0 else: if self.query: self.query.close() self.query = None - self.port = None self.answers = [] - self.os = program+squery + self.os = (program,squery) self.iterations = 0 - pg = jupyter_call( self, program, squery) - self.query = self.yapeng.query(pg) + pg = jupyter_query(self.engine,program,squery) + self.query = Query(self.engine, pg) self.answers = [] - self.port = "call" - found = False - self.answer = {} - while self.query.next(): - #sys.stderr.write('B '+str( self.answer) +'\n') - #sys.stderr.write('C '+ str(self.port) +'\n'+'\n') - found = True - print( "uek",self.answer ) - #self.answers += [self.answer] - print( "ek",self.answers ) + for answer in self.query: + self.answers += [answer] self.iterations += 1 - if self.port == "exit" or stop or howmany == self.iterations: - self.os = None - self.query.close() - self.query = None - if found: - sys.stderr.write('Completed, with '+str(self.answers)+'\n') - result.result = self.answers - return result.results + + self.os = None + self.query.close() + self.query = None + if self.answers: + sys.stderr.write('Completed, with '+str(self.answers)+'\n') + result.result = self.answers + return result.result except Exception as e: sys.stderr.write('Exception '+str(e)+'in query '+ str(self.query)+ - ':'+pg+'\n '+str( self.bindings)+ '\n') + '\n '+str( self.bindings)+ '\n') has_raised = True result.result = [] - return result + return result.result @@ -720,7 +696,7 @@ class YAPRun(InteractiveShell): try: builtin_mod.input = input self.shell.input = input - self.yapeng.mgoal(streams(True),"user", True) + self.engine.mgoal(streams(True),"user", True) if cell.strip('\n \t'): #create a Trace object, telling it what to ignore, and whether to # do tracing or line-counting or both. @@ -736,10 +712,11 @@ class YAPRun(InteractiveShell): # run the new command using the given tracer # # tracer.runfunc(f,self,cell,state) - self.prolog( cell ) - # state = tracer.runfunc(jupyter_query( self, cell ) ) - self.shell.last_execution_succeeded = True - result.result = [] + answers = self.prolog( cell, result ) + # state = tracer.runfunc(hist + # er_query( self, cell ) ) + self.shell.last_execution_succeeded = True + result.result = answers except Exception as e: has_raised = True result.result = [] @@ -766,7 +743,7 @@ class YAPRun(InteractiveShell): # Each cell is a *single* input, regardless of how many lines it has self.shell.execution_count += 1 - self.yapeng.mgoal(streams(False),"user", True) + self.engine.mgoal(streams(False),"user", True) return def clean_end(self,s): diff --git a/pl/control.yap b/pl/control.yap index b6307a5d8..c00c55652 100644 --- a/pl/control.yap +++ b/pl/control.yap @@ -389,20 +389,20 @@ version(T) :- fail. '$set_toplevel_hook'(_). -query_to_answer(G, V, Status, Bindings) :- - gated_call( true, (G,'$delayed_goals'(G, V, Vs, LGs, _DCP)), Status, '$answer'( Status, LGs, Vs, Bindings) ). +query_to_answer(G, V, Status, Vs) :- + gated_call( true, (G,'$delayed_goals'(G, V, Vs, LGs, _DCP)), Status, '$answer'( Status, LGs, Vs ) ). - '$answer'( exit, LGs, Vs, Bindings) :- - !, - '$process_answer'(Vs, LGs, Bindings). - '$answer'( answer, LGs, Vs, Bindings) :- - !, - '$process_answer'(Vs, LGs, Bindings). -'$answer'(!, _, _, _). -'$answer'(fail,_,_,_). +'$answer'( exit, LGs, Vs) :- + !. %, +%'$process_answer'(Vs, LGs). +'$answer'( answer, LGs, Vs) :- + !. %, +% '$process_answer'(Vs, LGs, Bindings). +'$answer'(!, _, _). +'$answer'(fail,_,_). '$answer'(exception(E),_,_,_) :- '$LoopError'(E,error). -'$answer'(external_exception(_),_,_,_). +'$answer'(external_exception(_),_,_). %% @} diff --git a/pl/top.yap b/pl/top.yap index 00d5bf2ca..b48018a63 100644 --- a/pl/top.yap +++ b/pl/top.yap @@ -330,10 +330,10 @@ live :- '$process_answer'(Vs, LGs, Bindings) :- -'$purge_dontcares'(Vs,IVs), -'$sort'(IVs, NVs), -'$prep_answer_var_by_var'(NVs, LAnsw, LGs), -'$name_vars_in_goals'(LAnsw, Vs, Bindings). + '$purge_dontcares'(Vs,IVs), + '$sort'(IVs, NVs), + '$prep_answer_var_by_var'(NVs, LAnsw, LGs), + '$name_vars_in_goals'(LAnsw, Vs, Bindings). % % *-> at this point would require compiler support, which does not exist. diff --git a/pl/yapor.yap b/pl/yapor.yap index ee58b3e7c..2684a2f94 100644 --- a/pl/yapor.yap +++ b/pl/yapor.yap @@ -1,3 +1,4 @@ + /** * @file yapor.yap * @author VITOR SANTOS COSTA