forked from GitHub/gf-core
Working readType, functionType, unmarshaller for types (except exprs) in Python bindings
This commit is contained in:
28
src/runtime/python/compat.h
Normal file
28
src/runtime/python/compat.h
Normal 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_
|
||||
@@ -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 */
|
||||
};
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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[] = {
|
||||
|
||||
@@ -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()
|
||||
|
||||
Reference in New Issue
Block a user