new jupiter intrface

This commit is contained in:
Vitor Santos Costa 2017-08-21 12:36:48 +01:00
parent 54234c7e1d
commit 3e6c24cc0c
40 changed files with 6329 additions and 1117 deletions

0
C/y Normal file
View File

0
packages/__init__.py Normal file
View File

View File

@ -0,0 +1,150 @@
#include "py4yap.h"
static foreign_t array_to_python_list(term_t addr, term_t type, term_t szt,
term_t py) {
void *src;
Py_ssize_t sz, i;
int is_float;
if (!PL_get_pointer(addr, &src) || !PL_get_bool(type, &is_float) ||
!PL_get_intptr(szt, &sz))
return false;
PyObject *list = PyList_New(sz);
if (!list)
return false;
if (is_float) {
double *v = (double *)src;
for (i = 0; i < sz; i++) {
PyObject *x = PyFloat_FromDouble(v[i]);
PyList_SET_ITEM(list, i, x);
}
} else {
YAP_Int *v = (YAP_Int *)src;
for (i = 0; i < sz; i++) {
PyObject *x = PyFloat_FromDouble(v[i]);
PyList_SET_ITEM(list, i, x);
}
}
if (PL_is_variable(py)) {
return address_to_term(list, py);
}
return assign_to_symbol(py, list);
}
static foreign_t array_to_python_tuple(term_t addr, term_t type, term_t szt,
term_t py) {
void *src;
Py_ssize_t sz, i;
int is_float;
if (!PL_get_pointer(addr, &src) || !PL_get_bool(type, &is_float) ||
!PL_get_intptr(szt, &sz))
return false;
PyObject *list = PyTuple_New(sz);
if (!list)
return false;
if (is_float) {
double *v = (double *)src;
for (i = 0; i < sz; i++) {
PyObject *x;
x = PyFloat_FromDouble(v[i]);
if (PyTuple_SetItem(list, i, x)) {
PyErr_Print();
return FALSE;
}
}
} else {
int32_t *v = (int32_t *)src;
PyObject *x;
for (i = 0; i < sz; i++) {
#if PY_MAJOR_VERSION < 3
x = PyInt_FromLong(v[i]);
#else
x = PyLong_FromLong(v[i]);
#endif
if (PyTuple_SetItem(list, i, x)) {
PyErr_Print();
return FALSE;
}
}
}
if (PL_is_variable(py)) {
return address_to_term(list, py);
}
return assign_to_symbol(py, list);
}
static foreign_t array_to_python_view(term_t addr, term_t type, term_t szt,
term_t colt, term_t py) {
void *src;
Py_ssize_t sz, rows;
int is_float;
Py_ssize_t shape[2];
if (!PL_get_pointer(addr, &src) || !PL_get_bool(type, &is_float) ||
!PL_get_intptr(szt, &sz) || !PL_get_intptr(colt, &rows))
return false;
Py_buffer buf;
buf.buf = src;
if (is_float) {
buf.len = sz * sizeof(double);
buf.itemsize = sizeof(double);
} else {
buf.len = sz * sizeof(YAP_Int);
buf.itemsize = sizeof(YAP_Int);
}
buf.readonly = false;
buf.format = NULL;
buf.ndim = 2;
buf.shape = shape;
buf.strides = NULL;
buf.suboffsets = NULL;
PyObject *o = PyMemoryView_FromBuffer(&buf);
if (!o) {
PyErr_Print();
return false;
}
if (PL_is_variable(py)) {
return address_to_term(o, py);
}
return assign_to_symbol(py, o);
}
static foreign_t prolog_list_to_python_list(term_t plist, term_t pyt, term_t tlen) {
size_t sz, i;
PyErr_Clear();
PyObject *pyl = term_to_python(pyt, true, NULL);
term_t targ = PL_new_term_ref();
if (PL_skip_list(plist, targ, &sz) <0 || ! PL_get_nil(targ)) {
pyErrorAndReturn( false, false);
}
if (!PyList_Check(pyl))
{
pyErrorAndReturn( false, false);
}
if (sz > PyList_GET_SIZE(pyl))
pyErrorAndReturn( false, false);
for (i=0; i < sz; i++) {
if (!PL_get_list(plist, targ, plist)) {
pyErrorAndReturn( false, false);
}
PyObject *t = term_to_python(targ, true, NULL);
PyList_SET_ITEM(pyl, i, t);
}
if (PL_is_variable(tlen)) {
PL_unify_int64(tlen, sz);
} else {
python_assign(tlen, PyLong_FromUnsignedLong(sz), NULL);
}
pyErrorAndReturn( true, false);
}
install_t install_pl2pl(void) {
PL_register_foreign("array_to_python_list", 4, array_to_python_list, 0);
PL_register_foreign("array_to_python_tuple", 4, array_to_python_tuple, 0);
PL_register_foreign("array_to_python_view", 5, array_to_python_view, 0);
PL_register_foreign("prolog_list_to_python_list", 3, prolog_list_to_python_list, 0);
}

View File

@ -0,0 +1,214 @@
#include "py4yap.h"
extern PyObject *py_Local, *py_Global;
PyObject *YE(term_t t, int line, const char *file, const char *code) {
YAPPy_ThrowError__(file, code, line, SYSTEM_ERROR_INTERNAL,t,"");
}
void YEM(const char *exp, int line, const char *file, const char *code) {
fprintf(stderr, "**** Warning,%s@%s:%d: failed while executing %s\n", code,
file, line, exp);
}
static PyObject *s_to_python(const char *s, bool eval, PyObject *p0) {
PyObject *o;
if (eval) {
o = PythonLookup(s, p0);
/* if (!o)
return o;
*/
} else {
o = PythonLookupSpecial(s);
}
if (o) {
Py_INCREF(o);
return CHECKNULL(YAP_MkStringTerm(s), o);
} else {
PyObject *pobj = PyUnicode_DecodeUTF8(s, strlen(s), NULL);
return pobj;
}
}
/**
* obtain the object matching a certain string.
*
* @param t handle to Prolog term
* @param t whether should try to evaluate evaluables.
*
* @return a Python object descriptor or NULL if failed
*/
X_API PyObject *string_to_python(const char *s, bool eval, PyObject *p0) {
char *buf = malloc(strlen(s) + 1), *child;
PyObject *p1;
while ((child = strchr(s, '.')) != NULL) {
size_t len = child - s;
strncpy(buf, s, len);
buf[len] = '\0';
p1 = s_to_python(buf, eval, p0);
Py_DecRef(p0);
Py_IncRef(p1)
s = child + 1;
p0 = p1;
}
p1 = s_to_python(s, eval, p0);
Py_DecRef(p0);
return p1;
}
/**
* term_to_python translates and evaluates from Prolog to Python
*
* @param t handle to Prolog term
* @param t whether should try to evaluate evaluables.
*
* @return a Python object descriptor or NULL if failed
*/
PyObject *term_to_python(term_t t, bool eval, PyObject *o) {
// o≈
PyObject *o;\
YAP_Term yt = YAP_GetFromSlot(t);
// Yap_DebugPlWriteln(yt);
switch (PL_term_type(t)) {
case PL_VARIABLE: {
if (t == 0) {
YAPPy_ThrowErrorYA(SYSTEM_ERROR_INTERNAL,t,"");
t }
PyObject *out = PyTuple_New(1);
PyTuple_SET_ITEM(out, 0, PyLong_FromLong(t));
Py_IncRef(out);
rc = term_to_nametuple("v", 1, out);
Py_IncRef(rc);
};
case PL_ATOM: {
YAP_Atom at = YAP_AtomOfTerm(yt);
const char *s;
s = YAP_AtomName(at);
if (eval) {
o = PythonLookup(s, o);
/* if (!o)
return o;
*/
} else {
o = PythonLookupSpecial(s);
}
if (o) {
Py_INCREF(o);
return CHECKNULL(t, o);
}
}
case PL_STRING: {
const char *s = NULL;
if (YAP_IsAtomTerm(yt)) {
s = YAP_AtomName(YAP_AtomOfTerm(yt));
} else if (YAP_IsStringTerm(yt)) {
s = YAP_StringOfTerm(yt);
} else {
return CHECKNULL(t, NULL);
}
#if PY_MAJOR_VERSION < 3
if (proper_ascii_string(s)) {
PyObject *o = PyString_FromStringAndSize(s, strlen(s));
Py_IncRef(o)
return CHECKNULL(t, o);
} else
#endif
{
// char *p = malloc(strlen(s)+1);
//strcpy(p, s);
PyObject *pobj = PyUnicode_FromString(s);
Py_IncRef(pobj);
return CHECKNULL(t, pobj);
}
} break;
case PL_INTEGER: {
int64_t j;
if (!PL_get_int64_ex(t, &j))
return CHECKNULL(t, NULL);
#if PY_MAJOR_VERSION < 3
PyObject *o = PyInt_FromLong(j);
return CHECKNULL(t, o);
#else
PyObject *o = PyLong_FromLong(j);
return CHECKNULL(t, o);
#endif
}
case PL_FLOAT: {
PyObject *out;
double fl;
if (!PL_get_float(t, &fl))
return CHECKNULL(t, NULL);
out = PyFloat_FromDouble(fl);
return CHECKNULL(t, out);
}
default: {
term_t tail = PL_new_term_ref(), arg;
size_t len, i;
if (PL_skip_list(t, tail, &len) && PL_get_nil(tail)) {
PyObject *out, *a;
arg = tail;
out = PyList_New(len);
if (!out) {
PL_reset_term_refs(tail);
return CHECKNULL(t, Py_None);
}
for (i = 0; i < len; i++) {
if (!PL_get_list(t, arg, t)) {
YAPPy_ThrowErrorYA(SYSTEM_ERROR_INTERNAL,t,"");
}
a = term_to_python(arg, eval, o);
if (a) {
if (PyList_SetItem(out, i, a) < 0) {
YAPPy_ThrowErrorYA(SYSTEM_ERROR_INTERNAL,t,"");
}
}
}
PL_reset_term_refs(tail);
return CHECKNULL(t, out);
} else {
functor_t fun;
PyObject *rc;
if (!PL_get_functor(t, &fun)) {
PL_reset_term_refs(tail);
return CHECKNULL(t, Py_None);
}
if (eval)
rc = compound_to_pyeval(t, o);
else
rc = compound_to_pytree(t, o);
PL_reset_term_refs(tail);
return rc;
}
}
}
return CHECKNULL(t, Py_None);
}
PyObject *yap_to_python(YAP_Term t, bool eval, PyObject *o) {
if (t == 0)
return NULL;
term_t yt = YAP_InitSlot(t);
o = term_to_python(yt, eval, o);
PL_reset_term_refs(yt);
return o;
}
PyObject *deref_term_to_python(term_t t) {
// Yap_DebugPlWrite(YAP_GetFromSlot(t)); fprintf(stderr, " here I
// am\n");
YAP_Term yt = YAP_GetFromSlot(t);
if (YAP_IsVarTerm(yt)) {
char s[32];
char *o = YAP_WriteBuffer(yt, s, 31, 0);
PyObject *p = PyUnicode_FromString(o);
return p;
}
return term_to_python(t, false, NULL);
}

View File

@ -0,0 +1,319 @@
#include "py4yap.h"
static foreign_t repr_term(PyObject *pVal, term_t t) {
term_t to = PL_new_term_ref(), t1 = PL_new_term_ref();
PL_put_pointer(t1, pVal);
PL_cons_functor(to, FUNCTOR_pointer1, t1);
Py_INCREF(pVal);
return PL_unify(t, to);
}
foreign_t assign_to_symbol(term_t t, PyObject *e);
foreign_t assign_to_symbol(term_t t, PyObject *e) {
char *s = NULL;
if (!PL_get_atom_chars(t, &s)) {
return false;
}
PyObject *dic;
if (!lookupPySymbol(s, NULL, &dic))
dic = py_Main;
return PyObject_SetAttrString(dic, s, e) == 0;
}
foreign_t python_to_term(PyObject *pVal, term_t t) {
bool rc = true;
term_t to = PL_new_term_ref();
// fputs(" <<*** ",stderr); PyObject_Print(pVal,stderr,0);
// fputs("<<***\n",stderr);
if (pVal == Py_None) {
// fputs("<<*** ",stderr);Yap_DebugPlWrite(YAP_GetFromSlot(t)); fputs("
// >>***\n",stderr);
rc = PL_unify_atom(t, ATOM_none);
// fputs("<<*** ",stderr);Yap_DebugPlWrite(YAP_GetFromSlot(t)); fputs("
// >>***\n",stderr);
} else if (PyBool_Check(pVal)) {
rc = rc && PL_unify_bool(t, PyObject_IsTrue(pVal));
} else if (PyLong_Check(pVal)) {
rc = rc && PL_unify_int64(t, PyLong_AsLong(pVal));
#if PY_MAJOR_VERSION < 3
} else if (PyInt_Check(pVal)) {
rc = rc && PL_unify_int64(t, PyInt_AsLong(pVal));
#endif
} else if (PyFloat_Check(pVal)) {
rc = rc && PL_unify_float(t, PyFloat_AsDouble(pVal));
} else if (PyComplex_Check(pVal)) {
term_t t1 = PL_new_term_ref(), t2 = PL_new_term_ref();
if (!PL_put_float(t1, PyComplex_RealAsDouble(pVal)) ||
!PL_put_float(t2, PyComplex_ImagAsDouble(pVal)) ||
!PL_cons_functor(to, FUNCTOR_complex2, t1, t2)) {
rc = false;
} else {
rc = rc && PL_unify(t, to);
}
} else if (PyUnicode_Check(pVal)) {
atom_t tmp_atom;
#if PY_MAJOR_VERSION < 3
size_t sz = PyUnicode_GetSize(pVal) + 1;
wchar_t *ptr = malloc(sizeof(wchar_t) * sz);
sz = PyUnicode_AsWideChar((PyUnicodeObject *)pVal, ptr, sz - 1);
tmp_atom = PL_new_atom_wchars(sz, ptr);
free(ptr);
#else
const char *s = PyUnicode_AsUTF8(pVal);
tmp_atom = PL_new_atom(s);
#endif
rc = rc && PL_unify_atom(t, tmp_atom);
} else if (PyByteArray_Check(pVal)) {
atom_t tmp_atom = PL_new_atom(PyByteArray_AsString(pVal));
rc = rc && PL_unify_atom(t, tmp_atom);
#if PY_MAJOR_VERSION < 3
} else if (PyString_Check(pVal)) {
atom_t tmp_atom = PL_new_atom(PyString_AsString(pVal));
rc = rc && PL_unify_atom(t, tmp_atom);
#endif
} else if (PyTuple_Check(pVal)) {
Py_ssize_t i, sz = PyTuple_Size(pVal);
functor_t f;
const char *s;
if (sz == 0) {
rc = rc && PL_unify_atom(t, ATOM_brackets);
} else {
if ((s = (Py_TYPE(pVal)->tp_name))) {
if (!strcmp(s, "H")) {
pVal = PyTuple_GetItem(pVal, 0);
if (pVal == NULL) {
pVal = Py_None;
PyErr_Clear();
}
}
if (s[0] == '$') {
char *ns = malloc(strlen(s) + 5);
strcpy(ns, "__");
strcat(ns, s + 1);
strcat(ns, "__");
f = PL_new_functor(PL_new_atom(ns), sz);
} else {
f = PL_new_functor(PL_new_atom(s), sz);
}
} else {
f = PL_new_functor(ATOM_t, sz);
}
if (PL_unify_functor(t, f)) {
for (i = 0; i < sz; i++) {
if (!PL_get_arg(i + 1, t, to))
rc = false;
PyObject *p = PyTuple_GetItem(pVal, i);
if (p == NULL) {
PyErr_Clear();
p = Py_None;
}
rc = rc && python_to_term(p, to);
}
} else {
rc = false;
}
// fputs(" ||*** ",stderr); Yap_DebugPlWrite(YAP_GetFromSlot(t)); fputs("
// ||***\n",stderr);
}
} else if (PyList_Check(pVal)) {
Py_ssize_t i, sz = PyList_GET_SIZE(pVal);
if (sz == 0) {
rc = rc && PL_unify_nil(t);
} else {
for (i = 0; i < sz; i++) {
PyObject *obj;
if (!PL_unify_list(t, to, t)) {
rc = false;
break;
}
if ((obj = PyList_GetItem(pVal, i)) == NULL) {
obj = Py_None;
}
rc = rc && python_to_term(obj, to);
}
rc = rc && PL_unify_nil(t);
}
// fputs("[***] ", stderr);
// Yap_DebugPlWrite(yt); fputs("[***]\n", stderr);
} else if (PyDict_Check(pVal)) {
Py_ssize_t pos = 0;
term_t to = PL_new_term_ref(), ti = to;
int left = PyDict_Size(pVal);
PyObject *key, *value;
if (left == 0) {
rc = rc && PL_unify_atom(t, ATOM_curly_brackets);
} else {
while (PyDict_Next(pVal, &pos, &key, &value)) {
term_t tkey = PL_new_term_ref(), tval = PL_new_term_ref(), tint,
tnew = PL_new_term_ref();
/* do something interesting with the values... */
if (!python_to_term(key, tkey)) {
continue;
}
if (!python_to_term(value, tval)) {
continue;
}
/* reuse */
tint = tkey;
if (!PL_cons_functor(tint, FUNCTOR_colon2, tkey, tval)) {
rc = false;
continue;
}
if (--left) {
if (!PL_cons_functor(tint, FUNCTOR_comma2, tint, tnew))
PL_reset_term_refs(tkey);
rc = false;
}
if (!PL_unify(ti, tint)) {
rc = false;
}
ti = tnew;
PL_reset_term_refs(tkey);
}
rc = rc && PL_unify(t, to);
}
} else {
rc = rc && repr_term(pVal, t);
}
PL_reset_term_refs(to);
return rc;
}
X_API YAP_Term pythonToYAP(PyObject *pVal) {
term_t t = PL_new_term_ref();
if (pVal == NULL || !python_to_term(pVal, t)) {
PL_reset_term_refs(t);
return 0;
}
YAP_Term tt = YAP_GetFromSlot(t);
PL_reset_term_refs(t);
Py_DECREF(pVal);
return tt;
}
PyObject *py_Local, *py_Global;
/**
* assigns the Python RHS to a Prolog term LHS, ie LHS = RHS
*
* @param root Python environment
* @param t left hand side, in Prolog, may be
* - a Prolog variable, exports the term to Prolog, A <- RHS
* - Python variable A, A <- RHS
* - Python variable $A, A <- RHS
* - Python string "A", A <- RHS
* - Python array range
* @param e the right-hand side
*
* @return -1 on failure.
*
* Note that this is an auxiliary routine to the Prolog
*python_assign.
*/
bool python_assign(term_t t, PyObject *exp, PyObject *context) {
context = find_obj(context, t, false);
// Yap_DebugPlWriteln(yt);
switch (PL_term_type(t)) {
case PL_VARIABLE: {
if (context == NULL) // prevent a.V= N*N[N-1]
return python_to_term(exp, t);
}
case PL_ATOM: {
char *s = NULL;
PL_get_atom_chars(t, &s);
if (!context)
context = py_Main;
return PyObject_SetAttrString(context, s, exp) == 0;
}
case PL_STRING:
case PL_INTEGER:
case PL_FLOAT:
// domain or type erro?
return false;
default: {
term_t tail = PL_new_term_ref(), arg = PL_new_term_ref();
size_t len, i;
if (PL_skip_list(t, tail, &len) &&
PL_get_nil(tail)) { // true list
bool o = true;
if (PySequence_Check(exp) && PySequence_Length(exp) == len)
for (i = 0; i < len; i++) {
PyObject *p;
if (!PL_get_list(t, arg, t)) {
PL_reset_term_refs(tail);
o = false;
p = Py_None;
}
if ((p = PySequence_GetItem(exp, i)) == NULL)
p = Py_None;
if (!python_assign(arg, p, context)) {
PL_reset_term_refs(tail);
o = false;
}
}
PL_reset_term_refs(tail);
return o;
} else {
functor_t fun;
if (!PL_get_functor(t, &fun)) {
PL_reset_term_refs(tail);
return false;
}
if (fun == FUNCTOR_sqbrackets2) {
if (!PL_get_arg(2, t, tail)) {
PL_reset_term_refs(tail);
return false;
}
PyObject *o = term_to_python(tail, true, context);
if (!PL_get_arg(2, t, tail) && !PL_get_nil(tail)) {
PL_reset_term_refs(tail);
return false;
}
if (!PL_get_arg(1, t, t)) {
PL_reset_term_refs(tail);
return false;
}
PL_reset_term_refs(tail);
PyObject *i = term_to_python(t, true, NULL);
if (!i) {
return false;
}
if (PyList_Check(i)) {
i = PyList_GetItem(i, 0);
if (i == NULL)
i = Py_None;
long int j;
if (PyList_Check(o)) {
#if PY_MAJOR_VERSION < 3
if (PyInt_Check(i))
j = PyInt_AsLong(i);
else
#endif
if (PyLong_Check(i))
j = PyLong_AsLong(i);
else
return NULL;
return PyList_SetItem(o, j, exp) == 0;
}
if (PyDict_Check(i)) {
return PyDict_SetItem(o, i, exp) == 0;
}
return PyObject_SetAttr(o, i, exp) == 0;
}
}
}
}
}
return NULL;
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,687 @@
#include "py4yap.h"
PyObject *py_Main;
void pyErrorHandler__(int line, const char *file, const char *code) {
// this code is called if a Python error is found.
fprintf(stderr, " Python error detected at %s %s:%d\n\n", code, file, line);
PyErr_Print();
}
static foreign_t python_len(term_t tobj, term_t tf) {
Py_ssize_t len;
PyObject *o;
o = term_to_python(tobj, true, NULL);
if (o == NULL) {
pyErrorAndReturn(false, false);
}
len = PyObject_Length(o);
pyErrorAndReturn(PL_unify_int64(tf, len), false);
}
static foreign_t python_dir(term_t tobj, term_t tf) {
PyObject *dir;
PyObject *o;
o = term_to_python(tobj, true, NULL);
if (o == NULL) {
pyErrorAndReturn(false, false);
}
dir = PyObject_Dir(o);
{
foreign_t rc = address_to_term(dir, tf);
;
pyErrorAndReturn(rc, false);
}
}
static foreign_t python_index(term_t tobj, term_t tindex, term_t val) {
PyObject *i;
PyObject *o;
PyObject *f;
o = term_to_python(tobj, true, NULL);
if (o == NULL) {
pyErrorAndReturn(false, false);
}
if (!PySequence_Check(o)) {
pyErrorAndReturn(false, false);
}
i = term_to_python(tindex, true, NULL);
if (i == NULL) {
pyErrorAndReturn(false, false);
}
#if PY_MAJOR_VERSION < 3
f = PyObject_CallMethodObjArgs(o, PyString_FromString("getitem"), i);
#else
f = PyObject_CallMethodObjArgs(o, PyUnicode_FromString("getitem"), i);
#endif
{
foreign_t rc = address_to_term(f, val);
;
pyErrorAndReturn(rc, false);
}
}
static foreign_t python_is(term_t tobj, term_t tf) {
PyObject *o;
term_t lim = python_acquire_GIL();
o = term_to_python(tobj, true, NULL);
if (!o) {
python_release_GIL(lim);
pyErrorAndReturn(false, false);
}
foreign_t rc = python_to_term(o, tf);
if (rc)
PyErr_Clear();
python_release_GIL(lim);
pyErrorAndReturn(rc, false);
}
static foreign_t python_proc(term_t tobj) {
PyObject *o;
term_t lim = python_acquire_GIL();
o = term_to_python(tobj, true, NULL);
python_release_GIL(lim);
bool rc = o != NULL;
pyErrorAndReturn(rc , false);
}
static foreign_t python_slice(term_t parent, term_t indx, term_t tobj) {
PyObject *pF, *pI;
PyObject *p;
// get Scope ...
pI = term_to_python(indx, true, NULL);
// got Scope.Exp
// get Scope ...
p = term_to_python(parent, true, NULL);
// Exp
if (!pI || !p) {
{ pyErrorAndReturn(false, false); }
} else if ((pF = PySequence_GetSlice(p, 0, 0)) == NULL) {
PyErr_Print();
{ pyErrorAndReturn(false, false); }
}
Py_DecRef(pI);
Py_DecRef(p);
Py_INCREF(pF);
{
foreign_t rc;
rc = address_to_term(pF, tobj);
pyErrorAndReturn(rc, false);
}
}
static foreign_t python_apply(term_t tin, term_t targs, term_t keywds,
term_t tf) {
PyObject *pF;
PyObject *pArgs, *pKeywords;
PyObject *pValue;
int i, arity;
atom_t aname;
foreign_t out;
term_t targ = PL_new_term_ref();
pF = term_to_python(tin, true, NULL);
PyErr_Clear();
if (pF == NULL) {
{ pyErrorAndReturn(false, false); }
}
if (PL_is_atom(targs)) {
pArgs = NULL;
} else {
if (!PL_get_name_arity(targs, &aname, &arity)) {
{ pyErrorAndReturn(false, false); }
}
if (arity == 1 && PL_get_arg(1, targs, targ) && PL_is_variable(targ)) {
/* ignore (_) */
pArgs = NULL;
} else {
pArgs = PyTuple_New(arity);
DebugPrintf("Tuple %p\n", pArgs);
if (!pArgs) {
pyErrorAndReturn(false, false);
}
for (i = 0; i < arity; i++) {
PyObject *pArg;
if (!PL_get_arg(i + 1, targs, targ)) {
pyErrorAndReturn(false, false);
}
pArg = term_to_python(targ, true, NULL);
if (pArg == NULL) {
pyErrorAndReturn(false, false);
}
/* pArg reference stolen here: */
PyTuple_SetItem(pArgs, i, pArg);
}
}
}
if (PL_is_atom(keywds)) {
pKeywords = NULL;
} else {
pKeywords = term_to_python(keywds, true, NULL);
}
if (PyCallable_Check(pF)) {
pValue = PyEval_CallObjectWithKeywords(pF, pArgs, pKeywords);
// PyObject_Print(pF,stderr,0);fprintf(stderr, "\n");
// PyObject_Print(pArgs,stderr,0);fprintf(stderr, " ");
// PyObject_Print(pKeywords,stderr,0);fprintf(stderr, "\n");
if (!pValue)
PyErr_Print();
else
Py_IncRef(pValue);
} else if (pArgs == NULL) {
pValue = pF;
if (pF) {
Py_IncRef(pValue);
}
} else {
PyErr_Print();
{ pyErrorAndReturn(false, false); }
}
if (pArgs)
Py_DECREF(pArgs);
Py_DECREF(pF);
if (pValue == NULL) {
pyErrorAndReturn(false, false);
}
out = address_to_term(pValue, tf);
pyErrorAndReturn(out, false);
}
static foreign_t assign_python(term_t exp, term_t name) {
term_t stackp = python_acquire_GIL();
PyObject *e = term_to_python(exp, true, NULL);
if (e == NULL) {
python_release_GIL(stackp);
pyErrorAndReturn(false, false);
}
bool b = python_assign(name, e, NULL);
python_release_GIL(stackp);
pyErrorAndReturn(b, false);
}
static foreign_t python_builtin_eval(term_t caller, term_t dict, term_t out) {
PyErr_Clear();
PyObject *pI, *pArgs, *pOut;
PyObject *env;
atom_t name;
char *s;
int i, arity;
term_t targ = PL_new_term_ref();
if ((env = py_Builtin) == NULL) {
// no point in even trying
{ pyErrorAndReturn(false, false); }
}
if (PL_get_name_arity(caller, &name, &arity)) {
if (!(s = PL_atom_chars(name))) {
pyErrorAndReturn(false, false);
}
if ((pI = PyObject_GetAttrString(env, s)) == NULL) {
PyErr_Print();
{ pyErrorAndReturn(false, false); }
}
Py_INCREF(pI);
} else {
// Prolog should make sure this never happens.
{ pyErrorAndReturn(false, false); }
}
pArgs = PyTuple_New(arity);
DebugPrintf("Tuple %p\n", pArgs);
for (i = 0; i < arity; i++) {
PyObject *pArg;
if (!PL_get_arg(i + 1, caller, targ)) {
pyErrorAndReturn(false, false);
}
/* ignore (_) */
if (i == 0 && PL_is_variable(targ)) {
pArg = Py_None;
} else {
pArg = term_to_python(targ, true, NULL);
if (pArg == NULL) {
pyErrorAndReturn(false, false);
}
}
/* pArg reference stolen here: */
if (PyTuple_SetItem(pArgs, i, pArg)) {
PyErr_Print();
{ pyErrorAndReturn(false, false); }
}
}
pOut = PyObject_CallObject(pI, pArgs);
Py_DECREF(pArgs);
Py_DECREF(pI);
if (pOut == NULL) {
PyErr_Print();
{ pyErrorAndReturn(false, false); }
}
{
foreign_t rc = address_to_term(pOut, out);
;
pyErrorAndReturn(rc, false);
}
}
static foreign_t python_access(term_t obj, term_t f, term_t out) {
PyErr_Clear();
PyObject *o = term_to_python(obj, true, NULL), *pValue, *pArgs, *pF;
atom_t name;
char *s = NULL;
int i, arity;
term_t targ = PL_new_term_ref();
if (o == NULL) {
pyErrorAndReturn(false, false);
}
if (PL_is_atom(f)) {
if (!PL_get_atom_chars(f, &s)) {
pyErrorAndReturn(false, false);
}
if ((pValue = PyObject_GetAttrString(o, s)) == NULL) {
PyErr_Print();
{ pyErrorAndReturn(false, false); }
}
Py_INCREF(pValue);
{ pyErrorAndReturn(python_to_term(pValue, out), false); }
}
if (!PL_get_name_arity(f, &name, &arity)) {
{ pyErrorAndReturn(false, false); }
}
s = PL_atom_chars(name);
if (!s) {
pyErrorAndReturn(false, false);
}
if ((pF = PyObject_GetAttrString(o, s)) == NULL) {
DebugPrintf("Function %p\n", pArgs);
PyErr_Print();
{ pyErrorAndReturn(false, false); }
}
pArgs = PyTuple_New(arity);
DebugPrintf("Tuple %p\n", pArgs);
for (i = 0; i < arity; i++) {
PyObject *pArg;
if (!PL_get_arg(i + 1, f, targ)) {
pyErrorAndReturn(false, false);
}
/* ignore (_) */
if (i == 0 && PL_is_variable(targ)) {
pArgs = Py_None;
}
pArg = term_to_python(targ, true, NULL);
if (pArg == NULL) {
pyErrorAndReturn(false, false);
}
/* pArg reference stolen here: */
PyTuple_SetItem(pArgs, i, pArg);
}
pValue = PyObject_CallObject(pF, pArgs);
Py_DECREF(pArgs);
Py_DECREF(pF);
if (pValue == NULL) {
{ pyErrorAndReturn(false, false); }
}
{ pyErrorAndReturn(python_to_term(pValue, out), false); }
}
static foreign_t python_field(term_t parent, term_t att, term_t tobj) {
PyObject *pF;
atom_t name;
char *s;
int arity;
if (!PL_get_name_arity(att, &name, &arity)) {
{ pyErrorAndReturn(false, false); }
} else {
PyObject *p;
// got Scope.Exp
// get Scope ...
p = term_to_python(parent, true, NULL);
// Exp
if (!PL_get_name_arity(att, &name, &arity)) {
{ pyErrorAndReturn(false, false); }
}
s = PL_atom_chars(name);
if (arity == 1 && !strcmp(s, "()")) {
if (!PL_get_arg(1, att, att)) {
pyErrorAndReturn(false, false);
}
if (!PL_get_name_arity(att, &name, &arity)) {
{ pyErrorAndReturn(false, false); }
}
s = PL_atom_chars(name);
}
if (!s || !p) {
{ pyErrorAndReturn(false, false); }
} else if ((pF = PyObject_GetAttrString(p, s)) == NULL) {
PyErr_Clear();
{ pyErrorAndReturn(false, false); }
}
}
{
foreign_t rc;
rc = address_to_term(pF, tobj);
pyErrorAndReturn(rc, false);
}
}
static foreign_t python_main_module(term_t mod) {
{
foreign_t rc;
PyErr_Clear();
rc = address_to_term(py_Main, mod);
pyErrorAndReturn(rc, false);
}
}
static foreign_t python_function(term_t tobj) {
PyErr_Clear();
PyObject *obj = term_to_python(tobj, true, NULL);
foreign_t rc = PyFunction_Check(obj);
pyErrorAndReturn(rc, false);
}
foreign_t python_builtin(term_t out) {
{
foreign_t rc;
PyErr_Clear();
rc = address_to_term(py_Builtin, out);
pyErrorAndReturn(rc, false);
}
}
static foreign_t python_run_file(term_t file) {
char *s;
size_t len;
char si[256];
s = si;
PyErr_Clear();
if (PL_get_nchars(file, &len, &s, CVT_ALL | CVT_EXCEPTION)) {
#if PY_MAJOR_VERSION < 3
PyObject *PyFileObject = PyFile_FromString(si, "r");
PyRun_SimpleFileEx(PyFile_AsFile(PyFileObject), "test.py", 1);
#else
FILE *f = fopen(s, "r");
if (f == NULL) {
pyErrorAndReturn(false, false);
}
PyRun_SimpleFileEx(f, s, 1);
#endif
{
{ pyErrorAndReturn(true, false); }
}
}
{ pyErrorAndReturn(false, false); }
}
extern PyThreadState *YAP_save;
static foreign_t python_run_command(term_t cmd) {
char *s;
bool rc = false;
size_t len;
char si[256];
PyErr_Clear();
s = si;
if (PL_get_nchars(cmd, &len, &s, CVT_ALL | CVT_EXCEPTION)) {
PyRun_SimpleString(s);
rc = true;
}
pyErrorAndReturn(rc, false);
}
static foreign_t python_run_script(term_t cmd, term_t fun) {
char si[256], sf[256];
size_t len = 255, len1 = 255;
PyObject *pName, *pModule, *pFunc;
PyObject *pArgs = NULL, *pValue;
char *s;
PyErr_Clear();
s = si;
if (PL_get_nchars(cmd, &len, &s, CVT_ALL | CVT_EXCEPTION) &&
(s = sf) != NULL &&
PL_get_nchars(fun, &len1, &s, CVT_ALL | CVT_EXCEPTION)) {
#if PY_MAJOR_VERSION < 3
pName = PyString_FromString("rbm");
#else
// asssumes UTF-8
pName = PyUnicode_FromString("rbm");
#endif
/* Error checking of pName left out */
pModule = PyImport_Import(pName);
PyErr_Clear();
Py_DECREF(pName);
if (pModule != NULL) {
pFunc = PyObject_GetAttrString(pModule, sf);
/* pFunc is a new reference */
if (pFunc && PyCallable_Check(pFunc)) {
pValue = PyObject_CallObject(pFunc, pArgs);
if (pValue != NULL) {
Py_DECREF(pValue);
} else {
Py_DECREF(pFunc);
Py_DECREF(pModule);
PyErr_Print();
fprintf(stderr, "Call failed\n");
{ pyErrorAndReturn(false, false); }
}
} else {
pyErrorHandler();
if (PyErr_Occurred())
PyErr_Print();
fprintf(stderr, "Cannot find function \"%s\"\n", sf);
}
Py_XDECREF(pFunc);
Py_DECREF(pModule);
} else {
PyErr_Print();
{ pyErrorAndReturn(false, false); }
}
{ pyErrorAndReturn(true, false); }
}
{ pyErrorAndReturn(false, false); }
}
static foreign_t python_export(term_t t, term_t pl) {
foreign_t rc = false;
PyErr_Clear();
if (PL_is_functor(t, FUNCTOR_pointer1)) {
void *ptr;
term_t targ = PL_new_term_ref();
if (!PL_get_arg(1, t, targ)) {
pyErrorAndReturn(false, false);
}
if (!PL_get_pointer(targ, &ptr)) {
pyErrorAndReturn(false, false);
}
Py_INCREF((PyObject *)ptr);
/* pyErrorAndReturn( __main__, false) */
rc = python_to_term((PyObject *)ptr, pl);
}
pyErrorAndReturn(rc, false);
}
/**
* @pred python_import(MName, Mod)
* Import a python module to the YAP environment.
*
* @param mname module name, either an atom or a sequence of atoms,
* eg os.sys
* @param mod the pointer to the Python object
* @return success?
*/
static int python_import(term_t mname, term_t mod) {
PyObject *pName;
term_t t0 = python_acquire_GIL();
term_t arg = PL_new_term_ref();
char s0[MAXPATHLEN], *s = s0;
while (true) {
size_t len;
len = (MAXPATHLEN - 1) - (s - s0);
if (PL_is_pair(mname)) {
char *sa = NULL;
if (!PL_get_arg(1, mname, arg) || !PL_get_atom_chars(arg, &sa) ||
!PL_get_arg(2, mname, mname)) {
python_release_GIL(t0);
pyErrorAndReturn(false, false);
}
PL_get_atom_chars(arg, &sa);
strcpy(s, sa);
s += strlen(s);
*s++ = '.';
s[0] = '\0';
} else if (!PL_get_nchars(mname, &len, &s,
CVT_ATOM | CVT_EXCEPTION | REP_UTF8)) {
python_release_GIL(t0);
pyErrorAndReturn(false, false);
} else {
break;
}
}
#if PY_MAJOR_VERSION < 3
pName = PyString_FromString(s0);
#else
pName = PyUnicode_FromString(s0);
#endif
python_release_GIL(t0);
if (pName == NULL) {
pyErrorAndReturn(false, false);
}
PyObject *pModule = PyImport_Import(pName);
Py_DECREF(pName);
if (pModule == NULL) {
#if EXTRA_MESSSAGES
if (PyErr_Occurred())
PyErr_Print();
PyErr_Clear();
#endif
{ pyErrorAndReturn(false, false); }
}
{
foreign_t rc = address_to_term(pModule, mod);
pyErrorAndReturn(rc, false);
}
}
static foreign_t python_to_rhs(term_t inp, term_t t) {
PyObject *pVal;
PyErr_Clear();
pVal = term_to_python(inp, true, NULL);
if (pVal == NULL)
pyErrorAndReturn(false, false);
pyErrorAndReturn(address_to_term(pVal, t), false);
}
// static PyThreadState *_saveP = NULL;
static bool _threaded = false;
/*
static YAP_Int
p_python_ensure(term_t ptr)
{
PyGILState_STATE _tState = PyGILState_Ensure();
pyErrorAndReturn( PL_unify_int64(ptr, _tState), false);
}
static YAP_Int
p_python_release(term_t ptr)
{
PyGILState_STATE _tState;
PL_get_int64( ptr, &_tState);
PyGILState_Release( _tState );
pyErrorAndReturn( true, false);
}
*/
int _locked = 0;
PyThreadState *tstate;
static YAP_Int p_python_threaded(void) {
PyErr_Clear();
// PyEval_ReleaseThread(tstate);
// _threaded = true;
// _locked = 0;
pyErrorAndReturn(true, false);
}
static PyGILState_STATE gstate;
term_t python_acquire_GIL(void) {
term_t curSlot = PL_new_term_ref();
if (!_threaded)
pyErrorAndReturn(curSlot, false);
// extern int Yap_do_low_level_trace;
// Yap_do_low_level_trace = 1;
// f[rintf( stderr, "++%d\n", ++_locked);
// if (_locked > 0) { _locked++ ; }
// else
gstate = PyGILState_Ensure();
pyErrorAndReturn(curSlot, false);
}
bool python_release_GIL(term_t curBlock) {
PyErr_Clear();
PL_reset_term_refs(curBlock);
if (_threaded) {
PyGILState_Release(gstate);
}
pyErrorAndReturn(true, false);
}
//: prolog: release python
install_t install_pypreds(void) {
PL_register_foreign("python_builtin_eval", 3, python_builtin_eval, 0);
PL_register_foreign("python_builtin", 1, python_builtin, 0);
PL_register_foreign("python_import", 2, python_import, 0);
PL_register_foreign("python_to_rhs", 2, python_to_rhs, 0);
PL_register_foreign("python_len", 2, python_len, 0);
PL_register_foreign("python_is", 2, python_is, 0);
PL_register_foreign("python_dir", 2, python_dir, 0);
PL_register_foreign("python_apply", 4, python_apply, 0);
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_export", 2, python_export, 0);
PL_register_foreign("python_function", 1, python_function, 0);
PL_register_foreign("python_slice", 4, python_slice, 0);
PL_register_foreign("python_run_file", 1, python_run_file, 0);
PL_register_foreign("python_proc", 1, python_proc, 0);
PL_register_foreign("python_run_command", 1, python_run_command, 0);
PL_register_foreign("python_run_script", 2, python_run_script, 0);
PL_register_foreign("python_main_module", 1, python_main_module, 0);
PL_register_foreign("python_import", 2, python_import, 0);
PL_register_foreign("python_access", 3, python_access, 0);
PL_register_foreign("python_threaded", 0, p_python_threaded, 0);
}

View File

@ -115,7 +115,7 @@ static foreign_t array_to_python_view(term_t addr, term_t type, term_t szt,
static foreign_t prolog_list_to_python_list(term_t plist, term_t pyt, term_t tlen) {
size_t sz, i;
PyErr_Clear();
PyObject *pyl = term_to_python(pyt, true, NULL);
PyObject *pyl = term_to_python(pyt, true, NULL, true);
term_t targ = PL_new_term_ref();
if (PL_skip_list(plist, targ, &sz) <0 || ! PL_get_nil(targ)) {
@ -131,7 +131,7 @@ static foreign_t prolog_list_to_python_list(term_t plist, term_t pyt, term_t tle
if (!PL_get_list(plist, targ, plist)) {
pyErrorAndReturn( false, false);
}
PyObject *t = term_to_python(targ, true, NULL);
PyObject *t = term_to_python(targ, true, NULL, true);
PyList_SET_ITEM(pyl, i, t);
}
if (PL_is_variable(tlen)) {

View File

@ -32,8 +32,8 @@ static PyObject *s_to_python(const char *s, bool eval, PyObject *p0) {
Py_INCREF(o);
return CHECKNULL(YAP_MkStringTerm(s), o);
} else {
//char *ns = Py_Malloc(strlen(s)+1);
///strcpy(ns,s);
// char *ns = Py_Malloc(strlen(s)+1);
/// strcpy(ns,s);
PyObject *pobj = PyUnicode_FromString(s);
return pobj;
}
@ -59,6 +59,42 @@ X_API PyObject *string_to_python(const char *s, bool eval, PyObject *p0) {
return s_to_python(s, eval, p0);
}
static bool copy_to_dictionary(PyObject *dict, term_t targ, term_t taux,
bool eval, bool cvt) {
PyObject *lhs, *rhs;
term_t tleft = PL_new_term_ref(), tright = PL_new_term_ref();
functor_t fun;
AOK(PL_get_functor(targ, &fun), false);
while (fun == FUNCTOR_comma2) {
AOK(PL_get_arg(1, targ, tleft), false);
if (!copy_to_dictionary(dict, tleft, taux, eval, cvt))
return false;
AOK(PL_get_arg(2, targ, targ), false);
return copy_to_dictionary(dict, tright, taux, eval, cvt);
}
// PyObject_Print(dict, stderr, 0); fprintf(stderr,"\n");
// Py_DECREF(lhs);
// Py_DECREF(rhs);
AOK(PL_get_arg(1, targ, tleft), false);
lhs = atom_to_python_string(tleft);
if (lhs == NULL) {
return FALSE;
}
AOK(PL_get_arg(2, targ, tright), false);
rhs = term_to_python(tright, eval, NULL, cvt);
if (rhs == NULL) {
PyErr_Print();
return false;
}
return PyDict_SetItem(dict, lhs, rhs) >= 0;
// PyObject_Print(dict, stderr, 0); fprintf(stderr,"\n");
// Py_DECREF(lhs);
// Py_DECREF(rhs);
}
/**
* term_to_python translates and evaluates from Prolog to Python
*
@ -67,7 +103,7 @@ X_API PyObject *string_to_python(const char *s, bool eval, PyObject *p0) {
*
* @return a Python object descriptor or NULL if failed
*/
PyObject *term_to_python(term_t t, bool eval, PyObject *o) {
PyObject *term_to_python(term_t t, bool eval, PyObject *o, bool cvt) {
// o≈
YAP_Term yt = YAP_GetFromSlot(t);
// Yap_DebugPlWriteln(yt);
@ -77,7 +113,9 @@ PyObject *term_to_python(term_t t, bool eval, PyObject *o) {
Yap_ThrowError(SYSTEM_ERROR_INTERNAL, yt, "in term_to_python");
}
PyObject *out = PyTuple_New(1);
PyTuple_SET_ITEM(out, 0, PyLong_FromLong(t));
PyTuple_SET_ITEM(out, 0, PyLong_FromLong((YAP_Int)YAP_GetFromSlot(t)));
if (!cvt)
return out;
return term_to_nametuple("v", 1, out);
};
case PL_ATOM: {
@ -90,12 +128,13 @@ PyObject *term_to_python(term_t t, bool eval, PyObject *o) {
/* if (!o)
return o;
*/
} else {
o = PythonLookupSpecial(s);
}
if (!o) {
o = PyUnicode_FromString(s);
}
if (o) {
Py_INCREF(o);
return CHECKNULL(t, o);
return o;
}
}
case PL_STRING: {
@ -115,7 +154,7 @@ PyObject *term_to_python(term_t t, bool eval, PyObject *o) {
#endif
{
// char *p = malloc(strlen(s)+1);
//strcpy(p, s);
// strcpy(p, s);
PyObject *pobj = PyUnicode_FromString(s);
Py_IncRef(pobj);
return CHECKNULL(t, pobj);
@ -142,81 +181,218 @@ PyObject *term_to_python(term_t t, bool eval, PyObject *o) {
out = PyFloat_FromDouble(fl);
return CHECKNULL(t, out);
}
default: {
term_t tail = PL_new_term_ref(), arg;
size_t len, i;
if (PL_skip_list(t, tail, &len) && PL_get_nil(tail)) {
PyObject *out, *a;
default:
if (PL_is_pair(t)) {
term_t tail = PL_new_term_ref();
term_t arg = PL_new_term_ref();
size_t len, i;
if (PL_skip_list(t, tail, &len) && PL_get_nil(tail)) {
PyObject *out, *a;
arg = tail;
out = PyList_New(len);
if (!out) {
PL_reset_term_refs(tail);
YAPPy_ThrowError(SYSTEM_ERROR_INTERNAL, t, "list->python");
}
out = PyList_New(len);
if (!out) {
PL_reset_term_refs(tail);
YAPPy_ThrowError(SYSTEM_ERROR_INTERNAL, t, "list->python");
}
for (i = 0; i < len; i++) {
if (!PL_get_list(t, arg, t)) {
PL_reset_term_refs(tail);
YAPPy_ThrowError(SYSTEM_ERROR_INTERNAL, t, "list->python");
}
a = term_to_python(arg, eval, o);
if (a) {
if (PyList_SetItem(out, i, a) < 0) {
PL_reset_term_refs(tail);
YAPPy_ThrowError(SYSTEM_ERROR_INTERNAL, t, "list->python");
}
}
for (i = 0; i < len; i++) {
if (!PL_get_list(t, arg, t)) {
PL_reset_term_refs(tail);
YAPPy_ThrowError(SYSTEM_ERROR_INTERNAL, t, "list->python");
}
a = term_to_python(arg, eval, o, cvt);
if (a) {
if (PyList_SetItem(out, i, a) < 0) {
YAPPy_ThrowError(SYSTEM_ERROR_INTERNAL, t, "list->python");
}
}
}
PL_reset_term_refs(tail);
return out;
} else {
PyObject *no = find_obj(o, t, false);
if (no == o)
return NULL;
return term_to_python(t, eval, no, cvt);
}
PL_reset_term_refs(tail);
return CHECKNULL(t, out);
} else {
functor_t fun;
atom_t name;
int arity;
PyObject *rc;
{
term_t tail = PL_new_term_ref();
functor_t fun;
atom_t name;
int arity;
PyObject *rc;
size_t len;
if (!PL_get_functor(t, &fun)) {
PL_reset_term_refs(tail);
YAPPy_ThrowError(SYSTEM_ERROR_INTERNAL, t, "list->python");
if (!PL_get_functor(t, &fun)) {
PL_reset_term_refs(tail);
YAPPy_ThrowError(SYSTEM_ERROR_INTERNAL, t, "list->python");
}
if (fun == FUNCTOR_pointer1) {
void *ptr;
AOK(PL_get_arg(1, t, t), NULL);
AOK(PL_get_pointer(t, &ptr), NULL)
/* return __main__,s */
return (PyObject *)ptr;
}
if (fun == FUNCTOR_sqbrackets2) {
term_t targ = PL_new_term_ref(), trhs = PL_new_term_ref();
PyObject *v;
Py_ssize_t min, max;
AOK(PL_get_arg(2, t, targ), NULL);
v = term_to_python(targ, eval, o, false);
AOK(PL_get_arg(1, t, targ), NULL);
AOK(PL_get_list(targ, trhs, targ), NULL);
if (PL_is_functor(trhs, FUNCTOR_colon2)) {
if (!PySequence_Check(v))
return NULL;
min = get_p_int(term_to_python(targ, true, NULL, false), 0);
AOK(PL_get_arg(1, trhs, targ), NULL);
if (PL_is_functor(targ, FUNCTOR_colon2)) {
return NULL;
}
max = get_p_int(term_to_python(targ, true, o, false),
PyObject_Size(v));
return PySequence_GetSlice(v, min, max);
} else {
PyObject *ip = term_to_python(trhs, eval, o, cvt);
if (PySequence_Check(v)) {
#if PY_MAJOR_VERSION < 3
if (PyLong_Check(ip) {
min = PyLong_AsLong(ip);
} else if (PyInt_Check(ip) {
min = PyInt_asInt(ip);
}
#else
if (PyLong_Check(ip)) {
PyObject *o = PySequence_GetItem(v, PyLong_AsLong(ip));
if (o == NULL)
o = Py_None;
if (CHECKNULL(t, o) == NULL)
return NULL;
Py_INCREF(o);
return o;
}
#endif
} else {
o = PyObject_GetItem(v, ip);
if (o == NULL)
o = Py_None;
Py_INCREF(o);
return o;
}
}
}
if (fun == FUNCTOR_dollar1) {
char *s = NULL;
term_t targ = PL_new_term_ref();
AOK(PL_get_arg(1, t, targ), NULL);
AOK(PL_get_atom_chars(targ, &s), NULL);
/* return __main__,s */
PyObject *o = PyObject_GetAttrString(py_Main, s);
return o;
}
if (fun == FUNCTOR_brackets1) {
AOK(PL_get_arg(1, t, t), NULL);
return term_to_python(t, true, NULL, true);
}
if (fun == FUNCTOR_complex2) {
term_t targ = PL_new_term_ref();
PyObject *lhs, *rhs;
double d1, d2;
AOK(PL_get_arg(1, t, targ), NULL);
lhs = term_to_python(targ, eval, NULL, cvt);
AOK(PyNumber_Check(lhs), NULL);
if (PyFloat_Check(lhs)) {
d1 = PyFloat_AsDouble(lhs);
} else if (PyLong_Check(lhs)) {
d1 = PyLong_AsLong(lhs);
#if PY_MAJOR_VERSION < 3
} else if (PyInt_Check(lhs)) {
d1 = PyInt_AsLong(lhs);
#endif
} else {
return NULL;
}
AOK(PL_get_arg(2, t, targ), NULL);
rhs = term_to_python(targ, eval, NULL, cvt);
AOK(PyNumber_Check(rhs), NULL);
if (PyFloat_Check(rhs)) {
d2 = PyFloat_AsDouble(rhs);
} else if (PyLong_Check(rhs)) {
d2 = PyLong_AsLong(rhs);
#if PY_MAJOR_VERSION < 3
} else if (PyInt_Check(rhs)) {
d2 = PyInt_AsLong(rhs);
#endif
} else {
return NULL;
}
return PyComplex_FromDoubles(d1, d2);
}
if (fun == FUNCTOR_curly1) {
term_t targ = PL_new_term_ref(), taux = PL_new_term_ref();
PyObject *dict;
AOK(PL_get_arg(1, t, t), NULL);
if (!(dict = PyDict_New()))
return NULL;
DebugPrintf("Dict %p\n", dict);
while (PL_is_functor(t, FUNCTOR_comma2)) {
AOK(PL_get_arg(1, t, targ), NULL);
AOK(PL_is_functor(targ, FUNCTOR_colon2), NULL);
AOK(copy_to_dictionary(dict, targ, taux, eval, cvt), NULL);
AOK(PL_get_arg(2, t, t), NULL);
}
if (PL_is_functor(t, FUNCTOR_colon2)) {
AOK(copy_to_dictionary(dict, t, taux, eval, cvt), NULL);
}
return dict;
}
AOK(PL_get_name_arity(t, &name, &arity), NULL);
if (name == ATOM_t) {
int i;
rc = PyTuple_New(arity);
for (i = 0; i < arity; i++) {
term_t arg = PL_new_term_ref();
if (!PL_get_arg(i + 1, t, arg)) {
PL_reset_term_refs(arg);
YAPPy_ThrowError(SYSTEM_ERROR_INTERNAL, t, "t(...)->python");
}
PyObject *a = term_to_python(arg, eval, o, cvt);
if (a) {
if (PyTuple_SetItem(rc, i, a) < 0) {
PL_reset_term_refs(arg);
YAPPy_ThrowError(SYSTEM_ERROR_INTERNAL, t, "t(...)->python");
}
}
PL_reset_term_refs(arg);
}
}
if (eval)
rc = compound_to_pyeval(t, o, cvt);
else
rc = compound_to_pytree(t, o, cvt);
PL_reset_term_refs(tail);
return rc;
}
AOK(PL_get_name_arity(t, &name, &arity), NULL);
if (name == ATOM_t) {
int i;
rc = PyTuple_New(arity);
for (i = 0; i < len; i++) {
term_t arg = PL_new_term_ref();
if (!PL_get_arg(i+1, t, arg)) {
PL_reset_term_refs(arg);
YAPPy_ThrowError(SYSTEM_ERROR_INTERNAL, t, "t(...)->python");
}
PyObject *a = term_to_python(arg, eval, o);
if (a) {
if (PyTuple_SetItem(rc, i, a) < 0) {
PL_reset_term_refs(arg);
YAPPy_ThrowError(SYSTEM_ERROR_INTERNAL, t, "t(...)->python");
}
}
PL_reset_term_refs(arg);
}
}
if (eval)
rc = compound_to_pyeval(t, o);
else
rc = compound_to_pytree(t, o);
PL_reset_term_refs(tail);
return rc;
}
}
}
return Py_None;
}
PyObject *yap_to_python(YAP_Term t, bool eval, PyObject *o) {
PyObject *yap_to_python(YAP_Term t, bool eval, PyObject *o, bool cvt) {
if (t == 0)
return NULL;
term_t yt = YAP_InitSlot(t);
o = term_to_python(yt, eval, o);
o = term_to_python(yt, eval, o, cvt);
PL_reset_term_refs(yt);
return o;
}
@ -231,9 +407,8 @@ PyObject *deref_term_to_python(term_t t) {
PyObject *p = PyUnicode_FromString(o);
return p;
}
return term_to_python(t, false, NULL);
return term_to_python(t, true, NULL, false);
}
void YAPPy_ThrowError__(const char *file, const char *function, int lineno,
yap_error_number type, term_t where, ...);
yap_error_number type, term_t where, ...);

View File

@ -3,52 +3,29 @@
#include <frameobject.h>
void YAPPy_ThrowError__(const char *file, const char *function, int lineno,
yap_error_number type, term_t where, ...) {
va_list ap;
char tmpbuf[MAXPATHLEN];
YAP_Term wheret = YAP_GetFromSlot(where);
yap_error_number type, term_t where, ...) {
va_list ap;
char tmpbuf[MAXPATHLEN];
YAP_Term wheret = YAP_GetFromSlot(where);
PyObject *ptype;
if (PyErr_Occurred()) {
PyErr_Print();
} else {
PyObject *ptype, *pvalue, *ptraceback;
PyObject *pystr, *module_name, *pyth_module, *pyth_func;
if ((ptype = PyErr_Occurred()) == NULL) {
PyErr_Print();
}
/* See if we can get a full traceback */
module_name = PyUnicode_FromString("traceback");
pyth_module = PyImport_Import(module_name);
Py_DECREF(module_name);
if (pyth_module != NULL) {
pyth_func = PyObject_GetAttrString(pyth_module, "format_exception");
if (pyth_func && PyCallable_Check(pyth_func)) {
PyObject *pyth_val;
pyth_val = PyObject_CallFunctionObjArgs(pyth_func, ptype, pvalue, ptraceback, NULL);
pystr = PyObject_Str(pyth_val);
fprintf(stderr, "%s", PyUnicode_AsUTF8(pystr));
Py_DECREF(pyth_val);
}
}
}
PyFrameObject *fr;
if ((fr = PyEval_GetFrame())) {
fprintf(stderr, "at frame %p, line %d\n", fr, PyFrame_GetLineNumber(fr));
}
va_start(ap, where);
char *format = va_arg(ap, char *);
if (format != NULL) {
va_start(ap, where);
char *format = va_arg(ap, char *);
if (format != NULL) {
#if HAVE_VSNPRINTF
(void)vsnprintf(tmpbuf, MAXPATHLEN - 1, format, ap);
(void)vsnprintf(tmpbuf, MAXPATHLEN - 1, format, ap);
#else
(void)vsprintf(tnpbuf, format, ap);
(void)vsprintf(tnpbuf, format, ap);
#endif
// fprintf(stderr, "warning: ");
Yap_ThrowError__(file, function, lineno, type, wheret, tmpbuf);
} else {
Yap_ThrowError__(file, function, lineno, type, wheret);
}
// fprintf(stderr, "warning: ");
Yap_ThrowError__(file, function, lineno, type, wheret, tmpbuf);
} else {
Yap_ThrowError__(file, function, lineno, type, wheret);
}
}
static foreign_t repr_term(PyObject *pVal, term_t t) {
@ -132,12 +109,14 @@ foreign_t python_to_term(PyObject *pVal, term_t t) {
rc = rc && PL_unify_atom(t, ATOM_brackets);
} else {
if ((s = (Py_TYPE(pVal)->tp_name))) {
if (!strcmp(s, "H")) {
if (!strcmp(s, "v")) {
pVal = PyTuple_GetItem(pVal, 0);
if (pVal == NULL) {
pVal = Py_None;
PyErr_Clear();
}
term_t v = YAP_InitSlot(PyLong_AsLong(pVal));
return PL_unify(v, t);
}
if (s[0] == '$') {
char *ns = malloc(strlen(s) + 5);
@ -171,22 +150,17 @@ foreign_t python_to_term(PyObject *pVal, term_t t) {
} else if (PyList_Check(pVal)) {
Py_ssize_t i, sz = PyList_GET_SIZE(pVal);
if (sz == 0) {
rc = rc && PL_unify_nil(t);
} else {
for (i = 0; i < sz; i++) {
PyObject *obj;
if (!PL_unify_list(t, to, t)) {
rc = false;
break;
}
if ((obj = PyList_GetItem(pVal, i)) == NULL) {
obj = Py_None;
}
rc = rc && python_to_term(obj, to);
for (i = 0; i < sz; i++) {
PyObject *obj;
rc = rc && PL_unify_list(t, to, t);
if ((obj = PyList_GetItem(pVal, i - 1)) == NULL) {
obj = Py_None;
}
rc = rc && PL_unify_nil(t);
rc = rc && python_to_term(obj, to);
if (!rc)
return false;
}
return rc && PL_unify_nil(t);
// fputs("[***] ", stderr);
// Yap_DebugPlWrite(yt); fputs("[***]\n", stderr);
} else if (PyDict_Check(pVal)) {
@ -279,7 +253,10 @@ bool python_assign(term_t t, PyObject *exp, PyObject *context) {
PL_get_atom_chars(t, &s);
if (!context)
context = py_Main;
return PyObject_SetAttrString(context, s, exp) == 0;
if (PyObject_SetAttrString(context, s, exp) == 0)
return true;
PyErr_Print();
return false;
}
case PL_STRING:
case PL_INTEGER:
@ -289,28 +266,29 @@ bool python_assign(term_t t, PyObject *exp, PyObject *context) {
default: {
term_t tail = PL_new_term_ref(), arg = PL_new_term_ref();
size_t len, i;
if (PL_skip_list(t, tail, &len) &&
PL_get_nil(tail)) { // true list
bool o = true;
if (PySequence_Check(exp) && PySequence_Length(exp) == len)
if (PL_is_pair(t)) {
if (PL_skip_list(t, tail, &len) &&
PL_get_nil(tail)) { // true list
for (i = 0; i < len; i++) {
PyObject *p;
if (!PL_get_list(t, arg, t)) {
PL_reset_term_refs(tail);
o = false;
p = Py_None;
bool o = true;
if (PySequence_Check(exp) && PySequence_Length(exp) == len)
for (i = 0; i < len; i++) {
PyObject *p;
if (!PL_get_list(t, arg, t)) {
PL_reset_term_refs(tail);
o = false;
p = Py_None;
}
if ((p = PySequence_GetItem(exp, i)) == NULL)
p = Py_None;
if (!python_assign(arg, p, context)) {
PL_reset_term_refs(tail);
o = false;
}
}
if ((p = PySequence_GetItem(exp, i)) == NULL)
p = Py_None;
if (!python_assign(arg, p, context)) {
PL_reset_term_refs(tail);
o = false;
}
}
PL_reset_term_refs(tail);
return o;
}
} else {
functor_t fun;
@ -320,50 +298,65 @@ bool python_assign(term_t t, PyObject *exp, PyObject *context) {
}
if (fun == FUNCTOR_sqbrackets2) {
// tail is the object o
if (!PL_get_arg(2, t, tail)) {
PL_reset_term_refs(tail);
return false;
}
PyObject *o = term_to_python(tail, true, context);
if (!PL_get_arg(2, t, tail) && !PL_get_nil(tail)) {
PyObject *o = term_to_python(tail, true, context, false);
// t now refers to the index
if (!PL_get_arg(1, t, t) || !PL_get_list(t, t, tail) ||
!PL_get_nil(tail)) {
PL_reset_term_refs(tail);
return false;
}
if (!PL_get_arg(1, t, t)) {
PL_reset_term_refs(tail);
return false;
}
PL_reset_term_refs(tail);
PyObject *i = term_to_python(t, true, NULL);
if (!i) {
return false;
}
if (PyList_Check(i)) {
i = PyList_GetItem(i, 0);
if (i == NULL)
i = Py_None;
PyObject *i = term_to_python(t, true, NULL, false);
// check numeric
if (PySequence_Check(o) && PyLong_Check(i)) {
long int j;
if (PyList_Check(o)) {
j = PyLong_AsLong(i);
return PySequence_SetItem(o, j, exp) == 0;
}
#if PY_MAJOR_VERSION < 3
if (PyInt_Check(i))
j = PyInt_AsLong(i);
else
if (PySequence_Check(o) && PyInt_Check(i)) {
long int j;
j = PyInt_AsLong(i);
return PySequence_SetItem(o, i, exp) == 0;
}
#endif
if (PyLong_Check(i))
j = PyLong_AsLong(i);
else
return NULL;
return PyList_SetItem(o, j, exp) == 0;
if (PyDict_Check(o)) {
if (PyDict_SetItem(o, i, exp) == 0)
return true;
}
if (PyObject_SetAttr(o, i, exp) == 0) {
return true;
}
} else {
atom_t s;
int n, i;
PL_get_name_arity(t, &s, &n);
PyObject *o = term_to_python(t, true, context, true);
if (PySequence_Check(o) && PySequence_Length(o) == n) {
for (i = 1; i <= n; i++) {
PyObject *p;
if (!PL_get_arg(i, t, arg)) {
PL_reset_term_refs(tail);
o = false;
p = Py_None;
}
if ((p = PySequence_GetItem(exp, i - 1)) == NULL)
p = Py_None;
else if (!python_assign(arg, p, NULL)) {
PL_reset_term_refs(tail);
o = NULL;
}
}
if (PyDict_Check(i)) {
return PyDict_SetItem(o, i, exp) == 0;
}
return PyObject_SetAttr(o, i, exp) == 0;
return true;
}
}
}
PL_reset_term_refs(tail);
}
return NULL;
}
return NULL;
}

View File

@ -1,12 +1,15 @@
#ifndef PY4YAP_H
#define PY4YAP_H 1
//@{
/** @brief Prolog to Python library
*
*
* Please look at python.pl for more information, and to real.pl and real.c
* for related work.
*/
*
*
* Please look at python.pl for more information, and to real.pl and real.c
* for related work.
*/
#ifdef _XOPEN_SOURCE
#undef _XOPEN_SOURCE // python does its own thing
@ -28,7 +31,6 @@
#define I_API
#define O_API
#define PYTHON_H 1
PyObject *find_obj(PyObject *ob, term_t lhs, bool eval);
@ -50,12 +52,15 @@ typedef struct s_mod_t {
} Py_mod;
extern X_API YAP_Term pythonToYAP(PyObject *pVal);
extern X_API PyObject *yap_to_python(YAP_Term t, bool eval, PyObject *o);
extern X_API PyObject *string_to_python( const char *s, bool eval, PyObject *p0);
extern X_API PyObject *yap_to_python(YAP_Term t, bool eval, PyObject *o,
bool cvt);
extern X_API PyObject *string_to_python(const char *s, bool eval, PyObject *p0);
typedef YAP_Arity arity_t;
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_comma, ATOM_builtin, ATOM_V, ATOM_A, ATOM_self, ATOM_nil,
ATOM_brackets, ATOM_curly_brackets;
;
extern functor_t FUNCTOR_dollar1, FUNCTOR_abs1, FUNCTOR_all1, FUNCTOR_any1,
FUNCTOR_bin1, FUNCTOR_brackets1, FUNCTOR_comma2, FUNCTOR_dir1,
@ -72,7 +77,7 @@ extern X_API PyObject *py_Yapex;
extern X_API PyObject *py_Local;
extern X_API PyObject *py_Global;
extern X_API PyObject *py_Context;
extern PyObject *py_F2P;
extern PyObject *Py_f2p;
extern PyObject *py_Sys;
extern PyObject *py_ModDict;
@ -133,20 +138,25 @@ static inline PyObject *atom_to_python_string(term_t t) {
}
}
#define CHECK_CALL(rc, t, call) \
PyErr_Clear();\
rc = call; \
if (rc == NULL || PyErr_Occurred()) {\
YE(t,__LINE__,__FILE__,__FUNCTION__);\
PyErr_Print(); PyErr_Clear();\
}
#define CHECKNULL(t,rc) (rc != NULL ? rc : YE(t,__LINE__,__FILE__,__FUNCTION__) )
#define AOK(rc, err) { if (!rc) YEM( #rc ,__LINE__,__FILE__,__FUNCTION__); }
#define CHECK_CALL(rc, t, call) \
PyErr_Clear(); \
rc = call; \
if (rc == NULL || PyErr_Occurred()) { \
YE(t, __LINE__, __FILE__, __FUNCTION__); \
PyErr_Print(); \
PyErr_Clear(); \
}
#define CHECKNULL(t, rc) \
(rc != NULL ? rc : YE(t, __LINE__, __FILE__, __FUNCTION__))
#define AOK(rc, err) \
{ \
if (!rc) \
YEM(#rc, __LINE__, __FILE__, __FUNCTION__); \
}
extern PyObject *YE(term_t t, int line, const char *file, const char *code);
extern void YEM( const char *ex, int line, const char *file, const char *code);
extern void YEM(const char *ex, int line, const char *file, const char *code);
extern void pyErrorHandler__(int line, const char *file, const char *code);
#define pyErrorHandler() \
@ -167,10 +177,11 @@ extern void pyErrorHandler__(int line, const char *file, const char *code);
}
// #define pyErrorAndReturn( x, y ) return x
extern PyObject *compound_to_pyeval(term_t t, PyObject *context);
extern PyObject *compound_to_pytree(term_t t, PyObject *context);
extern PyObject *compound_to_pyeval(term_t t, PyObject *context, bool cvt);
extern PyObject *compound_to_pytree(term_t t, PyObject *context, bool cvt);
extern PyObject *term_to_python(term_t t, bool eval, PyObject *contextxs);
extern PyObject *term_to_python(term_t t, bool eval, PyObject *contextxs,
bool eval_atom);
extern PyObject *term_to_nametuple(const char *s, arity_t arity, PyObject *);
@ -197,9 +208,12 @@ extern PyObject *PythonLookup(const char *s, PyObject *o);
extern PyObject *PythonLookupSpecial(const char *s);
#define YAPPy_ThrowError(id, inp, ...) \
YAPPy_ThrowError__(__FILE__, __FUNCTION__, __LINE__, id, inp, __VA_ARGS__)
#define YAPPy_ThrowError(id, inp, ...) \
YAPPy_ThrowError__(__FILE__, __FUNCTION__, __LINE__, id, inp, __VA_ARGS__)
extern void YAPPy_ThrowError__(const char *file, const char *function,
int lineno, yap_error_number type, term_t where,
...);
#endif
extern void YAPPy_ThrowError__(const char *file, const char *function, int lineno,
yap_error_number type, term_t where, ...);
#endif

View File

@ -92,21 +92,23 @@ PyObject *PythonLookup(const char *s, PyObject *oo) {
}
}
PyObject *find_obj(PyObject *ob, term_t l, bool eval) {
PyObject *
find_obj(PyObject *ob, term_t l, bool eval) {
YAP_Term hd, yt;
py_Context = NULL;
yt = YAP_GetFromSlot(l);
// Yap_DebugPlWriteln(yt);
while (YAP_IsPairTerm(yt)) {
hd = YAP_HeadOfTerm(yt);
ob = yap_to_python(hd, true, ob);
ob = CHECKNULL(yt, ob);
yt = YAP_TailOfTerm(yt);
YAP_PutInSlot(l, yt);
ob = yap_to_python(hd, true, ob, false);
if (!ob) {
return Py_None;
}
yt = YAP_TailOfTerm(yt);
}
YAP_PutInSlot(l, yt);
return ob;
}
@ -122,7 +124,7 @@ static PyObject *bip_abs(term_t t) {
PyObject *pVal, *nVal;
AOK(PL_get_arg(1, t, t), NULL);
pVal = term_to_python(t, true, NULL);
pVal = term_to_python(t, true, NULL, true);
pVal = CHECKNULL(t, pVal);
nVal = PyNumber_Absolute(pVal);
Py_DecRef(pVal);
@ -143,7 +145,7 @@ static PyObject *bip_all(term_t t) {
int cmp;
AOK(PL_get_arg(1, t, t), NULL);
(v = term_to_python(t, true, NULL));
(v = term_to_python(t, true, NULL, true));
v = CHECKNULL(t, v);
it = PyObject_GetIter(v);
if (CHECKNULL(t, it) == NULL)
@ -190,7 +192,7 @@ static PyObject *bip_any(term_t t) {
int cmp;
AOK(PL_get_arg(1, t, t), NULL);
v = term_to_python(t, true, NULL);
v = term_to_python(t, true, NULL, true);
it = PyObject_GetIter(v);
if (CHECKNULL(t, it) == NULL)
return Py_None;
@ -225,7 +227,7 @@ static PyObject *bip_bin(term_t t) {
PyObject *v;
AOK(PL_get_arg(1, t, t), NULL);
v = term_to_python(t, true, NULL);
v = term_to_python(t, true, NULL, true);
return PyNumber_ToBase(v, 2);
}
@ -233,7 +235,7 @@ static PyObject *bip_float(term_t t, bool eval) {
PyObject *pVal, *o;
AOK(PL_get_arg(1, t, t), NULL);
pVal = term_to_python(t, eval, NULL);
pVal = term_to_python(t, eval, NULL, eval);
if (PyLong_Check(pVal)) {
o = PyFloat_FromDouble(PyLong_AsLong(pVal));
#if PY_MAJOR_VERSION < 3
@ -252,7 +254,7 @@ static PyObject *bip_int(term_t t) {
PyObject *pVal, *o;
AOK(PL_get_arg(1, t, t), NULL);
pVal = term_to_python(t, true, NULL);
pVal = term_to_python(t, true, NULL, true);
#if PY_MAJOR_VERSION < 3
if (PyLong_Check(pVal)) {
o = PyInt_FromLong(PyLong_AsLong(pVal));
@ -278,7 +280,7 @@ static PyObject *bip_long(term_t t) {
PyObject *pVal, *o;
AOK(PL_get_arg(1, t, t), NULL);
pVal = term_to_python(t, true, NULL);
pVal = term_to_python(t, true, NULL, true);
if (PyLong_Check(pVal)) {
return pVal;
#if PY_MAJOR_VERSION < 3
@ -297,7 +299,7 @@ static PyObject *bip_iter(term_t t) {
PyObject *v;
AOK(PL_get_arg(1, t, t), NULL);
v = term_to_python(t, true, NULL);
v = term_to_python(t, true, NULL, true);
return PyObject_GetIter(v);
}
@ -306,7 +308,7 @@ static PyObject *bip_ord(term_t t) {
Py_ssize_t size;
AOK(PL_get_arg(1, t, t), NULL);
pVal = term_to_python(t, true, NULL);
pVal = term_to_python(t, true, NULL, true);
if (PyUnicode_Check(pVal)) {
#if PY_MAJOR_VERSION < 3
size = PyUnicode_GET_SIZE(pVal);
@ -349,7 +351,7 @@ static PyObject *bip_sum(term_t t) {
PyObject *temp, *item, *iter;
AOK(PL_get_arg(1, t, t), NULL);
seq = term_to_python(t, true, NULL);
seq = term_to_python(t, true, NULL, true);
iter = PyObject_GetIter(seq);
if (iter == NULL)
return NULL;
@ -517,7 +519,7 @@ static long get_int(term_t arg, bool eval) {
long low;
if (!PL_get_long(arg, &low)) {
PyObject *low = term_to_python(arg, eval, NULL);
PyObject *low = term_to_python(arg, eval, NULL, eval);
if (PyLong_Check(low)) {
return PyLong_AsLong(low);
#if PY_MAJOR_VERSION < 3
@ -696,546 +698,360 @@ static PyObject *structseq_repr(PyObject *iobj) {
}
#endif
PyObject *term_to_nametuple(const char *s, arity_t arity, PyObject *tuple) {
PyObject *o;
#if PY_MAJOR_VERSION >= 3
PyTypeObject *typp;
PyObject *key = PyUnicode_FromString(s);
if (py_F2P && PyDict_Contains(py_F2P, key)) {
typp = (PyTypeObject *)PyDict_GetItem(py_F2P, key);
Py_INCREF(typp);
} else {
typp = calloc(sizeof(PyTypeObject), 1);
PyStructSequence_Desc *desc = calloc(sizeof(PyStructSequence_Desc), 1);
desc->name = PyMem_Malloc(strlen(s) + 1);
strcpy(desc->name, s);
Py_DECREF(key);
desc->doc = "YAPTerm";
desc->fields = pnull;
desc->n_in_sequence = arity;
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);
// don't do this: we cannot add a type as an atribute.
// PyModule_AddGObject(py_Main, s, (PyObject *)typp);
if (py_F2P)
PyDict_SetItem(py_F2P, key, (PyObject *)typp);
Py_INCREF(typp);
}
o = PyStructSequence_New(typp);
Py_INCREF(typp);
arity_t i;
for (i = 0; i < arity; i++) {
PyObject *pArg = PyTuple_GET_ITEM(tuple, i);
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;
// PyObject_Print(o,stderr,0);fputc('\n',stderr);
return o;
#else
PyObject *o1;
o1 = PyTuple_New(2);
PyTuple_SET_ITEM(o1, 0, PyUnicode_FromString(s));
PyTuple_SET_ITEM(o1, 1, tuple);
return o1;
#endif
static bool
legal_symbol( const char *s)
{
int ch;
while(((ch = *s++) != '\0')) {
if (isalnum(ch) || ch == '_')
continue;
return false;
}
return true;
}
static PyObject *bip_range(term_t t) {
long ilow = 0, ihigh = 0, istep = 1;
long bign;
Py_ssize_t i, n;
int arity;
atom_t name;
term_t arg = PL_new_term_ref();
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);
if (Py_f2p && (d = PyList_GetItem(Py_f2p, arity)) &&
PyDict_Contains(d, key)) {
typp = (PyTypeObject *) PyDict_GetItem(d, key);
Py_INCREF(typp);
} else {
typp = calloc(sizeof(PyTypeObject), 1);
PyStructSequence_Desc *desc = calloc(sizeof(PyStructSequence_Desc), 1);
desc->name = PyMem_Malloc(strlen(s) + 1);
strcpy(desc->name, s);
desc->doc = "YAPTerm";
desc->fields = pnull;
desc->n_in_sequence = arity;
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);
// 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);
Py_DECREF(key);
Py_INCREF(typp);
}
o = PyStructSequence_New(typp);
Py_INCREF(typp);
arity_t i;
for (i = 0; i < arity; i++) {
PyObject *pArg = PyTuple_GET_ITEM(tuple, i);
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;
// PyObject_Print(o,stderr,0);fputc('\n',stderr);
return o;
} else {
PyObject *o1;
o1 = PyTuple_New(2);
PyTuple_SET_ITEM(o1, 0, PyUnicode_FromString(s));
PyTuple_SET_ITEM(o1, 1, tuple);
return o1;
}
}
PyObject *v;
static PyObject *bip_range(term_t t) {
long ilow = 0, ihigh = 0, istep = 1;
long bign;
Py_ssize_t i, n;
int arity;
atom_t name;
term_t arg = PL_new_term_ref();
if (!PL_get_name_arity(t, &name, &arity))
return NULL;
AOK(PL_get_arg(1, t, arg), NULL);
ilow = get_int(arg, true);
if (arity == 1) {
ihigh = ilow;
ilow = 0;
} else {
AOK(PL_get_arg(2, t, arg), NULL);
ihigh = get_int(arg, true);
if (arity == 3) {
AOK(PL_get_arg(3, t, arg), NULL);
istep = get_int(arg, true);
}
}
if (istep == 0) {
PyErr_SetString(PyExc_ValueError, "range() step argument must not be zero");
return NULL;
}
if (istep > 0)
bign = get_len_of_range(ilow, ihigh, istep);
else
bign = get_len_of_range(ihigh, ilow, -istep);
n = (Py_ssize_t)bign;
AOK(((bign >= 0 && (long)n == bign) || "range() result has too many items"),
NULL);
v = PyList_New(n);
PyObject *v;
if (v == NULL)
return Py_None;
for (i = 0; i < n; i++) {
if (!PL_get_name_arity(t, &name, &arity))
return NULL;
AOK(PL_get_arg(1, t, arg), NULL);
ilow = get_int(arg, true);
if (arity == 1) {
ihigh = ilow;
ilow = 0;
} else {
AOK(PL_get_arg(2, t, arg), NULL);
ihigh = get_int(arg, true);
if (arity == 3) {
AOK(PL_get_arg(3, t, arg), NULL);
istep = get_int(arg, true);
}
}
if (istep == 0) {
PyErr_SetString(PyExc_ValueError, "range() step argument must not be zero");
return NULL;
}
if (istep > 0)
bign = get_len_of_range(ilow, ihigh, istep);
else
bign = get_len_of_range(ihigh, ilow, -istep);
n = (Py_ssize_t)bign;
AOK(((bign >= 0 && (long)n == bign) || "range() result has too many items"),
NULL);
v = PyList_New(n);
if (v == NULL)
return Py_None;
for (i = 0; i < n; i++) {
#if PY_MAJOR_VERSION < 3
PyObject *w = PyInt_FromLong(ilow);
PyObject *w = PyInt_FromLong(ilow);
#else
PyObject *w = PyLong_FromLong(ilow);
PyObject *w = PyLong_FromLong(ilow);
#endif
if (w == NULL) {
Py_DECREF(v);
return NULL;
}
PyList_SET_ITEM(v, i, w);
Py_INCREF(w);
ilow += istep;
}
return v;
}
if (w == NULL) {
Py_DECREF(v);
return NULL;
}
PyList_SET_ITEM(v, i, w);
Py_INCREF(w);
ilow += istep;
}
return v;
}
static bool copy_to_dictionary(PyObject *dict, term_t targ, term_t taux,
bool eval) {
PyObject *lhs, *rhs;
term_t tleft = PL_new_term_ref(), tright = PL_new_term_ref();
PyObject *compound_to_pytree(term_t t, PyObject *context, bool cvt) {
PyObject *o = py_Main;
functor_t fun;
atom_t name;
int arity;
functor_t fun;
o = find_obj(context, t, false);
AOK(PL_get_name_arity(t, &name, &arity), NULL);
if (arity == 0)
return term_to_python(t, false, o, false);
AOK(PL_get_functor(t, &fun), NULL);
if (!arity) {
char *s = NULL;
AOK(PL_get_functor(targ, &fun), false);
while (fun == FUNCTOR_comma2) {
AOK(PL_get_arg(1, targ, tleft), false);
if (!copy_to_dictionary(dict, tleft, taux, eval))
return false;
AOK(PL_get_arg(2, targ, targ), false);
return copy_to_dictionary(dict, tright, taux, eval);
}
// PyObject_Print(dict, stderr, 0); fprintf(stderr,"\n");
// Py_DECREF(lhs);
// Py_DECREF(rhs);
AOK(!PL_get_atom_chars(t, &s), NULL);
// this should never happen
return term_to_python(t, false, o, cvt);
} else {
const char *s;
if (!(s = PL_atom_chars(name))) {
return NULL;
}
term_t tleft;
int i;
AOK(PL_get_arg(1, targ, tleft), false);
lhs = atom_to_python_string(tleft);
if (lhs == NULL) {
return FALSE;
}
AOK(PL_get_arg(2, targ, tright), false);
rhs = term_to_python(tright, eval, NULL);
if (rhs == NULL) {
PyErr_Print();
return false;
}
return PyDict_SetItem(dict, lhs, rhs) >= 0;
// PyObject_Print(dict, stderr, 0); fprintf(stderr,"\n");
// Py_DECREF(lhs);
// Py_DECREF(rhs);
}
PyObject *out = PyTuple_New(arity);
DebugPrintf("Tuple %p\n", o);
tleft = PL_new_term_ref();
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);
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 *compound_to_data(term_t t, PyObject *o, functor_t fun, bool exec) {
atom_t name;
int len;
if (c && PyCallable_Check(c)) {
PyObject *n = PyTuple_New(arity);
PyTuple_SET_ITEM(n, 0, c);
PyTuple_SET_ITEM(n, 1, out);
return n;
}
return term_to_nametuple(s, arity, out);
}
}
AOK(PL_get_name_arity(t, &name, &len), o);
PyObject *compound_to_pyeval(term_t t, PyObject *context, bool cvt) {
PyObject *o = NULL;
atom_t name;
int arity;
functor_t fun;
PyObject *d = NULL;
if (fun == FUNCTOR_pointer1) {
void *ptr;
o = find_obj(context, t, true);
AOK(PL_get_name_arity(t, &name, &arity), NULL);
if (arity == 0) {
return term_to_python(t, true, o, cvt);
}
if (!PL_get_functor(t, &fun))
return NULL;
if (fun == FUNCTOR_abs1) {
return bip_abs(t);
} else if (fun == FUNCTOR_all1) {
return bip_all(t);
} else if (fun == FUNCTOR_any1) {
return bip_any(t);
} else if (fun == FUNCTOR_bin1) {
return bip_bin(t);
} else if (fun == FUNCTOR_ord1) {
return bip_ord(t);
} else if (fun == FUNCTOR_int1) {
return bip_int(t);
} else if (fun == FUNCTOR_long1) {
return bip_long(t);
} else if (fun == FUNCTOR_float1) {
return bip_float(t, true);
} else if (fun == FUNCTOR_iter1) {
return bip_iter(t);
} else if (fun == FUNCTOR_range1 || fun == FUNCTOR_range2 ||
fun == FUNCTOR_range3) {
return bip_range(t);
} else if (fun == FUNCTOR_sum1) {
return bip_sum(t);
}
if (fun == FUNCTOR_len1) {
term_t targ = PL_new_term_ref();
PyObject *ptr;
AOK(PL_get_arg(1, t, t), NULL);
AOK(PL_get_pointer(t, &ptr), NULL)
/* return __main__,s */
return (PyObject *)ptr;
}
if (name == ATOM_t) {
term_t targ = PL_new_term_ref();
PyObject *out;
int i;
AOK(PL_get_arg(1, t, targ), NULL);
ptr = term_to_python(targ, true, NULL, true);
return PyLong_FromLong(PyObject_Length(ptr));
}
out = PyTuple_New(len);
DebugPrintf("Tuple %p\n", out);
if (fun == FUNCTOR_div2) {
term_t targ = PL_new_term_ref();
PyObject *lhs, *rhs;
if (!out)
return NULL;
for (i = 0; i < len; i++) {
AOK(PL_get_arg(i + 1, t, targ), NULL);
PyErr_Clear();
PyObject *oa = term_to_python(targ, true, o);
bool rc = PyTuple_SET_ITEM(out, i, oa) == 0;
if (rc) {
PyErr_Print();
}
Py_INCREF(oa);
}
return out;
} else if (fun == FUNCTOR_div2) {
term_t targ = PL_new_term_ref();
PyObject *lhs, *rhs;
AOK(PL_get_arg(1, t, targ), NULL);
lhs = term_to_python(targ, true, NULL);
if (!PyNumber_Check(lhs))
return NULL;
AOK(PL_get_arg(2, t, targ), NULL);
rhs = term_to_python(targ, true, NULL);
if (!PyNumber_Check(rhs))
return NULL;
AOK(PL_get_arg(1, t, targ), NULL);
lhs = term_to_python(targ, true, NULL, false);
if (!PyNumber_Check(lhs))
return NULL;
AOK(PL_get_arg(2, t, targ), NULL);
rhs = term_to_python(targ, true, NULL, false);
if (!PyNumber_Check(rhs))
return NULL;
#if PY_MAJOR_VERSION < 3
return PyNumber_Divide(lhs, rhs);
return PyNumber_Divide(lhs, rhs);
#else
return PyNumber_TrueDivide(lhs, rhs);
return PyNumber_TrueDivide(lhs, rhs);
#endif
}
if (fun == FUNCTOR_sqbrackets2) {
term_t targ = PL_new_term_ref(), trhs = PL_new_term_ref();
PyObject *v;
Py_ssize_t min, max;
AOK(PL_get_arg(2, t, targ), NULL);
v = term_to_python(targ, true, o);
}
if (fun == FUNCTOR_dir1) {
term_t targ = PL_new_term_ref();
PyObject *ptr;
AOK(PL_get_arg(1, t, targ), NULL);
AOK(PL_get_list(targ, trhs, targ), NULL);
if (PL_is_functor(trhs, FUNCTOR_colon2)) {
if (!PySequence_Check(v))
return NULL;
min = get_p_int(term_to_python(targ, true, NULL), 0);
AOK(PL_get_arg(1, trhs, targ), NULL);
if (PL_is_functor(targ, FUNCTOR_colon2)) {
return NULL;
}
max = get_p_int(term_to_python(targ, true, o), PyObject_Size(v));
return PySequence_GetSlice(v, min, max);
} else {
PyObject *ip = term_to_python(trhs, true, o);
if (PySequence_Check(v)) {
AOK(PL_get_arg(1, t, targ), NULL);
ptr = term_to_python(targ, true, NULL, true);
return PyObject_Dir(ptr);
}
else if (fun == FUNCTOR_plus2) {
term_t targ = PL_new_term_ref();
PyObject *lhs, *rhs;
if (!PL_get_arg(1, t, targ))
return NULL;
lhs = term_to_python(targ, true, NULL, true);
AOK(PL_get_arg(2, t, targ), NULL);
rhs = term_to_python(targ, true, NULL, true);
if (PySequence_Check(lhs) && PySequence_Check(rhs)) {
return PySequence_Concat(lhs, rhs);
}
if (!PyNumber_Check(lhs))
return NULL;
if (!PyNumber_Check(rhs))
return NULL;
return PyNumber_Add(lhs, rhs);
} else if (fun == FUNCTOR_sub2) {
term_t targ = PL_new_term_ref();
PyObject *lhs, *rhs;
if (!PL_get_arg(1, t, targ))
return NULL;
lhs = term_to_python(targ, true, NULL, true);
if (!PyNumber_Check(lhs))
return NULL;
if (!PL_get_arg(2, t, targ))
return NULL;
rhs = term_to_python(targ, true, NULL, true);
if (!PyNumber_Check(rhs))
return NULL;
return PyNumber_Subtract(lhs, rhs);
} else if (fun == FUNCTOR_mul2) {
term_t targ = PL_new_term_ref();
PyObject *lhs, *rhs;
AOK(PL_get_arg(1, t, targ), NULL);
(lhs = term_to_python(targ, true, NULL, true));
CHECKNULL(targ, lhs);
AOK(PL_get_arg(2, t, targ), NULL);
(rhs = term_to_python(targ, true, NULL, true));
CHECKNULL(targ, rhs);
if (PySequence_Check(lhs) && (
#if PY_MAJOR_VERSION < 3
if (PyLong_Check(ip) {
min = PyLong_AsLong(ip);
} else if (PyInt_Check(ip) {
min = PyInt_asInt(ip);
}
#else
if (PyLong_Check(ip)) {
PyObject *o = PySequence_GetItem(v, PyLong_AsLong(ip));
if (o == NULL)
o = Py_None;
if (CHECKNULL(t, o) == NULL)
return NULL;
Py_INCREF(o);
return o;
}
PyInt_Check(rhs) ||
#endif
} else {
o = PyObject_GetItem(v, ip);
if (o == NULL)
o = Py_None;
Py_INCREF(o);
return o;
}
}
}
if (fun == FUNCTOR_dollar1) {
char *s = NULL;
term_t targ = PL_new_term_ref();
AOK(PL_get_arg(1, t, targ), NULL);
AOK(PL_get_atom_chars(targ, &s), NULL);
/* return __main__,s */
PyObject *o = PyObject_GetAttrString(py_Main, s);
return o;
}
if (fun == FUNCTOR_brackets1) {
AOK(PL_get_arg(1, t, t), NULL);
return term_to_python(t, true, NULL);
}
if (fun == FUNCTOR_complex2) {
term_t targ = PL_new_term_ref();
PyObject *lhs, *rhs;
double d1, d2;
PyLong_Check(rhs))) {
return PySequence_Repeat(lhs, get_p_int(rhs, 0));
}
if (!PyNumber_Check(lhs) + !PyNumber_Check(rhs))
return NULL;
return PyNumber_Multiply(lhs, rhs);
}
if (!arity) {
char *s = NULL;
PyObject *pValue;
AOK(PL_get_arg(1, t, targ), NULL);
lhs = term_to_python(targ, true, NULL);
AOK(PyNumber_Check(lhs), NULL);
if (PyFloat_Check(lhs)) {
d1 = PyFloat_AsDouble(lhs);
} else if (PyLong_Check(lhs)) {
d1 = PyLong_AsLong(lhs);
#if PY_MAJOR_VERSION < 3
} else if (PyInt_Check(lhs)) {
d1 = PyInt_AsLong(lhs);
#endif
} else {
return NULL;
}
AOK(PL_get_arg(2, t, targ), NULL);
rhs = term_to_python(targ, true, NULL);
AOK(PyNumber_Check(rhs), NULL);
if (PyFloat_Check(rhs)) {
d2 = PyFloat_AsDouble(rhs);
} else if (PyLong_Check(rhs)) {
d2 = PyLong_AsLong(rhs);
#if PY_MAJOR_VERSION < 3
} else if (PyInt_Check(rhs)) {
d2 = PyInt_AsLong(rhs);
#endif
} else {
return NULL;
}
AOK(PL_get_atom_chars(t, &s), NULL);
pValue = PyObject_GetAttrString(o, s);
if (CHECKNULL(t, pValue) == NULL) {
PyErr_Print();
return NULL;
}
return pValue;
} else {
char *s = PL_atom_chars(name);
PyObject *ys = lookupPySymbol(s, o, NULL);
PyObject *pArgs = PyTuple_New(arity);
DebugPrintf("Tuple %p\n", pArgs);
int i;
term_t tleft = PL_new_term_ref();
for (i = 0; i < arity; i++) {
PyObject *pArg;
AOK(PL_get_arg(i + 1, t, tleft), NULL);
/* ignore (_) */
if (i == 0 && PL_is_variable(tleft)) {
pArg = Py_None;
} else {
pArg = term_to_python(tleft, true, NULL, true);
// PyObject_Print(pArg,fdopen(2,"w"),0);
if (pArg == NULL) {
pArg = Py_None;
}
/* pArg reference stolen here: */
Py_INCREF(pArg);
}
return PyComplex_FromDoubles(d1, d2);
}
if (fun == FUNCTOR_curly1) {
term_t targ = PL_new_term_ref(), taux = PL_new_term_ref();
PyObject *dict;
PyTuple_SetItem(pArgs, i, pArg);
}
AOK(PL_get_arg(1, t, t), NULL);
if (!(dict = PyDict_New()))
return NULL;
DebugPrintf("Dict %p\n", dict);
PyObject *rc;
if (ys && PyCallable_Check(ys)) {
while (PL_is_functor(t, FUNCTOR_comma2)) {
AOK(PL_get_arg(1, t, targ), NULL);
AOK(PL_is_functor(targ, FUNCTOR_colon2), NULL);
AOK(copy_to_dictionary(dict, targ, taux, true), NULL);
AOK(PL_get_arg(2, t, t), NULL);
}
if (PL_is_functor(t, FUNCTOR_colon2)) {
AOK(copy_to_dictionary(dict, t, taux, true), NULL);
}
return dict;
}
return o;
}
PyObject *compound_to_pytree(term_t t, PyObject *context) {
PyObject *o = py_Main, *no;
functor_t fun;
atom_t name;
int arity;
o = find_obj(context, t, false);
AOK(PL_get_name_arity(t, &name, &arity), NULL);
if (arity == 0)
return term_to_python(t, false, o);
AOK(PL_get_functor(t, &fun), NULL);
if ((no = compound_to_data(t, o, fun, false)) != o && no) {
return no;
}
if (!arity) {
char *s = NULL;
AOK(!PL_get_atom_chars(t, &s), NULL);
// this should never happen
return term_to_python(t, false, o);
} else {
const char *s;
if (!(s = PL_atom_chars(name))) {
return NULL;
}
term_t tleft;
int i;
PyObject *out = PyTuple_New(arity);
DebugPrintf("Tuple %p\n", o);
tleft = PL_new_term_ref();
for (i = 0; i < arity; i++) {
PyObject *pArg;
AOK(PL_get_arg(i + 1, t, tleft), NULL);
pArg = term_to_python(tleft, false, NULL);
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);
if (c && PyCallable_Check(c)) {
PyObject *n = PyTuple_New(arity);
PyTuple_SET_ITEM(n, 0, c);
PyTuple_SET_ITEM(n, 1, out);
return n;
}
return term_to_nametuple(s, arity, out);
}
}
PyObject *compound_to_pyeval(term_t t, PyObject *context) {
PyObject *o = NULL, *no;
atom_t name;
int arity;
functor_t fun;
o = find_obj(context, t, true);
AOK(PL_get_name_arity(t, &name, &arity), NULL);
if (arity == 0)
return term_to_python(t, true, o);
if (!PL_get_functor(t, &fun))
return NULL;
if ((no = compound_to_data(t, o, fun, true)) != o && no) {
return no;
}
if (fun == FUNCTOR_abs1) {
return bip_abs(t);
} else if (fun == FUNCTOR_all1) {
return bip_all(t);
} else if (fun == FUNCTOR_any1) {
return bip_any(t);
} else if (fun == FUNCTOR_bin1) {
return bip_bin(t);
} else if (fun == FUNCTOR_ord1) {
return bip_ord(t);
} else if (fun == FUNCTOR_int1) {
return bip_int(t);
} else if (fun == FUNCTOR_long1) {
return bip_long(t);
} else if (fun == FUNCTOR_float1) {
return bip_float(t, true);
} else if (fun == FUNCTOR_iter1) {
return bip_iter(t);
} else if (fun == FUNCTOR_range1 || fun == FUNCTOR_range2 ||
fun == FUNCTOR_range3) {
return bip_range(t);
} else if (fun == FUNCTOR_sum1) {
return bip_sum(t);
}
if (fun == FUNCTOR_len1) {
term_t targ = PL_new_term_ref();
PyObject *ptr;
AOK(PL_get_arg(1, t, targ), NULL);
ptr = term_to_python(targ, true, NULL);
return PyLong_FromLong(PyObject_Length(ptr));
}
if (fun == FUNCTOR_dir1) {
term_t targ = PL_new_term_ref();
PyObject *ptr;
AOK(PL_get_arg(1, t, targ), NULL);
ptr = term_to_python(targ, true, NULL);
return PyObject_Dir(ptr);
}
else if (fun == FUNCTOR_plus2) {
term_t targ = PL_new_term_ref();
PyObject *lhs, *rhs;
if (!PL_get_arg(1, t, targ))
return NULL;
lhs = term_to_python(targ, true, NULL);
AOK(PL_get_arg(2, t, targ), NULL);
rhs = term_to_python(targ, true, NULL);
if (PySequence_Check(lhs) && PySequence_Check(rhs)) {
return PySequence_Concat(lhs, rhs);
}
if (!PyNumber_Check(lhs))
return NULL;
if (!PyNumber_Check(rhs))
return NULL;
return PyNumber_Add(lhs, rhs);
} else if (fun == FUNCTOR_sub2) {
term_t targ = PL_new_term_ref();
PyObject *lhs, *rhs;
if (!PL_get_arg(1, t, targ))
return NULL;
lhs = term_to_python(targ, true, NULL);
if (!PyNumber_Check(lhs))
return NULL;
if (!PL_get_arg(2, t, targ))
return NULL;
rhs = term_to_python(targ, true, NULL);
if (!PyNumber_Check(rhs))
return NULL;
return PyNumber_Subtract(lhs, rhs);
} else if (fun == FUNCTOR_mul2) {
term_t targ = PL_new_term_ref();
PyObject *lhs, *rhs;
AOK(PL_get_arg(1, t, targ), NULL);
(lhs = term_to_python(targ, true, NULL));
CHECKNULL(targ, lhs);
AOK(PL_get_arg(2, t, targ), NULL);
(rhs = term_to_python(targ, true, NULL));
CHECKNULL(targ, rhs);
if (PySequence_Check(lhs) && (
#if PY_MAJOR_VERSION < 3
PyInt_Check(rhs) ||
#endif
PyLong_Check(rhs))) {
return PySequence_Repeat(lhs, get_p_int(rhs, 0));
}
if (!PyNumber_Check(lhs) + !PyNumber_Check(rhs))
return NULL;
return PyNumber_Multiply(lhs, rhs);
}
if (!arity) {
char *s = NULL;
PyObject *pValue;
AOK(PL_get_atom_chars(t, &s), NULL);
pValue = PyObject_GetAttrString(o, s);
if (CHECKNULL(t, pValue) == NULL) {
PyErr_Print();
return NULL;
}
return pValue;
} else {
char *s = PL_atom_chars(name);
o = lookupPySymbol(s, o, NULL);
if (CHECKNULL(t, o) == NULL) {
PyErr_Print();
return NULL;
}
PyObject *pArgs = PyTuple_New(arity);
DebugPrintf("Tuple %p\n", pArgs);
int i;
term_t tleft = PL_new_term_ref();
for (i = 0; i < arity; i++) {
PyObject *pArg;
AOK(PL_get_arg(i + 1, t, tleft), NULL);
/* ignore (_) */
if (i == 0 && PL_is_variable(tleft)) {
pArg = Py_None;
} else {
pArg = term_to_python(tleft, true, NULL);
// PyObject_Print(pArg,fdopen(2,"w"),0);
if (pArg == NULL) {
pArg = Py_None;
}
/* pArg reference stolen here: */
Py_INCREF(pArg);
}
PyTuple_SetItem(pArgs, i, pArg);
}
if (!PyCallable_Check(o)) {
return term_to_nametuple(s, arity, pArgs);
}
PyObject *rc;
// PyObject_Print(pArgs, stderr, 0);
// PyObject_Print(o, stderr, 0);
CHECK_CALL(rc, t, PyObject_CallObject(o, pArgs));
Py_DECREF(pArgs);
Py_DECREF(o);
DebugPrintf("CallObject %p\n", rc);
return rc;
}
}
// PyObject_Print(pArgs, stderr, 0);
// PyObject_Print(o, stderr, 0);
CHECK_CALL(rc, t, PyObject_CallObject(ys, pArgs));
Py_DECREF(pArgs);
Py_DECREF(ys);
DebugPrintf("CallObject %p\n", rc);
} else {
rc = term_to_nametuple(s, arity, pArgs);
}
return rc;
}
}

View File

@ -12,7 +12,7 @@ static foreign_t python_len(term_t tobj, term_t tf) {
Py_ssize_t len;
PyObject *o;
o = term_to_python(tobj, true, NULL);
o = term_to_python(tobj, true, NULL, true);
if (o == NULL) {
pyErrorAndReturn(false, false);
}
@ -24,7 +24,7 @@ static foreign_t python_dir(term_t tobj, term_t tf) {
PyObject *dir;
PyObject *o;
o = term_to_python(tobj, true, NULL);
o = term_to_python(tobj, true, NULL, true);
if (o == NULL) {
pyErrorAndReturn(false, false);
}
@ -41,14 +41,14 @@ static foreign_t python_index(term_t tobj, term_t tindex, term_t val) {
PyObject *o;
PyObject *f;
o = term_to_python(tobj, true, NULL);
o = term_to_python(tobj, true, NULL, true);
if (o == NULL) {
pyErrorAndReturn(false, false);
}
if (!PySequence_Check(o)) {
pyErrorAndReturn(false, false);
}
i = term_to_python(tindex, true, NULL);
i = term_to_python(tindex, true, NULL, true);
if (i == NULL) {
pyErrorAndReturn(false, false);
}
@ -69,7 +69,7 @@ static foreign_t python_is(term_t tobj, term_t tf) {
term_t lim = python_acquire_GIL();
o = term_to_python(tobj, true, NULL);
o = term_to_python(tobj, true, NULL, true);
if (!o) {
python_release_GIL(lim);
pyErrorAndReturn(false, false);
@ -87,7 +87,7 @@ static foreign_t python_proc(term_t tobj) {
term_t lim = python_acquire_GIL();
o = term_to_python(tobj, true, NULL);
o = term_to_python(tobj, true, NULL, true);
python_release_GIL(lim);
bool rc = o != NULL;
pyErrorAndReturn(rc , false);
@ -100,10 +100,10 @@ static foreign_t python_slice(term_t parent, term_t indx, term_t tobj) {
PyObject *p;
// get Scope ...
pI = term_to_python(indx, true, NULL);
pI = term_to_python(indx, true, NULL, true);
// got Scope.Exp
// get Scope ...
p = term_to_python(parent, true, NULL);
p = term_to_python(parent, true, NULL, true);
// Exp
if (!pI || !p) {
{ pyErrorAndReturn(false, false); }
@ -131,7 +131,7 @@ static foreign_t python_apply(term_t tin, term_t targs, term_t keywds,
foreign_t out;
term_t targ = PL_new_term_ref();
pF = term_to_python(tin, true, NULL);
pF = term_to_python(tin, true, NULL, true);
PyErr_Clear();
if (pF == NULL) {
{ pyErrorAndReturn(false, false); }
@ -159,7 +159,7 @@ static foreign_t python_apply(term_t tin, term_t targs, term_t keywds,
if (!PL_get_arg(i + 1, targs, targ)) {
pyErrorAndReturn(false, false);
}
pArg = term_to_python(targ, true, NULL);
pArg = term_to_python(targ, true, NULL, true);
if (pArg == NULL) {
pyErrorAndReturn(false, false);
}
@ -171,7 +171,7 @@ static foreign_t python_apply(term_t tin, term_t targs, term_t keywds,
if (PL_is_atom(keywds)) {
pKeywords = NULL;
} else {
pKeywords = term_to_python(keywds, true, NULL);
pKeywords = term_to_python(keywds, true, NULL, true);
}
if (PyCallable_Check(pF)) {
pValue = PyEval_CallObjectWithKeywords(pF, pArgs, pKeywords);
@ -204,7 +204,7 @@ static foreign_t python_apply(term_t tin, term_t targs, term_t keywds,
static foreign_t assign_python(term_t exp, term_t name) {
term_t stackp = python_acquire_GIL();
PyObject *e = term_to_python(exp, true, NULL);
PyObject *e = term_to_python(exp, true, NULL, true);
if (e == NULL) {
python_release_GIL(stackp);
@ -253,7 +253,7 @@ static foreign_t python_builtin_eval(term_t caller, term_t dict, term_t out) {
if (i == 0 && PL_is_variable(targ)) {
pArg = Py_None;
} else {
pArg = term_to_python(targ, true, NULL);
pArg = term_to_python(targ, true, NULL, true);
if (pArg == NULL) {
pyErrorAndReturn(false, false);
}
@ -280,7 +280,7 @@ static foreign_t python_builtin_eval(term_t caller, term_t dict, term_t out) {
static foreign_t python_access(term_t obj, term_t f, term_t out) {
PyErr_Clear();
PyObject *o = term_to_python(obj, true, NULL), *pValue, *pArgs, *pF;
PyObject *o = term_to_python(obj, true, NULL, true), *pValue, *pArgs, *pF;
atom_t name;
char *s = NULL;
int i, arity;
@ -323,7 +323,7 @@ static foreign_t python_access(term_t obj, term_t f, term_t out) {
if (i == 0 && PL_is_variable(targ)) {
pArgs = Py_None;
}
pArg = term_to_python(targ, true, NULL);
pArg = term_to_python(targ, true, NULL, true);
if (pArg == NULL) {
pyErrorAndReturn(false, false);
}
@ -352,7 +352,7 @@ static foreign_t python_field(term_t parent, term_t att, term_t tobj) {
// got Scope.Exp
// get Scope ...
p = term_to_python(parent, true, NULL);
p = term_to_python(parent, true, NULL, true);
// Exp
if (!PL_get_name_arity(att, &name, &arity)) {
{ pyErrorAndReturn(false, false); }
@ -392,7 +392,7 @@ static foreign_t python_main_module(term_t mod) {
static foreign_t python_function(term_t tobj) {
PyErr_Clear();
PyObject *obj = term_to_python(tobj, true, NULL);
PyObject *obj = term_to_python(tobj, true, NULL, true);
foreign_t rc = PyFunction_Check(obj);
pyErrorAndReturn(rc, false);
@ -595,7 +595,7 @@ if (pName == NULL) {
static foreign_t python_to_rhs(term_t inp, term_t t) {
PyObject *pVal;
PyErr_Clear();
pVal = term_to_python(inp, true, NULL);
pVal = term_to_python(inp, true, NULL, true);
if (pVal == NULL)
pyErrorAndReturn(false, false);
pyErrorAndReturn(address_to_term(pVal, t), false);

View File

@ -1,19 +1,23 @@
#include "py4yap.h"
#include <VFS.h>
#include "YapStreams.h"
atom_t ATOM_true, ATOM_false, ATOM_colon, ATOM_dot, ATOM_none, ATOM_t,
ATOM_comma, ATOM_builtin, ATOM_A, ATOM_V, ATOM_self, ATOM_nil, ATOM_brackets, ATOM_curly_brackets;
ATOM_comma, ATOM_builtin, ATOM_A, ATOM_V, ATOM_self, ATOM_nil,
ATOM_brackets, ATOM_curly_brackets;
functor_t FUNCTOR_dollar1, FUNCTOR_abs1, FUNCTOR_all1, FUNCTOR_any1,
FUNCTOR_bin1, FUNCTOR_brackets1, FUNCTOR_comma2, FUNCTOR_dir1,
FUNCTOR_float1, FUNCTOR_int1, FUNCTOR_iter1, FUNCTOR_iter2, FUNCTOR_long1,
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_brackets1;
FUNCTOR_bin1, FUNCTOR_brackets1, FUNCTOR_comma2, FUNCTOR_dir1,
FUNCTOR_float1, FUNCTOR_int1, FUNCTOR_iter1, FUNCTOR_iter2, FUNCTOR_long1,
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_brackets1;
X_API PyObject *py_Builtin;
X_API PyObject *py_Yapex;
@ -23,77 +27,88 @@ PyObject *py_ModDict;
VFS_t pystream;
static void *
py_open( const char *name, const char *io_mode) {
static void *py_open(const char *name, const char *io_mode) {
#if HAVE_STRCASESTR
if (strcasestr(name,"//python/")== name)
if (strcasestr(name, "//python/") == name)
name += strlen("//python/");
#else
if (strstr(name,"//python/")== name)
#else
if (strstr(name, "//python/") == name)
name += strlen("//python/");
#endif
// we assume object is already open, so there is no need to open it.
PyObject *stream = string_to_python( name, true, NULL);
PyObject *stream = string_to_python(name, true, NULL);
if (stream == Py_None)
return NULL;
Py_INCREF(stream);
return stream;
}
static bool
py_close(int sno) {
PyObject *s = YAP_foreign_stream(sno);
PyObject* fclose = PyObject_GetAttrString(s, "close");
PyObject* rc= PyObject_CallObject(fclose, NULL);
static bool py_close(int sno) {
StreamDesc *s = YAP_GetStreamFromId(sno);
PyObject *fclose = PyObject_GetAttrString(s->u.private_data, "close");
PyObject *rc = PyObject_CallObject(fclose, NULL);
bool v = (rc == Py_True);
return v;
}
static PyObject * pyw; // buffer
static int pyw_kind;
PyObject * pyw_data;
static int
py_put(int sno, int ch) {
PyObject *s = YAP_foreign_stream(sno);
PyUnicode_WRITE( pyw_kind, pyw_data, 0, ch );
PyObject* fput = PyObject_GetAttrString(s, "write");
PyObject_CallFunctionObjArgs(fput, pyw, NULL);
static int py_put(int sno, int ch) {
PyObject *pyw; // buffer
//int pyw_kind;
//PyObject *pyw_data;
char s[2];
StreamDesc *st = YAP_GetStreamFromId(sno);
// PyUnicode_WRITE(pyw_kind, pyw_data, 0, ch);
PyObject *fput = PyObject_GetAttrString(st->u.private_data, "write");
s[0] = ch;
s[1] = '\0';
PyObject_CallFunctionObjArgs(fput, PyBytes_FromString(s), NULL);
return ch;
}
static int
py_get(int sno) {
PyObject *s = YAP_foreign_stream(sno);
PyObject* fget = PyObject_GetAttrString(s, "read");
static int py_get(int sno) {
StreamDesc *s = YAP_GetStreamFromId(sno);
PyObject *fget = PyObject_GetAttrString(s->u.private_data, "read");
PyObject *pyr = PyObject_CallFunctionObjArgs(fget, PyLong_FromLong(1), NULL);
return PyUnicode_READ_CHAR( pyr, 0) ;
return PyUnicode_READ_CHAR(pyr, 0);
}
static int64_t py_seek(int sno, int64_t where, int how) {
PyObject *s = YAP_foreign_stream(sno);
PyObject* fseek = PyObject_GetAttrString(s, "seek");
PyObject *pyr = PyObject_CallFunctionObjArgs(fseek, PyLong_FromLong(where), PyLong_FromLong(how), NULL);
static int64_t py_seek(int sno, int64_t where, int how) {
StreamDesc *s = YAP_GetStreamFromId(sno);
PyObject *fseek = PyObject_GetAttrString(s->u.private_data, "seek");
PyObject *pyr = PyObject_CallFunctionObjArgs(fseek, PyLong_FromLong(where),
PyLong_FromLong(how), NULL);
return PyLong_AsLong(pyr);
}
static void
py_flush(int sno) {
PyObject *s = YAP_foreign_stream(sno);
PyObject* flush = PyObject_GetAttrString(s, "flush");
PyObject_CallFunction( flush, NULL);
static void py_flush(int sno) {
StreamDesc *s = YAP_GetStreamFromId(sno);
PyObject *flush = PyObject_GetAttrString(s->u.private_data, "flush");
PyObject_CallFunction(flush, NULL);
}
#if 0
static void python_output(void) {
PyObject *stream = string_to_python("sys.stdout", true, NULL);
StreamDesc *st = YAP_GetStreamFromId(1);
st->u.private_data = stream;
st->vfs = &pystream;
stream = string_to_python("sys.stderr", true, NULL);
st = YAP_GetStreamFromIds(2);
st->u.private_data = stream;
st->vfs = &pystream;
}
#endif
static bool init_python_stream(void) {
//pyw = PyUnicode_FromString("x");
//pyw_kind = PyUnicode_KIND(pyw);
//pyw_data = PyUnicode_DATA(pyw);
static bool
init_python_stream(void)
{
pyw = PyUnicode_FromString("x");
pyw_kind = PyUnicode_KIND(pyw);
pyw_data = PyUnicode_DATA(pyw);
pystream.name = "python stream";
pystream.vflags = VFS_CAN_WRITE|VFS_CAN_EXEC| VFS_CAN_SEEK|VFS_HAS_PREFIX;
pystream.vflags =
VFS_CAN_WRITE | VFS_CAN_EXEC | VFS_CAN_SEEK | VFS_HAS_PREFIX;
pystream.prefix = "//python/";
pystream.suffix = NULL;
pystream.open = py_open;
@ -108,7 +123,7 @@ init_python_stream(void)
return true;
}
X_API PyObject *py_F2P;
X_API PyObject *Py_f2p;
extern X_API bool python_in_python;
@ -125,11 +140,12 @@ static void add_modules(void) {
py_Yapex = PyImport_AddModule("yap4py.yapi");
if (py_Yapex)
Py_INCREF(py_Yapex);
py_F2P = PyDict_New();
Py_f2p = PythonLookup("f2p", NULL);
if (Py_f2p)
Py_INCREF(Py_f2p);
init_python_stream();
}
static void install_py_constants(void) {
FUNCTOR_dot2 = PL_new_functor(PL_new_atom("."), 2);
// FUNCTOR_equal2 = PL_new_functor(PL_new_atom("="), 2);
@ -176,7 +192,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);
}
}
foreign_t end_python(void) {
if (!python_in_python)
@ -189,11 +205,11 @@ static bool libpython_initialized = 0;
X_API bool do_init_python(void) {
// char **argv;
if (libpython_initialized)
if (libpython_initialized)
return true;
libpython_initialized = true;
// PyGILState_STATE gstate = PyGILState_Ensure();
// PyGILState_STATE gstate = PyGILState_Ensure();
term_t t = PL_new_term_ref();
if (!python_in_python)
Py_Initialize();
@ -201,7 +217,7 @@ X_API bool do_init_python(void) {
PL_reset_term_refs(t);
install_pl2pl();
// PyGILState_Release(gstate);
add_modules();
add_modules();
// python_output();
return true;
}

View File

@ -0,0 +1 @@
import yap4py.yapi

View File

@ -1,54 +0,0 @@
/*
%% @file yapi.yap
%% @brief support yap shell
%%
:- module(yapi, [bindvars/2]).
:- use_module( library(maplist) ).
:- use_module( library(rbtrees) ).
bindvars( [], [] ) :- !.
bindvars( L, NL ) :-
rb_new(T),
% trace,
foldl2( bind, L, NL, T, _ , 0, _),
term_variables(NL, Vs),
foldl( bind_new, Vs, 0, _).
bind(t(_,t(X,Y)), Z, T0, T, N1, N2) :-
!,
bind(X=Y, Z, T0, T, N1, N2).
bind(tuple(_,tuple(X,Y)), Z, T0, T, N1, N2) :-
!,
bind(X=Y, Z, T0, T, N1, N2).
bind(X=Y, X=X, T0, T, N, N) :-
var(Y),
!,
rb_update(T0, Y, X, T).
bind(X = G, X = G, T, T, N0, N0) :-
ground(G),
!.
bind(X = C, X = NC, T, NT, N0, NF) :-
C =.. [N|L],
foldl2(newb, L, NL, T, NT, N0, NF),
NC =.. [N|NL].
newb(Y, X, T, T, N, N) :-
var(Y),
rb_lookup(Y, X, T),
!.
newb(Y, X, T, TN, N, NF) :-
var(Y),
!,
rb_insert(Y, T, X, TN),
NF is N+1,
atomic_concat('_',N,X).
newb(Y, Y, T, T, N, N) :-
ground(Y),
!.
newb(Y, X, T, NT, N0, NF) :-
Y =.. [N|L],
foldl2(newb, L, NL, T, NT, N0, NF),
X =.. [N|NL].
*/

View File

@ -1,6 +1,7 @@
import os.path
import sys
import keyword
# debugging support.
# import pdb
from collections import namedtuple
@ -20,6 +21,8 @@ class Engine( YAPEngine ):
YAPEngine.__init__(self,args)
self.goal( set_prolog_flag('verbose', 'silent' ) )
self.goal( use_module(library('yapi') ) )
self.goal( set_prolog_flag('verbose', 'normal' ) )
def run(self, g, m=None):
if m:
@ -81,7 +84,16 @@ class PrologTableIter:
self.q = None
raise StopIteration()
f2p = []
for i in range(16):
f2p += [{}]
def named( name, arity):
if arity > 0 and name.isidentifier() and not keyword.iskeyword(name):
s = []
for i in range(arity):
s += ["A" + str(i)]
f2p[arity][name] = namedtuple(name, s)
class PrologPredicate( YAPPrologPredicate ):
""" Interface to Prolog Predicate"""
@ -103,8 +115,12 @@ yapi_query = namedtuple( 'yapi_query', 'vars dict')
show_answer = namedtuple( 'show_answer', 'vars dict')
set_prolog_flag = namedtuple('set_prolog_flag', 'flag new_value')
def v():
return yap.YAPVarTerm()
class v(YAPVarTerm):
def __init__(self):
super().__init__()
def binding(self):
return self.term()
def numbervars( q ):
Dict = {}
@ -113,105 +129,110 @@ def numbervars( q ):
return Dict
rc = q.namedVarsVector()
q.r = q.goal().numbervars()
print( rc )
o = []
for i in rc:
if len(i) == 2:
do = str(i[0]) + " = " + str( i[1] ) + "\n"
o += do
print(do)
else:
do = str(i[0]) + " = " + str( i[1] ) + "\n"
o += do
print(do)
return o
def answer(q):
try:
v = q.next()
if v:
print( bindings )
return v
except Exception as e:
print(e.args[1])
return False
class YAPShell:
def query_prolog(engine, s):
# import pdb; pdb.set_trace()
#
# construct a query from a one-line string
# q is opaque to Python
bindings = {}
q = engine.query(python_query(s, bindings))
# vs is the list of variables
# you can print it out, the left-side is the variable name,
# the right side wraps a handle to a variable
# pdb.set_trace()
# #pdb.set_trace()
# atom match either symbols, or if no symbol exists, sttrings, In this case
# variable names should match strings
#for eq in vs:
# if not isinstance(eq[0],str):
# print( "Error: Variable Name matches a Python Symbol")
# return
ask = True
# launch the query
while answer(q):
# deterministic = one solution
if q.deterministic():
# done
q.close()
return True, True
if ask:
s = input("more(;), all(*), no(\\n), python(#) ?").lstrip()
if s.startswith(';') or s.startswith('y'):
continue
elif s.startswith('#'):
try:
exec(s.lstrip('#'))
except:
raise
elif s.startswith('*') or s.startswith('a'):
ask = False
continue
else:
break
print("No (more) answers")
q.close()
return
def live(**kwargs):
loop = True
while loop:
def answer(self, q):
try:
s = input("?- ")
if not s:
loop = False
else:
query_prolog(engine, s)
except SyntaxError as err:
print("Syntax Error error: {0}".format(err))
except EOFError:
return
except RuntimeError as err:
print("YAP Execution Error: {0}".format(err))
except ValueError:
print("Could not convert data to an integer.")
except:
print("Unexpected error:", sys.exc_info()[0])
raise
engine.close()
#
# initialize engine
# engine = yap.YAPEngine();
# engine = yap.YAPEngine(yap.YAPParams());
#
#
self.bindings = {}
v = q.next()
if v:
print( self.bindings )
return v
except Exception as e:
print(e.args[1])
return False
def boot_yap(**kwargs):
return Engine(**kwargs)
def query_prolog(self, engine, s):
# import pdb; pdb.set_trace()
#
# construct a query from a one-line string
# q is opaque to Python
#
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,
# the right side wraps a handle to a variable
# pdb.set_trace()
# #pdb.set_trace()
# atom match either symbols, or if no symbol exists, sttrings, In this case
# variable names should match strings
#for eq in vs:
# if not isinstance(eq[0],str):
# print( "Error: Variable Name matches a Python Symbol")
# return
do_ask = True
self.port = "call"
# launch the query
while self.answer(q):
if self.port == "exit":
# done
q.close()
return True, True
if do_ask:
s = input("more(;), all(*), no(\\n), python(#) ?").lstrip()
if s.startswith(';') or s.startswith('y'):
continue
elif s.startswith('#'):
try:
exec(s.lstrip('#'))
except:
raise
elif s.startswith('*') or s.startswith('a'):
do_ask = False
continue
else:
break
print("No (more) answers")
q.close()
return
def live(self, engine, **kwargs):
loop = True
while loop:
try:
s = input("?- ")
if not s:
loop = False
else:
self.query_prolog(engine, s)
except SyntaxError as err:
print("Syntax Error error: {0}".format(err))
except EOFError:
return
except RuntimeError as err:
print("YAP Execution Error: {0}".format(err))
except ValueError:
print("Could not convert data to an integer.")
except:
print("Unexpected error:", sys.exc_info()[0])
raise
engine.close()
#
# initialize engine
# engine = yap.YAPEngine();
# engine = yap.YAPEngine(yap.YAPParams());
#
def __init__(self, engine, **kwargs):
self.live(engine)
def main():
engine = Engine()
handler = numbervars
YAPShell(engine)
if __name__ == "__main__":
engine = boot_yap()
handler = numbervars
live()
main()

View File

@ -1,12 +1,19 @@
drye%% @file yapi.yap
%% @file yapi.yap
%% @brief support yap shell
%%
:- module(yapi, [python_query/2,
% :- yap_flag(verbose, verbose).
:- use_module( library(python) ).
:- module(yapi, [
python_ouput/0,
show_answer/2,
show_answer/3,
yap_query/4,
yapi_query/2]).
python_query/2,
yapi_query/2
]).
:- use_module( library(lists) ).
:- use_module( library(maplist) ).
@ -14,102 +21,49 @@ drye%% @file yapi.yap
:- use_module( library(terms) ).
:- use_module( library(python) ).
%% @pred yap_query(sGoal, + VarList, +OutStream, - Dictionary)
%% @pred yap_query(0:Goal, + VarList, - Dictionary)
%%
%% dictionary, Examples
%%
%%
python_query( String, D ) :-
atomic_to_term( String, Goal, VarNames ),
yap_query( Goal, VarNames, user_error, Dict),
D := Dict,
yap4py.yapi.bindings := Dict.
:- python_import(yap4py.yapi).
%% @pred yapi_query( + VarList, - Dictionary)
%%
%% dictionary, Examples
%%
%%
yapi_query( VarNames, Dict ) :-
show_answer(VarNames, Dict).
yapi_query( VarNames, Self ) :-
show_answer(VarNames, Dict),
Self.bindings := Dict.
:- initialization set_preds.
%% @pred yap_query(0:Goal, + VarList, +OutStream, - Dictionary)
%% @pred yap_query(0:Goal, + VarList, - Dictionary)
%%
%% dictionary, Examples
%%
%%
yap_query( Goal, VarNames, Stream, Dictionary) :-
(
call(Goal)
*->
!,
show_answer(VarNames, Stream, Dictionary)
).
yap_query( VarNames, Dictionary) :-
yap_query( VarNames, user_output, Dictionary).
show_answer(QVs0, Dict) :-
show_answer(QVs0, user_error, Dict).
show_answer(QVs0, Stream, Dict) :-
copy_term(QVs0, QVs),
copy_term(QVs0, QVs1),
rb_new(RB),
foldl2(bind_qv, QVs, QVs1, [], LP, {}-RB, Dict-_),
!,
term_variables(QVs, IVs),
term_variables(QVs1, IVs1),
foldl( enumerate, IVs, IVs1, 1, _ ),
out(LP, Stream ).
show_answer(_, _, {}) :-
format(' yes.~n', [] ).
bind_qv(V=V0, V1 = V01, Vs, Vs, Vs1-RB, Vs1-RB) :-
var(V0),
!,
'$VAR'(V) = V0,
V1 = V01.
% atom_string(V1, V01).
bind_qv(V='$VAR'(Vi), V1=S1, Vs, [V='$VAR'(Vi)|Vs], D0-RB, D-RB) :- !,
add2dict(D0, V1:S1, D).
bind_qv(V=S, V1=S1, Vs, [V=S|Vs], D0-RB0, D-RB0) :-
% fix_tree( S, SS, S1, SS1, RB0, RBT),
add2dict(D0, V1:S1, D).
add2dict({}, B, {B}).
add2dict({C}, B, {B,C}).
enumerate('$VAR'(A), A, I, I1) :-
enum(I, Chars),
atom_codes(A,[0'_|Chars]),
I1 is I + 1.
enum(I, [C]) :-
I < 26,
!,
C is "A" + I.
enum(I, [C|Cs]) :-
J is I//26,
K is I mod 26,
C is "A" +K,
enum(J, Cs).
out(Bs, S) :-
output(Bs, S),
!.
out([_|Bs], S) :-
out(Bs, S).
output([V=B], S) :-
!,
format(S, '~a = ~q~n', [V, B]).
output([V=B|_Ns], S) :-
format( S, '~a = ~q.~n', [V, B]),
set_preds :-
current_predicate(P, Q),
functor(Q,P,A),
atom_string(P,S),
:= yap4py.yapi.named( S, A),
fail.
set_preds :-
system_predicate(P/A),
atom_string(P,S),
:= yap4py.yapi.named( S, A),
fail.
set_preds.
argi(N,I,I1) :-
atomic_concat(`A`,I,N),
I1 is I+1.
python_query( Self, String ) :-
yap_flag(typein_module, Mod),
atomic_to_term( String, Goal, VarNames ),
query_to_answer( Mod:Goal, VarNames, Status, Bindings),
maplist(in_dict(Self.bindings), Bindings),
write_query_answer( Bindings ),
nl( user_error ),
Self.port := Status.
in_dict(Dict, var([V0,V|Vs])) :- !,
Dict[V] := V0,
in_dict( Dict, var([V0|Vs])).
in_dict(Dict, nonvar([V0|Vs],G)) :- !,
Dict[V0] := G,
in_dict( Dict, var([V0|Vs])).
in_dict(_, _).

View File

@ -49,9 +49,13 @@
configure_file(setup.py.in ${CMAKE_CURRENT_BINARY_DIR}/setup.py)
file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/yap_kernel/resources)
file( GENERATE OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/yap_kernel/resources/logo-32x32.png INPUT ${CMAKE_SOURCE_DIR}/docs/icons/yap_32x32x32.png )
file( GENERATE OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/yap_kernel/resources/logo-64x64.png INPUT ${CMAKE_SOURCE_DIR}/docs/icons/yap_64x64x32.png )
file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/yap_kernel/resources )
file( COPY ${CMAKE_SOURCE_DIR}/docs/icons/yap_32x32x32.png
DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/yap_kernel/resources/ )
file( RENAME ${CMAKE_CURRENT_BINARY_DIR}/yap_kernel/resources/yap_32x32x32.png ${CMAKE_CURRENT_BINARY_DIR}/yap_kernel/resources/logo-32x32.png )
file( COPY ${CMAKE_SOURCE_DIR}/docs/icons/yap_64x64x32.png DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/yap_kernel/resources )
file( RENAME ${CMAKE_CURRENT_BINARY_DIR}/yap_kernel/resources/yap_64x64x32.png ${CMAKE_CURRENT_BINARY_DIR}/yap_kernel/resources/logo-64x64.png )
file( COPY ${CMAKE_CURRENT_SOURCE_DIR}/kernel.js DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/yap_kernel/resources/ )
file( COPY ${CMAKE_SOURCE_DIR}/misc/editors/prolog.js DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/yap_kernel/resources/)
set(SETUP_PY ${CMAKE_CURRENT_BINARY_DIR}/setup.py)

View File

@ -1,6 +1,10 @@
#include COPYING.md
#include CONTRIBUTING.md
include README.md
include yap_kernel/resources/logo-32x32.png
include yap_kernel/resources/logo-64x64.png
include yap_kernel/resources/kernel.js
include yap_kernel/resources/kernel.json
# Documentation

View File

View File

@ -14,6 +14,7 @@ name = 'yap_kernel'
#-----------------------------------------------------------------------------
import sys
import sysconfig
import setuptools
v = sys.version_info
@ -43,8 +44,10 @@ packages = setuptools.find_packages('${CMAKE_CURRENT_SOURCE_DIR}')
# if os.path.exists(pjoin(d, '__init__.py')):
# packages.append(d[len(here)+1:].replace(os.path.sep, '.'))
sys.path.insert(0, "${CMAKE_CURRENT_SOURCE_DIR}")
package_data = {
'yap_kernel': ['resources/*.*','prolog/*.*'],
'yap_ipython': ['prolog/*.*'],
'yap_kernel': ['resources/*.*']
}
@ -62,9 +65,9 @@ setup_args = dict(
packages = packages,
py_modules = ['yap_kernel_launcher'],
package_data = package_data,
package_dir = {'':"${CMAKE_CURRENT_SOURCE_DIR}" },
package_dir = {'':"${CMAKE_CURRENT_SOURCE_DIR}"},
description = "YAP Kernel for Jupyter",
author = 'YP Development Team',
author = 'YAP Development Team',
author_email = 'YAP-dev@scipy.org',
url = 'http://ipython.org',
license = 'BSD',
@ -91,15 +94,26 @@ install_requires = setuptools_args['install_requires'] = [
if any(a.startswith(('bdist', 'build', 'install')) for a in sys.argv):
from yap_kernel.kernelspec import write_kernel_spec, make_yap_kernel_cmd, KERNEL_NAME
argv = make_yap_kernel_cmd(executable='python')
dest = os.path.join(here, 'data_kernelspec')
dest = os.path.join(here, 'resources')
if os.path.exists(dest):
shutil.rmtree(dest)
write_kernel_spec(dest, overrides={'argv': argv})
shutil.copy('${CMAKE_CURRENT_SOURCE_DIR}/kernel.js',dest)
shutil.copy('${CMAKE_SOURCE_DIR}/misc/editors/prolog.js',dest)
shutil.copy('${CMAKE_SOURCE_DIR}/docs/icons/yap_32x32x32.png',os.path.join(dest,'logo-32x32.png'))
shutil.copy('${CMAKE_SOURCE_DIR}/docs/icons/yap_64x64x32.png',os.path.join(dest,'logo-64x64.png'))
setup_args['data_files'] = [
(pjoin('share', 'jupyter', 'kernels', KERNEL_NAME), glob(pjoin(dest, '*'))),
]
mode_loc = pjoin( sysconfig.get_path('platlib'), 'notebook', 'static', 'components', 'codemirror', 'mode', 'prolog')
try:
os.mkdir(mode_loc)
except:
pass
shutil.copy( "${CMAKE_SOURCE_DIR}/misc/editors/prolog.js" , mode_loc)
extras_require = setuptools_args['extras_require'] = {
'test:python_version=="2.7"': ['mock'],

View File

@ -0,0 +1,151 @@
# encoding: utf-8
"""
IPython: tools for interactive and parallel computing in Python.
http://ipython.org
"""
#-----------------------------------------------------------------------------
# Copyright (c) 2008-2011, IPython Development Team.
# Copyright (c) 2001-2007, Fernando Perez <fernando.perez@colorado.edu>
# Copyright (c) 2001, Janko Hauser <jhauser@zscout.de>
# Copyright (c) 2001, Nathaniel Gray <n8gray@caltech.edu>
#
# Distributed under the terms of the Modified BSD License.
#
# The full license is in the file COPYING.txt, distributed with this software.
#-----------------------------------------------------------------------------
#-----------------------------------------------------------------------------
# Imports
#-----------------------------------------------------------------------------
import os
import sys
#-----------------------------------------------------------------------------
# Setup everything
#-----------------------------------------------------------------------------
# Don't forget to also update setup.py when this changes!
if sys.version_info < (3,3):
raise ImportError(
"""
IPython 6.0+ does not support Python 2.6, 2.7, 3.0, 3.1, or 3.2.
When using Python 2.7, please install IPython 5.x LTS Long Term Support version.
Beginning with IPython 6.0, Python 3.3 and above is required.
See IPython `README.rst` file for more information:
https://github.com/ipython/ipython/blob/master/README.rst
""")
# Make it easy to import extensions - they are always directly on pythonpath.
# Therefore, non-IPython modules can be added to extensions directory.
# This should probably be in ipapp.py.
sys.path.append(os.path.join(os.path.dirname(__file__), "extensions"))
#-----------------------------------------------------------------------------
# Setup the top level names
#-----------------------------------------------------------------------------
from .core.getipython import get_ipython
from .core import release
from IPython.core.application import Application
from IPython.terminal.embed import embed
from .core.interactiveshell import YAPInteractive as InteractiveShell
from IPython.testing import test
from IPython.utils.sysinfo import sys_info
from IPython.utils.frame import extract_module_locals
# Release data
__author__ = '%s <%s>' % (release.author, release.author_email)
__license__ = release.license
__version__ = release.version
version_info = release.version_info
def embed_kernel(module=None, local_ns=None, **kwargs):
"""Embed and start an IPython kernel in a given scope.
If you don't want the kernel to initialize the namespace
from the scope of the surrounding function,
and/or you want to load full IPython configuration,
you probably want `IPython.start_kernel()` instead.
Parameters
----------
module : ModuleType, optional
The module to load into IPython globals (default: caller)
local_ns : dict, optional
The namespace to load into IPython user namespace (default: caller)
kwargs : various, optional
Further keyword args are relayed to the IPKernelApp constructor,
allowing configuration of the Kernel. Will only have an effect
on the first embed_kernel call for a given process.
"""
(caller_module, caller_locals) = extract_module_locals(1)
if module is None:
module = caller_module
if local_ns is None:
local_ns = caller_locals
# Only import .zmq when we really need it
from ipykernel.embed import embed_kernel as real_embed_kernel
real_embed_kernel(module=module, local_ns=local_ns, **kwargs)
def start_ipython(argv=None, **kwargs):
"""Launch a normal IPython instance (as opposed to embedded)
`IPython.embed()` puts a shell in a particular calling scope,
such as a function or method for debugging purposes,
which is often not desirable.
`start_ipython()` does full, regular IPython initialization,
including loading startup files, configuration, etc.
much of which is skipped by `embed()`.
This is a public API method, and will survive implementation changes.
Parameters
----------
argv : list or None, optional
If unspecified or None, IPython will parse command-line options from sys.argv.
To prevent any command-line parsing, pass an empty list: `argv=[]`.
user_ns : dict, optional
specify this dictionary to initialize the IPython user namespace with particular values.
kwargs : various, optional
Any other kwargs will be passed to the Application constructor,
such as `config`.
"""
from IPython.terminal.ipapp import launch_new_instance
return launch_new_instance(argv=argv, **kwargs)
def start_kernel(argv=None, **kwargs):
"""Launch a normal IPython kernel instance (as opposed to embedded)
`IPython.embed_kernel()` puts a shell in a particular calling scope,
such as a function or method for debugging purposes,
which is often not desirable.
`start_kernel()` does full, regular IPython initialization,
including loading startup files, configuration, etc.
much of which is skipped by `embed()`.
Parameters
----------
argv : list or None, optional
If unspecified or None, IPython will parse command-line options from sys.argv.
To prevent any command-line parsing, pass an empty list: `argv=[]`.
user_ns : dict, optional
specify this dictionary to initialize the IPython user namespace with particular values.
kwargs : various, optional
Any other kwargs will be passed to the Application constructor,
such as `config`.
"""
from IPython.kernel.zmq.kernelapp import launch_new_instance
return launch_new_instance(argv=argv, **kwargs)

View File

@ -0,0 +1,20 @@
#-----------------------------------------------------------------------------
# Copyright (C) 2013 The IPython Development Team
#
# Distributed under the terms of the BSD License. The full license is in
# the file COPYING, distributed as part of this software.
#-----------------------------------------------------------------------------
#-----------------------------------------------------------------------------
# Classes and functions
#-----------------------------------------------------------------------------
def get_ipython():
"""Get the global InteractiveShell instance.
Returns None if no InteractiveShell instance is registered.
"""
from yap_ipython.core.interactiveshell import YAPInteractive
if YAPInteractive.initialized():
return YAPInteractive.instance()

View File

@ -0,0 +1,397 @@
import os
import sys
import abc
import yap4py.yapi
from IPython.core import interactiveshell
from IPython.core.completer import IPCompleter
from IPython.core.interactiveshell import ExecutionResult, InteractiveShell
from IPython.utils.strdispatch import StrDispatch
# import yap_ipython.core
from traitlets import Instance
from pygments import highlight
from pygments.lexers.prolog import PrologLexer
from pygments.formatters import HtmlFormatter
from collections import namedtuple
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_query = namedtuple('jupyter_query', 'self string')
enter_cell = namedtuple('enter_cell', 'self' )
exit_cell = namedtuple('exit_cell', 'self' )
completions = namedtuple('completions', 'txt self' )
class YAPCompleter:
def __init__(self, engine):
self.yapeng = engine
self.completions = None
def complete(self, text, line=None, cursor_pos=None):
"""Return the completed text and a list of completions.
Parameters
----------
text : string
A string of text to be completed on. It can be given as empty and
instead a line/position pair are given. In this case, the
completer itself will split the line like readline does.
line : string, optional
The complete line that text is part of.
cursor_pos : int, optional
The position of the cursor on the input line.
Returns
-------
text : string
The actual text that was completed.
matches : list
A sorted list with all possible completions.
The optional arguments allow the completion to take more context into
account, and are part of the low-level completion API.
This is a wrapper around the completion mechanism, similar to what
readline does at the command line when the TAB key is hit. By
exposing it as a method, it can be used by other non-readline
environments (such as GUIs) for text completion.
Simple usage example:
In [1]: x = 'hello'
In [2]: _ip.complete('x.l')
Out[2]: ('x.l', ['x.ljust', 'x.lower', 'x.lstrip'])
"""
if not text:
text = line[:cursor_pos]
self.yapeng.goal(completions(text, self))
return text, self.completions
# def _init__(self, **kwargs) -> None:
# PyCompleter.__init__(**kwargs__)
class YAPInteractive(InteractiveShell):
"""An enhanced, interactive shell for YAP."""
def init_yap_completer(self):
"""Initialize the completion machinery.
This creates completion machinery that can be used by client code,
either interactively in-process (typically triggered by the readline
library), programmatically (such as in test suites) or out-of-process
(typically over the network by remote frontends).
"""
print(self)
# Add custom completers to the basic ones built into IPCompleter
self.Completer = YAPCompleter(self.yapeng)
self.configurables.append(self.Completer)
def __init__(self, **kwargs):
super(YAPInteractive, self).__init__(**kwargs)
# type: (object, object) -> object
pjoin = os.path.join
here = os.path.dirname(__file__)
self.yapeng = yap4py.yapi.Engine()
self.yapeng.goal(use_module(pjoin(here, '../prolog/jupyter.yap')))
self.q = None
self.run = False
self.os = ""
self.port = None
self.init_yap_completer()
def init_syntax_highlighting(self, changes=None):
# Python source parser/formatter for syntax highlighting
# pyformat = PyColorize.Parser(style=self.colors, parent=self).format
# self.pycolorize = lambda src: pyformat(src,'str')
self.pycolorize = lambda code : highlight(code, PrologLexer(), HtmlFormatter())
def complete(self, text, line=None, cursor_pos=None):
"""Return the completed text and a list of completions.
Parameters
----------
text : string
A string of text to be completed on. It can be given as empty and
instead a line/position pair are given. In this case, the
completer itself will split the line like readline does.
line : string, optional
The complete line that text is part of.
cursor_pos : int, optional
The position of the cursor on the input line.
Returns
-------
text : string
The actual text that was completed.
matches : list
A sorted list with all possible completions.
The optional arguments allow the completion to take more context into
account, and are part of the low-level completion API.
This is a wrapper around the completion mechanism, similar to what
readline does at the command line when the TAB key is hit. By
exposing it as a method, it can be used by other non-readline
environments (such as GUIs) for text completion.
Simple usage example:
In [1]: x = 'hello'
In [2]: _ip.complete('x.l')
Out[2]: ('x.l', ['x.ljust', 'x.lower', 'x.lstrip'])
"""
# Inject names into __builtin__ so we can complete on the added names.
return self.Completer.complete(text, line, cursor_pos)
def run_cell(self, raw_cell, store_history=True, silent=False,
shell_futures=True):
"""Run a complete IPython cell.
Parameters
----------
raw_cell : str
The code (including IPython code such as
%magic functions) to run.
store_history : bool
If True, the raw and translated cell will be stored in IPython's
history. For user code calling back into
IPython's machinery, this
should be set to False.
silent : bool
If True, avoid side-effects, such as implicit displayhooks and
and logging. silent=True forces store_history=False.
shell_futures : bool
If True, the code will share future statements with the interactive
shell. It will both be affected by previous
__future__ imports, and any __future__ imports in the code
will affect the shell. If False,
__future__ imports are not shared in either direction.
Returns
-------
`result : :class:`ExecutionResult`
"""
# construct a query from a one-line string
# q is opaque to Python
# vs is the list of variables
# you can print it out, the left-side is the variable name,
# the right side wraps a handle to a variable
# pdb.set_trace()
# #pdb.set_trace()
# atom match either symbols, or if no symbol exists, strings, In this case
# variable names should match strings
# ask = True
# launch the query
result = ExecutionResult()
if (not raw_cell) or raw_cell.isspace():
self.last_execution_succeeded = True
return result
if silent:
store_history = False
if store_history:
result.execution_count = self.execution_count
def error_before_exec(value):
result.error_before_exec = value
self.last_execution_succeeded = False
return result
self.events.trigger('pre_execute')
if not silent:
self.events.trigger('pre_run_cell')
# If any of our input transformation (input_transformer_manager or
# prefilter_manager) raises an exception, we store it in this variable
# so that we can display the error after logging the input and storing
# it in the history.
# preprocessing_exc_tuple = None
# try:
# # Static input transformations
# cell = raw_cell #self.input_transformer_manager.transform_cell(raw_cell)
# except SyntaxError:
# preprocessing_exc_tuple = sys.exc_info()
cell = raw_cell # cell has to exist so it can be stored/logged
# else:
# # import pdb; pdb.set_trace()
# if False and len(cell.splitlines()) == 1:
# # Dynamic transformations - only applied for single line commands
# with self.builtin_trap:
# try:
# # use prefilter_lines to handle trailing newlines
# # restore trailing newline for ast.parse
# cell = self.prefilter_manager.prefilter_lines(cell) + '\n'
# except Exception:
# # don't allow prefilter errors to crash IPython
# preprocessing_exc_tuple = sys.exc_info()
# Store raw and processed history
if store_history:
self.history_manager.store_inputs(self.execution_count,
cell, raw_cell)
if not silent:
self.logger.log(cell, raw_cell)
# # Display the exception if input processing failed.
# if preprocessing_exc_tuple is not None:
# self.showtraceback(preprocessing_exc_tuple)
# if store_history:
# self.execution_count += 1
# return error_before_exec(preprocessing_exc_tuple[2])
# Our own compiler remembers the __future__ environment. If we want to
# run code with a separate __future__ environment, use the default
# compiler
# compiler = self.compile if shell_futures else CachingCompiler()
cell_name = str( self.execution_count)
if cell[0] == '%':
if cell[1] == '%':
linec = False
mcell = cell.lstrip('%%')
else:
linec = True
mcell = cell.lstrip('%')
txt0 = mcell.split(maxsplit = 2, sep = '\n')
txt = txt0[0].split(maxsplit = 2)
magic = txt[0]
if len(txt) == 2:
line = txt[1]
else:
line = ""
if linec:
self.run_line_magic(magic, line)
if len(txt0) == 2:
cell = txt0[1]
else:
cellArea = ""
else:
self.run_cell_magic(magic, line, cell)
return
# Give the displayhook a reference to our ExecutionResult so it
# can fill in the output value.
self.displayhook.exec_result = result
has_raised = False
try:
self.bindings = dict = {}
state = self.jupyter_query(cell)
if state:
self.last_execution_succeeded = True
result.result = (True, dict)
else:
self.last_execution_succeeded = True
result.result = (True, {})
except Exception as e:
print(e)
has_raised = True
result.result = False
self.last_execution_succeeded = not has_raised
# Reset this so later displayed values do not modify the
# ExecutionResult
self.displayhook.exec_result = None
print(self.complete)
self.events.trigger('post_execute')
if not silent:
self.events.trigger('post_run_cell')
if store_history:
# Write output to the database. Does nothing unless
# history output logging is enabled.
self.history_manager.store_output(self.execution_count)
# Each cell is a *single* input, regardless of how many lines it has
self.execution_count += 1
return result
def jupyter_query(self, s):
# import pdb; pdb.set_trace()
#
# construct a self.query from a one-line string
# self.q is opaque to Python
self.bindings = {}
self.port = "call"
if self.q and s != self.os:
self.q.close()
self.q = None
if not self.q:
self.q = self.yapeng.query(jupyter_query(self, s))
self.os = s
# vs is the list of variables
# you can print it out, the left-side is the variable name,
# the right side wraps a handle to a variable
# pdb.set_trace()
# #pdb.set_trace()
# atom match either symbols, or if no symbol exists, sttrings, In this case
# variable names should match strings
#for eq in vs:
# if not isinstance(eq[0],str):
# print( "Error: Variable Name matches a Python Symbol")
# return
# ask = True
# launch the query
# run the new command using the given tracer
rc = self.answer(self.q)
if rc:
# deterministic = one solution
if self.port == "exit":
# done
self.q.close()
self.q = None
self.os = ""
print("yes")
return True, self.bindings
print("No (more) answers")
self.q.close()
self.q = None
return True, None
def answer(self, q):
try:
return q.next()
except Exception as e:
print(e.args[1])
self.yapeng.goal(exit_cell(self))
return False, None
class YAPInteractiveABC(metaclass=abc.ABCMeta):
"""An abstract base class for YAPInteractive."""
YAPInteractiveABC.register(YAPInteractive)

View File

@ -0,0 +1,13 @@
from modulefinder import ModuleFinder
finder = ModuleFinder()
finder.run_script('__main__.py')
print('Loaded modules:')
for name, mod in finder.modules.items():
print('%s: ' % name, end='')
print(','.join(list(mod.globalnames.keys())[:3]))
print('-'*50)
print('Modules not imported:')
print('\n'.join(finder.badmodules.keys()))

View File

@ -0,0 +1,118 @@
# -*- coding: utf-8 -*-
"""Release data for the IPython project."""
#-----------------------------------------------------------------------------
# Copyright (c) 2008, IPython Development Team.
# Copyright (c) 2001, Fernando Perez <fernando.perez@colorado.edu>
# Copyright (c) 2001, Janko Hauser <jhauser@zscout.de>
# Copyright (c) 2001, Nathaniel Gray <n8gray@caltech.edu>
#
# Distributed under the terms of the Modified BSD License.
#
# The full license is in the file COPYING.txt, distributed with this software.
#-----------------------------------------------------------------------------
# Name of the package for release purposes. This is the name which labels
# the tarballs and RPMs made by distutils, so it's best to lowercase it.
name = 'ipython'
# IPython version information. An empty _version_extra corresponds to a full
# release. 'dev' as a _version_extra string means this is a development
# version
_version_major = 0
_version_minor = 1
_version_patch = 0
_version_extra = '.dev'
# _version_extra = 'rc2'
_version_extra = '' # Uncomment this for full releases
# Construct full version string from these.
_ver = [_version_major, _version_minor, _version_patch]
__version__ = '.'.join(map(str, _ver))
if _version_extra:
__version__ = __version__ + _version_extra
version = __version__ # backwards compatibility name
version_info = (_version_major, _version_minor, _version_patch, _version_extra)
# Change this when incrementing the kernel protocol version
kernel_protocol_version_info = (5, 0)
kernel_protocol_version = "%i.%i" % kernel_protocol_version_info
description = "IPython: Productive Interactive Computing"
long_description = \
"""
IPython provides a rich toolkit to help you make the most out of using Python
interactively. Its main components are:
* A powerful interactive Python shell
* A `Jupyter <http://jupyter.org/>`_ kernel to work with Python code in Jupyter
notebooks and other interactive frontends.
The enhanced interactive Python shells have the following main features:
* Comprehensive object introspection.
* Input history, persistent across sessions.
* Caching of output results during a session with automatically generated
references.
* Extensible tab completion, with support by default for completion of python
variables and keywords, filenames and function keywords.
* Extensible system of 'magic' commands for controlling the environment and
performing many tasks related either to IPython or the operating system.
* A rich configuration system with easy switching between different setups
(simpler than changing $PYTHONSTARTUP environment variables every time).
* Session logging and reloading.
* Extensible syntax processing for special purpose situations.
* Access to the system shell with user-extensible alias system.
* Easily embeddable in other Python programs and GUIs.
* Integrated access to the pdb debugger and the Python profiler.
The latest development version is always available from IPython's `GitHub
site <http://github.com/ipython>`_.
"""
license = 'BSD'
authors = {'Fernando' : ('Fernando Perez','fperez.net@gmail.com'),
'Janko' : ('Janko Hauser','jhauser@zscout.de'),
'Nathan' : ('Nathaniel Gray','n8gray@caltech.edu'),
'Ville' : ('Ville Vainio','vivainio@gmail.com'),
'Brian' : ('Brian E Granger', 'ellisonbg@gmail.com'),
'Min' : ('Min Ragan-Kelley', 'benjaminrk@gmail.com'),
'Thomas' : ('Thomas A. Kluyver', 'takowl@gmail.com'),
'Jorgen' : ('Jorgen Stenarson', 'jorgen.stenarson@bostream.nu'),
'Matthias' : ('Matthias Bussonnier', 'bussonniermatthias@gmail.com'),
}
author = 'The IPython Development Team'
author_email = 'ipython-dev@python.org'
url = 'https://ipython.org'
platforms = ['Linux','Mac OSX','Windows']
keywords = ['Interactive','Interpreter','Shell', 'Embedding']
classifiers = [
'Framework :: IPython',
'Intended Audience :: Developers',
'Intended Audience :: Science/Research',
'License :: OSI Approved :: BSD License',
'Programming Language :: Python',
'Programming Language :: Python :: 3',
'Topic :: System :: Shells'
]

View File

@ -0,0 +1,414 @@
# encoding: utf-8
"""
A mixin for :class:`~IPython.core.application.Application` classes that
launch InteractiveShell instances, load extensions, etc.
"""
# Copyright (c) IPython Development Team.
# Distributed under the terms of the Modified BSD License.
import glob
from itertools import chain
import os
import sys
from traitlets.config.application import boolean_flag
from traitlets.config.configurable import Configurable
from traitlets.config.loader import Config
from IPython.core.application import SYSTEM_CONFIG_DIRS
from IPython.core import pylabtools
from IPython.utils.contexts import preserve_keys
from IPython.utils.path import filefind
from traitlets import (
Unicode, Instance, List, Bool, CaselessStrEnum, observe,
)
from IPython.terminal import pt_inputhooks
ENV_CONFIG_DIRS = []
_env_config_dir = os.path.join(sys.prefix, 'etc', 'ipython')
if _env_config_dir not in SYSTEM_CONFIG_DIRS:
# only add ENV_CONFIG if sys.prefix is not already included
ENV_CONFIG_DIRS.append(_env_config_dir)
#-----------------------------------------------------------------------------
# Aliases and Flags
#-----------------------------------------------------------------------------
gui_keys = tuple(sorted(pt_inputhooks.backends) + sorted(pt_inputhooks.aliases))
backend_keys = sorted(pylabtools.backends.keys())
backend_keys.insert(0, 'auto')
shell_flags = {}
addflag = lambda *args: shell_flags.update(boolean_flag(*args))
addflag('autoindent', 'YAPInteractive.autoindent',
'Turn on autoindenting.', 'Turn off autoindenting.'
)
addflag('automagic', 'YAPInteractive.automagic',
"""Turn on the auto calling of magic commands. Type %%magic at the
IPython prompt for more information.""",
'Turn off the auto calling of magic commands.'
)
addflag('pdb', 'YAPInteractive.pdb',
"Enable auto calling the pdb debugger after every exception.",
"Disable auto calling the pdb debugger after every exception."
)
addflag('pprint', 'PlainTextFormatter.pprint',
"Enable auto pretty printing of results.",
"Disable auto pretty printing of results."
)
addflag('color-info', 'YAPInteractive.color_info',
"""IPython can display information about objects via a set of functions,
and optionally can use colors for this, syntax highlighting
source code and various other elements. This is on by default, but can cause
problems with some pagers. If you see such problems, you can disable the
colours.""",
"Disable using colors for info related things."
)
nosep_config = Config()
nosep_config.YAPInteractive.separate_in = ''
nosep_config.YAPInteractive.separate_out = ''
nosep_config.YAPInteractive.separate_out2 = ''
shell_flags['nosep']=(nosep_config, "Eliminate all spacing between prompts.")
shell_flags['pylab'] = (
{'YAPInteractiveApp' : {'pylab' : 'auto'}},
"""Pre-load matplotlib and numpy for interactive use with
the default matplotlib backend."""
)
shell_flags['matplotlib'] = (
{'YAPInteractiveApp' : {'matplotlib' : 'auto'}},
"""Configure matplotlib for interactive use with
the default matplotlib backend."""
)
# it's possible we don't want short aliases for *all* of these:
shell_aliases = dict(
autocall='YAPInteractive.autocall',
colors='YAPInteractive.colors',
logfile='YAPInteractive.logfile',
logappend='YAPInteractive.logappend',
c='YAPInteractiveApp.code_to_run',
m='YAPInteractiveApp.module_to_run',
ext='YAPInteractiveApp.extra_extension',
gui='YAPInteractiveApp.gui',
pylab='YAPInteractiveApp.pylab',
matplotlib='YAPInteractiveApp.matplotlib',
)
shell_aliases['cache-size'] = 'YAPInteractive.cache_size'
#-----------------------------------------------------------------------------
# Main classes and functions
#-----------------------------------------------------------------------------
class YAPInteractiveApp(Configurable):
"""A Mixin for applications that start YAPInteractive instances.
Provides configurables for loading extensions and executing files
as part of configuring a Shell environment.
The following methods should be called by the :meth:`initialize` method
of the subclass:
- :meth:`init_path`
- :meth:`init_shell` (to be implemented by the subclass)
- :meth:`init_gui_pylab`
- :meth:`init_extensions`
- :meth:`init_code`
"""
extensions = List(Unicode(),
help="A list of dotted module names of IPython extensions to load."
).tag(config=True)
extra_extension = Unicode('',
help="dotted module name of an IPython extension to load."
).tag(config=True)
reraise_ipython_extension_failures = Bool(False,
help="Reraise exceptions encountered loading IPython extensions?",
).tag(config=True)
# Extensions that are always loaded (not configurable)
default_extensions = List(Unicode(), [u'storemagic']).tag(config=False)
hide_initial_ns = Bool(True,
help="""Should variables loaded at startup (by startup files, exec_lines, etc.)
be hidden from tools like %who?"""
).tag(config=True)
exec_files = List(Unicode(),
help="""List of files to run at IPython startup."""
).tag(config=True)
exec_PYTHONSTARTUP = Bool(True,
help="""Run the file referenced by the PYTHONSTARTUP environment
variable at IPython startup."""
).tag(config=True)
file_to_run = Unicode('',
help="""A file to be run""").tag(config=True)
exec_lines = List(Unicode(),
help="""lines of code to run at IPython startup."""
).tag(config=True)
code_to_run = Unicode('',
help="Execute the given command string."
).tag(config=True)
module_to_run = Unicode('',
help="Run the module as a script."
).tag(config=True)
gui = CaselessStrEnum(gui_keys, allow_none=True,
help="Enable GUI event loop integration with any of {0}.".format(gui_keys)
).tag(config=True)
matplotlib = CaselessStrEnum(backend_keys, allow_none=True,
help="""Configure matplotlib for interactive use with
the default matplotlib backend."""
).tag(config=True)
pylab = CaselessStrEnum(backend_keys, allow_none=True,
help="""Pre-load matplotlib and numpy for interactive use,
selecting a particular matplotlib backend and loop integration.
"""
).tag(config=True)
pylab_import_all = Bool(True,
help="""If true, IPython will populate the user namespace with numpy, pylab, etc.
and an ``import *`` is done from numpy and pylab, when using pylab mode.
When False, pylab mode should not import any names into the user namespace.
"""
).tag(config=True)
shell = Instance('yap_ipython.core.interactiveshell.YAPInteractiveABC',
allow_none=True)
# whether interact-loop should start
interact = Bool(True)
user_ns = Instance(dict, args=None, allow_none=True)
@observe('user_ns')
def _user_ns_changed(self, change):
if self.shell is not None:
self.shell.user_ns = change['new']
self.shell.init_user_ns()
def init_path(self):
"""Add current working directory, '', to sys.path"""
if sys.path[0] != '':
sys.path.insert(0, '')
def init_shell(self):
raise NotImplementedError("Override in subclasses")
def init_gui_pylab(self):
"""Enable GUI event loop integration, taking pylab into account."""
enable = False
shell = self.shell
if self.pylab:
enable = lambda key: shell.enable_pylab(key, import_all=self.pylab_import_all)
key = self.pylab
elif self.matplotlib:
enable = shell.enable_matplotlib
key = self.matplotlib
elif self.gui:
enable = shell.enable_gui
key = self.gui
if not enable:
return
try:
r = enable(key)
except ImportError:
self.log.warning("Eventloop or matplotlib integration failed. Is matplotlib installed?")
self.shell.showtraceback()
return
except Exception:
self.log.warning("GUI event loop or pylab initialization failed")
self.shell.showtraceback()
return
if isinstance(r, tuple):
gui, backend = r[:2]
self.log.info("Enabling GUI event loop integration, "
"eventloop=%s, matplotlib=%s", gui, backend)
if key == "auto":
print("Using matplotlib backend: %s" % backend)
else:
gui = r
self.log.info("Enabling GUI event loop integration, "
"eventloop=%s", gui)
def init_extensions(self):
"""Load all IPython extensions in IPythonApp.extensions.
This uses the :meth:`ExtensionManager.load_extensions` to load all
the extensions listed in ``self.extensions``.
"""
try:
self.log.debug("Loading IPython extensions...")
extensions = self.default_extensions + self.extensions
if self.extra_extension:
extensions.append(self.extra_extension)
for ext in extensions:
try:
self.log.info("Loading IPython extension: %s" % ext)
self.shell.extension_manager.load_extension(ext)
except:
if self.reraise_ipython_extension_failures:
raise
msg = ("Error in loading extension: {ext}\n"
"Check your config files in {location}".format(
ext=ext,
location=self.profile_dir.location
))
self.log.warning(msg, exc_info=True)
except:
if self.reraise_ipython_extension_failures:
raise
self.log.warning("Unknown error in loading extensions:", exc_info=True)
def init_code(self):
"""run the pre-flight code, specified via exec_lines"""
self._run_startup_files()
self._run_exec_lines()
self._run_exec_files()
# Hide variables defined here from %who etc.
if self.hide_initial_ns:
self.shell.user_ns_hidden.update(self.shell.user_ns)
# command-line execution (ipython -i script.py, ipython -m module)
# should *not* be excluded from %whos
self._run_cmd_line_code()
self._run_module()
# flush output, so itwon't be attached to the first cell
sys.stdout.flush()
sys.stderr.flush()
def _run_exec_lines(self):
"""Run lines of code in IPythonApp.exec_lines in the user's namespace."""
if not self.exec_lines:
return
try:
self.log.debug("Running code from IPythonApp.exec_lines...")
for line in self.exec_lines:
try:
self.log.info("Running code in user namespace: %s" %
line)
self.shell.run_cell(line, store_history=False)
except:
self.log.warning("Error in executing line in user "
"namespace: %s" % line)
self.shell.showtraceback()
except:
self.log.warning("Unknown error in handling IPythonApp.exec_lines:")
self.shell.showtraceback()
def _exec_file(self, fname, shell_futures=False):
try:
full_filename = filefind(fname, [u'.', self.ipython_dir])
except IOError:
self.log.warning("File not found: %r"%fname)
return
# Make sure that the running script gets a proper sys.argv as if it
# were run from a system shell.
save_argv = sys.argv
sys.argv = [full_filename] + self.extra_args[1:]
try:
if os.path.isfile(full_filename):
self.log.info("Running file in user namespace: %s" %
full_filename)
# Ensure that __file__ is always defined to match Python
# behavior.
with preserve_keys(self.shell.user_ns, '__file__'):
self.shell.user_ns['__file__'] = fname
if full_filename.endswith('.ipy'):
self.shell.safe_execfile_ipy(full_filename,
shell_futures=shell_futures)
else:
# default to python, even without extension
self.shell.safe_execfile(full_filename,
self.shell.user_ns,
shell_futures=shell_futures,
raise_exceptions=True)
finally:
sys.argv = save_argv
def _run_startup_files(self):
"""Run files from profile startup directory"""
startup_dirs = [self.profile_dir.startup_dir] + [
os.path.join(p, 'startup') for p in chain(ENV_CONFIG_DIRS, SYSTEM_CONFIG_DIRS)
]
startup_files = []
if self.exec_PYTHONSTARTUP and os.environ.get('PYTHONSTARTUP', False) and \
not (self.file_to_run or self.code_to_run or self.module_to_run):
python_startup = os.environ['PYTHONSTARTUP']
self.log.debug("Running PYTHONSTARTUP file %s...", python_startup)
try:
self._exec_file(python_startup)
except:
self.log.warning("Unknown error in handling PYTHONSTARTUP file %s:", python_startup)
self.shell.showtraceback()
for startup_dir in startup_dirs[::-1]:
startup_files += glob.glob(os.path.join(startup_dir, '*.py'))
startup_files += glob.glob(os.path.join(startup_dir, '*.ipy'))
if not startup_files:
return
self.log.debug("Running startup files from %s...", startup_dir)
try:
for fname in sorted(startup_files):
self._exec_file(fname)
except:
self.log.warning("Unknown error in handling startup files:")
self.shell.showtraceback()
def _run_exec_files(self):
"""Run files from IPythonApp.exec_files"""
if not self.exec_files:
return
self.log.debug("Running files in IPythonApp.exec_files...")
try:
for fname in self.exec_files:
self._exec_file(fname)
except:
self.log.warning("Unknown error in handling IPythonApp.exec_files:")
self.shell.showtraceback()
def _run_cmd_line_code(self):
"""Run code or file specified at the command-line"""
if self.code_to_run:
line = self.code_to_run
try:
self.log.info("Running code given at command line (c=): %s" %
line)
self.shell.run_cell(line, store_history=False)
except:
self.log.warning("Error in executing line in user namespace: %s" %
line)
self.shell.showtraceback()
if not self.interact:
self.exit(1)
# Like Python itself, ignore the second if the first of these is present
elif self.file_to_run:
fname = self.file_to_run
if os.path.isdir(fname):
fname = os.path.join(fname, "__main__.py")
try:
self._exec_file(fname, shell_futures=True)
except:
self.shell.showtraceback(tb_offset=4)
if not self.interact:
self.exit(1)
def _run_module(self):
"""Run module specified at the command-line."""
if self.module_to_run:
# Make sure that the module gets a proper sys.argv as if it were
# run using `python -m`.
save_argv = sys.argv
sys.argv = [sys.executable] + self.extra_args
try:
self.shell.safe_run_module(self.module_to_run,
self.shell.user_ns)
finally:
sys.argv = save_argv

View File

@ -0,0 +1,83 @@
:- use_module(library(yapi)).
:- use_module(library(python)).
:- python_import(sys).
jupyter_query(Self, Cell) :-
setup_call_cleanup(
enter_cell(Self),
python_query(Self, Cell),
exit_cell(Self)
).
enter_cell(_Self) :-
open('//python/sys.stdout', append, _Output, [alias(jupo)]),
open('//python/sys.stdout', append, _, [alias(jupe)]),
set_prolog_flag(user_output, jupo),
set_prolog_flag(user_error, jupe).
exit_cell(_Self) :-
close( jupo),
close( jupe).
completions(S, Self) :-
open(atom(S), read, St),
scan_to_list(St, Tokens),
reverse(Tokens, RTokens),
setof( Completion, complete(RTokens, Completion), Cs),
Self.completions := Cs.
complete( [atom(F)|LibRest], C) :-
LibRest = [l, atom(Where)|Consult],
isconsult(Consult, Rest),
\+ arg( Rest ),
check_library( F, Where, C).
complete( [atom(F)|Consult], C) :-
isconsult(Consult, Rest),
\+ arg( Rest ),
check_file( F, C).
complete( [atom(F)|Rest], C) :-
\+ arg( Rest ),
predicate( F, Pred, Arity ),
cont( Arity, Pred, C).
isconsult( [l, use_module| _Rest]).
isconsult( [l, ensure_loaded| _Rest]).
isconsult( [l, compile| _Rest]).
isconsult( [l, consult| _Rest]).
isconsult( [l, reconsult| _Rest]).
isconsult( [l, load_files| _Rest]).
isconsult( ['-', ']'| _Rest]).
isconsult( [']'| _Rest]).
arg(([']'|_]).
arg(([l|_]).
check_file(F,C) :-
atom_concat( F, '*' , Pat),
absolute_file_name( Pat, C0, [glob(true)] ),
atom_concat(['\'',C0,'\''], C).
check_library( Lib, F, C) :-
atom_concat( F, '*' , Pat),
LibF =.. [Lib(Pat)],
absolute_file_name( LibF, Lib, [glob(true)] ),
file_directory_name( Lib, Name),
( atom_concat(C, '.yap', Name) -> true ;
atom_concat(C, '.ypp', Name) -> true ;
atom_concat(C, '.prolog', Name) -> true
).
predicate(N,P,A) :-
system_predicate(P0/A),
atom_concat(N,P,P0).
predicate(N,P,A) :-
current_predicate(P0/A),
atom_concat(N,P,P0).
cont(0, P, P).
cont( _, P, PB ):-
atom_concat( P, '(', PB ).

View File

@ -1,5 +1,16 @@
import sys
import trace
# create a Trace object, telling it what to ignore, and whether to
# do tracing or line-counting or both.
tracer = trace.Trace(
# ignoredirs=[sys.prefix, sys.exec_prefix],
trace=1,
count=0)
if __name__ == '__main__':
from yap_kernel import kernelapp as app
# tracer.run('app.launch_new_instance()')
app.launch_new_instance()

View File

@ -5,6 +5,8 @@
from __future__ import absolute_import
from IPython.utils.py3compat import str_to_bytes
import json
import sys
from subprocess import Popen, PIPE
@ -13,7 +15,6 @@ import warnings
from IPython.core.profiledir import ProfileDir
from IPython.paths import get_ipython_dir
from ipython_genutils.path import filefind
from ipython_genutils.py3compat import str_to_bytes
import jupyter_client
from jupyter_client import write_connection_file
@ -39,7 +40,7 @@ def get_connection_file(app=None):
def find_connection_file(filename='kernel-*.json', profile=None):
"""DEPRECATED: find a connection file, and return its absolute path.
THIS FUNCION IS DEPRECATED. Use juptyer_client.find_connection_file instead.
Parameters
@ -54,7 +55,7 @@ def find_connection_file(filename='kernel-*.json', profile=None):
-------
str : The absolute path of the connection file.
"""
import warnings
warnings.warn("""yap_kernel.find_connection_file is deprecated, use jupyter_client.find_connection_file""",
DeprecationWarning, stacklevel=2)
@ -77,13 +78,13 @@ def find_connection_file(filename='kernel-*.json', profile=None):
# find profiledir by profile name:
profile_dir = ProfileDir.find_profile_dir_by_name(get_ipython_dir(), profile)
security_dir = profile_dir.security_dir
return jupyter_client.find_connection_file(filename, path=['.', security_dir])
def _find_connection_file(connection_file, profile=None):
"""Return the absolute path for a connection file
- If nothing specified, return current Kernel's connection file
- If profile specified, show deprecation warning about finding connection files in profiles
- Otherwise, call jupyter_client.find_connection_file

View File

@ -0,0 +1,941 @@
# -*- coding: utf-8 -*-
"""Display formatters.
Inheritance diagram:
.. inheritance-diagram:: IPython.core.formatters
:parts: 3
"""
# Copyright (c) IPython Development Team.
# Distributed under the terms of the Modified BSD License.
import abc
import json
import sys
import traceback
import warnings
from io import StringIO
from IPython.lib import pretty
from IPython.utils.dir2 import get_real_method
from IPython.utils.sentinel import Sentinel
from decorator import decorator
from traitlets import (
Bool, Dict, Integer, Unicode, CUnicode, ObjectName, List,
ForwardDeclaredInstance,
default, observe,
)
from traitlets.config.configurable import Configurable
from packages.python.yap_kernel.core.yap_kernel.getipython import get_ipython
class DisplayFormatter(Configurable):
active_types = List(Unicode(),
help="""List of currently active mime-types to display.
You can use this to set a white-list for formats to display.
Most users will not need to change this value.
""").tag(config=True)
@default('active_types')
def _active_types_default(self):
return self.format_types
@observe('active_types')
def _active_types_changed(self, change):
for key, formatter in self.formatters.items():
if key in change['new']:
formatter.enabled = True
else:
formatter.enabled = False
ipython_display_formatter = ForwardDeclaredInstance('FormatterABC')
@default('ipython_display_formatter')
def _default_formatter(self):
return IPythonDisplayFormatter(parent=self)
# A dict of formatter whose keys are format types (MIME types) and whose
# values are subclasses of BaseFormatter.
formatters = Dict()
@default('formatters')
def _formatters_default(self):
"""Activate the default formatters."""
formatter_classes = [
PlainTextFormatter,
HTMLFormatter,
MarkdownFormatter,
SVGFormatter,
PNGFormatter,
PDFFormatter,
JPEGFormatter,
LatexFormatter,
JSONFormatter,
JavascriptFormatter
]
d = {}
for cls in formatter_classes:
f = cls(parent=self)
d[f.format_type] = f
return d
def format(self, obj, include=None, exclude=None):
"""Return a format data dict for an object.
By default all format types will be computed.
The following MIME types are currently implemented:
* text/plain
* text/html
* text/markdown
* text/latex
* application/json
* application/javascript
* application/pdf
* image/png
* image/jpeg
* image/svg+xml
Parameters
----------
obj : object
The Python object whose format data will be computed.
include : list or tuple, optional
A list of format type strings (MIME types) to include in the
format data dict. If this is set *only* the format types included
in this list will be computed.
exclude : list or tuple, optional
A list of format type string (MIME types) to exclude in the format
data dict. If this is set all format types will be computed,
except for those included in this argument.
Returns
-------
(format_dict, metadata_dict) : tuple of two dicts
format_dict is a dictionary of key/value pairs, one of each format that was
generated for the object. The keys are the format types, which
will usually be MIME type strings and the values and JSON'able
data structure containing the raw data for the representation in
that format.
metadata_dict is a dictionary of metadata about each mime-type output.
Its keys will be a strict subset of the keys in format_dict.
"""
format_dict = {}
md_dict = {}
if self.ipython_display_formatter(obj):
# object handled itself, don't proceed
return {}, {}
for format_type, formatter in self.formatters.items():
if include and format_type not in include:
continue
if exclude and format_type in exclude:
continue
md = None
try:
data = formatter(obj)
except:
# FIXME: log the exception
raise
# formatters can return raw data or (data, metadata)
if isinstance(data, tuple) and len(data) == 2:
data, md = data
if data is not None:
format_dict[format_type] = data
if md is not None:
md_dict[format_type] = md
return format_dict, md_dict
@property
def format_types(self):
"""Return the format types (MIME types) of the active formatters."""
return list(self.formatters.keys())
#-----------------------------------------------------------------------------
# Formatters for specific format types (text, html, svg, etc.)
#-----------------------------------------------------------------------------
def _safe_repr(obj):
"""Try to return a repr of an object
always returns a string, at least.
"""
try:
return repr(obj)
except Exception as e:
return "un-repr-able object (%r)" % e
class FormatterWarning(UserWarning):
"""Warning class for errors in formatters"""
@decorator
def catch_format_error(method, self, *args, **kwargs):
"""show traceback on failed format call"""
try:
r = method(self, *args, **kwargs)
except NotImplementedError:
# don't warn on NotImplementedErrors
return None
except Exception:
exc_info = sys.exc_info()
ip = get_ipython()
if ip is not None:
ip.showtraceback(exc_info)
else:
traceback.print_exception(*exc_info)
return None
return self._check_return(r, args[0])
class FormatterABC(metaclass=abc.ABCMeta):
""" Abstract base class for Formatters.
A formatter is a callable class that is responsible for computing the
raw format data for a particular format type (MIME type). For example,
an HTML formatter would have a format type of `text/html` and would return
the HTML representation of the object when called.
"""
# The format type of the data returned, usually a MIME type.
format_type = 'text/plain'
# Is the formatter enabled...
enabled = True
@abc.abstractmethod
def __call__(self, obj):
"""Return a JSON'able representation of the object.
If the object cannot be formatted by this formatter,
warn and return None.
"""
return repr(obj)
def _mod_name_key(typ):
"""Return a (__module__, __name__) tuple for a type.
Used as key in Formatter.deferred_printers.
"""
module = getattr(typ, '__module__', None)
name = getattr(typ, '__name__', None)
return (module, name)
def _get_type(obj):
"""Return the type of an instance (old and new-style)"""
return getattr(obj, '__class__', None) or type(obj)
_raise_key_error = Sentinel('_raise_key_error', __name__,
"""
Special value to raise a KeyError
Raise KeyError in `BaseFormatter.pop` if passed as the default value to `pop`
""")
class BaseFormatter(Configurable):
"""A base formatter class that is configurable.
This formatter should usually be used as the base class of all formatters.
It is a traited :class:`Configurable` class and includes an extensible
API for users to determine how their objects are formatted. The following
logic is used to find a function to format an given object.
1. The object is introspected to see if it has a method with the name
:attr:`print_method`. If is does, that object is passed to that method
for formatting.
2. If no print method is found, three internal dictionaries are consulted
to find print method: :attr:`singleton_printers`, :attr:`type_printers`
and :attr:`deferred_printers`.
Users should use these dictionaries to register functions that will be
used to compute the format data for their objects (if those objects don't
have the special print methods). The easiest way of using these
dictionaries is through the :meth:`for_type` and :meth:`for_type_by_name`
methods.
If no function/callable is found to compute the format data, ``None`` is
returned and this format type is not used.
"""
format_type = Unicode('text/plain')
_return_type = str
enabled = Bool(True).tag(config=True)
print_method = ObjectName('__repr__')
# The singleton printers.
# Maps the IDs of the builtin singleton objects to the format functions.
singleton_printers = Dict().tag(config=True)
# The type-specific printers.
# Map type objects to the format functions.
type_printers = Dict().tag(config=True)
# The deferred-import type-specific printers.
# Map (modulename, classname) pairs to the format functions.
deferred_printers = Dict().tag(config=True)
@catch_format_error
def __call__(self, obj):
"""Compute the format for an object."""
if self.enabled:
# lookup registered printer
try:
printer = self.lookup(obj)
except KeyError:
pass
else:
return printer(obj)
# Finally look for special method names
method = get_real_method(obj, self.print_method)
if method is not None:
return method()
return None
else:
return None
def __contains__(self, typ):
"""map in to lookup_by_type"""
try:
self.lookup_by_type(typ)
except KeyError:
return False
else:
return True
def _check_return(self, r, obj):
"""Check that a return value is appropriate
Return the value if so, None otherwise, warning if invalid.
"""
if r is None or isinstance(r, self._return_type) or \
(isinstance(r, tuple) and r and isinstance(r[0], self._return_type)):
return r
else:
warnings.warn(
"%s formatter returned invalid type %s (expected %s) for object: %s" % \
(self.format_type, type(r), self._return_type, _safe_repr(obj)),
FormatterWarning
)
def lookup(self, obj):
"""Look up the formatter for a given instance.
Parameters
----------
obj : object instance
Returns
-------
f : callable
The registered formatting callable for the type.
Raises
------
KeyError if the type has not been registered.
"""
# look for singleton first
obj_id = id(obj)
if obj_id in self.singleton_printers:
return self.singleton_printers[obj_id]
# then lookup by type
return self.lookup_by_type(_get_type(obj))
def lookup_by_type(self, typ):
"""Look up the registered formatter for a type.
Parameters
----------
typ : type or '__module__.__name__' string for a type
Returns
-------
f : callable
The registered formatting callable for the type.
Raises
------
KeyError if the type has not been registered.
"""
if isinstance(typ, str):
typ_key = tuple(typ.rsplit('.',1))
if typ_key not in self.deferred_printers:
# We may have it cached in the type map. We will have to
# iterate over all of the types to check.
for cls in self.type_printers:
if _mod_name_key(cls) == typ_key:
return self.type_printers[cls]
else:
return self.deferred_printers[typ_key]
else:
for cls in pretty._get_mro(typ):
if cls in self.type_printers or self._in_deferred_types(cls):
return self.type_printers[cls]
# If we have reached here, the lookup failed.
raise KeyError("No registered printer for {0!r}".format(typ))
def for_type(self, typ, func=None):
"""Add a format function for a given type.
Parameters
-----------
typ : type or '__module__.__name__' string for a type
The class of the object that will be formatted using `func`.
func : callable
A callable for computing the format data.
`func` will be called with the object to be formatted,
and will return the raw data in this formatter's format.
Subclasses may use a different call signature for the
`func` argument.
If `func` is None or not specified, there will be no change,
only returning the current value.
Returns
-------
oldfunc : callable
The currently registered callable.
If you are registering a new formatter,
this will be the previous value (to enable restoring later).
"""
# if string given, interpret as 'pkg.module.class_name'
if isinstance(typ, str):
type_module, type_name = typ.rsplit('.', 1)
return self.for_type_by_name(type_module, type_name, func)
try:
oldfunc = self.lookup_by_type(typ)
except KeyError:
oldfunc = None
if func is not None:
self.type_printers[typ] = func
return oldfunc
def for_type_by_name(self, type_module, type_name, func=None):
"""Add a format function for a type specified by the full dotted
module and name of the type, rather than the type of the object.
Parameters
----------
type_module : str
The full dotted name of the module the type is defined in, like
``numpy``.
type_name : str
The name of the type (the class name), like ``dtype``
func : callable
A callable for computing the format data.
`func` will be called with the object to be formatted,
and will return the raw data in this formatter's format.
Subclasses may use a different call signature for the
`func` argument.
If `func` is None or unspecified, there will be no change,
only returning the current value.
Returns
-------
oldfunc : callable
The currently registered callable.
If you are registering a new formatter,
this will be the previous value (to enable restoring later).
"""
key = (type_module, type_name)
try:
oldfunc = self.lookup_by_type("%s.%s" % key)
except KeyError:
oldfunc = None
if func is not None:
self.deferred_printers[key] = func
return oldfunc
def pop(self, typ, default=_raise_key_error):
"""Pop a formatter for the given type.
Parameters
----------
typ : type or '__module__.__name__' string for a type
default : object
value to be returned if no formatter is registered for typ.
Returns
-------
obj : object
The last registered object for the type.
Raises
------
KeyError if the type is not registered and default is not specified.
"""
if isinstance(typ, str):
typ_key = tuple(typ.rsplit('.',1))
if typ_key not in self.deferred_printers:
# We may have it cached in the type map. We will have to
# iterate over all of the types to check.
for cls in self.type_printers:
if _mod_name_key(cls) == typ_key:
old = self.type_printers.pop(cls)
break
else:
old = default
else:
old = self.deferred_printers.pop(typ_key)
else:
if typ in self.type_printers:
old = self.type_printers.pop(typ)
else:
old = self.deferred_printers.pop(_mod_name_key(typ), default)
if old is _raise_key_error:
raise KeyError("No registered value for {0!r}".format(typ))
return old
def _in_deferred_types(self, cls):
"""
Check if the given class is specified in the deferred type registry.
Successful matches will be moved to the regular type registry for future use.
"""
mod = getattr(cls, '__module__', None)
name = getattr(cls, '__name__', None)
key = (mod, name)
if key in self.deferred_printers:
# Move the printer over to the regular registry.
printer = self.deferred_printers.pop(key)
self.type_printers[cls] = printer
return True
return False
class PlainTextFormatter(BaseFormatter):
"""The default pretty-printer.
This uses :mod:`IPython.lib.pretty` to compute the format data of
the object. If the object cannot be pretty printed, :func:`repr` is used.
See the documentation of :mod:`IPython.lib.pretty` for details on
how to write pretty printers. Here is a simple example::
def dtype_pprinter(obj, p, cycle):
if cycle:
return p.text('dtype(...)')
if hasattr(obj, 'fields'):
if obj.fields is None:
p.text(repr(obj))
else:
p.begin_group(7, 'dtype([')
for i, field in enumerate(obj.descr):
if i > 0:
p.text(',')
p.breakable()
p.pretty(field)
p.end_group(7, '])')
"""
# The format type of data returned.
format_type = Unicode('text/plain')
# This subclass ignores this attribute as it always need to return
# something.
enabled = Bool(True).tag(config=False)
max_seq_length = Integer(pretty.MAX_SEQ_LENGTH,
help="""Truncate large collections (lists, dicts, tuples, sets) to this size.
Set to 0 to disable truncation.
"""
).tag(config=True)
# Look for a _repr_pretty_ methods to use for pretty printing.
print_method = ObjectName('_repr_pretty_')
# Whether to pretty-print or not.
pprint = Bool(True).tag(config=True)
# Whether to be verbose or not.
verbose = Bool(False).tag(config=True)
# The maximum width.
max_width = Integer(79).tag(config=True)
# The newline character.
newline = Unicode('\n').tag(config=True)
# format-string for pprinting floats
float_format = Unicode('%r')
# setter for float precision, either int or direct format-string
float_precision = CUnicode('').tag(config=True)
@observe('float_precision')
def _float_precision_changed(self, change):
"""float_precision changed, set float_format accordingly.
float_precision can be set by int or str.
This will set float_format, after interpreting input.
If numpy has been imported, numpy print precision will also be set.
integer `n` sets format to '%.nf', otherwise, format set directly.
An empty string returns to defaults (repr for float, 8 for numpy).
This parameter can be set via the '%precision' magic.
"""
new = change['new']
if '%' in new:
# got explicit format string
fmt = new
try:
fmt%3.14159
except Exception:
raise ValueError("Precision must be int or format string, not %r"%new)
elif new:
# otherwise, should be an int
try:
i = int(new)
assert i >= 0
except ValueError:
raise ValueError("Precision must be int or format string, not %r"%new)
except AssertionError:
raise ValueError("int precision must be non-negative, not %r"%i)
fmt = '%%.%if'%i
if 'numpy' in sys.modules:
# set numpy precision if it has been imported
import numpy
numpy.set_printoptions(precision=i)
else:
# default back to repr
fmt = '%r'
if 'numpy' in sys.modules:
import numpy
# numpy default is 8
numpy.set_printoptions(precision=8)
self.float_format = fmt
# Use the default pretty printers from IPython.lib.pretty.
@default('singleton_printers')
def _singleton_printers_default(self):
return pretty._singleton_pprinters.copy()
@default('type_printers')
def _type_printers_default(self):
d = pretty._type_pprinters.copy()
d[float] = lambda obj,p,cycle: p.text(self.float_format%obj)
return d
@default('deferred_printers')
def _deferred_printers_default(self):
return pretty._deferred_type_pprinters.copy()
#### FormatterABC interface ####
@catch_format_error
def __call__(self, obj):
"""Compute the pretty representation of the object."""
if not self.pprint:
return repr(obj)
else:
stream = StringIO()
printer = pretty.RepresentationPrinter(stream, self.verbose,
self.max_width, self.newline,
max_seq_length=self.max_seq_length,
singleton_pprinters=self.singleton_printers,
type_pprinters=self.type_printers,
deferred_pprinters=self.deferred_printers)
printer.pretty(obj)
printer.flush()
return stream.getvalue()
class HTMLFormatter(BaseFormatter):
"""An HTML formatter.
To define the callables that compute the HTML representation of your
objects, define a :meth:`_repr_html_` method or use the :meth:`for_type`
or :meth:`for_type_by_name` methods to register functions that handle
this.
The return value of this formatter should be a valid HTML snippet that
could be injected into an existing DOM. It should *not* include the
```<html>`` or ```<body>`` tags.
"""
format_type = Unicode('text/html')
print_method = ObjectName('_repr_html_')
class MarkdownFormatter(BaseFormatter):
"""A Markdown formatter.
To define the callables that compute the Markdown representation of your
objects, define a :meth:`_repr_markdown_` method or use the :meth:`for_type`
or :meth:`for_type_by_name` methods to register functions that handle
this.
The return value of this formatter should be a valid Markdown.
"""
format_type = Unicode('text/markdown')
print_method = ObjectName('_repr_markdown_')
class SVGFormatter(BaseFormatter):
"""An SVG formatter.
To define the callables that compute the SVG representation of your
objects, define a :meth:`_repr_svg_` method or use the :meth:`for_type`
or :meth:`for_type_by_name` methods to register functions that handle
this.
The return value of this formatter should be valid SVG enclosed in
```<svg>``` tags, that could be injected into an existing DOM. It should
*not* include the ```<html>`` or ```<body>`` tags.
"""
format_type = Unicode('image/svg+xml')
print_method = ObjectName('_repr_svg_')
class PNGFormatter(BaseFormatter):
"""A PNG formatter.
To define the callables that compute the PNG representation of your
objects, define a :meth:`_repr_png_` method or use the :meth:`for_type`
or :meth:`for_type_by_name` methods to register functions that handle
this.
The return value of this formatter should be raw PNG data, *not*
base64 encoded.
"""
format_type = Unicode('image/png')
print_method = ObjectName('_repr_png_')
_return_type = (bytes, str)
class JPEGFormatter(BaseFormatter):
"""A JPEG formatter.
To define the callables that compute the JPEG representation of your
objects, define a :meth:`_repr_jpeg_` method or use the :meth:`for_type`
or :meth:`for_type_by_name` methods to register functions that handle
this.
The return value of this formatter should be raw JPEG data, *not*
base64 encoded.
"""
format_type = Unicode('image/jpeg')
print_method = ObjectName('_repr_jpeg_')
_return_type = (bytes, str)
class LatexFormatter(BaseFormatter):
"""A LaTeX formatter.
To define the callables that compute the LaTeX representation of your
objects, define a :meth:`_repr_latex_` method or use the :meth:`for_type`
or :meth:`for_type_by_name` methods to register functions that handle
this.
The return value of this formatter should be a valid LaTeX equation,
enclosed in either ```$```, ```$$``` or another LaTeX equation
environment.
"""
format_type = Unicode('text/latex')
print_method = ObjectName('_repr_latex_')
class JSONFormatter(BaseFormatter):
"""A JSON string formatter.
To define the callables that compute the JSONable representation of
your objects, define a :meth:`_repr_json_` method or use the :meth:`for_type`
or :meth:`for_type_by_name` methods to register functions that handle
this.
The return value of this formatter should be a JSONable list or dict.
JSON scalars (None, number, string) are not allowed, only dict or list containers.
"""
format_type = Unicode('application/json')
_return_type = (list, dict)
print_method = ObjectName('_repr_json_')
def _check_return(self, r, obj):
"""Check that a return value is appropriate
Return the value if so, None otherwise, warning if invalid.
"""
if r is None:
return
md = None
if isinstance(r, tuple):
# unpack data, metadata tuple for type checking on first element
r, md = r
# handle deprecated JSON-as-string form from IPython < 3
if isinstance(r, str):
warnings.warn("JSON expects JSONable list/dict containers, not JSON strings",
FormatterWarning)
r = json.loads(r)
if md is not None:
# put the tuple back together
r = (r, md)
return super(JSONFormatter, self)._check_return(r, obj)
class JavascriptFormatter(BaseFormatter):
"""A Javascript formatter.
To define the callables that compute the Javascript representation of
your objects, define a :meth:`_repr_javascript_` method or use the
:meth:`for_type` or :meth:`for_type_by_name` methods to register functions
that handle this.
The return value of this formatter should be valid Javascript code and
should *not* be enclosed in ```<script>``` tags.
"""
format_type = Unicode('application/javascript')
print_method = ObjectName('_repr_javascript_')
class PDFFormatter(BaseFormatter):
"""A PDF formatter.
To define the callables that compute the PDF representation of your
objects, define a :meth:`_repr_pdf_` method or use the :meth:`for_type`
or :meth:`for_type_by_name` methods to register functions that handle
this.
The return value of this formatter should be raw PDF data, *not*
base64 encoded.
"""
format_type = Unicode('application/pdf')
print_method = ObjectName('_repr_pdf_')
_return_type = (bytes, str)
class IPythonDisplayFormatter(BaseFormatter):
"""A Formatter for objects that know how to display themselves.
To define the callables that compute the representation of your
objects, define a :meth:`_ipython_display_` method or use the :meth:`for_type`
or :meth:`for_type_by_name` methods to register functions that handle
this. Unlike mime-type displays, this method should not return anything,
instead calling any appropriate display methods itself.
This display formatter has highest priority.
If it fires, no other display formatter will be called.
"""
print_method = ObjectName('_ipython_display_')
_return_type = (type(None), bool)
@catch_format_error
def __call__(self, obj):
"""Compute the format for an object."""
if self.enabled:
# lookup registered printer
try:
printer = self.lookup(obj)
except KeyError:
pass
else:
printer(obj)
return True
# Finally look for special method names
method = get_real_method(obj, self.print_method)
if method is not None:
method()
return True
FormatterABC.register(BaseFormatter)
FormatterABC.register(PlainTextFormatter)
FormatterABC.register(HTMLFormatter)
FormatterABC.register(MarkdownFormatter)
FormatterABC.register(SVGFormatter)
FormatterABC.register(PNGFormatter)
FormatterABC.register(PDFFormatter)
FormatterABC.register(JPEGFormatter)
FormatterABC.register(LatexFormatter)
FormatterABC.register(JSONFormatter)
FormatterABC.register(JavascriptFormatter)
FormatterABC.register(IPythonDisplayFormatter)
def format_display_data(obj, include=None, exclude=None):
"""Return a format data dict for an object.
By default all format types will be computed.
The following MIME types are currently implemented:
* text/plain
* text/html
* text/markdown
* text/latex
* application/json
* application/javascript
* application/pdf
* image/png
* image/jpeg
* image/svg+xml
Parameters
----------
obj : object
The Python object whose format data will be computed.
Returns
-------
format_dict : dict
A dictionary of key/value pairs, one or each format that was
generated for the object. The keys are the format types, which
will usually be MIME type strings and the values and JSON'able
data structure containing the raw data for the representation in
that format.
include : list or tuple, optional
A list of format type strings (MIME types) to include in the
format data dict. If this is set *only* the format types included
in this list will be computed.
exclude : list or tuple, optional
A list of format type string (MIME types) to exclue in the format
data dict. If this is set all format types will be computed,
except for those included in this argument.
"""
from yap_ipython.core.interactiveshell import InteractiveShell
return InteractiveShell.instance().display_formatter.format(
obj,
include,
exclude
)

View File

@ -0,0 +1,525 @@
"""Input transformer classes to support IPython special syntax.
This includes the machinery to recognise and transform ``%magic`` commands,
``!system`` commands, ``help?`` querying, prompt stripping, and so forth.
"""
import abc
import functools
import re
from io import StringIO
from IPython.core.splitinput import LineInfo
from IPython.utils import tokenize2
from IPython.utils.tokenize2 import generate_tokens, untokenize, TokenError
#-----------------------------------------------------------------------------
# Globals
#-----------------------------------------------------------------------------
# The escape sequences that define the syntax transformations IPython will
# apply to user input. These can NOT be just changed here: many regular
# expressions and other parts of the code may use their hardcoded values, and
# for all intents and purposes they constitute the 'IPython syntax', so they
# should be considered fixed.
ESC_SHELL = '!' # Send line to underlying system shell
ESC_SH_CAP = '!!' # Send line to system shell and capture output
ESC_HELP = '?' # Find information about object
ESC_HELP2 = '??' # Find extra-detailed information about object
ESC_MAGIC = '%' # Call magic function
ESC_MAGIC2 = '%%' # Call cell-magic function
ESC_QUOTE = ',' # Split args on whitespace, quote each as string and call
ESC_QUOTE2 = ';' # Quote all args as a single string, call
ESC_PAREN = '/' # Call first argument with rest of line as arguments
ESC_SEQUENCES = [ESC_SHELL, ESC_SH_CAP, ESC_HELP ,\
ESC_HELP2, ESC_MAGIC, ESC_MAGIC2,\
ESC_QUOTE, ESC_QUOTE2, ESC_PAREN ]
class InputTransformer(metaclass=abc.ABCMeta):
"""Abstract base class for line-based input transformers."""
@abc.abstractmethod
def push(self, line):
"""Send a line of input to the transformer, returning the transformed
input or None if the transformer is waiting for more input.
Must be overridden by subclasses.
Implementations may raise ``SyntaxError`` if the input is invalid. No
other exceptions may be raised.
"""
pass
@abc.abstractmethod
def reset(self):
"""Return, transformed any lines that the transformer has accumulated,
and reset its internal state.
Must be overridden by subclasses.
"""
pass
@classmethod
def wrap(cls, func):
"""Can be used by subclasses as a decorator, to return a factory that
will allow instantiation with the decorated object.
"""
@functools.wraps(func)
def transformer_factory(**kwargs):
return cls(func, **kwargs)
return transformer_factory
class StatelessInputTransformer(InputTransformer):
"""Wrapper for a stateless input transformer implemented as a function."""
def __init__(self, func):
self.func = func
def __repr__(self):
return "StatelessInputTransformer(func={0!r})".format(self.func)
def push(self, line):
"""Send a line of input to the transformer, returning the
transformed input."""
return self.func(line)
def reset(self):
"""No-op - exists for compatibility."""
pass
class CoroutineInputTransformer(InputTransformer):
"""Wrapper for an input transformer implemented as a coroutine."""
def __init__(self, coro, **kwargs):
# Prime it
self.coro = coro(**kwargs)
next(self.coro)
def __repr__(self):
return "CoroutineInputTransformer(coro={0!r})".format(self.coro)
def push(self, line):
"""Send a line of input to the transformer, returning the
transformed input or None if the transformer is waiting for more
input.
"""
return self.coro.send(line)
def reset(self):
"""Return, transformed any lines that the transformer has
accumulated, and reset its internal state.
"""
return self.coro.send(None)
class TokenInputTransformer(InputTransformer):
"""Wrapper for a token-based input transformer.
func should accept a list of tokens (5-tuples, see tokenize docs), and
return an iterable which can be passed to tokenize.untokenize().
"""
def __init__(self, func):
self.func = func
self.buf = []
self.reset_tokenizer()
def reset_tokenizer(self):
it = iter(self.buf)
self.tokenizer = generate_tokens(it.__next__)
def push(self, line):
self.buf.append(line + '\n')
if all(l.isspace() for l in self.buf):
return self.reset()
tokens = []
stop_at_NL = False
try:
for intok in self.tokenizer:
tokens.append(intok)
t = intok[0]
if t == tokenize2.NEWLINE or (stop_at_NL and t == tokenize2.NL):
# Stop before we try to pull a line we don't have yet
break
elif t == tokenize2.ERRORTOKEN:
stop_at_NL = True
except TokenError:
# Multi-line statement - stop and try again with the next line
self.reset_tokenizer()
return None
return self.output(tokens)
def output(self, tokens):
self.buf.clear()
self.reset_tokenizer()
return untokenize(self.func(tokens)).rstrip('\n')
def reset(self):
l = ''.join(self.buf)
self.buf.clear()
self.reset_tokenizer()
if l:
return l.rstrip('\n')
class assemble_python_lines(TokenInputTransformer):
def __init__(self):
super(assemble_python_lines, self).__init__(None)
def output(self, tokens):
return self.reset()
@CoroutineInputTransformer.wrap
def assemble_logical_lines():
"""Join lines following explicit line continuations (\)"""
line = ''
while True:
line = (yield line)
if not line or line.isspace():
continue
parts = []
while line is not None:
if line.endswith('\\') and (not has_comment(line)):
parts.append(line[:-1])
line = (yield None) # Get another line
else:
parts.append(line)
break
# Output
line = ''.join(parts)
# Utilities
def _make_help_call(target, esc, lspace, next_input=None):
"""Prepares a pinfo(2)/psearch call from a target name and the escape
(i.e. ? or ??)"""
method = 'pinfo2' if esc == '??' \
else 'psearch' if '*' in target \
else 'pinfo'
arg = " ".join([method, target])
if next_input is None:
return '%sget_ipython().magic(%r)' % (lspace, arg)
else:
return '%sget_ipython().set_next_input(%r);get_ipython().magic(%r)' % \
(lspace, next_input, arg)
# These define the transformations for the different escape characters.
def _tr_system(line_info):
"Translate lines escaped with: !"
cmd = line_info.line.lstrip().lstrip(ESC_SHELL)
return '%sget_ipython().system(%r)' % (line_info.pre, cmd)
def _tr_system2(line_info):
"Translate lines escaped with: !!"
cmd = line_info.line.lstrip()[2:]
return '%sget_ipython().getoutput(%r)' % (line_info.pre, cmd)
def _tr_help(line_info):
"Translate lines escaped with: ?/??"
# A naked help line should just fire the intro help screen
if not line_info.line[1:]:
return 'get_ipython().show_usage()'
return _make_help_call(line_info.ifun, line_info.esc, line_info.pre)
def _tr_magic(line_info):
"Translate lines escaped with: %"
tpl = '%sget_ipython().magic(%r)'
if line_info.line.startswith(ESC_MAGIC2):
return line_info.line
cmd = ' '.join([line_info.ifun, line_info.the_rest]).strip()
return tpl % (line_info.pre, cmd)
def _tr_quote(line_info):
"Translate lines escaped with: ,"
return '%s%s("%s")' % (line_info.pre, line_info.ifun,
'", "'.join(line_info.the_rest.split()) )
def _tr_quote2(line_info):
"Translate lines escaped with: ;"
return '%s%s("%s")' % (line_info.pre, line_info.ifun,
line_info.the_rest)
def _tr_paren(line_info):
"Translate lines escaped with: /"
return '%s%s(%s)' % (line_info.pre, line_info.ifun,
", ".join(line_info.the_rest.split()))
tr = { ESC_SHELL : _tr_system,
ESC_SH_CAP : _tr_system2,
ESC_HELP : _tr_help,
ESC_HELP2 : _tr_help,
ESC_MAGIC : _tr_magic,
ESC_QUOTE : _tr_quote,
ESC_QUOTE2 : _tr_quote2,
ESC_PAREN : _tr_paren }
@StatelessInputTransformer.wrap
def escaped_commands(line):
"""Transform escaped commands - %magic, !system, ?help + various autocalls.
"""
if not line or line.isspace():
return line
lineinf = LineInfo(line)
if lineinf.esc not in tr:
return line
return tr[lineinf.esc](lineinf)
_initial_space_re = re.compile(r'\s*')
_help_end_re = re.compile(r"""(%{0,2}
[a-zA-Z_*][\w*]* # Variable name
(\.[a-zA-Z_*][\w*]*)* # .etc.etc
)
(\?\??)$ # ? or ??
""",
re.VERBOSE)
# Extra pseudotokens for multiline strings and data structures
_MULTILINE_STRING = object()
_MULTILINE_STRUCTURE = object()
def _line_tokens(line):
"""Helper for has_comment and ends_in_comment_or_string."""
readline = StringIO(line).readline
toktypes = set()
try:
for t in generate_tokens(readline):
toktypes.add(t[0])
except TokenError as e:
# There are only two cases where a TokenError is raised.
if 'multi-line string' in e.args[0]:
toktypes.add(_MULTILINE_STRING)
else:
toktypes.add(_MULTILINE_STRUCTURE)
return toktypes
def has_comment(src):
"""Indicate whether an input line has (i.e. ends in, or is) a comment.
This uses tokenize, so it can distinguish comments from # inside strings.
Parameters
----------
src : string
A single line input string.
Returns
-------
comment : bool
True if source has a comment.
"""
return (tokenize2.COMMENT in _line_tokens(src))
def ends_in_comment_or_string(src):
"""Indicates whether or not an input line ends in a comment or within
a multiline string.
Parameters
----------
src : string
A single line input string.
Returns
-------
comment : bool
True if source ends in a comment or multiline string.
"""
toktypes = _line_tokens(src)
return (tokenize2.COMMENT in toktypes) or (_MULTILINE_STRING in toktypes)
@StatelessInputTransformer.wrap
def help_end(line):
"""Translate lines with ?/?? at the end"""
m = _help_end_re.search(line)
if m is None or ends_in_comment_or_string(line):
return line
target = m.group(1)
esc = m.group(3)
lspace = _initial_space_re.match(line).group(0)
# If we're mid-command, put it back on the next prompt for the user.
next_input = line.rstrip('?') if line.strip() != m.group(0) else None
return _make_help_call(target, esc, lspace, next_input)
@CoroutineInputTransformer.wrap
def cellmagic(end_on_blank_line=False):
"""Captures & transforms cell magics.
After a cell magic is started, this stores up any lines it gets until it is
reset (sent None).
"""
tpl = 'get_ipython().run_cell_magic(%r, %r, %r)'
cellmagic_help_re = re.compile('%%\w+\?')
line = ''
while True:
line = (yield line)
# consume leading empty lines
while not line:
line = (yield line)
if not line.startswith(ESC_MAGIC2):
# This isn't a cell magic, idle waiting for reset then start over
while line is not None:
line = (yield line)
continue
if cellmagic_help_re.match(line):
# This case will be handled by help_end
continue
first = line
body = []
line = (yield None)
while (line is not None) and \
((line.strip() != '') or not end_on_blank_line):
body.append(line)
line = (yield None)
# Output
magic_name, _, first = first.partition(' ')
magic_name = magic_name.lstrip(ESC_MAGIC2)
line = tpl % (magic_name, first, u'\n'.join(body))
def _strip_prompts(prompt_re, initial_re=None, turnoff_re=None):
"""Remove matching input prompts from a block of input.
Parameters
----------
prompt_re : regular expression
A regular expression matching any input prompt (including continuation)
initial_re : regular expression, optional
A regular expression matching only the initial prompt, but not continuation.
If no initial expression is given, prompt_re will be used everywhere.
Used mainly for plain Python prompts, where the continuation prompt
``...`` is a valid Python expression in Python 3, so shouldn't be stripped.
If initial_re and prompt_re differ,
only initial_re will be tested against the first line.
If any prompt is found on the first two lines,
prompts will be stripped from the rest of the block.
"""
if initial_re is None:
initial_re = prompt_re
line = ''
while True:
line = (yield line)
# First line of cell
if line is None:
continue
out, n1 = initial_re.subn('', line, count=1)
if turnoff_re and not n1:
if turnoff_re.match(line):
# We're in e.g. a cell magic; disable this transformer for
# the rest of the cell.
while line is not None:
line = (yield line)
continue
line = (yield out)
if line is None:
continue
# check for any prompt on the second line of the cell,
# because people often copy from just after the first prompt,
# so we might not see it in the first line.
out, n2 = prompt_re.subn('', line, count=1)
line = (yield out)
if n1 or n2:
# Found a prompt in the first two lines - check for it in
# the rest of the cell as well.
while line is not None:
line = (yield prompt_re.sub('', line, count=1))
else:
# Prompts not in input - wait for reset
while line is not None:
line = (yield line)
@CoroutineInputTransformer.wrap
def classic_prompt():
"""Strip the >>>/... prompts of the Python interactive shell."""
# FIXME: non-capturing version (?:...) usable?
prompt_re = re.compile(r'^(>>>|\.\.\.)( |$)')
initial_re = re.compile(r'^>>>( |$)')
# Any %magic/!system is IPython syntax, so we needn't look for >>> prompts
turnoff_re = re.compile(r'^[%!]')
return _strip_prompts(prompt_re, initial_re, turnoff_re)
@CoroutineInputTransformer.wrap
def ipy_prompt():
"""Strip IPython's In [1]:/...: prompts."""
# FIXME: non-capturing version (?:...) usable?
prompt_re = re.compile(r'^(In \[\d+\]: |\s*\.{3,}: ?)')
# Disable prompt stripping inside cell magics
turnoff_re = re.compile(r'^%%')
return _strip_prompts(prompt_re, turnoff_re=turnoff_re)
@CoroutineInputTransformer.wrap
def leading_indent():
"""Remove leading indentation.
If the first line starts with a spaces or tabs, the same whitespace will be
removed from each following line until it is reset.
"""
space_re = re.compile(r'^[ \t]+')
line = ''
while True:
line = (yield line)
if line is None:
continue
m = space_re.match(line)
if m:
space = m.group(0)
while line is not None:
if line.startswith(space):
line = line[len(space):]
line = (yield line)
else:
# No leading spaces - wait for reset
while line is not None:
line = (yield line)
_assign_pat = \
r'''(?P<lhs>(\s*)
([\w\.]+) # Initial identifier
(\s*,\s*
\*?[\w\.]+)* # Further identifiers for unpacking
\s*?,? # Trailing comma
)
\s*=\s*
'''
assign_system_re = re.compile(r'{}!\s*(?P<cmd>.*)'.format(_assign_pat), re.VERBOSE)
assign_system_template = '%s = get_ipython().getoutput(%r)'
@StatelessInputTransformer.wrap
def assign_from_system(line):
"""Transform assignment from system commands (e.g. files = !ls)"""
m = assign_system_re.match(line)
if m is None:
return line
return assign_system_template % m.group('lhs', 'cmd')
assign_magic_re = re.compile(r'{}%\s*(?P<cmd>.*)'.format(_assign_pat), re.VERBOSE)
assign_magic_template = '%s = get_ipython().magic(%r)'
@StatelessInputTransformer.wrap
def assign_from_magic(line):
"""Transform assignment from magic commands (e.g. a = %who_ls)"""
m = assign_magic_re.match(line)
if m is None:
return line
return assign_magic_template % m.group('lhs', 'cmd')

View File

@ -21,8 +21,8 @@ from IPython.core.application import (
BaseIPythonApplication, base_flags, base_aliases, catch_config_error
)
from IPython.core.profiledir import ProfileDir
from IPython.core.shellapp import (
InteractiveShellApp, shell_flags, shell_aliases
from yap_ipython.core.shellapp import (
YAPInteractiveApp, shell_flags, shell_aliases
)
from IPython.utils import io
from ipython_genutils.path import filefind, ensure_dir_exists
@ -96,7 +96,7 @@ To read more about this, see https://github.com/ipython/ipython/issues/2049
# Application class for starting an IPython Kernel
#-----------------------------------------------------------------------------
class YAPKernelApp(BaseIPythonApplication, InteractiveShellApp,
class YAPKernelApp(BaseIPythonApplication, YAPInteractiveApp,
ConnectionFileMixin):
name='YAP Kernel'
aliases = Dict(kernel_aliases)
@ -385,7 +385,7 @@ class YAPKernelApp(BaseIPythonApplication, InteractiveShellApp,
if not os.environ.get('MPLBACKEND'):
os.environ['MPLBACKEND'] = 'module://yap_kernel.pylab.backend_inline'
# Provide a wrapper for :meth:`InteractiveShellApp.init_gui_pylab`
# Provide a wrapper for :meth:`YAPInteractiveApp.init_gui_pylab`
# to ensure that any exception is printed straight to stderr.
# Normally _showtraceback associates the reply with an execution,
# which means frontends will never draw it, as this exception
@ -400,7 +400,7 @@ class YAPKernelApp(BaseIPythonApplication, InteractiveShellApp,
file=sys.stderr)
print (shell.InteractiveTB.stb2text(stb), file=sys.stderr)
shell._showtraceback = print_tb
InteractiveShellApp.init_gui_pylab(self)
YAPInteractiveApp.init_gui_pylab(self)
finally:
shell._showtraceback = _showtraceback

View File

@ -16,7 +16,7 @@ from jupyter_client.kernelspec import KernelSpecManager
pjoin = os.path.join
KERNEL_NAME = 'YAPKernel'
KERNEL_NAME = 'yap_kernel'
# path to kernelspec resources
RESOURCES = pjoin(os.path.dirname(__file__), 'resources')
@ -59,7 +59,7 @@ def get_kernel_dict(extra_arguments=None):
}
def write_kernel_spec(path=None, overrides=None, extra_arguments=None):
def write_kernel_spec(path=os.path.join(tempfile.mkdtemp(suffix='_kernels'), KERNEL_NAME), overrides=None, extra_arguments=None):
"""Write a kernel spec directory to `path`
If `path` is not specified, a temporary directory is created.
@ -69,7 +69,7 @@ def write_kernel_spec(path=None, overrides=None, extra_arguments=None):
"""
if path is None:
path = os.path.join(tempfile.mkdtemp(suffix='_kernels'), KERNEL_NAME)
print( path )
# stage resources
shutil.copytree(RESOURCES, path)
# write kernel.json
@ -142,7 +142,7 @@ from traitlets.config import Application
class InstallYAPKernelSpecApp(Application):
"""Dummy app wrapping argparse"""
name = 'ipython-kernel-install'
name = 'yap-kernel-install'
def initialize(self, argv=None):
if argv is None:
@ -152,12 +152,12 @@ class InstallYAPKernelSpecApp(Application):
def start(self):
import argparse
parser = argparse.ArgumentParser(prog=self.name,
description="Install the IPython kernel spec.")
description="Install the YAP kernel spec.")
parser.add_argument('--user', action='store_true',
help="Install for the current user instead of system-wide")
parser.add_argument('--name', type=str, default=KERNEL_NAME,
help="Specify a name for the kernelspec."
" This is needed to have multiple IPython kernels at the same time.")
" This is needed to have multiple YAP kernels at the same time.")
parser.add_argument('--display-name', type=str,
help="Specify the display name for the kernelspec."
" This is helpful when you have multiple IPython kernels.")

View File

@ -1,28 +0,0 @@
:- use_module(library(python)).
:- initialization
ensure_loaded(library(yapi) ),
python_import(sys).
%% @pred yap_query(0:Goalc, - Dictionary)
%%
%% dictionary, Examples
%%
%%
jupyter_query( Self, String ) :-
set_python_output( Self, Output , Error),
python_query( Self, String ),
close( Output ),
cloe( Error ).
set_python_output(_Self,Output,Error) :-
open('//python/sys.stdout', append, Output, [alias(output)]),
open('//python/sys.stderr', append, Error, [alias(error)]),
yap_flag(user_output, output),
yap_flag(user_error, error).

View File

@ -2,20 +2,19 @@
import getpass
import sys
import traceback
from IPython.core import release
from ipython_genutils.py3compat import builtin_mod, PY3, unicode_type, safe_unicode
from IPython.utils.tokenutil import token_at_cursor, line_at_cursor
from ipython_genutils.py3compat import builtin_mod, PY3, unicode_type, safe_unicode
from traitlets import Instance, Type, Any, List
from yap_ipython.core.interactiveshell import YAPInteractive
from .comm import CommManager
from .kernelbase import Kernel as KernelBase
from .zmqshell import ZMQInteractiveShell
from .interactiveshell import YAPInteraction
class YAPKernel(KernelBase):
shell = Instance('IPython.core.interactiveshell.InteractiveShellABC',
shell = Instance('yap_ipython.core.interactiveshell.YAPInteractiveABC',
allow_none=True)
shell_class = Type(ZMQInteractiveShell)
user_module = Any()
@ -57,7 +56,7 @@ class YAPKernel(KernelBase):
for msg_type in comm_msg_types:
self.shell_handlers[msg_type] = getattr(self.comm_manager, msg_type)
self.engine = YAPInteraction(self)
self.engine = YAPInteractive()
self.shell._last_traceback = None
self.shell.run_cell = self.engine.run_cell
@ -100,8 +99,8 @@ class YAPKernel(KernelBase):
'version': '6.3',
'mimetype': 'text/x-prolog',
'codemirror_mode': {
'name': 'prolog',
'version': sys.version_info[0]
'name': 'prolog' #,
#'version': '3'
},
'pygments_lexer': 'prolog',
'nbconvert_exporter': 'prolog',

View File

@ -25,8 +25,8 @@ from threading import local
from tornado import ioloop
from IPython.core.interactiveshell import (
InteractiveShell, InteractiveShellABC
from yap_ipython.core.interactiveshell import (
YAPInteractive, YAPInteractiveABC
)
from IPython.core import page
from IPython.core.autocall import ZMQExitAutocall
@ -437,7 +437,7 @@ class KernelMagics(Magics):
print("Autosave disabled")
class ZMQInteractiveShell(InteractiveShell):
class ZMQInteractiveShell(YAPInteractive):
"""A subclass of InteractiveShell for ZMQ."""
displayhook_class = Type(ZMQShellDisplayHook)
@ -598,4 +598,4 @@ class ZMQInteractiveShell(InteractiveShell):
# https://ipython.readthedocs.io/en/latest/install/kernel_install.html
pass
InteractiveShellABC.register(ZMQInteractiveShell)
YAPInteractiveABC.register(ZMQInteractiveShell)

View File

@ -12,5 +12,5 @@ if __name__ == '__main__':
if sys.path[0] == '':
del sys.path[0]
from inprocess.ipkernel import kernelapp as app
from yap_kernel import kernelapp as app
app.launch_new_instance()