From e78e9102be9ddec38efe0fbec3ea6a6a1ac5a218 Mon Sep 17 00:00:00 2001 From: "John J. Camilleri" Date: Mon, 13 Sep 2021 22:29:23 +0200 Subject: [PATCH] Add variable expressions --- src/runtime/python/expr.c | 96 +++++++++++++++++++++++++++++++- src/runtime/python/expr.h | 9 ++- src/runtime/python/marshaller.c | 22 +++++--- src/runtime/python/pypgf.c | 6 ++ src/runtime/python/test_suite.py | 19 +++++++ 5 files changed, 141 insertions(+), 11 deletions(-) diff --git a/src/runtime/python/expr.c b/src/runtime/python/expr.c index dcd5b16e7..82ac1f028 100644 --- a/src/runtime/python/expr.c +++ b/src/runtime/python/expr.c @@ -242,10 +242,10 @@ ExprMeta_init(ExprMetaObject *self, PyObject *args, PyObject *kwds) return -1; } if (lit == NULL) { - self->index = PyLong_FromLong(0); + self->id = PyLong_FromLong(0); return 0; } else if (PyLong_Check(lit)) { - self->index = lit; + self->id = lit; return 0; } else { PyErr_SetString(PyExc_TypeError, "invalid argument in ExprMeta_init"); @@ -257,7 +257,7 @@ static PyObject * ExprMeta_richcompare(ExprMetaObject *t1, ExprMetaObject *t2, int op) { bool same = false; - if (PyObject_RichCompareBool(t1->index, t2->index, Py_EQ) != 1) goto done; + if (PyObject_RichCompareBool(t1->id, t2->id, Py_EQ) != 1) goto done; same = true; done: @@ -317,6 +317,96 @@ PyTypeObject pgf_ExprMetaType = { // ---------------------------------------------------------------------------- +static ExprVarObject * +ExprVar_new(PyTypeObject *subtype, PyObject *args, PyObject *kwds) +{ + ExprVarObject* self = (ExprVarObject *)subtype->tp_alloc(subtype, 0); + return self; +} + +static int +ExprVar_init(ExprVarObject *self, PyObject *args, PyObject *kwds) +{ + PyObject* lit = NULL; + if (!PyArg_ParseTuple(args, "|O", &lit)) { + return -1; + } + if (lit == NULL) { + self->index = PyLong_FromLong(0); + return 0; + } else if (PyLong_Check(lit)) { + self->index = lit; + return 0; + } else { + PyErr_SetString(PyExc_TypeError, "invalid argument in ExprVar_init"); + return -1; + } +} + +static PyObject * +ExprVar_richcompare(ExprVarObject *t1, ExprVarObject *t2, int op) +{ + bool same = false; + if (PyObject_RichCompareBool(t1->index, t2->index, Py_EQ) != 1) 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_ExprVarType = { + PyVarObject_HEAD_INIT(NULL, 0) + //0, /*ob_size*/ + "pgf.ExprVar", /*tp_name*/ + sizeof(ExprVarObject), /*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*/ + "variable", /*tp_doc*/ + 0, /*tp_traverse */ + 0, /*tp_clear */ + (richcmpfunc) ExprVar_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) ExprVar_init, /*tp_init */ + 0, /*tp_alloc */ + (newfunc) ExprVar_new, /*tp_new */ +}; + +// ---------------------------------------------------------------------------- + static PyObject * Type_str(TypeObject *self) { diff --git a/src/runtime/python/expr.h b/src/runtime/python/expr.h index e1e2562de..19b3fa45d 100644 --- a/src/runtime/python/expr.h +++ b/src/runtime/python/expr.h @@ -28,13 +28,20 @@ typedef struct { typedef struct { PyObject_HEAD - PyObject *index; + PyObject *id; } ExprMetaObject; +typedef struct { + PyObject_HEAD + PyObject *index; +} ExprVarObject; + extern PyTypeObject pgf_ExprType; extern PyTypeObject pgf_ExprLitType; extern PyTypeObject pgf_ExprMetaType; +extern PyTypeObject pgf_ExprVarType; + #endif // PYPGF_EXPR_H_ diff --git a/src/runtime/python/marshaller.c b/src/runtime/python/marshaller.c index ee1702712..257fd8e9a 100644 --- a/src/runtime/python/marshaller.c +++ b/src/runtime/python/marshaller.c @@ -38,7 +38,7 @@ PgfExpr elit(PgfUnmarshaller *this, PgfLiteral lit) PgfExpr emeta(PgfUnmarshaller *this, PgfMetaId meta) { ExprMetaObject *pyexpr = (ExprMetaObject *)pgf_ExprMetaType.tp_alloc(&pgf_ExprMetaType, 0); - pyexpr->index = PyLong_FromLong(meta); + pyexpr->id = PyLong_FromLong(meta); return (PgfExpr) pyexpr; } @@ -50,8 +50,9 @@ PgfExpr efun(PgfUnmarshaller *this, PgfText *name) PgfExpr evar(PgfUnmarshaller *this, int index) { - PyErr_SetString(PyExc_NotImplementedError, "evar not implemented"); - return 0; + ExprVarObject *pyexpr = (ExprVarObject *)pgf_ExprVarType.tp_alloc(&pgf_ExprVarType, 0); + pyexpr->index = PyLong_FromLong(index); + return (PgfExpr) pyexpr; } PgfExpr etyped(PgfUnmarshaller *this, PgfExpr expr, PgfType typ) @@ -221,14 +222,21 @@ object match_lit(PgfMarshaller *this, PgfUnmarshaller *u, PgfLiteral lit) } } -object match_expr(PgfMarshaller *this, PgfUnmarshaller *u, PgfExpr ex) +object match_expr(PgfMarshaller *this, PgfUnmarshaller *u, PgfExpr expr) { - ExprObject *expr = (ExprObject *)ex; + PyObject *pyobj = (PyObject *)expr; - if (expr->ob_base.ob_type == &pgf_ExprLitType) { // use PyObject_IsInstance ? - ExprLitObject *elit= (ExprLitObject *)expr; + 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)) { + ExprMetaObject *emeta = (ExprMetaObject *)expr; + return u->vtbl->emeta(u, (PgfMetaId) PyLong_AsLong(emeta->id)); + } else if (PyObject_TypeCheck(pyobj, &pgf_ExprVarType)) { + ExprVarObject *evar = (ExprVarObject *)expr; + return u->vtbl->evar(u, PyLong_AsLong(evar->index)); } else { + PyErr_SetString(PyExc_TypeError, "unable to match on expression"); return 0; } } diff --git a/src/runtime/python/pypgf.c b/src/runtime/python/pypgf.c index 438e51bfe..aaa4fd3e8 100644 --- a/src/runtime/python/pypgf.c +++ b/src/runtime/python/pypgf.c @@ -2636,6 +2636,9 @@ MOD_INIT(pgf) if (PyType_Ready(&pgf_ExprMetaType) < 0) return MOD_ERROR_VAL; + if (PyType_Ready(&pgf_ExprVarType) < 0) + return MOD_ERROR_VAL; + if (PyType_Ready(&pgf_TypeType) < 0) return MOD_ERROR_VAL; @@ -2670,6 +2673,9 @@ MOD_INIT(pgf) PyModule_AddObject(m, "ExprMeta", (PyObject *) &pgf_ExprMetaType); Py_INCREF(&pgf_ExprMetaType); + PyModule_AddObject(m, "ExprVar", (PyObject *) &pgf_ExprVarType); + Py_INCREF(&pgf_ExprVarType); + PyModule_AddObject(m, "Type", (PyObject *) &pgf_TypeType); Py_INCREF(&pgf_TypeType); diff --git a/src/runtime/python/test_suite.py b/src/runtime/python/test_suite.py index bbb170879..47e420327 100644 --- a/src/runtime/python/test_suite.py +++ b/src/runtime/python/test_suite.py @@ -227,6 +227,19 @@ def test_readExpr_lstr_str(): # ,TestCase (assertEqual "show expression 6" "z" (showExpr ["z","y","x"] (EVar 0))) # ,TestCase (assertEqual "show expression 7" "y" (showExpr ["z","y","x"] (EVar 1))) +# def test_readExpr_evar_equality_1(): +# assert pgf.readExpr("#0") == pgf.ExprVar() +# assert pgf.readExpr("#0") == pgf.ExprVar(0) + +# def test_readExpr_evar_equality_2(): +# assert pgf.readExpr("#42") == pgf.ExprVar(42) + +def test_readExpr_evar_str_1(): + assert str(pgf.ExprVar(0)) == "#0" + +def test_readExpr_evar_str_2(): + assert str(pgf.ExprVar(42)) == "#42" + # expressions: lambda abstractions # ,TestCase (assertEqual "show expression 8" "\\w->w" (showExpr ["z","y","x"] (EAbs Explicit "w" (EVar 0)))) @@ -247,6 +260,12 @@ def test_readExpr_emeta_1(): def test_readExpr_emeta_2(): assert pgf.readExpr("?42") == pgf.ExprMeta(42) +def test_readExpr_emeta_str_1(): + assert str(pgf.readExpr("?")) == "?" + +def test_readExpr_emeta_str_2(): + assert str(pgf.readExpr("?42")) == "?42" + # expressions: typed expressions # ,TestCase (assertEqual "show expression 18" "" (showExpr [] (ETyped (EFun "z") (DTyp [] "N" []))))