Add variable expressions

This commit is contained in:
John J. Camilleri
2021-09-13 22:29:23 +02:00
parent cf7673525f
commit e78e9102be
5 changed files with 141 additions and 11 deletions

View File

@@ -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)
{

View File

@@ -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_

View File

@@ -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;
}
}

View File

@@ -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);

View File

@@ -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" "<z : N>" (showExpr [] (ETyped (EFun "z") (DTyp [] "N" []))))