diff --git a/src/runtime/python/expr.c b/src/runtime/python/expr.c index 82ac1f028..7d6229296 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,174 @@ 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->name = lit; + return 0; +} + +static PyObject * +ExprFun_richcompare(ExprFunObject *t1, ExprFunObject *t2, int op) +{ + bool same = false; + if (PyUnicode_Compare(t1->name, t2->name) != 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 ExprAppObject * +ExprApp_new(PyTypeObject *subtype, PyObject *args, PyObject *kwds) +{ + ExprAppObject* self = (ExprAppObject *)subtype->tp_alloc(subtype, 0); + return self; +} + +static int +ExprApp_init(ExprAppObject *self, PyObject *args, PyObject *kwds) +{ + PyObject* e1 = NULL; + PyObject* e2 = NULL; + if (!PyArg_ParseTuple(args, "O!O!", &pgf_ExprType, &e1, &pgf_ExprType, &e2)) { + return -1; + } + + self->e1 = (ExprObject *)e1; + self->e2 = (ExprObject *)e2; + return 0; +} + +static PyObject * +ExprApp_richcompare(ExprAppObject *t1, ExprAppObject *t2, 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 */ +PyTypeObject pgf_ExprAppType = { + PyVarObject_HEAD_INIT(NULL, 0) + //0, /*ob_size*/ + "pgf.ExprApp", /*tp_name*/ + sizeof(ExprAppObject), /*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*/ + "application", /*tp_doc*/ + 0, /*tp_traverse */ + 0, /*tp_clear */ + (richcmpfunc) ExprApp_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) ExprApp_init, /*tp_init */ + 0, /*tp_alloc */ + (newfunc) ExprApp_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..04576a0a1 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,36 @@ typedef struct { typedef struct { PyObject_HEAD - PyObject *value; + PyObject *name; // PyUnicodeObject +} ExprFunObject; + +typedef struct { + PyObject_HEAD + ExprObject *e1; // ExprObject + ExprObject *e2; // ExprObject +} ExprAppObject; + +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_ExprAppType; + extern PyTypeObject pgf_ExprLitType; extern PyTypeObject pgf_ExprMetaType; diff --git a/src/runtime/python/marshaller.c b/src/runtime/python/marshaller.c index e2dab89fd..7dcb4bd63 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. @@ -22,8 +51,12 @@ PgfExpr eabs(PgfUnmarshaller *this, PgfBindType btype, PgfText *name, PgfExpr bo PgfExpr eapp(PgfUnmarshaller *this, PgfExpr fun, PgfExpr arg) { - PyErr_SetString(PyExc_NotImplementedError, "eapp not implemented"); - return 0; + ExprAppObject *pyexpr = (ExprAppObject *)pgf_ExprAppType.tp_alloc(&pgf_ExprAppType, 0); + pyexpr->e1 = (ExprObject *)fun; + pyexpr->e2 = (ExprObject *)arg; + // Py_INCREF(fun); + // Py_INCREF(arg); + return (PgfExpr) pyexpr; } PgfExpr elit(PgfUnmarshaller *this, PgfLiteral lit) @@ -44,8 +77,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->name = pyobj; + Py_INCREF(pyobj); + return (PgfExpr) pyexpr; } PgfExpr evar(PgfUnmarshaller *this, int index) @@ -154,27 +190,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; @@ -226,13 +241,23 @@ object match_expr(PgfMarshaller *this, PgfUnmarshaller *u, PgfExpr expr) { PyObject *pyobj = (PyObject *)expr; + if (PyObject_TypeCheck(pyobj, &pgf_ExprFunType)) { + ExprFunObject *efun = (ExprFunObject *)expr; + return u->vtbl->efun(u, PyUnicode_AsPgfText(efun->name)); + } else + if (PyObject_TypeCheck(pyobj, &pgf_ExprAppType)) { + ExprAppObject *eapp = (ExprAppObject *)expr; + return u->vtbl->eapp(u, (PgfExpr) eapp->e1, (PgfExpr) eapp->e2); // TODO check + } else if (PyObject_TypeCheck(pyobj, &pgf_ExprLitType)) { ExprLitObject *elit = (ExprLitObject *)expr; return this->vtbl->match_lit(this, u, (PgfLiteral) elit->value); - } else if (PyObject_TypeCheck(pyobj, &pgf_ExprMetaType)) { + } else + if (PyObject_TypeCheck(pyobj, &pgf_ExprMetaType)) { ExprMetaObject *emeta = (ExprMetaObject *)expr; return u->vtbl->emeta(u, (PgfMetaId) PyLong_AsLong(emeta->id)); - } else if (PyObject_TypeCheck(pyobj, &pgf_ExprVarType)) { + } else + if (PyObject_TypeCheck(pyobj, &pgf_ExprVarType)) { ExprVarObject *evar = (ExprVarObject *)expr; return u->vtbl->evar(u, PyLong_AsLong(evar->index)); } else { 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..335d7fc1a 100644 --- a/src/runtime/python/pypgf.c +++ b/src/runtime/python/pypgf.c @@ -2666,6 +2666,12 @@ 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_ExprAppType) < 0) + return MOD_ERROR_VAL; + if (PyType_Ready(&pgf_ExprLitType) < 0) return MOD_ERROR_VAL; @@ -2703,6 +2709,12 @@ 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, "ExprApp", (PyObject *) &pgf_ExprAppType); + Py_INCREF(&pgf_ExprAppType); + 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..0e47ceae4 100644 --- a/src/runtime/python/test_suite.py +++ b/src/runtime/python/test_suite.py @@ -216,8 +216,27 @@ def test_readExpr_lstr_str(): # expressions: functions - # ,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"))))) +def test_readExpr_efun_equality_1(): + assert pgf.readExpr("f") == pgf.ExprFun("f") + +def test_readExpr_efun_equality_2(): + assert pgf.readExpr("f x y") == pgf.ExprApp( + pgf.ExprApp( + pgf.ExprFun("f"), + pgf.ExprFun("x") + ), + pgf.ExprFun("y") + ) + +def test_readExpr_efun_equality_3(): + assert pgf.readExpr("f (g x)") == pgf.ExprApp( + pgf.ExprFun("f"), + pgf.ExprApp( + pgf.ExprFun("g"), + pgf.ExprFun("x") + ) + ) + # ,TestCase (assertEqual "show expression 3" "f {g x}" (showExpr [] (EApp (EFun "f") (EImplArg (EApp (EFun "g") (EFun "x")))))) # expressions: variables