1
0
forked from GitHub/gf-core

Add Expr and ExprLit types to Python bindings. Seem to work for readExpr.

This commit is contained in:
John J. Camilleri
2021-09-08 16:03:54 +02:00
parent 44ee5718e9
commit 3b1907cd8c
7 changed files with 269 additions and 983 deletions

3
.gitignore vendored
View File

@@ -5,6 +5,7 @@
*.jar
*.gfo
*.pgf
*.ngf
debian/.debhelper
debian/debhelper-build-stamp
debian/gf
@@ -46,6 +47,8 @@ src/runtime/c/sg/.dirstamp
src/runtime/c/stamp-h1
src/runtime/java/.libs/
src/runtime/python/build/
src/runtime/python/__pycache__/
src/runtime/python/.pytest_cache/
.cabal-sandbox
cabal.sandbox.config
.stack-work

File diff suppressed because it is too large Load Diff

View File

@@ -17,11 +17,18 @@ typedef struct {
extern PyTypeObject pgf_TypeType;
// typedef struct {
// PyObject_HEAD
// PyObject* master;
// GuPool* pool;
// PgfExpr expr;
// } ExprObject;
typedef struct {
PyObject_HEAD
} ExprObject;
typedef struct {
PyObject_HEAD
int type; // 0 = int, 1 = float, 2 = str
PyObject *value; // depends on type
} ExprLitObject;
extern PyTypeObject pgf_ExprType;
extern PyTypeObject pgf_ExprLitType;
#endif // PYPGF_EXPR_H_

View File

@@ -16,56 +16,72 @@
PgfExpr eabs(PgfUnmarshaller *this, PgfBindType btype, PgfText *name, PgfExpr body)
{
PyErr_SetString(PyExc_NotImplementedError, "eabs not implemented");
return 0;
Py_RETURN_NOTIMPLEMENTED;
}
PgfExpr eapp(PgfUnmarshaller *this, PgfExpr fun, PgfExpr arg)
{
PyErr_SetString(PyExc_NotImplementedError, "eapp not implemented");
return 0;
Py_RETURN_NOTIMPLEMENTED;
}
PgfExpr elit(PgfUnmarshaller *this, PgfLiteral lit)
{
PyErr_SetString(PyExc_NotImplementedError, "elit not implemented");
return 0;
ExprLitObject *pyexpr = (ExprLitObject *)pgf_ExprLitType.tp_alloc(&pgf_ExprLitType, 0);
PyObject *pyobj = (PyObject *)lit;
pyexpr->value = pyobj;
if (PyLong_Check(pyobj)) {
pyexpr->type = 0;
} else if (PyFloat_Check(pyobj)) {
pyexpr->type = 1;
} else if (PyString_Check(pyobj)) {
pyexpr->type = 2;
} else {
PyErr_SetString(PyExc_TypeError, "unable to unmarshall literal");
return 0;
}
Py_INCREF(pyobj);
return (PgfExpr) pyexpr;
}
PgfExpr emeta(PgfUnmarshaller *this, PgfMetaId meta)
{
PyErr_SetString(PyExc_NotImplementedError, "emeta not implemented");
return 0;
Py_RETURN_NOTIMPLEMENTED;
}
PgfExpr efun(PgfUnmarshaller *this, PgfText *name)
{
PyErr_SetString(PyExc_NotImplementedError, "efun not implemented");
return 0;
Py_RETURN_NOTIMPLEMENTED;
}
PgfExpr evar(PgfUnmarshaller *this, int index)
{
PyErr_SetString(PyExc_NotImplementedError, "evar not implemented");
return 0;
Py_RETURN_NOTIMPLEMENTED;
}
PgfExpr etyped(PgfUnmarshaller *this, PgfExpr expr, PgfType typ)
{
PyErr_SetString(PyExc_NotImplementedError, "etyped not implemented");
return 0;
Py_RETURN_NOTIMPLEMENTED;
}
PgfExpr eimplarg(PgfUnmarshaller *this, PgfExpr expr)
{
PyErr_SetString(PyExc_NotImplementedError, "eimplarg not implemented");
return 0;
Py_RETURN_NOTIMPLEMENTED;
}
PgfLiteral lint(PgfUnmarshaller *this, size_t size, uintmax_t *v)
{
if (size > 1) {
PyErr_SetString(PyExc_NotImplementedError, "multi-part integers not implemented"); // TODO
return 0;
Py_RETURN_NOTIMPLEMENTED;
}
PyObject *i = PyLong_FromUnsignedLong(*v);
return (PgfLiteral) i;
@@ -160,17 +176,14 @@ object match_lit(PgfUnmarshaller *u, PgfLiteral lit)
if (PyLong_Check(pyobj)) {
uintmax_t i = PyLong_AsUnsignedLong(pyobj);
size_t size = 1; // TODO
return u->vtbl->lint(NULL, size, &i);
}
else if (PyFloat_Check(pyobj)) {
return u->vtbl->lint(u, size, &i);
} else if (PyFloat_Check(pyobj)) {
double d = PyFloat_AsDouble(pyobj);
return u->vtbl->lflt(NULL, d);
}
else if (PyString_Check(pyobj)) {
return u->vtbl->lflt(u, d);
} else if (PyString_Check(pyobj)) {
PgfText *t = PyString_AsPgfText(pyobj);
return u->vtbl->lstr(NULL, t);
}
else {
return u->vtbl->lstr(u, t);
} else {
PyErr_SetString(PyExc_TypeError, "unable to match on literal");
return 0;
}
@@ -179,14 +192,14 @@ object match_lit(PgfUnmarshaller *u, PgfLiteral lit)
object match_expr(PgfUnmarshaller *u, PgfExpr expr)
{
PyErr_SetString(PyExc_NotImplementedError, "match_expr not implemented");
return 0;
Py_RETURN_NOTIMPLEMENTED;
}
object match_type(PgfUnmarshaller *u, PgfType ty)
{
TypeObject *type = (TypeObject *)ty;
PySys_WriteStdout(">%s<\n", PyUnicode_AS_DATA(type->cat));
// PySys_WriteStdout(">%s<\n", PyUnicode_AS_DATA(type->cat));
int n_hypos = 0; //PyList_Size(type->hypos);
PgfTypeHypo *hypos = NULL; // TODO
@@ -196,7 +209,7 @@ object match_type(PgfUnmarshaller *u, PgfType ty)
int n_exprs = 0; //PyList_Size(type->exprs);
PgfExpr *exprs = NULL; // TODO
return u->vtbl->dtyp(NULL, n_hypos, hypos, cat, n_exprs, exprs);
return u->vtbl->dtyp(u, n_hypos, hypos, cat, n_exprs, exprs);
}
static PgfMarshallerVtbl marshallerVtbl =

View File

@@ -1740,7 +1740,7 @@ typedef struct {
// }
static PyObject*
PGF_repr(PGFObject *self)
PGF_str(PGFObject *self)
{
// GuPool* tmp_pool = gu_local_pool();
//
@@ -2369,7 +2369,7 @@ static PyTypeObject pgf_PGFType = {
0, /*tp_as_mapping*/
0, /*tp_hash */
0, /*tp_call*/
(reprfunc) PGF_repr, /*tp_str*/
(reprfunc) PGF_str, /*tp_str*/
0, /*tp_getattro*/
0, /*tp_setattro*/
0, /*tp_as_buffer*/
@@ -2476,35 +2476,27 @@ pgf_readNGF(PyObject *self, PyObject *args)
return py_pgf;
}
// static ExprObject*
// pgf_readExpr(PyObject *self, PyObject *args) {
// Py_ssize_t len;
// const uint8_t *buf;
// if (!PyArg_ParseTuple(args, "s#", &buf, &len))
// return NULL;
//
// ExprObject* pyexpr = (ExprObject*) pgf_ExprType.tp_alloc(&pgf_ExprType, 0);
// if (pyexpr == NULL)
// return NULL;
//
// GuPool* tmp_pool = gu_local_pool();
// GuIn* in = gu_data_in(buf, len, tmp_pool);
// GuExn* err = gu_new_exn(tmp_pool);
//
// pyexpr->pool = gu_new_pool();
// pyexpr->expr = pgf_read_expr(in, pyexpr->pool, tmp_pool, err);
// pyexpr->master = NULL;
//
// if (!gu_ok(err) || gu_variant_is_null(pyexpr->expr)) {
// PyErr_SetString(PGFError, "The expression cannot be parsed");
// Py_DECREF(pyexpr);
// gu_pool_free(tmp_pool);
// return NULL;
// }
//
// gu_pool_free(tmp_pool);
// return pyexpr;
// }
static ExprObject*
pgf_readExpr(PyObject *self, PyObject *args)
{
const char *s;
Py_ssize_t size;
if (!PyArg_ParseTuple(args, "s#", &s, &size))
return NULL;
PgfText *input = (PgfText *)PyMem_Malloc(sizeof(PgfText)+size+1);
memcpy(input->text, s, size+1);
input->size = size;
PgfExpr expr = pgf_read_expr(input, &unmarshaller);
PyMem_Free(input);
if (expr == 0) {
PyErr_SetString(PGFError, "expression cannot be parsed");
return NULL;
}
return (ExprObject *)expr;
}
static TypeObject *
pgf_readType(PyObject *self, PyObject *args)
@@ -2535,8 +2527,8 @@ static PyMethodDef module_methods[] = {
"Reads a PGF file into memory and stores the unpacked data in an NGF file"},
{"readNGF", (void*)pgf_readNGF, METH_VARARGS,
"Reads an NGF file into memory"},
// {"readExpr", (void*)pgf_readExpr, METH_VARARGS,
// "Parses a string as an abstract tree"},
{"readExpr", (void*)pgf_readExpr, METH_VARARGS,
"Parses a string as an abstract tree"},
{"readType", (void*)pgf_readType, METH_VARARGS,
"Parses a string as an abstract type"},
{NULL, NULL, 0, NULL} /* Sentinel */
@@ -2564,6 +2556,7 @@ MOD_INIT(pgf)
if (PyType_Ready(&pgf_PGFType) < 0)
return MOD_ERROR_VAL;
// if (PyType_Ready(&pgf_ConcrType) < 0)
// return MOD_ERROR_VAL;
//
@@ -2572,9 +2565,12 @@ MOD_INIT(pgf)
//
// if (PyType_Ready(&pgf_BINDType) < 0)
// return MOD_ERROR_VAL;
//
// if (PyType_Ready(&pgf_ExprType) < 0)
// return MOD_ERROR_VAL;
if (PyType_Ready(&pgf_ExprType) < 0)
return MOD_ERROR_VAL;
if (PyType_Ready(&pgf_ExprLitType) < 0)
return MOD_ERROR_VAL;
if (PyType_Ready(&pgf_TypeType) < 0)
return MOD_ERROR_VAL;
@@ -2601,8 +2597,11 @@ MOD_INIT(pgf)
// PyModule_AddObject(m, "TypeError", TypeError);
// Py_INCREF(TypeError);
// PyModule_AddObject(m, "Expr", (PyObject *) &pgf_ExprType);
// Py_INCREF(&pgf_ExprType);
PyModule_AddObject(m, "Expr", (PyObject *) &pgf_ExprType);
Py_INCREF(&pgf_ExprType);
PyModule_AddObject(m, "ExprLit", (PyObject *) &pgf_ExprLitType);
Py_INCREF(&pgf_ExprType);
PyModule_AddObject(m, "Type", (PyObject *) &pgf_TypeType);
Py_INCREF(&pgf_TypeType);

View File

@@ -10,7 +10,7 @@ if libraries==['']:
pgf_module = Extension('pgf',
sources = ['pypgf.c', 'marshaller.c', 'expr.c'],
extra_compile_args = ['-std=c99', '-Werror', '-Wno-comment'],
extra_compile_args = ['-std=c99', '-Werror', '-Wno-error=int-conversion', '-Wno-comment'],
include_dirs = includes,
library_dirs = libraries,
libraries = ['pgf'])

View File

@@ -64,7 +64,7 @@ def test_readNGF(NGF):
pgf.readNGF("./basic.ngf")
# TODO assert read actually worked
# abstract expressions
# abstract syntax
def test_abstractName(PGF):
assert PGF.abstractName == "basic"
@@ -84,6 +84,8 @@ def test_functionsByCat_2(PGF):
def test_functionsByCat_non_existant(PGF):
assert PGF.functionsByCat("X") == []
# types
def test_readType_invalid():
with pytest.raises(pgf.PGFError):
pgf.readType("->")
@@ -103,7 +105,7 @@ def test_readType_inequality_1():
def test_readType_inequality_2():
assert pgf.readType("A -> B") != pgf.readType("B->B")
# def test_Type_str_1():
# def test_readType_str():
# assert str(pgf.readType("A-> B")) == "A -> B"
def test_functionType_1(PGF):
@@ -123,6 +125,31 @@ 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
assert PGF.startCat == pgf.readType("S")
# expressions
def test_readExpr_invalid():
with pytest.raises(pgf.PGFError):
pgf.readExpr("->")
def test_readExpr_equality_int():
assert pgf.readExpr("123") == pgf.readExpr("123")
def test_readExpr_inequality_int():
assert pgf.readExpr("123") != pgf.readExpr("456")
def test_readExpr_equality_float():
assert pgf.readExpr("3.142") == pgf.readExpr("3.142")
def test_readExpr_inequality_float():
assert pgf.readExpr("3.142") != pgf.readExpr("3")
def test_readExpr_equality_string():
assert pgf.readExpr("\"abc\"") == pgf.readExpr("\"abc\"")
def test_readExpr_inequality_string():
assert pgf.readExpr("\"abc\"") != pgf.readExpr("\"def\"")
# def test_readExpr_str_int():
# assert str(pgf.readExpr("123")) == "123"