Add ExprFun to Python bindings

This commit is contained in:
John J. Camilleri
2021-09-14 15:07:03 +02:00
parent 05813384e0
commit 6ebb8e5fda
6 changed files with 158 additions and 47 deletions

View File

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

View File

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

View File

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

View File

@@ -8,6 +8,8 @@
PgfText *PyUnicode_AsPgfText(PyObject *pystr);
PyObject *PyUnicode_FromPgfText(PgfText *text);
extern PgfUnmarshaller unmarshaller;
extern PgfMarshaller marshaller;

View File

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

View File

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