1
0
forked from GitHub/gf-core

Working readType, functionType, unmarshaller for types (except exprs) in Python bindings

This commit is contained in:
John J. Camilleri
2021-09-06 14:06:57 +02:00
parent 9a2d2b345d
commit a8efc61579
6 changed files with 133 additions and 116 deletions

View File

@@ -0,0 +1,28 @@
#ifndef PYPGF_COMPAT_H_
#define PYPGF_COMPAT_H_
#if PY_MAJOR_VERSION >= 3
// #define PyIntObject PyLongObject
// #define PyInt_Type PyLong_Type
// #define PyInt_Check(op) PyLong_Check(op)
// #define PyInt_CheckExact(op) PyLong_CheckExact(op)
// #define PyInt_FromString PyLong_FromString
// #define PyInt_FromUnicode PyLong_FromUnicode
// #define PyInt_FromLong PyLong_FromLong
// #define PyInt_FromSize_t PyLong_FromSize_t
// #define PyInt_FromSsize_t PyLong_FromSsize_t
// #define PyInt_AsLong PyLong_AsLong
// #define PyInt_AS_LONG PyLong_AS_LONG
// #define PyInt_AsSsize_t PyLong_AsSsize_t
// #define PyInt_AsUnsignedLongMask PyLong_AsUnsignedLongMask
// #define PyInt_AsUnsignedLongLongMask PyLong_AsUnsignedLongLongMask
#define PyStringObject PyUnicodeObject
// #define PyString_Check PyUnicode_Check
#define PyString_FromStringAndSize PyUnicode_FromStringAndSize
// #define PyString_FromFormat PyUnicode_FromFormat
// #define PyString_Concat(ps,s) {PyObject* tmp = *(ps); *(ps) = PyUnicode_Concat(tmp,s); Py_DECREF(tmp);}
#define PyString_Compare PyUnicode_Compare
#endif
#endif // PYPGF_COMPAT_H_

View File

@@ -2,7 +2,7 @@
#include <Python.h>
#include <stdbool.h>
#include "expr.h"
#include "./expr.h"
// static ExprObject*
// Expr_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
@@ -665,36 +665,28 @@
// ----------------------------------------------------------------------------
static TypeObject*
Type_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
{
TypeObject* self = (TypeObject *)type->tp_alloc(type, 0);
if (self != NULL) {
self->master = NULL;
// self->pool = NULL;
// self->type = NULL;
self->cat = NULL;
}
// static TypeObject*
// Type_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
// {
// TypeObject* self = (TypeObject *)type->tp_alloc(type, 0);
// if (self != NULL) {
// self->hypos = NULL;
// self->cat = NULL;
// self->exprs = NULL;
// }
//
// return self;
// }
return self;
}
// static void
// Type_dealloc(TypeObject *self)
// {
// Py_TYPE(self)->tp_free((PyObject*)self);
// }
static void
Type_dealloc(TypeObject* self)
{
if (self->master != NULL) {
Py_DECREF(self->master);
}
// if (self->pool != NULL) {
// gu_pool_free(self->pool);
// }
Py_TYPE(self)->tp_free((PyObject*)self);
}
static int
Type_init(TypeObject *self, PyObject *args, PyObject *kwds)
{
// static int
// Type_init(TypeObject *self, PyObject *args, PyObject *kwds)
// {
// PyObject* py_hypos;
// const char* catname_s;
// PyObject* py_exprs;
@@ -813,9 +805,9 @@ Type_init(TypeObject *self, PyObject *args, PyObject *kwds)
//
// self->type->exprs[i] = ((ExprObject*) obj)->expr;
// }
return 0;
}
//
// return 0;
// }
static PyObject *
Type_repr(TypeObject *self)
@@ -835,29 +827,43 @@ Type_repr(TypeObject *self)
// return pystr;
PyErr_SetString(PyExc_TypeError, "Type_repr: not implemented");
return NULL;
}
bool pgfTextEqual(PgfText *t1, PgfText *t2) {
if (t1->size != t2->size) return false;
for (size_t i = 0; i < t1->size; i++) {
if (t1->text[i] != t2->text[i]) return false;
}
return true;
Py_RETURN_NOTIMPLEMENTED;
}
static PyObject *
Type_richcompare(TypeObject *t1, TypeObject *t2, int op)
{
bool cmp = pgfTextEqual(t1->cat, t2->cat);
bool same = false;
if (PyString_Compare(t1->cat, t2->cat) != 0) goto done;
if (PyList_Size(t1->hypos) != PyList_Size(t2->hypos)) goto done;
for (Py_ssize_t n = 0; n < PyList_Size(t1->hypos); n++) {
PyObject *h1 = PyList_GetItem(t1->hypos, n);
PyObject *h2 = PyList_GetItem(t2->hypos, n);
if (PyTuple_GetItem(h1, 0) != PyTuple_GetItem(h2, 0)) goto done;
if (PyString_Compare(PyTuple_GetItem(h1, 1), PyTuple_GetItem(h2, 1)) != 0) goto done;
TypeObject *ht1 = (TypeObject *)PyTuple_GetItem(h1, 2);
TypeObject *ht2 = (TypeObject *)PyTuple_GetItem(h2, 2);
if (Type_richcompare(ht1, ht2, Py_EQ) != Py_True) goto done;
}
if (PyList_Size(t1->exprs) != PyList_Size(t2->exprs)) goto done;
// for (Py_ssize_t n = 0; n < PyList_Size(t1->exprs); n++) {
// ExprObject *e1 = PyList_GetItem(t1->exprs, n);
// ExprObject *e2 = PyList_GetItem(t2->exprs, n);
// if (Expr_richcompare(e1, e2, Py_EQ) != Py_True) goto done; // TODO
// }
same = true;
done:
if (op == Py_EQ) {
if (cmp) Py_RETURN_TRUE; else Py_RETURN_FALSE;
if (same) Py_RETURN_TRUE; else Py_RETURN_FALSE;
} else if (op == Py_NE) {
if (cmp) Py_RETURN_FALSE; else Py_RETURN_TRUE;
if (same) Py_RETURN_FALSE; else Py_RETURN_TRUE;
} else {
PyErr_SetString(PyExc_TypeError, "comparison operation not supported");
return NULL;
Py_RETURN_NOTIMPLEMENTED;
}
}
@@ -1044,7 +1050,7 @@ PyTypeObject pgf_TypeType = {
"pgf.Type", /*tp_name*/
sizeof(TypeObject), /*tp_basicsize*/
0, /*tp_itemsize*/
(destructor) Type_dealloc, /*tp_dealloc*/
0, //(destructor) Type_dealloc, /*tp_dealloc*/
0, /*tp_print*/
0, /*tp_getattr*/
0, /*tp_setattr*/
@@ -1075,7 +1081,7 @@ PyTypeObject pgf_TypeType = {
0, /*tp_descr_get */
0, /*tp_descr_set */
0, /*tp_dictoffset */
(initproc) Type_init, /*tp_init */
0, //(initproc) Type_init, /*tp_init */
0, /*tp_alloc */
(newfunc) Type_new, /*tp_new */
0, //(newfunc) Type_new, /*tp_new */
};

View File

@@ -6,12 +6,13 @@
#include <pgf/pgf.h>
#include "./compat.h"
typedef struct {
PyObject_HEAD
PyObject* master;
// GuPool* pool;
// PgfType* type;
PgfText *cat;
PyObject *hypos; // PyListObject of PyTupleObject: (bind_type: int, cid: string, type: TypeObject)
PyObject *cat; // PyStringObject
PyObject *exprs; // PyListObject of ExprObject
} TypeObject;
extern PyTypeObject pgf_TypeType;

View File

@@ -1,7 +1,9 @@
// #define PY_SSIZE_T_CLEAN
// #include <Python.h>
#define PY_SSIZE_T_CLEAN
#include <Python.h>
#include <pgf/pgf.h>
#include "./compat.h"
#include "./expr.h"
/* The PgfUnmarshaller structure tells the runtime how to create
@@ -71,12 +73,22 @@ PgfLiteral lstr(PgfUnmarshaller *this, PgfText *v)
PgfType dtyp(PgfUnmarshaller *this, int n_hypos, PgfTypeHypo *hypos, PgfText *cat, int n_exprs, PgfExpr *exprs)
{
PgfText *catname = (PgfText*) malloc(sizeof(PgfText)+cat->size+1);
memcpy(catname->text, cat->text, cat->size+1);
catname->size = cat->size;
TypeObject *pytype = (TypeObject *)pgf_TypeType.tp_alloc(&pgf_TypeType, 0);
TypeObject *pytype = (TypeObject*) pgf_TypeType.tp_alloc(&pgf_TypeType, 0);
pytype->cat = catname;
pytype->hypos = PyList_New(0);
for (int i = 0; i < n_hypos; i++) {
PgfTypeHypo *hypo = hypos + i;
PyObject *tup = PyTuple_New(3);
PyTuple_SetItem(tup, 0, PyLong_FromLong(hypo->bind_type == PGF_BIND_TYPE_EXPLICIT ? 0 : 1)); // TODO
PyTuple_SetItem(tup, 1, PyString_FromStringAndSize(hypo->cid->text, hypo->cid->size));
PyTuple_SetItem(tup, 2, (PyObject *)hypo->type);
Py_INCREF(hypo->type);
PyList_Append(pytype->hypos, tup);
}
pytype->cat = PyString_FromStringAndSize(cat->text, cat->size);
pytype->exprs = PyList_New(0);
return (PgfType) pytype;
}

View File

@@ -3,34 +3,11 @@
#include "structmember.h"
#include <pgf/pgf.h>
#include "./compat.h"
#include "./expr.h"
#include "./marshaller.h"
#if PY_MAJOR_VERSION >= 3
#define PyIntObject PyLongObject
#define PyInt_Type PyLong_Type
#define PyInt_Check(op) PyLong_Check(op)
#define PyInt_CheckExact(op) PyLong_CheckExact(op)
#define PyInt_FromString PyLong_FromString
#define PyInt_FromUnicode PyLong_FromUnicode
#define PyInt_FromLong PyLong_FromLong
#define PyInt_FromSize_t PyLong_FromSize_t
#define PyInt_FromSsize_t PyLong_FromSsize_t
#define PyInt_AsLong PyLong_AsLong
#define PyInt_AS_LONG PyLong_AS_LONG
#define PyInt_AsSsize_t PyLong_AsSsize_t
#define PyInt_AsUnsignedLongMask PyLong_AsUnsignedLongMask
#define PyInt_AsUnsignedLongLongMask PyLong_AsUnsignedLongLongMask
#endif
#if PY_MAJOR_VERSION >= 3
#define PyString_Check PyUnicode_Check
#define PyString_FromStringAndSize PyUnicode_FromStringAndSize
#define PyString_FromFormat PyUnicode_FromFormat
#define PyString_Concat(ps,s) {PyObject* tmp = *(ps); *(ps) = PyUnicode_Concat(tmp,s); Py_DECREF(tmp);}
#endif
static PyObject* PGFError;
static PyObject *PGFError;
// static PyObject* ParseError;
@@ -38,7 +15,7 @@ static PyObject* PGFError;
typedef struct {
PyObject_HEAD
PgfPGF* pgf;
PgfPGF *pgf;
} PGFObject;
// typedef struct IterObject {
@@ -1983,33 +1960,25 @@ PGF_functionsByCat(PGFObject* self, PyObject *args)
return functions;
}
static TypeObject*
PGF_functionType(PGFObject* self, PyObject *args)
static TypeObject *
PGF_functionType(PGFObject *self, PyObject *args)
{
const char* s;
const char *s;
Py_ssize_t size;
if (!PyArg_ParseTuple(args, "s#", &s, &size))
return NULL;
PgfText* funname = (PgfText*) alloca(sizeof(PgfText)+size+1);
PgfText *funname = (PgfText *)alloca(sizeof(PgfText)+size+1);
memcpy(funname->text, s, size+1);
funname->size = size;
PgfType type = pgf_function_type(self->pgf, funname, &unmarshaller);
// if (type == NULL) {
// PyErr_Format(PyExc_KeyError, "Function '%s' is not defined", funname->text);
// return NULL;
// }
//
// TypeObject* pytype = (TypeObject*) pgf_TypeType.tp_alloc(&pgf_TypeType, 0);
// if (pytype == NULL)
// return NULL;
// // pytype->pool = NULL;
// pytype->type = &type;
// pytype->master = (PyObject*) self;
// Py_XINCREF(self);
// return pytype;
return (TypeObject*) type;
if (type == 0) {
PyErr_Format(PyExc_KeyError, "Function '%s' is not defined", funname->text);
return NULL;
}
return (TypeObject *)type;
}
// static IterObject*
@@ -2525,15 +2494,15 @@ pgf_readNGF(PyObject *self, PyObject *args)
// return pyexpr;
// }
static TypeObject*
static TypeObject *
pgf_readType(PyObject *self, PyObject *args)
{
const char* s;
const char *s;
Py_ssize_t size;
if (!PyArg_ParseTuple(args, "s#", &s, &size))
return NULL;
PgfText* input = (PgfText*) alloca(sizeof(PgfText)+size+1);
PgfText *input = (PgfText *)alloca(sizeof(PgfText)+size+1);
memcpy(input->text, s, size+1);
input->size = size;
@@ -2543,16 +2512,7 @@ pgf_readType(PyObject *self, PyObject *args)
return NULL;
}
// TypeObject* pytype = (TypeObject*) pgf_TypeType.tp_alloc(&pgf_TypeType, 0);
// if (pytype == NULL)
// return NULL;
// // pytype->pool = NULL;
// pytype->type = &type;
// pytype->master = (PyObject*) self;
// Py_XINCREF(self);
// return pytype;
return (TypeObject*) type;
return (TypeObject *)type;
}
static PyMethodDef module_methods[] = {

View File

@@ -94,6 +94,9 @@ def test_readType_equality_1():
def test_readType_equality_2():
assert pgf.readType("A -> B") == pgf.readType("A->B")
def test_readType_equality_3():
assert pgf.readType("A -> B -> C") == pgf.readType("A->B -> C")
def test_readType_inequality_1():
assert pgf.readType("A") != pgf.readType("B")
@@ -109,6 +112,13 @@ def test_functionType_2(PGF):
def test_functionType_3(PGF):
assert PGF.functionType("c") == pgf.readType("N -> S")
def test_functionType_non_existant(PGF):
with pytest.raises(KeyError):
assert PGF.functionType("cbx")
def test_functionType_wrong(PGF):
assert PGF.functionType("c") != pgf.readType("N -> S -> X")
def test_startCat(PGF):
with pytest.raises(pgf.PGFError):
PGF.startCat()