diff --git a/src/runtime/python/expr.c b/src/runtime/python/expr.c index 82ac1f028..889d85d2c 100644 --- a/src/runtime/python/expr.c +++ b/src/runtime/python/expr.c @@ -15,25 +15,25 @@ Expr_str(ExprObject *self) return str; } -static PyObject * -Expr_richcompare(ExprObject *e1, ExprObject *e2, int op) -{ - bool same = false; - - // TODO - - // same = true; -// done: - - if (op == Py_EQ) { - if (same) Py_RETURN_TRUE; else Py_RETURN_FALSE; - } else if (op == Py_NE) { - if (same) Py_RETURN_FALSE; else Py_RETURN_TRUE; - } else { - PyErr_SetString(PyExc_TypeError, "comparison operation not supported"); - Py_RETURN_NOTIMPLEMENTED; - } -} +// static PyObject * +// Expr_richcompare(ExprObject *e1, ExprObject *e2, int op) +// { +// bool same = false; +// +// // TODO +// +// // same = true; +// // done: +// +// if (op == Py_EQ) { +// if (same) Py_RETURN_TRUE; else Py_RETURN_FALSE; +// } else if (op == Py_NE) { +// if (same) Py_RETURN_FALSE; else Py_RETURN_TRUE; +// } else { +// PyErr_SetString(PyExc_TypeError, "comparison operation not supported"); +// Py_RETURN_NOTIMPLEMENTED; +// } +// } static PyMethodDef Expr_methods[] = { // {"unpack", (PyCFunction)Expr_unpack, METH_VARARGS, @@ -106,7 +106,7 @@ PyTypeObject pgf_ExprType = { "abstract syntax tree", /*tp_doc*/ 0, /*tp_traverse */ 0, /*tp_clear */ - (richcmpfunc) Expr_richcompare, /*tp_richcompare */ + 0, //(richcmpfunc) Expr_richcompare, /*tp_richcompare */ 0, /*tp_weaklistoffset */ 0, /*tp_iter */ 0, /*tp_iternext */ @@ -125,6 +125,88 @@ PyTypeObject pgf_ExprType = { // ---------------------------------------------------------------------------- +static ExprFunObject * +ExprFun_new(PyTypeObject *subtype, PyObject *args, PyObject *kwds) +{ + ExprFunObject* self = (ExprFunObject *)subtype->tp_alloc(subtype, 0); + return self; +} + +static int +ExprFun_init(ExprFunObject *self, PyObject *args, PyObject *kwds) +{ + PyObject* lit = NULL; + if (!PyArg_ParseTuple(args, "U", &lit)) { + return -1; + } + self->fun = lit; + return 0; +} + +static PyObject * +ExprFun_richcompare(ExprFunObject *t1, ExprFunObject *t2, int op) +{ + bool same = false; + if (PyUnicode_Compare(t1->fun, t2->fun) != 0) goto done; + + same = true; +done: + + if (op == Py_EQ) { + if (same) Py_RETURN_TRUE; else Py_RETURN_FALSE; + } else if (op == Py_NE) { + if (same) Py_RETURN_FALSE; else Py_RETURN_TRUE; + } else { + PyErr_SetString(PyExc_TypeError, "comparison operation not supported"); + Py_RETURN_NOTIMPLEMENTED; + } +} + +/* static */ +PyTypeObject pgf_ExprFunType = { + PyVarObject_HEAD_INIT(NULL, 0) + //0, /*ob_size*/ + "pgf.ExprFun", /*tp_name*/ + sizeof(ExprFunObject), /*tp_basicsize*/ + 0, /*tp_itemsize*/ + 0, //(destructor)Expr_dealloc, /*tp_dealloc*/ + 0, /*tp_print*/ + 0, /*tp_getattr*/ + 0, /*tp_setattr*/ + 0, /*tp_compare*/ + 0, /*tp_repr*/ + 0, /*tp_as_number*/ + 0, /*tp_as_sequence*/ + 0, /*tp_as_mapping*/ + 0, //(hashfunc) Expr_hash, /*tp_hash */ + 0, //(ternaryfunc) Expr_call, /*tp_call*/ + 0, //(reprfunc) Expr_str, /*tp_str*/ + 0, //(getattrofunc) Expr_getattro,/*tp_getattro*/ + 0, /*tp_setattro*/ + 0, /*tp_as_buffer*/ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/ + "function or data constructor", /*tp_doc*/ + 0, /*tp_traverse */ + 0, /*tp_clear */ + (richcmpfunc) ExprFun_richcompare, /*tp_richcompare */ + 0, /*tp_weaklistoffset */ + 0, /*tp_iter */ + 0, /*tp_iternext */ + 0, //Expr_methods, /*tp_methods */ + 0, /*tp_members */ + 0, //Expr_getseters, /*tp_getset */ + &pgf_ExprType, /*tp_base */ + 0, /*tp_dict */ + 0, /*tp_descr_get */ + 0, /*tp_descr_set */ + 0, /*tp_dictoffset */ + (initproc) ExprFun_init, /*tp_init */ + 0, /*tp_alloc */ + (newfunc) ExprFun_new, /*tp_new */ +}; + +// ---------------------------------------------------------------------------- + static ExprLitObject * ExprLit_new(PyTypeObject *subtype, PyObject *args, PyObject *kwds) { diff --git a/src/runtime/python/expr.h b/src/runtime/python/expr.h index 19b3fa45d..b1bab6940 100644 --- a/src/runtime/python/expr.h +++ b/src/runtime/python/expr.h @@ -11,7 +11,7 @@ typedef struct { PyObject_HEAD PyObject *hypos; // PyListObject of PyTupleObject: (bind_type: int, cid: string, type: TypeObject) - PyObject *cat; // PyStringObject + PyObject *cat; // PyUnicodeObject PyObject *exprs; // PyListObject of ExprObject } TypeObject; @@ -23,21 +23,28 @@ typedef struct { typedef struct { PyObject_HEAD - PyObject *value; + PyObject *fun; // PyUnicodeObject +} ExprFunObject; + +typedef struct { + PyObject_HEAD + PyObject *value; // PyLongObject | PyFloatObject | PyUnicodeObject } ExprLitObject; typedef struct { PyObject_HEAD - PyObject *id; + PyObject *id; // PyLongObject } ExprMetaObject; typedef struct { PyObject_HEAD - PyObject *index; + PyObject *index; // PyLongObject } ExprVarObject; extern PyTypeObject pgf_ExprType; +extern PyTypeObject pgf_ExprFunType; + extern PyTypeObject pgf_ExprLitType; extern PyTypeObject pgf_ExprMetaType; diff --git a/src/runtime/python/marshaller.c b/src/runtime/python/marshaller.c index e2dab89fd..fa183bd2f 100644 --- a/src/runtime/python/marshaller.c +++ b/src/runtime/python/marshaller.c @@ -7,6 +7,35 @@ #include "./compat.h" #include "./expr.h" +// ---------------------------------------------------------------------------- + +PgfText * +PyUnicode_AsPgfText(PyObject *pystr) +{ + if (!PyUnicode_Check(pystr)) { + PyErr_SetString(PyExc_TypeError, "input to PyUnicode_AsPgfText is not a string"); + return NULL; + } + if (PyUnicode_READY(pystr) != 0) { + return NULL; + } + + Py_ssize_t size; + const char *enc = PyUnicode_AsUTF8AndSize(pystr, &size); + PgfText *ptext = malloc(sizeof(PgfText)+size+1); + memcpy(ptext->text, enc, size+1); + ptext->size = size; + return ptext; +} + +PyObject * +PyUnicode_FromPgfText(PgfText *text) +{ + return PyUnicode_FromStringAndSize(text->text, text->size); +} + +// ---------------------------------------------------------------------------- + /* The PgfUnmarshaller structure tells the runtime how to create * abstract syntax expressions and types in the heap of the host language. * In Python the expressions are normal objects. @@ -44,8 +73,11 @@ PgfExpr emeta(PgfUnmarshaller *this, PgfMetaId meta) PgfExpr efun(PgfUnmarshaller *this, PgfText *name) { - PyErr_SetString(PyExc_NotImplementedError, "efun not implemented"); - return 0; + ExprFunObject *pyexpr = (ExprFunObject *)pgf_ExprFunType.tp_alloc(&pgf_ExprFunType, 0); + PyObject *pyobj = PyUnicode_FromPgfText(name); + pyexpr->fun = pyobj; + Py_INCREF(pyobj); + return (PgfExpr) pyexpr; } PgfExpr evar(PgfUnmarshaller *this, int index) @@ -154,27 +186,6 @@ PgfUnmarshaller unmarshaller = { &unmarshallerVtbl }; // ---------------------------------------------------------------------------- -PgfText * -PyUnicode_AsPgfText(PyObject *pystr) -{ - if (!PyUnicode_Check(pystr)) { - PyErr_SetString(PyExc_TypeError, "input to PyUnicode_AsPgfText is not a string"); - return NULL; - } - if (PyUnicode_READY(pystr) != 0) { - return NULL; - } - - Py_ssize_t size; - const char *enc = PyUnicode_AsUTF8AndSize(pystr, &size); - PgfText *ptext = malloc(sizeof(PgfText)+size+1); - memcpy(ptext->text, enc, size+1); - ptext->size = size; - return ptext; -} - -// ---------------------------------------------------------------------------- - object match_lit(PgfMarshaller *this, PgfUnmarshaller *u, PgfLiteral lit) { PyObject *pyobj = (PyObject *)lit; diff --git a/src/runtime/python/marshaller.h b/src/runtime/python/marshaller.h index bec013fe8..110334f21 100644 --- a/src/runtime/python/marshaller.h +++ b/src/runtime/python/marshaller.h @@ -8,6 +8,8 @@ PgfText *PyUnicode_AsPgfText(PyObject *pystr); +PyObject *PyUnicode_FromPgfText(PgfText *text); + extern PgfUnmarshaller unmarshaller; extern PgfMarshaller marshaller; diff --git a/src/runtime/python/pypgf.c b/src/runtime/python/pypgf.c index 6b4bff183..9126e9ad5 100644 --- a/src/runtime/python/pypgf.c +++ b/src/runtime/python/pypgf.c @@ -2666,6 +2666,9 @@ MOD_INIT(pgf) if (PyType_Ready(&pgf_ExprType) < 0) return MOD_ERROR_VAL; + if (PyType_Ready(&pgf_ExprFunType) < 0) + return MOD_ERROR_VAL; + if (PyType_Ready(&pgf_ExprLitType) < 0) return MOD_ERROR_VAL; @@ -2703,6 +2706,9 @@ MOD_INIT(pgf) PyModule_AddObject(m, "Expr", (PyObject *) &pgf_ExprType); Py_INCREF(&pgf_ExprType); + PyModule_AddObject(m, "ExprFun", (PyObject *) &pgf_ExprFunType); + Py_INCREF(&pgf_ExprFunType); + PyModule_AddObject(m, "ExprLit", (PyObject *) &pgf_ExprLitType); Py_INCREF(&pgf_ExprLitType); diff --git a/src/runtime/python/test_suite.py b/src/runtime/python/test_suite.py index b3fb45a59..dab835551 100644 --- a/src/runtime/python/test_suite.py +++ b/src/runtime/python/test_suite.py @@ -216,6 +216,9 @@ def test_readExpr_lstr_str(): # expressions: functions +def test_readExpr_efun_equality_1(): + assert pgf.readExpr("f") == pgf.ExprFun("f") + # ,TestCase (assertEqual "show expression 1" "f x y" (showExpr [] (EApp (EApp (EFun "f") (EFun "x")) (EFun "y")))) # ,TestCase (assertEqual "show expression 2" "f (g x)" (showExpr [] (EApp (EFun "f") (EApp (EFun "g") (EFun "x"))))) # ,TestCase (assertEqual "show expression 3" "f {g x}" (showExpr [] (EApp (EFun "f") (EImplArg (EApp (EFun "g") (EFun "x"))))))