From bac1b63080f1b04a22df3ce8b8b6667054c64df6 Mon Sep 17 00:00:00 2001 From: Vitor Santos Costa Date: Mon, 23 Jul 2018 17:13:51 +0100 Subject: [PATCH] ipython --- C/errors.c | 1 + include/YapStreams.h | 9 +++ library/dialect/swi/fli/swi.c | 3 +- os/yapio.h | 6 -- packages/packages/python/pypreds.c | 2 +- packages/python/py4yap.h | 7 ++ packages/python/pybips.c | 7 +- packages/python/pypreds.c | 72 +++++++++++-------- packages/python/python.c | 2 + packages/python/swig/prolog/yapi.yap | 11 ++- packages/python/yap_kernel/CMakeLists.txt | 21 +++--- .../yap_kernel/yap_ipython/prolog/jupyter.yap | 6 +- .../python/yap_kernel/yap_ipython/yapi.py | 55 +++++++++----- 13 files changed, 123 insertions(+), 79 deletions(-) diff --git a/C/errors.c b/C/errors.c index 65ede1582..5cd46bf6a 100755 --- a/C/errors.c +++ b/C/errors.c @@ -17,6 +17,7 @@ #include "absmi.h" #include "yapio.h" +#include "YapStreams.h" #if HAVE_STDARG_H #include #endif diff --git a/include/YapStreams.h b/include/YapStreams.h index 27a1a769c..d0468afc0 100644 --- a/include/YapStreams.h +++ b/include/YapStreams.h @@ -265,4 +265,13 @@ typedef struct stream_desc { encoding_t encoding; /** current encoding for stream */ } StreamDesc; + + +extern bool Yap_set_stream_to_buf(StreamDesc *st, const char *bufi, + size_t nchars + #ifdef USES_REGS + USES_REGS + #endif + ); + #endif diff --git a/library/dialect/swi/fli/swi.c b/library/dialect/swi/fli/swi.c index 1cdfef195..93443b87b 100755 --- a/library/dialect/swi/fli/swi.c +++ b/library/dialect/swi/fli/swi.c @@ -221,8 +221,9 @@ X_API int PL_get_nchars(term_t l, size_t *lengthp, char **s, unsigned flags) { if (s) { size_t len = strlen(out.val.c); if (flags & (BUF_DISCARDABLE | BUF_RING)) { - strncpy(LOCAL_FileNameBuf, out.val.c, YAP_FILENAME_MAX); + if (!*s) *s = LOCAL_FileNameBuf; + strncpy(*s, out.val.c, YAP_FILENAME_MAX); pop_text_stack(lvl); return true; } diff --git a/os/yapio.h b/os/yapio.h index 76ee6f0bb..4344623e4 100644 --- a/os/yapio.h +++ b/os/yapio.h @@ -22,8 +22,6 @@ #undef HAVE_LIBREADLINE #endif -#include "YapStreams.h" - #include #include @@ -196,9 +194,5 @@ extern uint64_t Yap_StartOfWTimes; extern bool Yap_HandleSIGINT(void); -extern bool Yap_set_stream_to_buf(StreamDesc *st, const char *bufi, - size_t nchars USES_REGS); - - #endif diff --git a/packages/packages/python/pypreds.c b/packages/packages/python/pypreds.c index a62b830c0..e38221148 100644 --- a/packages/packages/python/pypreds.c +++ b/packages/packages/python/pypreds.c @@ -558,7 +558,7 @@ term_t t0 = python_acquire_GIL(); *s++ = '.'; s[0] = '\0'; } else if (!PL_get_nchars(mname, &len, &s, - CVT_ATOM | CVT_EXCEPTION | REP_UTF8)) { + CVT_ATOM | CVT_STRING| CVT_EXCEPTION | REP_UTF8)) { python_release_GIL(t0); pyErrorAndReturn(false, false); } else { diff --git a/packages/python/py4yap.h b/packages/python/py4yap.h index cb925e731..2c8eb27b8 100644 --- a/packages/python/py4yap.h +++ b/packages/python/py4yap.h @@ -1,7 +1,14 @@ +#undef PASS_REGS +#undef USES_REGS + #ifndef PY4YAP_H #define PY4YAP_H 1 + +#define PASS_REGS +#define USES_REGSg + //@{ /** @brief Prolog to Python library diff --git a/packages/python/pybips.c b/packages/python/pybips.c index e52850146..aa89c596f 100644 --- a/packages/python/pybips.c +++ b/packages/python/pybips.c @@ -710,10 +710,9 @@ static bool legal_symbol(const char *s) { } PyObject *term_to_nametuple(const char *s, arity_t arity, PyObject *tuple) { - PyObject *o, *d = NULL; if (legal_symbol(s)) { PyTypeObject *typp; - PyObject *key = PyUnicode_FromString(s); + PyObject *key = PyUnicode_FromString(s), *d; if (Py_f2p && (d = PyList_GetItem(Py_f2p, arity)) && PyDict_Contains(d, key)) { typp = (PyTypeObject *)PyDict_GetItem(d, key); @@ -737,10 +736,10 @@ PyObject *term_to_nametuple(const char *s, arity_t arity, PyObject *tuple) { // PyModule_AddGObject(py_Main, s, (PyObject *)typp); if (d && !PyDict_Contains(d, key)) PyDict_SetItem(d, key, (PyObject *)typp); - Py_DECREF(key); + Py_INCREF(key); Py_INCREF(typp); } - o = PyStructSequence_New(typp); + PyObject *o = PyStructSequence_New(typp); Py_INCREF(typp); arity_t i; for (i = 0; i < arity; i++) { diff --git a/packages/python/pypreds.c b/packages/python/pypreds.c index 758458796..666222fae 100644 --- a/packages/python/pypreds.c +++ b/packages/python/pypreds.c @@ -1,4 +1,6 @@ +#include "Yap.h" + #include "py4yap.h" PyObject *py_Main; @@ -544,36 +546,46 @@ static int python_import(term_t mname, term_t mod) { PyObject *pName; bool do_as = false; - term_t arg = PL_new_term_ref(); - char s0[MAXPATHLEN], *s = s0, *t; - functor_t f; - while (true) { - size_t len; - //PyErr_Clear(); - len = (MAXPATHLEN - 1) - (s - s0); - if (PL_is_pair(mname)) { - char *sa = NULL; - if (!PL_get_arg(1, mname, arg) || !PL_get_chars(arg, &sa, CVT_ALL | CVT_EXCEPTION | REP_UTF8) || - !PL_get_arg(2, mname, mname)) { - pyErrorAndReturn(false); - } - PL_get_chars(arg, &sa, CVT_ALL | CVT_EXCEPTION | REP_UTF8); - strcpy(s, sa); - s += strlen(s); - *s++ = '.'; - s[0] = '\0'; - } else if (PL_get_functor(mname, &f) && f == FUNCTOR_as2 && PL_get_arg(2, mname,arg) && - PL_get_chars(arg, &t, CVT_ALL | CVT_EXCEPTION | REP_UTF8)) { - do_as = true; - PL_get_arg(1, mname,mname); - } else if (!PL_get_nchars(mname, &len, &s, - CVT_ALL | CVT_EXCEPTION | REP_UTF8)) { - pyErrorAndReturn(false); - } else { - break; - } + char s0[MAXPATHLEN], *s = s0; + const char*sn; + Term t = Deref(ARG1), sm; + if (IsApplTerm(t)) { + Functor f = FunctorOfTerm(t); + if (f != Yap_MkFunctor(Yap_LookupAtom("as"),2)) + return false; + do_as = true; + sm = ArgOfTerm(2,t); + if (IsAtomTerm(sm)) + sn = RepAtom(AtomOfTerm(sm))->StrOfAE; + else if (IsStringTerm(sm)) + sn = StringOfTerm(sm); + else + return false; } - term_t t0 = python_acquire_GIL(); + while (IsPairTerm(t)) { + Term ti = HeadOfTerm(t); + Term t2 = TailOfTerm(t); + if (IsAtomTerm(ti)) + sn = RepAtom(AtomOfTerm(ti))->StrOfAE; + else if (IsStringTerm(ti)) + sn = StringOfTerm(ti); + else + return false; + strcat(s,sn); + if (IsPairTerm(t2)) { + strcat(s,"."); + continue; + } + sm = ArgOfTerm(2,t); + } + sm = t; + if (IsAtomTerm(sm)) + sn = RepAtom(AtomOfTerm(sm))->StrOfAE; + else if (IsStringTerm(sm)) + sn = StringOfTerm(sm); + else + return false; + term_t t0 = python_acquire_GIL(); #if PY_MAJOR_VERSION < 3 pName = PyString_FromString(s0); #else @@ -595,7 +607,7 @@ static int python_import(term_t mname, term_t mod) { { foreign_t rc = address_to_term(pModule, mod); - if (do_as && PyObject_SetAttrString(py_Main, t, pModule) <0) + if (do_as && PyObject_SetAttrString(py_Main, sn, pModule) <0) return false; python_release_GIL(t0); pyErrorAndReturn(rc); diff --git a/packages/python/python.c b/packages/python/python.c index 09ff42390..b48b80e00 100644 --- a/packages/python/python.c +++ b/packages/python/python.c @@ -3,6 +3,8 @@ #include "py4yap.h" #include +#define USES_REGS + #include "YapStreams.h" atom_t ATOM_true, ATOM_false, ATOM_colon, ATOM_dot, ATOM_none, ATOM_t, diff --git a/packages/python/swig/prolog/yapi.yap b/packages/python/swig/prolog/yapi.yap index 76dea4574..23da8e0f5 100644 --- a/packages/python/swig/prolog/yapi.yap +++ b/packages/python/swig/prolog/yapi.yap @@ -71,21 +71,20 @@ argi(N,I,I1) :- python_query( Caller, String ) :- atomic_to_term( String, Goal, VarNames ), query_to_answer( Goal, VarNames, Status, Bindings), - atom_to_string( Status, SStatus ), - % Caller.port := SStatus, + Caller.port := Status, write_query_answer( Bindings ), nl(user_error), Caller.answer := {}, - maplist(in_dict(Caller.answer), Bindings). - + maplist(in_dict(Caller.answer), Bindings). + in_dict(Dict, var([V0,V|Vs])) :- !, Dict[V] := V0, in_dict( Dict, var([V0|Vs])). in_dict(_Dict, var([_],_G)) :- !. in_dict(Dict, nonvar([V0|Vs],G)) :- !, - Dict[V0] := G, +term_to_atom(G,A,_), + Dict[V0] := A, in_dict( Dict, nonvar(Vs, G) ). in_dict(_Dict, nonvar([],_G)) :- !. in_dict(_, _) - diff --git a/packages/python/yap_kernel/CMakeLists.txt b/packages/python/yap_kernel/CMakeLists.txt index faa4eaf87..56aa585b1 100644 --- a/packages/python/yap_kernel/CMakeLists.txt +++ b/packages/python/yap_kernel/CMakeLists.txt @@ -287,12 +287,6 @@ set(FILES ${PYTHON_SOURCES} ${PL_SOURCES} ${EXTRAS} ${RESOURCES}) set(SETUP_PY ${CMAKE_CURRENT_BINARY_DIR}/setup.py) -add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/yap.tgz - COMMAND ${CMAKE_COMMAND} -E tar czf ${CMAKE_CURRENT_BINARY_DIR}/yap.tgz ${FILES} - WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} - DEPENDS ${FILES} -) - add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/yap_kernel/resources/logo-32x32.png COMMAND ${CMAKE_COMMAND} -E make_directory yap_kernel/resources @@ -315,16 +309,23 @@ add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/yap_kernel/resources/prolo DEPENDS ${CMAKE_SOURCE_DIR}/misc/editors/yap.js ) +foreach(f ${FILES}) + add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${f} + COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/${f} ${CMAKE_CURRENT_BINARY_DIR}/${f} + DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/${f} + ) + list(APPEND OUTS ${CMAKE_CURRENT_BINARY_DIR}/${f} ) +endforeach() + add_custom_target(YAP_KERNEL ALL - COMMAND ${CMAKE_COMMAND} -E tar xzf ${CMAKE_CURRENT_BINARY_DIR}/yap.tgz + COMMAND ${PYTHON_EXECUTABLE} ${SETUP_PY} build sdist bdist WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} - DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/yap_kernel/resources/logo-32x32.png ${CMAKE_CURRENT_BINARY_DIR}/yap_kernel/resources/logo-64x64.png yap.tgz ${CMAKE_CURRENT_BINARY_DIR}/yap_kernel/resources/kernel.js ${CMAKE_CURRENT_BINARY_DIR}/yap_kernel/resources/prolog.js ${CMAKE_CURRENT_BINARY_DIR}/yap.tgz + DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/yap_kernel/resources/logo-32x32.png ${CMAKE_CURRENT_BINARY_DIR}/yap_kernel/resources/logo-64x64.png ${CMAKE_CURRENT_BINARY_DIR}/yap_kernel/resources/kernel.js ${CMAKE_CURRENT_BINARY_DIR}/yap_kernel/resources/prolog.js ${OUTS} ) install(CODE "execute_process( - COMMAND ${PYTHON_EXECUTABLE} ${SETUP_PY} build sdist bdist - COMMAND ${PYTHON_EXECUTABLE} -m pip install ${PYTHON_USER_INSTALL} --ignore-installed --no-deps . + COMMAND ${PYTHON_EXECUTABLE} -m pip install ${PYTHON_USER_INSTALL} --ignore-installed --no-deps . COMMAND ${PYTHON_EXECUTABLE} -m yap_kernel.kernelspec ERROR_VARIABLE setupErr OUTPUT_VARIABLE setupOut diff --git a/packages/python/yap_kernel/yap_ipython/prolog/jupyter.yap b/packages/python/yap_kernel/yap_ipython/prolog/jupyter.yap index d9696d51f..b1bf13e92 100644 --- a/packages/python/yap_kernel/yap_ipython/prolog/jupyter.yap +++ b/packages/python/yap_kernel/yap_ipython/prolog/jupyter.yap @@ -33,14 +33,14 @@ jupyter_query(Caller, Cell, Line ) :- jupyter_cell(_Caller, Cell, _Line) :- jupyter_consult(Cell), %stack_dump, fail. -jupyter_cell( _Caller, _, `` ) :- !. +jupyter_cell( _Caller, _, ¨¨ ) :- !. jupyter_cell( _Caller, _, Line ) :- blank( Line ), !. jupyter_cell(Caller, _, Line ) :- - Self := Caller.query, + Query = Caller, catch( - python_query(Self,Line), + python_query(Query,Line), E=error(A,B), system_error(A,B) ). diff --git a/packages/python/yap_kernel/yap_ipython/yapi.py b/packages/python/yap_kernel/yap_ipython/yapi.py index 3dfe95be0..70673485d 100644 --- a/packages/python/yap_kernel/yap_ipython/yapi.py +++ b/packages/python/yap_kernel/yap_ipython/yapi.py @@ -16,6 +16,7 @@ from yap_ipython.core.interactiveshell import * from yap_ipython.core import interactiveshell from collections import namedtuple +import traceback use_module = namedtuple('use_module', 'file') bindvars = namedtuple('bindvars', 'list') @@ -516,13 +517,22 @@ class YAPRun: self.query = None self.os = None self.it = None + self.port = None + self.answers = None + self.bindings = dicts = [] self.shell.yapeng = self.yapeng self._get_exc_info = shell._get_exc_info - def showtraceback(self, tuple): - return None - + def showtraceback(self, exc_info): + try: + (etype, value, tb) = e + traceback.print_exception(etype, value, tb) + except: + print(e) + pass + + def syntaxErrors(self, text): """Return whether a legal query """ @@ -545,28 +555,34 @@ class YAPRun: # sys.settrace(tracefunc) 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 = None self.os = program+squery self.iterations = 0 - self.bindings = [] pg = jupyter_query( self, program, squery) self.query = self.yapeng.query(pg) - self.query.answer = {} + self.answers = [] + self.port = "call" + self.answer = {} while self.query.next(): - answer = self.query.answer + #sys.stderr.write('B '+str( self.answer) +'\n') + #sys.stderr.write('C '+ str(self.port) +'\n'+'\n') found = True - self.bindings += [answer] + self.answers += [self.answer] self.iterations += 1 - if self.query.port == "exit": + if self.port == "exit": self.os = None - sys.stderr.writeln('Done, with', self.bindings) + sys.stderr.write('Done, with'+str(self.answers)+'\n') return True,self.bindings if stop or howmany == self.iterations: - return True, self.bindings + return True, self.answers if found: - sys.stderr.writeln('Done, with ', self.bindings) + sys.stderr.write('Done, with '+str(self.answers)+'\n') else: self.os = None self.query.close() @@ -574,7 +590,7 @@ class YAPRun: sys.stderr.write('Fail\n') return True,self.bindings except Exception as e: - sys.stderr.write('Exception after', self.bindings, '\n') + sys.stderr.write('Exception '+str(e)+' after '+str( self.bindings)+ '\n') has_raised = True return False,[] @@ -660,7 +676,7 @@ class YAPRun: for i in self.syntaxErrors(raw_cell): try: (what,lin,_,text) = i - e = SyntaxError(what, ("", lin, 1, text)) + e = SyntaxError(what, ("", lin, 1, text+'\n')) raise e except SyntaxError: self.shell.showsyntaxerror( ) @@ -712,7 +728,6 @@ class YAPRun: has_raised = False try: self.yapeng.mgoal(streams(True),"user", True) - self.bindings = dicts = [] if cell.strip('\n \t'): #create a Trace object, telling it what to ignore, and whether to # do tracing or line-counting or both. @@ -731,14 +746,17 @@ class YAPRun: self.jupyter_query( cell ) # state = tracer.runfunc(jupyter_query( self, cell ) ) self.shell.last_execution_succeeded = True - self.result.result = (True, dicts) except Exception as e: has_raised = True self.result.result = False - self.yapeng.mgoal(streams(False),"user", True) + try: + (etype, value, tb) = e + traceback.print_exception(etype, value, tb) + except: + print(e) + pass - self.yapeng.mgoal(streams(False),"user", True) self.shell.last_execution_succeeded = not has_raised # Reset this so later displayed values do not modify the @@ -755,6 +773,7 @@ class YAPRun: # 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) return self.result def clean_end(self,s): @@ -796,7 +815,7 @@ class YAPRun: last line if the last line is non-empty and does not terminate on a dot. You can also finish with - - `;`: you request all solutions + - `*`: you request all solutions - ';'[N]: you want an answer; optionally you want N answers If the line terminates on a `*/` or starts on a `%` we assume the line