This repository has been archived on 2023-08-20. You can view files and clone it, but cannot push or open issues or pull requests.
yap-6.3/packages/python/py2pl.c

310 lines
8.2 KiB
C
Raw Normal View History

2016-07-31 16:09:21 +01:00
#include "python.h"
2017-02-20 14:37:26 +00:00
static foreign_t repr_term(PyObject *pVal, term_t t) {
2016-07-31 16:09:21 +01:00
term_t to = PL_new_term_ref(), t1 = PL_new_term_ref();
2017-02-20 14:37:26 +00:00
PL_put_pointer(t1, pVal);
2016-07-31 16:09:21 +01:00
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) {
2017-02-20 14:37:26 +00:00
char *s = NULL;
2016-07-31 16:09:21 +01:00
if (!PL_get_atom_chars(t, &s)) {
2017-02-20 14:37:26 +00:00
return false;
2016-07-31 16:09:21 +01:00
}
2017-02-20 14:37:26 +00:00
PyObject *dic;
if (!lookupPySymbol(s, NULL, &dic))
dic = py_Main;
return PyObject_SetAttrString(dic, s, e) == 0;
2016-07-31 16:09:21 +01:00
}
foreign_t python_to_term(PyObject *pVal, term_t t) {
2017-05-02 07:38:23 +01:00
bool rc = true;
term_t to = PL_new_term_ref();
fputs(" <<*** ",stderr); PyObject_Print(pVal,stderr,0); fputs("<<***\n",stderr);
2016-07-31 16:09:21 +01:00
if (pVal == Py_None) {
2017-05-02 07:38:23 +01:00
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);
2016-07-31 16:09:21 +01:00
}
if (PyBool_Check(pVal)) {
if (PyObject_IsTrue(pVal)) {
2017-05-02 07:38:23 +01:00
rc = PL_unify_atom(t, ATOM_true);
2016-07-31 16:09:21 +01:00
} else {
2017-05-02 07:38:23 +01:00
rc = PL_unify_atom(t, ATOM_false);
2016-07-31 16:09:21 +01:00
}
} else if (PyLong_Check(pVal)) {
2017-05-02 07:38:23 +01:00
rc = PL_unify_int64(t, PyLong_AsLong(pVal));
2016-07-31 16:09:21 +01:00
#if PY_MAJOR_VERSION < 3
} else if (PyInt_Check(pVal)) {
2017-05-02 07:38:23 +01:00
rc = PL_unify_int64(t, PyInt_AsLong(pVal));
2016-07-31 16:09:21 +01:00
#endif
} else if (PyFloat_Check(pVal)) {
2017-05-02 07:38:23 +01:00
rc = PL_unify_float(t, PyFloat_AsDouble(pVal));
2016-07-31 16:09:21 +01:00
} else if (PyComplex_Check(pVal)) {
2017-05-02 07:38:23 +01:00
term_t t1 = PL_new_term_ref(),
2016-07-31 16:09:21 +01:00
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)) {
2017-05-02 07:38:23 +01:00
rc = false;
2016-07-31 16:09:21 +01:00
} else {
rc = PL_unify(t, to);
}
} else if (PyUnicode_Check(pVal)) {
atom_t tmp_atom;
#if PY_MAJOR_VERSION < 3
2017-05-02 07:38:23 +01:00
size_t sz = PyUnicode_GetSize(pVal) + 1;
2016-07-31 16:09:21 +01:00
wchar_t *ptr = malloc(sizeof(wchar_t) * sz);
sz = PyUnicode_AsWideChar((PyUnicodeObject *)pVal, ptr, sz - 1);
2017-05-02 07:38:23 +01:00
tmp_atom = PL_new_atom_wchars(sz, ptr);
2017-02-20 14:37:26 +00:00
free(ptr);
2016-07-31 16:09:21 +01:00
#else
2017-02-20 14:37:26 +00:00
const char *s = PyUnicode_AsUTF8(pVal);
2017-05-02 07:38:23 +01:00
tmp_atom = PL_new_atom( s);
2016-07-31 16:09:21 +01:00
#endif
2017-05-02 07:38:23 +01:00
rc = PL_unify_atom(t, tmp_atom);
2016-07-31 16:09:21 +01:00
} else if (PyByteArray_Check(pVal)) {
atom_t tmp_atom = PL_new_atom(PyByteArray_AsString(pVal));
2017-05-02 07:38:23 +01:00
rc = PL_unify_atom(t, tmp_atom);
2016-07-31 16:09:21 +01:00
#if PY_MAJOR_VERSION < 3
} else if (PyString_Check(pVal)) {
atom_t tmp_atom = PL_new_atom(PyString_AsString(pVal));
2017-05-02 07:38:23 +01:00
rc = PL_unify_atom(t, tmp_atom);
2016-07-31 16:09:21 +01:00
#endif
} else if (PyTuple_Check(pVal)) {
Py_ssize_t i, sz = PyTuple_Size(pVal);
2016-09-30 23:11:13 +01:00
functor_t f;
const char *s;
2016-10-20 04:38:17 +01:00
if ((s = (Py_TYPE(pVal)->tp_name))) {
2016-12-10 07:01:10 +00:00
if (!strcmp(s, "H")) {
pVal = PyTuple_GetItem(pVal, 0);
2017-05-02 07:38:23 +01:00
if (pVal==NULL) {
pVal = Py_None;
PyErr_Clear();
}
2016-12-10 07:01:10 +00:00
}
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);
}
2017-05-02 07:38:23 +01:00
} else {
2016-09-30 23:11:13 +01:00
f = PL_new_functor(ATOM_t, sz);
2016-07-31 16:09:21 +01:00
}
2017-05-02 07:38:23 +01:00
if (PL_unify_functor(t, f)) {
rc = true;
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);
2016-07-31 16:09:21 +01:00
} else if (PyList_Check(pVal)) {
2017-05-02 07:38:23 +01:00
YAP_Term yt = YAP_GetFromSlot(t);
2016-07-31 16:09:21 +01:00
Py_ssize_t i, sz = PyList_GET_SIZE(pVal);
for (i = 0; i < sz; i++) {
2017-05-02 07:38:23 +01:00
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);
2016-07-31 16:09:21 +01:00
}
2017-05-02 07:38:23 +01:00
rc = rc && PL_unify_nil(t);
fputs("[***] ", stderr);
Yap_DebugPlWrite(yt); fputs("[***]\n", stderr);
2016-07-31 16:09:21 +01:00
} 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;
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)) {
2017-05-02 07:38:23 +01:00
continue;
2016-07-31 16:09:21 +01:00
}
if (!python_to_term(value, tval)) {
2017-05-02 07:38:23 +01:00
continue;
2016-07-31 16:09:21 +01:00
}
/* reuse */
tint = tkey;
if (!PL_cons_functor(tint, FUNCTOR_colon2, tkey, tval)) {
2017-05-02 07:38:23 +01:00
rc = false;
continue;
2016-07-31 16:09:21 +01:00
}
if (--left) {
if (!PL_cons_functor(tint, FUNCTOR_comma2, tint, tnew))
2017-02-20 14:37:26 +00:00
PL_reset_term_refs(tkey);
2017-05-02 07:38:23 +01:00
rc = false;
2016-07-31 16:09:21 +01:00
}
2017-02-20 14:37:26 +00:00
if (!PL_unify(ti, tint)) {
2017-05-02 07:38:23 +01:00
rc = false; }
2016-07-31 16:09:21 +01:00
ti = tnew;
2017-02-20 14:37:26 +00:00
PL_reset_term_refs(tkey);
2016-07-31 16:09:21 +01:00
}
2017-05-02 07:38:23 +01:00
rc = PL_unify(t, to);
2016-07-31 16:09:21 +01:00
} else {
2017-05-02 07:38:23 +01:00
rc = repr_term(pVal, t);
2016-07-31 16:09:21 +01:00
}
2017-05-02 07:38:23 +01:00
PL_reset_term_refs(to);
return rc;
2016-07-31 16:09:21 +01:00
}
2016-09-27 18:28:54 +01:00
X_API YAP_Term pythonToYAP(PyObject *pVal) {
term_t t = PL_new_term_ref();
2017-05-02 07:38:23 +01:00
if (pVal == NULL ||
!python_to_term(pVal, t))
2016-09-27 18:28:54 +01:00
return 0;
YAP_Term tt = YAP_GetFromSlot(t);
2017-02-20 14:37:26 +00:00
PL_reset_term_refs(t);
Py_DECREF(pVal);
2016-09-27 18:28:54 +01:00
return tt;
}
2017-02-20 14:37:26 +00:00
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
2017-05-02 07:38:23 +01:00
bool o = true;
if (PySequence_Check(exp) && PySequence_Length(exp) == len)
2017-02-20 14:37:26 +00:00
2017-05-02 07:38:23 +01:00
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;
2017-02-20 14:37:26 +00:00
} 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);
2017-05-02 07:38:23 +01:00
if (i==NULL)
i = Py_None;
2017-02-20 14:37:26 +00:00
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;
}