From c26aec892f26ee21067a0beb9dd79a8c834e6dba Mon Sep 17 00:00:00 2001 From: Omer Zak Date: Sun, 22 May 2016 11:03:43 +0300 Subject: Added all old files of interest to version control. --- pytoguile.c | 747 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 747 insertions(+) create mode 100644 pytoguile.c (limited to 'pytoguile.c') diff --git a/pytoguile.c b/pytoguile.c new file mode 100644 index 0000000..640ddaa --- /dev/null +++ b/pytoguile.c @@ -0,0 +1,747 @@ +// pytoguile functions +// Functions for conversion from PyObjects into Guile SCMs. +//////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2008 Omer Zak. +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with this library, in a file named COPYING; if not, write to the +// Free Software Foundation, Inc., 59 Temple Place, Suite 330, +// Boston, MA 02111-1307 USA +// +// For licensing issues, contact . +// +//////////////////////////////////////////////////////////////////////// +//#include // included in pytoguile.h +//#include // included in pytoguile.h +#include "pytoguile.h" +#include "pysmob.h" +#include "g2p2g_smob.h" // used in pytoguile.inc +#include "verbose.h" +#include "pyscm.h" + +//////////////////////////////////////////////////////////////////////// +// Convert data from Python (PyObject *) into Guile (SCM) +// representation +//////////////////////////////////////////////////////////////////////// + +// The following functions convert each a single data type. +// They have to be efficient. +// The interface conventions are: +// 1. The function gets a single PyObject * argument, and upon +// success - returns a single SCM. +// 2. The function is responsible for checking the data type of +// and whether the value of its argument is in range. +// If any of them fails, the function returns SCM_UNDEFINED. +// 3. If there is any error not associated with wrong data type +// of its argument, the function throws a scm exception. +// 4. Naming convention: +// p2g_{Python datatype name}2{Guile datatype name} + + +//////////////////////////////////////////////////////////////////////// +// Apply a template to PyObject for converting it into a SCM +//////////////////////////////////////////////////////////////////////// + +SCM +p2g_apply(PyObject *pobj,SCM stemplate) +{ + if (IS_P2G_SMOBP(stemplate)) { + if (pyguile_verbosity_test(PYGUILE_VERBOSE_G2P2G_ALWAYS)) { + scm_simple_format(scm_current_output_port(),scm_makfrom0str("# p2g_apply: pobj=~S smob-stemplate=~S\n"),scm_list_2(verbosity_repr(pobj),stemplate)); + } + return((get_p2g_function(stemplate))(pobj,SCM_UNSPECIFIED)); + } + else if (!SCM_EQ_P(SCM_BOOL_F,scm_pair_p(stemplate))) { + if (IS_P2G_SMOBP(SCM_CAR(stemplate))) { + if (pyguile_verbosity_test(PYGUILE_VERBOSE_G2P2G_ALWAYS)) { + scm_simple_format(scm_current_output_port(),scm_makfrom0str("# p2g_apply: pobj=~S pair-stemplate=~S\n"),scm_list_2(verbosity_repr(pobj),stemplate)); + } + return((get_p2g_function(SCM_CAR(stemplate)))(pobj,SCM_CDR(stemplate))); + } + else { + scm_misc_error("p2g_apply","bad template CAR item ~S", + scm_list_1(SCM_CAR(stemplate))); + } + } + else { + scm_misc_error("p2g_apply","bad template item ~S", + scm_list_1(stemplate)); + } +} + +////////////////////////// leaf //////////////////////////////////////// + +// Perform 'leaf' data conversion. +// Normally, stemplate is a list of templates, to be tried one by one +// until one of them succeeds. +SCM +p2g_leaf(PyObject *pobj,SCM stemplate) +{ + if (IS_P2G_SMOBP(stemplate)) { + if (pyguile_verbosity_test(PYGUILE_VERBOSE_G2P2G_ALWAYS)) { + scm_simple_format(scm_current_output_port(),scm_makfrom0str("# p2g_leaf: pobj=~S smob-stemplate=~S\n"),scm_list_2(verbosity_repr(pobj),stemplate)); + } + return((get_p2g_function(stemplate))(pobj,SCM_UNSPECIFIED)); + } + if (!SCM_EQ_P(SCM_BOOL_F,scm_list_p(stemplate))) { + // Each template list item is examined. + // If the template list item is itself a list, then its CAR is invoked + // and gets its CDR as template, and the whole sobj (which is + // expected to be Template or List, too) as the argument. + // If the template list item is a P2G_SMOB, then it is invoked with + // pobj. + // + // At any case, template list items are invoked one by one until + // one of them succeeds. + if (pyguile_verbosity_test(PYGUILE_VERBOSE_G2P2G_ALWAYS)) { + scm_simple_format(scm_current_output_port(),scm_makfrom0str("# p2g_leaf: pobj=~S list-stemplate=~S\n"),scm_list_2(verbosity_repr(pobj),stemplate)); + } + SCM slist; + for (slist = stemplate; (!SCM_EQ_P(slist,SCM_EOL)); + slist = SCM_CDR(slist)) { + SCM scandidate = SCM_CAR(slist); + SCM sobj = p2g_apply(pobj,scandidate); + if (!SCM_UNBNDP(sobj)) { + if (pyguile_verbosity_test(PYGUILE_VERBOSE_G2P2G_SUCCESSFUL)) { + scm_simple_format(scm_current_output_port(),scm_makfrom0str("# p2g_leaf: successful conversion of ~S into SCM\n"),scm_list_1(verbosity_repr(pobj))); + } + return(sobj); + } + } + return(SCM_UNDEFINED); // None of the templates in the list fit the sobj. + // Supports backtracking if the template is so designed. + } + scm_wrong_type_arg("p2g_leaf",SCM_ARG2,stemplate); // Bad template +} + +////////////////////////// None //////////////////////////////////////// + +// This function is somewhat unusual in that its stemplate argument, +// if specified, does not have to be a P2G_SMOB. +// This argument is the one which is returned if the Python value +// is None. +SCM +p2g_None2SCM_EOL(PyObject *pobj,SCM stemplate) +{ + //return((Py_None != pobj) + // ? SCM_UNDEFINED + // : (SCM_EQ_P(stemplate,SCM_UNSPECIFIED) || SCM_UNBNDP(stemplate)) + // ? SCM_EOL + // : stemplate); + if (Py_None != pobj) { + if (pyguile_verbosity_test(PYGUILE_VERBOSE_G2P2G_ALWAYS)) { + scm_simple_format(scm_current_output_port(),scm_makfrom0str("# p2g_None2SCM_EOL: pobj=~S stemplate=~S\n"),scm_list_2(verbosity_repr(pobj),stemplate)); + } + return(SCM_UNDEFINED); + } + else { + SCM stemp = (SCM_EQ_P(stemplate,SCM_UNSPECIFIED) || SCM_UNBNDP(stemplate)) + ? SCM_EOL : stemplate; + if (pyguile_verbosity_test(PYGUILE_VERBOSE_G2P2G_SUCCESSFUL)) { + scm_simple_format(scm_current_output_port(),scm_makfrom0str("# p2g_None2SCM_EOL: successful conversion of None into ~S\n"),scm_list_1(stemp)); + } + return(stemp); + } +} + +///////////////////////// Boolean ////////////////////////////////////// + +SCM +p2g_Bool2SCM_BOOL(PyObject *pobj,SCM stemplate) +{ + if (PyBool_Check(pobj)) { + if (pyguile_verbosity_test(PYGUILE_VERBOSE_G2P2G_SUCCESSFUL)) { + scm_simple_format(scm_current_output_port(),scm_makfrom0str("# p2g_Bool2SCM_BOOL: successful conversion of ~S into SCM\n"),scm_list_1(verbosity_repr(pobj))); + } + return (PyInt_AsLong(pobj) ? SCM_BOOL_T : SCM_BOOL_F); + } + else { + if (pyguile_verbosity_test(PYGUILE_VERBOSE_G2P2G_ALWAYS)) { + scm_simple_format(scm_current_output_port(),scm_makfrom0str("# p2g_Bool2SCM_BOOL: failed to convert pobj=~S using stemplate=~S\n"),scm_list_2(verbosity_repr(pobj),stemplate)); + } + return(SCM_UNDEFINED); + } +} + +///////////////////////// Numeric ////////////////////////////////////// + +SCM +p2g_Int2num(PyObject *pobj,SCM stemplate) +{ + if (PyInt_Check(pobj)) { + if (pyguile_verbosity_test(PYGUILE_VERBOSE_G2P2G_SUCCESSFUL)) { + scm_simple_format(scm_current_output_port(),scm_makfrom0str("# p2g_Int2num: successful conversion of ~S into SCM\n"),scm_list_1(verbosity_repr(pobj))); + } + return (scm_long2num(PyInt_AsLong(pobj))); + } + else { + if (pyguile_verbosity_test(PYGUILE_VERBOSE_G2P2G_ALWAYS)) { + scm_simple_format(scm_current_output_port(),scm_makfrom0str("# p2g_Int2num: failed to convert pobj=~S using stemplate=~S\n"),scm_list_2(verbosity_repr(pobj),stemplate)); + } + return(SCM_UNDEFINED); + } +} + +SCM +p2g_Long2bignum(PyObject *pobj,SCM stemplate) +{ + if (PyLong_Check(pobj)) { + PyObject *pstr = PyObject_Repr(pobj); + if (NULL == pstr) { + PyObject *pexception = PyErr_Occurred(); // NOT COVERED BY TESTS + if (pexception) { // NOT COVERED BY TESTS + PyErr_Clear(); // NOT COVERED BY TESTS + scm_misc_error("p2g_Long2bignum","internal conversion error of bignum", // NOT COVERED BY TESTS + SCM_UNDEFINED); + } + else { + scm_misc_error("p2g_Long2bignum","unknown internal conversion error of bignum", // NOT COVERED BY TESTS + SCM_UNDEFINED); + } + } + char *cstr = PyString_AsString(pstr); + long cstrlen = strlen(cstr); + if (cstrlen < 1) { + scm_misc_error("p2g_Long2bignum","conversion error of bignum - too short result string", // NOT COVERED BY TESTS + SCM_UNDEFINED); + } + if ('L' == cstr[cstrlen-1]) { + --cstrlen; + } + //return(scm_istring2number(cstr,cstrlen,10)); // scm_istring2number seems to be deprecated in newer versions of Guile. + SCM sstr = scm_mem2string(cstr,cstrlen); + Py_DECREF(pstr); + if (pyguile_verbosity_test(PYGUILE_VERBOSE_G2P2G_SUCCESSFUL)) { + // Note: here verbosity_repr is inefficient in that it converts again + // a PyObject into a SCM string - but it is not critical for performance + // and code clarity is more important. + scm_simple_format(scm_current_output_port(),scm_makfrom0str("# p2g_Long2bignum: successful conversion of ~S into SCM\n"),scm_list_1(verbosity_repr(pobj))); + } + return(scm_string_to_number(sstr,scm_long2num((long)10))); + } + else { + if (pyguile_verbosity_test(PYGUILE_VERBOSE_G2P2G_ALWAYS)) { + scm_simple_format(scm_current_output_port(),scm_makfrom0str("# p2g_Long2bignum: failed to convert pobj=~S using stemplate=~S\n"),scm_list_2(verbosity_repr(pobj),stemplate)); + } + return(SCM_UNDEFINED); + } +} + +SCM +p2g_Float2real(PyObject *pobj,SCM stemplate) +{ + if (PyFloat_Check(pobj)) { + if (pyguile_verbosity_test(PYGUILE_VERBOSE_G2P2G_SUCCESSFUL)) { + scm_simple_format(scm_current_output_port(),scm_makfrom0str("# p2g_Float2real: successful conversion of ~S into SCM\n"),scm_list_1(verbosity_repr(pobj))); + } + return (scm_double2num(PyFloat_AsDouble(pobj))); + } + else { + if (pyguile_verbosity_test(PYGUILE_VERBOSE_G2P2G_ALWAYS)) { + scm_simple_format(scm_current_output_port(),scm_makfrom0str("# p2g_Float2real: failed to convert pobj=~S using stemplate=~S\n"),scm_list_2(verbosity_repr(pobj),stemplate)); + } + return(SCM_UNDEFINED); + } +} + +SCM +p2g_Complex2complex(PyObject *pobj,SCM stemplate) +{ + if (PyComplex_Check(pobj)) { + if (pyguile_verbosity_test(PYGUILE_VERBOSE_G2P2G_SUCCESSFUL)) { + scm_simple_format(scm_current_output_port(),scm_makfrom0str("# p2g_Complex2complex: successful conversion of ~S into SCM\n"),scm_list_1(verbosity_repr(pobj))); + } + double re = PyComplex_RealAsDouble(pobj); + double im = PyComplex_ImagAsDouble(pobj); + return(scm_make_complex(re,im)); + } + else { + if (pyguile_verbosity_test(PYGUILE_VERBOSE_G2P2G_ALWAYS)) { + scm_simple_format(scm_current_output_port(),scm_makfrom0str("# p2g_Complex2complex: failed to convert pobj=~S using stemplate=~S\n"),scm_list_2(verbosity_repr(pobj),stemplate)); + } + return(SCM_UNDEFINED); + } +} + +///////////////////////// Strings ////////////////////////////////////// + +SCM +p2g_String2string(PyObject *pobj,SCM stemplate) +{ + if (PyString_CheckExact(pobj)) { + if (pyguile_verbosity_test(PYGUILE_VERBOSE_G2P2G_SUCCESSFUL)) { + scm_simple_format(scm_current_output_port(),scm_makfrom0str("# p2g_String2string: successful conversion of ~S into SCM\n"),scm_list_1(verbosity_repr(pobj))); + } + int strlength = PyString_Size(pobj); + char *strtext = PyString_AsString(pobj); + //scm_makfrom0str - duplicates zero-terminated string + //scm_take0str - takes over ownership of the zero-terminated string + //scm_mem2string(const char*,len) + //scm_take_str(const char*,len) + return(scm_mem2string(strtext,strlength)); + } + else { + if (pyguile_verbosity_test(PYGUILE_VERBOSE_G2P2G_ALWAYS)) { + scm_simple_format(scm_current_output_port(),scm_makfrom0str("# p2g_String2string: failed to convert pobj=~S using stemplate=~S\n"),scm_list_2(verbosity_repr(pobj),stemplate)); + } + return(SCM_UNDEFINED); + } +} + +SCM +p2g_String2symbol(PyObject *pobj,SCM stemplate) +{ + if (PyString_CheckExact(pobj)) { + if (pyguile_verbosity_test(PYGUILE_VERBOSE_G2P2G_SUCCESSFUL)) { + scm_simple_format(scm_current_output_port(),scm_makfrom0str("# p2g_String2symbol: successful conversion of ~S into SCM\n"),scm_list_1(verbosity_repr(pobj))); + } + //int strlength = PyString_Size(pobj); + char *strtext = PyString_AsString(pobj); + return(scm_str2symbol(strtext)); + } + else { + if (pyguile_verbosity_test(PYGUILE_VERBOSE_G2P2G_ALWAYS)) { + scm_simple_format(scm_current_output_port(),scm_makfrom0str("# p2g_String2symbol: failed to convert pobj=~S using stemplate=~S\n"),scm_list_2(verbosity_repr(pobj),stemplate)); + } + return(SCM_UNDEFINED); + } +} + +SCM +p2g_String2keyword(PyObject *pobj,SCM stemplate) +{ + if (PyString_CheckExact(pobj)) { + int strlength = PyString_Size(pobj); + if (strlength < 1) { + // Ensure that there is at least one character in the + // real string. + if (pyguile_verbosity_test(PYGUILE_VERBOSE_G2P2G_ALWAYS)) { + scm_simple_format(scm_current_output_port(),scm_makfrom0str("# p2g_String2keyword: failed to convert pobj=~S using stemplate=~S - zero-length string\n"),scm_list_2(verbosity_repr(pobj),stemplate)); + } + return(SCM_UNDEFINED); + } + if (pyguile_verbosity_test(PYGUILE_VERBOSE_G2P2G_SUCCESSFUL)) { + scm_simple_format(scm_current_output_port(),scm_makfrom0str("# p2g_String2keyword: successful conversion of ~S into SCM\n"),scm_list_1(verbosity_repr(pobj))); + } + char *strtext = PyString_AsString(pobj); + // Prefixing dash to the string. + char *dashstr = malloc(strlength+2); + dashstr[0] = '-'; + dashstr[1] = '\0'; + strncat(dashstr,strtext,strlength); + SCM ssymbol = scm_str2symbol(dashstr); + return(scm_make_keyword_from_dash_symbol(ssymbol)); + } + else { + if (pyguile_verbosity_test(PYGUILE_VERBOSE_G2P2G_ALWAYS)) { + scm_simple_format(scm_current_output_port(),scm_makfrom0str("# p2g_String2keyword: failed to convert pobj=~S using stemplate=~S\n"),scm_list_2(verbosity_repr(pobj),stemplate)); + } + return(SCM_UNDEFINED); + } +} + +SCM +p2g_1String2char(PyObject *pobj,SCM stemplate) +{ + if (PyString_CheckExact(pobj)) { + int strlength = PyString_Size(pobj); + if (1 != strlength) { + if (pyguile_verbosity_test(PYGUILE_VERBOSE_G2P2G_ALWAYS)) { + scm_simple_format(scm_current_output_port(),scm_makfrom0str("# p2g_1String2char: failed to convert pobj=~S using stemplate=~S - wrong-length string\n"),scm_list_2(verbosity_repr(pobj),stemplate)); + } + return(SCM_UNDEFINED); + } + if (pyguile_verbosity_test(PYGUILE_VERBOSE_G2P2G_SUCCESSFUL)) { + scm_simple_format(scm_current_output_port(),scm_makfrom0str("# p2g_1String2char: successful conversion of ~S into SCM\n"),scm_list_1(verbosity_repr(pobj))); + } + char *strtext = PyString_AsString(pobj); + return(SCM_MAKE_CHAR(strtext[0])); + } + else { + if (pyguile_verbosity_test(PYGUILE_VERBOSE_G2P2G_ALWAYS)) { + scm_simple_format(scm_current_output_port(),scm_makfrom0str("# p2g_1String2char: failed to convert pobj=~S using stemplate=~S\n"),scm_list_2(verbosity_repr(pobj),stemplate)); + } + return(SCM_UNDEFINED); + } +} + +/////////////////////// Aggregates ///////////////////////////////////// + +// Convert a 2-tuple into a pair. Fails if the object is not a +// 2-tuple. The template must be a pair as well. +SCM +p2g_2Tuple2pair(PyObject *pobj,SCM stemplate) +{ + if (pyguile_verbosity_test(PYGUILE_VERBOSE_G2P2G_ALWAYS)) { + scm_simple_format(scm_current_output_port(),scm_makfrom0str("# p2g_2Tuple2pair: trying to convert pobj=~S using stemplate=~S\n"),scm_list_2(verbosity_repr(pobj),stemplate)); + } + if (SCM_EQ_P(SCM_BOOL_F,scm_pair_p(stemplate))) { + scm_misc_error("p2g_2Tuple2pair","bad template item ~S", + scm_list_1(stemplate)); + } + if (!PyTuple_CheckExact(pobj)) { + return(SCM_UNDEFINED); + } + if (2 != PyTuple_GET_SIZE(pobj)) { + return(SCM_UNDEFINED); + } + + SCM sobj_car = p2g_apply(PyTuple_GET_ITEM(pobj,0),SCM_CAR(stemplate)); + if (SCM_UNBNDP(sobj_car)) { + return(SCM_UNDEFINED); + } + SCM sobj_cdr = p2g_apply(PyTuple_GET_ITEM(pobj,1),SCM_CDR(stemplate)); + if (SCM_UNBNDP(sobj_cdr)) { + return(SCM_UNDEFINED); + } + if (pyguile_verbosity_test(PYGUILE_VERBOSE_G2P2G_ALWAYS)) { + scm_simple_format(scm_current_output_port(),scm_makfrom0str("# p2g_2Tuple2pair: successful conversion\n"),SCM_EOL); + } + return(scm_cons(sobj_car,sobj_cdr)); +} + +// Very similar to p2g_2Tuple2pair. +SCM +p2g_2List2pair(PyObject *pobj,SCM stemplate) +{ + if (pyguile_verbosity_test(PYGUILE_VERBOSE_G2P2G_ALWAYS)) { + scm_simple_format(scm_current_output_port(),scm_makfrom0str("# p2g_2List2pair: trying to convert pobj=~S using stemplate=~S\n"),scm_list_2(verbosity_repr(pobj),stemplate)); + } + if (SCM_EQ_P(SCM_BOOL_F,scm_pair_p(stemplate))) { + scm_misc_error("p2g_2List2pair","bad template item ~S", + scm_list_1(stemplate)); + } + if (!PyList_CheckExact(pobj)) { + return(SCM_UNDEFINED); + } + if (2 != PyList_GET_SIZE(pobj)) { + return(SCM_UNDEFINED); + } + + SCM sobj_car = p2g_apply(PyList_GET_ITEM(pobj,0),SCM_CAR(stemplate)); + if (SCM_UNBNDP(sobj_car)) { + return(SCM_UNDEFINED); + } + SCM sobj_cdr = p2g_apply(PyList_GET_ITEM(pobj,1),SCM_CDR(stemplate)); + if (SCM_UNBNDP(sobj_cdr)) { + return(SCM_UNDEFINED); + } + if (pyguile_verbosity_test(PYGUILE_VERBOSE_G2P2G_ALWAYS)) { + scm_simple_format(scm_current_output_port(),scm_makfrom0str("# p2g_2List2pair: successful conversion\n"),SCM_EOL); + } + return(scm_cons(sobj_car,sobj_cdr)); +} + +// Convert a Tuple (of any length) into a list. +// The template may be either P2G_SMOB (to be used for converting +// all Tuple items) or a list of templates. +// The length of the list of templates may be shorter than the length +// of the Tuple. If shorter, list items will be cyclically reused. +SCM +p2g_Tuple2list(PyObject *pobj,SCM stemplate) +{ + if (!PyTuple_CheckExact(pobj)) { + if (pyguile_verbosity_test(PYGUILE_VERBOSE_G2P2G_ALWAYS)) { + scm_simple_format(scm_current_output_port(),scm_makfrom0str("# p2g_Tuple2list: pobj=~S stemplate=~S\n"),scm_list_2(verbosity_repr(pobj),stemplate)); + } + return(SCM_UNDEFINED); + } + int size = PyTuple_GET_SIZE(pobj); + if (IS_P2G_SMOBP(stemplate)) { + // Conversion loop for the case in which the template is + // a single P2G_SMOB + int ind1; + SCM slist1 = SCM_EOL; + for (ind1 = size-1; ind1 >= 0; --ind1) { + PyObject *pitem1 = PyTuple_GET_ITEM(pobj, ind1); + if (NULL == pitem1) { + PyObject *pexception = PyErr_Occurred(); // NOT COVERED BY TESTS + if (pexception) { // NOT COVERED BY TESTS + PyErr_Clear(); // NOT COVERED BY TESTS + } + scm_misc_error("p2g_Tuple2list","access error of Python Tuple", // NOT COVERED BY TESTS + SCM_UNSPECIFIED); + } + SCM sitem1 = p2g_apply(pitem1,stemplate); + if (SCM_UNBNDP(sitem1)) { + // Conversion failure + return(SCM_UNDEFINED); + } + if (pyguile_verbosity_test(PYGUILE_VERBOSE_G2P2G_ALWAYS)) { + scm_simple_format(scm_current_output_port(),scm_makfrom0str("# p2g_Tuple2list: 1. converted item pobj=~S[~S], stemplate=~S\n"),scm_list_3(scm_long2num(ind1),verbosity_repr(pitem1),stemplate)); + } + slist1 = scm_cons(sitem1,slist1); + } + return(slist1); + } + + if (SCM_EQ_P(SCM_BOOL_F,scm_list_p(stemplate))) { + // Bad template. + scm_wrong_type_arg("p2g_Tuple2list",SCM_ARG2,stemplate); + } + // Conversion loop for the case in which the template is a list. + SCM slist2 = SCM_EOL; + SCM stemp = SCM_EOL; // We loop over stemplate again and again as needed. + int ind2; + for (ind2 = 0; ind2 < size; + stemp = SCM_CDR(stemp),++ind2) { + if (SCM_EQ_P(stemp,SCM_EOL)) { + stemp = stemplate; // Loop back to stemplate's beginning. + } + //scm_simple_format(scm_current_output_port(),scm_makfrom0str("# DEBUG: going to convert item according to template ~S\n"),scm_list_1(SCM_CAR(stemp))); + PyObject *pitem2 = PyTuple_GET_ITEM(pobj, ind2); + if (NULL == pitem2) { + PyObject *pexception = PyErr_Occurred(); // NOT COVERED BY TESTS + if (pexception) { // NOT COVERED BY TESTS + PyErr_Clear(); // NOT COVERED BY TESTS + } + scm_misc_error("p2g_Tuple2list","access error of Python Tuple", // NOT COVERED BY TESTS + SCM_UNSPECIFIED); + } + SCM sitem2 = p2g_apply(pitem2,SCM_CAR(stemp)); + if (SCM_UNBNDP(sitem2)) { + // Conversion failure + return(SCM_UNDEFINED); + } + if (pyguile_verbosity_test(PYGUILE_VERBOSE_G2P2G_ALWAYS)) { + scm_simple_format(scm_current_output_port(),scm_makfrom0str("# p2g_Tuple2list: 2. converted item pobj=~S[~S], stemplate=~S\n"),scm_list_3(scm_long2num(ind2),verbosity_repr(pitem2),SCM_CAR(stemp))); + } + slist2 = scm_cons(sitem2,slist2); + } + return(scm_reverse(slist2)); +} + +// Very similar to p2g_Tuple2list above. +SCM +p2g_List2list(PyObject *pobj,SCM stemplate) +{ + if (!PyList_CheckExact(pobj)) { + if (pyguile_verbosity_test(PYGUILE_VERBOSE_G2P2G_ALWAYS)) { + scm_simple_format(scm_current_output_port(),scm_makfrom0str("# p2g_List2list: pobj=~S stemplate=~S\n"),scm_list_2(verbosity_repr(pobj),stemplate)); + } + return(SCM_UNDEFINED); + } + int size = PyList_GET_SIZE(pobj); + if (IS_P2G_SMOBP(stemplate)) { + // Conversion loop for the case in which the template is + // a single P2G_SMOB + int ind1; + SCM slist1 = SCM_EOL; + for (ind1 = size-1; ind1 >= 0; --ind1) { + PyObject *pitem1 = PyList_GET_ITEM(pobj, ind1); + if (NULL == pitem1) { + PyObject *pexception = PyErr_Occurred(); // NOT COVERED BY TESTS + if (pexception) { // NOT COVERED BY TESTS + PyErr_Clear(); // NOT COVERED BY TESTS + } + scm_misc_error("p2g_List2list","access error of Python List", // NOT COVERED BY TESTS + SCM_UNSPECIFIED); + } + SCM sitem1 = p2g_apply(pitem1,stemplate); + if (SCM_UNBNDP(sitem1)) { + // Conversion failure + return(SCM_UNDEFINED); + } + if (pyguile_verbosity_test(PYGUILE_VERBOSE_G2P2G_ALWAYS)) { + scm_simple_format(scm_current_output_port(),scm_makfrom0str("# p2g_List2list: converted item pobj[~S]=~S, stemplate=~S\n"),scm_list_3(scm_long2num(ind1),verbosity_repr(pitem1),stemplate)); + } + slist1 = scm_cons(sitem1,slist1); + } + return(slist1); + } + + if (SCM_EQ_P(SCM_BOOL_F,scm_list_p(stemplate))) { + // Bad template. + scm_wrong_type_arg("p2g_List2list",SCM_ARG2,stemplate); + } + // Conversion loop for the case in which the template is a list. + SCM slist2 = SCM_EOL; + SCM stemp = SCM_EOL; // We loop over stemplate again and again as needed. + int ind2; + for (ind2 = 0; ind2 < size; + stemp = SCM_CDR(stemp),++ind2) { + if (SCM_EQ_P(stemp,SCM_EOL)) { + stemp = stemplate; // Loop back to stemplate's beginning. + } + PyObject *pitem2 = PyList_GET_ITEM(pobj, ind2); + if (NULL == pitem2) { + PyObject *pexception = PyErr_Occurred(); // NOT COVERED BY TESTS + if (pexception) { // NOT COVERED BY TESTS + PyErr_Clear(); // NOT COVERED BY TESTS + } + scm_misc_error("p2g_List2list","access error of Python List", // NOT COVERED BY TESTS + SCM_UNSPECIFIED); + } + SCM sitem2 = p2g_apply(pitem2,SCM_CAR(stemp)); + if (SCM_UNBNDP(sitem2)) { + // Conversion failure + return(SCM_UNDEFINED); + } + if (pyguile_verbosity_test(PYGUILE_VERBOSE_G2P2G_ALWAYS)) { + scm_simple_format(scm_current_output_port(),scm_makfrom0str("# p2g_List2list: 2. converted item pobj=~S[~S], stemplate=~S\n"),scm_list_3(scm_long2num(ind2),verbosity_repr(pitem2),SCM_CAR(stemp))); + } + slist2 = scm_cons(sitem2,slist2); + } + return(scm_reverse(slist2)); +} + +// Conversion of Dict into alist. +// All keys are convertible using a single template (SCM_CAR(stemplate)). +// +// In the most general case, the keys will be used as keys into +// SCM_CDR(stemplate) which would be an hash table. +// However, this most general case is not currently implemented. +// There is a single template also in SCM_CDR(stemplate), which is +// used for converting all values. Any flexibility needed is to be +// obtained through wise p2g_leaf() usage. + +SCM +p2g_Dict2alist(PyObject *pobj,SCM stemplate) +{ + if (pyguile_verbosity_test(PYGUILE_VERBOSE_G2P2G_ALWAYS)) { + scm_simple_format(scm_current_output_port(),scm_makfrom0str("# p2g_Dict2alist: trying to convert pobj=~S using stemplate=~S\n"),scm_list_2(verbosity_repr(pobj),stemplate)); + } + + if (SCM_EQ_P(SCM_BOOL_F,scm_pair_p(stemplate))) { + scm_misc_error("p2g_Dict2alist","bad template ~S", + scm_list_1(stemplate)); + } + //if (!IS_P2G_SMOBP(SCM_CAR(stemplate))) { + // scm_misc_error("p2g_Dict2alist","bad template CAR item ~S", + // scm_list_1(SCM_CAR(stemplate))); + //} + //if (!IS_P2G_SMOBP(SCM_CDR(stemplate))) { + // scm_misc_error("p2g_Dict2alist","bad template CDR item ~S", + // scm_list_1(SCM_CDR(stemplate))); + //} + + if (!PyDict_CheckExact(pobj)) { + return(SCM_UNDEFINED); + } + int iterstate = 0; + PyObject *pkey = NULL; + PyObject *pval = NULL; + SCM salist = SCM_EOL; + while (PyDict_Next(pobj, &iterstate, &pkey, &pval)) { + SCM skey = p2g_apply(pkey,SCM_CAR(stemplate)); + if (SCM_UNBNDP(skey)) { + // Conversion failure. + return(SCM_UNDEFINED); + } + SCM sval = p2g_apply(pval,SCM_CDR(stemplate)); + if (SCM_UNBNDP(sval)) { + // Conversion failure. + return(SCM_UNDEFINED); + } + salist = scm_cons(scm_cons(skey,sval),salist); + } + if (pyguile_verbosity_test(PYGUILE_VERBOSE_G2P2G_ALWAYS)) { + scm_simple_format(scm_current_output_port(),scm_makfrom0str("# p2g_Dict2alist: successful conversion of Dict into ~S\n"),scm_list_1(salist)); + } + return(salist); +} + +SCM +p2g_PySCMObject2SCM(PyObject *pobj,SCM stemplate) +{ + if (pyguile_verbosity_test(PYGUILE_VERBOSE_G2P2G_ALWAYS)) { + scm_simple_format(scm_current_output_port(),scm_makfrom0str("# p2g_PySCMObject2SCM: trying to convert pobj=~S using stemplate=~S\n"),scm_list_2(verbosity_repr(pobj),stemplate)); + } + + if (!PySCMObject_Check(pobj)) { + return(SCM_UNDEFINED); + } + return(unwrap_pyscm_object(pobj)); +} + +//////////////////////////////////////////////////////////////////////// +// Big default conversion function +//////////////////////////////////////////////////////////////////////// +// The python2guile function chooses reasonable defaults, whenever +// there is a possibility for ambiguity concerning the desired +// Scheme datatype. +// It ignores the stemplate argument. + +static SCM python2guile_smob; // for use by default templates +static SCM python2guile_dict_default; // used by python2guile(). + +SCM +python2guile(PyObject *pobj,SCM stemplate) +{ + SCM sres = SCM_UNDEFINED; + if (pyguile_verbosity_test(PYGUILE_VERBOSE_G2P2G_ALWAYS)) { + scm_simple_format(scm_current_output_port(),scm_makfrom0str("# python2guile: trying to convert pobj=~S using stemplate=~S\n"),scm_list_2(verbosity_repr(pobj),stemplate)); + } + + if (NULL == pobj) { + // Regarded as an error. + scm_misc_error("python2guile","no python value to be converted", + SCM_UNSPECIFIED); + //return(SCM_UNDEFINED); + } + + sres = p2g_None2SCM_EOL(pobj,SCM_UNSPECIFIED); + if (!SCM_UNBNDP(sres)) return(sres); // if (SCM_UNDEFINED != sres) return(sres); + + sres = p2g_Bool2SCM_BOOL(pobj,SCM_UNSPECIFIED); + if (!SCM_UNBNDP(sres)) return(sres); // if (SCM_UNDEFINED != sres) return(sres); + + // Numeric + + sres = p2g_Int2num(pobj,SCM_UNSPECIFIED); + if (!SCM_UNBNDP(sres)) return(sres); // if (SCM_UNDEFINED != sres) return(sres); + + sres = p2g_Long2bignum(pobj,SCM_UNSPECIFIED); + if (!SCM_UNBNDP(sres)) return(sres); // if (SCM_UNDEFINED != sres) return(sres); + + sres = p2g_Float2real(pobj,SCM_UNSPECIFIED); + if (!SCM_UNBNDP(sres)) return(sres); // if (SCM_UNDEFINED != sres) return(sres); + + sres = p2g_Complex2complex(pobj,SCM_UNSPECIFIED); + if (!SCM_UNBNDP(sres)) return(sres); // if (SCM_UNDEFINED != sres) return(sres); + + // Strings + + sres = p2g_String2string(pobj,SCM_UNSPECIFIED); + if (!SCM_UNBNDP(sres)) return(sres); // if (SCM_UNDEFINED != sres) return(sres); + + // Aggregates + + sres = p2g_Tuple2list(pobj,python2guile_smob); + if (!SCM_UNBNDP(sres)) return(sres); // if (SCM_UNDEFINED != sres) return(sres); + + sres = p2g_List2list(pobj,python2guile_smob); + if (!SCM_UNBNDP(sres)) return(sres); // if (SCM_UNDEFINED != sres) return(sres); + + sres = p2g_Dict2alist(pobj,python2guile_dict_default); + if (!SCM_UNBNDP(sres)) return(sres); // if (SCM_UNDEFINED != sres) return(sres); + + // PySCMObjects + + sres = p2g_PySCMObject2SCM(pobj,SCM_UNSPECIFIED); + if (!SCM_UNBNDP(sres)) return(sres); + + // !!! Implement here hooks for decoding more data types. + + // If none of the above decoded the data type, then just + // wrap the PyObject with pysmob and return the pysmob. + return(wrap_pyobject(pobj)); +} + +//////////////////////////////////////////////////////////////////////// +// Register all p2g_* functions + +#include "pytoguile.inc" + +//////////////////////////////////////////////////////////////////////// +// End of pytoguile.c -- cgit v1.2.3