diff --git a/src/runtime/python/ffi.h b/src/runtime/python/ffi.h index c8b140c02..751cd74f8 100644 --- a/src/runtime/python/ffi.h +++ b/src/runtime/python/ffi.h @@ -1,5 +1,5 @@ -#ifndef PYPGF_MARSHALLER_H_ -#define PYPGF_MARSHALLER_H_ +#ifndef PYPGF_FFI_H_ +#define PYPGF_FFI_H_ #define PY_SSIZE_T_CLEAN #include @@ -21,4 +21,4 @@ PyObject *PyUnicode_FromPgfText(PgfText *text); extern PgfUnmarshaller unmarshaller; extern PgfMarshaller marshaller; -#endif // PYPGF_MARSHALLER_H_ +#endif // PYPGF_FFI_H_ diff --git a/src/runtime/python/pypgf.c b/src/runtime/python/pypgf.c index b53820a7d..dc8baa233 100644 --- a/src/runtime/python/pypgf.c +++ b/src/runtime/python/pypgf.c @@ -1710,16 +1710,16 @@ // }; static void -PGF_dealloc(PGFObject* self) +PGF_dealloc(PGFObject *self) { pgf_free(self->db); - Py_TYPE(self)->tp_free((PyObject*)self); + Py_TYPE(self)->tp_free((PyObject *)self); } typedef struct { PgfItor fn; - PGFObject* grammar; - void* collection; + PGFObject *grammar; + void *collection; } PyPGFClosure; // static void @@ -1757,11 +1757,11 @@ typedef struct { // return NULL; // } -static PyObject* +static PyObject * PGF_getAbstractName(PGFObject *self, void *closure) { PgfExn err; - PgfText* txt = pgf_abstract_name(self->db, self->revision, &err); + PgfText *txt = pgf_abstract_name(self->db, self->revision, &err); if (handleError(err) != PGF_EXN_NONE) { return NULL; @@ -1837,12 +1837,12 @@ PGF_getAbstractName(PGFObject *self, void *closure) // } static void -pgf_collect_cats(PgfItor* fn, PgfText* key, void* value, PgfExn *err) +pgf_collect_cats(PgfItor *fn, PgfText *key, void *value, PgfExn *err) { - PgfText* name = key; - PyPGFClosure* clo = (PyPGFClosure*) fn; + PgfText *name = key; + PyPGFClosure *clo = (PyPGFClosure*) fn; - PyObject* py_name = PyUnicode_FromStringAndSize(name->text, name->size); + PyObject *py_name = PyUnicode_FromStringAndSize(name->text, name->size); if (py_name == NULL) { err->type = PGF_EXN_OTHER_ERROR; err->msg = "unable to create string from category"; @@ -1856,10 +1856,10 @@ pgf_collect_cats(PgfItor* fn, PgfText* key, void* value, PgfExn *err) } } -static PyObject* +static PyObject * PGF_getCategories(PGFObject *self, void *closure) { - PyObject* categories = PyList_New(0); + PyObject *categories = PyList_New(0); if (categories == NULL) return NULL; @@ -1874,7 +1874,7 @@ PGF_getCategories(PGFObject *self, void *closure) return categories; } -static PyObject* +static PyObject * PGF_categoryContext(PGFObject *self, PyObject *args) { const char *s; @@ -1937,12 +1937,12 @@ PGF_getStartCat(PGFObject *self, void *closure) } static void -pgf_collect_funs(PgfItor* fn, PgfText* key, void* value, PgfExn *err) +pgf_collect_funs(PgfItor *fn, PgfText *key, void *value, PgfExn *err) { - PgfText* name = key; - PyPGFClosure* clo = (PyPGFClosure*) fn; + PgfText *name = key; + PyPGFClosure *clo = (PyPGFClosure*) fn; - PyObject* py_name = PyUnicode_FromStringAndSize(name->text, name->size); + PyObject *py_name = PyUnicode_FromStringAndSize(name->text, name->size); if (py_name == NULL) { err->type = PGF_EXN_OTHER_ERROR; err->msg = "unable to create string from function"; @@ -1955,10 +1955,10 @@ pgf_collect_funs(PgfItor* fn, PgfText* key, void* value, PgfExn *err) } } -static PyObject* +static PyObject * PGF_getFunctions(PGFObject *self, void *closure) { - PyObject* functions = PyList_New(0); + PyObject *functions = PyList_New(0); if (functions == NULL) return NULL; @@ -2389,18 +2389,8 @@ static PyMethodDef PGF_methods[] = { "Checks whether a function is a constructor" }, - - {"createFunction", (PyCFunction)PGF_createFunction, METH_VARARGS, - "Create function" - }, - {"dropFunction", (PyCFunction)PGF_dropFunction, METH_VARARGS, - "Drop function" - }, - {"createCategory", (PyCFunction)PGF_createCategory, METH_VARARGS, - "Create category" - }, - {"dropCategory", (PyCFunction)PGF_dropCategory, METH_VARARGS, - "Drop category" + {"newTransaction", (PyCFunction)PGF_newTransaction, METH_VARARGS, + "Create new transaction" }, // {"generateAll", (PyCFunction)PGF_generateAll, METH_VARARGS | METH_KEYWORDS, @@ -2474,14 +2464,14 @@ static PyTypeObject pgf_PGFType = { // ---------------------------------------------------------------------------- -static PGFObject* +static PGFObject * pgf_readPGF(PyObject *self, PyObject *args) { const char *fpath; if (!PyArg_ParseTuple(args, "s", &fpath)) return NULL; - PGFObject* py_pgf = (PGFObject*) pgf_PGFType.tp_alloc(&pgf_PGFType, 0); + PGFObject *py_pgf = (PGFObject *)pgf_PGFType.tp_alloc(&pgf_PGFType, 0); // Read the PGF grammar. PgfExn err; @@ -2494,7 +2484,7 @@ pgf_readPGF(PyObject *self, PyObject *args) return py_pgf; } -static PGFObject* +static PGFObject * pgf_bootNGF(PyObject *self, PyObject *args) { const char *fpath; // pgf @@ -2502,7 +2492,7 @@ pgf_bootNGF(PyObject *self, PyObject *args) if (!PyArg_ParseTuple(args, "ss", &fpath, &npath)) return NULL; - PGFObject* py_pgf = (PGFObject*) pgf_PGFType.tp_alloc(&pgf_PGFType, 0); + PGFObject *py_pgf = (PGFObject *)pgf_PGFType.tp_alloc(&pgf_PGFType, 0); // Read the PGF grammar. PgfExn err; @@ -2515,14 +2505,14 @@ pgf_bootNGF(PyObject *self, PyObject *args) return py_pgf; } -static PGFObject* +static PGFObject * pgf_readNGF(PyObject *self, PyObject *args) { const char *fpath; if (!PyArg_ParseTuple(args, "s", &fpath)) return NULL; - PGFObject* py_pgf = (PGFObject*) pgf_PGFType.tp_alloc(&pgf_PGFType, 0); + PGFObject *py_pgf = (PGFObject *)pgf_PGFType.tp_alloc(&pgf_PGFType, 0); // Read the NGF grammar. PgfExn err; @@ -2535,7 +2525,7 @@ pgf_readNGF(PyObject *self, PyObject *args) return py_pgf; } -static PGFObject* +static PGFObject * pgf_newNGF(PyObject *self, PyObject *args) { const char *s; @@ -2548,7 +2538,7 @@ pgf_newNGF(PyObject *self, PyObject *args) memcpy(absname->text, s, size+1); absname->size = size; - PGFObject* py_pgf = (PGFObject*) pgf_PGFType.tp_alloc(&pgf_PGFType, 0); + PGFObject *py_pgf = (PGFObject *)pgf_PGFType.tp_alloc(&pgf_PGFType, 0); // Read the NGF grammar. PgfExn err; @@ -2769,9 +2759,15 @@ MOD_INIT(pgf) if (PyType_Ready(&pgf_PGFType) < 0) return MOD_ERROR_VAL; + if (PyType_Ready(&pgf_TransactionType) < 0) + return MOD_ERROR_VAL; + // if (PyType_Ready(&pgf_ConcrType) < 0) // return MOD_ERROR_VAL; // + // if (PyType_Ready(&pgf_IterType) < 0) + // return MOD_ERROR_VAL; + // // if (PyType_Ready(&pgf_BracketType) < 0) // return MOD_ERROR_VAL; // @@ -2808,9 +2804,6 @@ MOD_INIT(pgf) if (PyType_Ready(&pgf_TypeType) < 0) return MOD_ERROR_VAL; - // if (PyType_Ready(&pgf_IterType) < 0) - // return MOD_ERROR_VAL; - MOD_DEF(m, "pgf", "The Runtime for Portable Grammar Format in Python", module_methods); if (m == NULL) return MOD_ERROR_VAL; @@ -2829,6 +2822,24 @@ MOD_INIT(pgf) // PyModule_AddObject(m, "TypeError", TypeError); // Py_INCREF(TypeError); + PyModule_AddObject(m, "PGF", (PyObject *) &pgf_PGFType); + Py_INCREF(&pgf_PGFType); + + PyModule_AddObject(m, "Transaction", (PyObject *) &pgf_TransactionType); + Py_INCREF(&pgf_TransactionType); + + // PyModule_AddObject(m, "Concr", (PyObject *) &pgf_ConcrType); + // Py_INCREF(&pgf_ConcrType); + // + // PyModule_AddObject(m, "Iter", (PyObject *) &pgf_IterType); + // Py_INCREF(&pgf_IterType); + // + // PyModule_AddObject(m, "Bracket", (PyObject *) &pgf_BracketType); + // Py_INCREF(&pgf_BracketType); + // + // PyModule_AddObject(m, "BIND", (PyObject *) &pgf_BINDType); + // Py_INCREF(&pgf_BINDType); + PyModule_AddObject(m, "Expr", (PyObject *) &pgf_ExprType); Py_INCREF(&pgf_ExprType); @@ -2859,21 +2870,6 @@ MOD_INIT(pgf) PyModule_AddObject(m, "Type", (PyObject *) &pgf_TypeType); Py_INCREF(&pgf_TypeType); - PyModule_AddObject(m, "PGF", (PyObject *) &pgf_PGFType); - Py_INCREF(&pgf_PGFType); - - // PyModule_AddObject(m, "Concr", (PyObject *) &pgf_ConcrType); - // Py_INCREF(&pgf_ConcrType); - // - // PyModule_AddObject(m, "Iter", (PyObject *) &pgf_IterType); - // Py_INCREF(&pgf_IterType); - // - // PyModule_AddObject(m, "Bracket", (PyObject *) &pgf_BracketType); - // Py_INCREF(&pgf_BracketType); - // - // PyModule_AddObject(m, "BIND", (PyObject *) &pgf_BINDType); - // Py_INCREF(&pgf_BINDType); - PyModule_AddIntConstant(m, "BIND_TYPE_EXPLICIT", 0); PyModule_AddIntConstant(m, "BIND_TYPE_IMPLICIT", 1); diff --git a/src/runtime/python/tests/test_basic.py b/src/runtime/python/tests/test_basic.py index fdee52434..161571e32 100644 --- a/src/runtime/python/tests/test_basic.py +++ b/src/runtime/python/tests/test_basic.py @@ -1,81 +1,81 @@ import os import pytest -import pgf +from pgf import * # readPGF @pytest.fixture(scope="module") def PGF(): - return pgf.readPGF("../haskell/tests/basic.pgf") + return readPGF("../haskell/tests/basic.pgf") def test_readPGF_non_existant(): with pytest.raises(FileNotFoundError): - pgf.readPGF("../haskell/tests/abc.pgf") + readPGF("../haskell/tests/abc.pgf") def test_readPGF_GF(): - with pytest.raises(pgf.PGFError): - pgf.readPGF("../haskell/tests/basic.gf") + with pytest.raises(PGFError): + readPGF("../haskell/tests/basic.gf") def test_readPGF_NGF(NGF): - with pytest.raises(pgf.PGFError): - pgf.readPGF("./basic.ngf") + with pytest.raises(PGFError): + readPGF("./basic.ngf") # bootNGF @pytest.fixture(scope="module") def NGF(): - ngf = pgf.bootNGF("../haskell/tests/basic.pgf", "./basic.ngf") + ngf = bootNGF("../haskell/tests/basic.pgf", "./basic.ngf") yield ngf os.remove("./basic.ngf") def test_bootNGF_non_existant(): with pytest.raises(FileNotFoundError): - pgf.bootNGF("../haskell/tests/abc.pgf", "./abc.ngf") + bootNGF("../haskell/tests/abc.pgf", "./abc.ngf") def test_bootNGF_GF(): - with pytest.raises(pgf.PGFError): - pgf.bootNGF("../haskell/tests/basic.gf", "./abc.ngf") + with pytest.raises(PGFError): + bootNGF("../haskell/tests/basic.gf", "./abc.ngf") def test_bootNGF_NGF(NGF): - with pytest.raises(pgf.PGFError): - pgf.bootNGF("./basic.ngf", "./abc.ngf") + with pytest.raises(PGFError): + bootNGF("./basic.ngf", "./abc.ngf") def test_bootNGF_existing(NGF): with pytest.raises(FileExistsError): - pgf.bootNGF("../haskell/tests/basic.pgf", "./basic.ngf") + bootNGF("../haskell/tests/basic.pgf", "./basic.ngf") # readNGF def test_readNGF_non_existant(): with pytest.raises(FileNotFoundError): - pgf.readNGF("./abc.ngf") + readNGF("./abc.ngf") def test_readNGF_GF(): - with pytest.raises(pgf.PGFError): - pgf.readNGF("../haskell/tests/basic.gf") + with pytest.raises(PGFError): + readNGF("../haskell/tests/basic.gf") def test_readNGF_PGF(): - with pytest.raises(pgf.PGFError): - pgf.readNGF("../haskell/tests/basic.pgf") + with pytest.raises(PGFError): + readNGF("../haskell/tests/basic.pgf") def test_readNGF(NGF): - PGF = pgf.readNGF("./basic.ngf") + PGF = readNGF("./basic.ngf") assert len(PGF.categories) > 0 # newNGF def test_newNGF_file(NGF): - PGF = pgf.newNGF("empty", "./empty.ngf") + PGF = newNGF("empty", "./empty.ngf") assert len(PGF.categories) == 0 os.remove("./empty.ngf") # cleanup def test_newNGF_memory(NGF): - PGF = pgf.newNGF("empty") + PGF = newNGF("empty") assert len(PGF.categories) == 0 def test_newNGF_existing(NGF): with pytest.raises(FileExistsError): - pgf.newNGF("empty", "./basic.ngf") + newNGF("empty", "./basic.ngf") # abstract syntax @@ -109,7 +109,7 @@ def test_categoryContext_3(PGF): tup = cxt[0] assert tup[0] == 0 # explicit assert tup[1] == "_" # cid - assert tup[2] == pgf.readType("N") + assert tup[2] == readType("N") def test_categoryContext_4(PGF): assert PGF.categoryContext("X") == None @@ -129,293 +129,293 @@ def test_functionIsConstructor_4(PGF): # types def test_readType_invalid(): - with pytest.raises(pgf.PGFError): - pgf.readType("->") + with pytest.raises(PGFError): + readType("->") def test_readType_equality_1(): - assert pgf.readType("A") == pgf.readType("A") + assert readType("A") == readType("A") def test_readType_equality_2(): - assert pgf.readType("A -> B") == pgf.readType("A->B") + assert readType("A -> B") == readType("A->B") def test_readType_equality_3(): - assert pgf.readType("A -> B -> C") == pgf.readType("A->B -> C") + assert readType("A -> B -> C") == readType("A->B -> C") def test_readType_inequality_1(): - assert pgf.readType("A") != pgf.readType("B") + assert readType("A") != readType("B") def test_readType_inequality_2(): - assert pgf.readType("A -> B") != pgf.readType("B->B") + assert readType("A -> B") != readType("B->B") def test_readType_str(): - assert str(pgf.readType("A-> BÄ->C")) == "A -> BÄ -> C" + assert str(readType("A-> BÄ->C")) == "A -> BÄ -> C" def test_functionType_1(PGF): - assert PGF.functionType("z") == pgf.readType("N") + assert PGF.functionType("z") == readType("N") def test_functionType_2(PGF): - assert PGF.functionType("s") == pgf.readType("N->N") + assert PGF.functionType("s") == readType("N->N") def test_functionType_3(PGF): - assert PGF.functionType("c") == pgf.readType("N -> S") + assert PGF.functionType("c") == 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") + assert PGF.functionType("c") != readType("N -> S -> X") def test_startCat(PGF): - assert PGF.startCat == pgf.readType("S") + assert PGF.startCat == readType("S") def test_showType_1(PGF): - type = pgf.Type([], "N", []) - assert pgf.showType([], type) == "N" + type = Type([], "N", []) + assert showType([], type) == "N" def test_showType_2(PGF): - type = pgf.Type([pgf.mkHypo(pgf.Type([], "N", []))], "N", []) - assert pgf.showType([], type) == "N -> N" + type = Type([mkHypo(Type([], "N", []))], "N", []) + assert showType([], type) == "N -> N" def test_showType_3(PGF): - type = pgf.Type([pgf.mkHypo(pgf.Type([pgf.mkHypo(pgf.Type([], "N", []))], "N", []))], "N", []) - assert pgf.showType([], type) == "(N -> N) -> N" + type = Type([mkHypo(Type([mkHypo(Type([], "N", []))], "N", []))], "N", []) + assert showType([], type) == "(N -> N) -> N" def test_showType_4(PGF): - type = pgf.Type([pgf.mkDepHypo("x", pgf.Type([], "N", []))], "P", [pgf.ExprVar(0)]) - assert pgf.showType([], type) == "(x : N) -> P x" + type = Type([mkDepHypo("x", Type([], "N", []))], "P", [ExprVar(0)]) + assert showType([], type) == "(x : N) -> P x" def test_showType_5(PGF): - type = pgf.Type([pgf.mkDepHypo("f", pgf.Type([pgf.mkHypo(pgf.Type([], "N", []))], "N", []))], "P", [pgf.ExprApp(pgf.ExprVar(0), pgf.ExprFun("z"))]) - assert pgf.showType([], type) == "(f : N -> N) -> P (f z)" + type = Type([mkDepHypo("f", Type([mkHypo(Type([], "N", []))], "N", []))], "P", [ExprApp(ExprVar(0), ExprFun("z"))]) + assert showType([], type) == "(f : N -> N) -> P (f z)" def test_showType_6(PGF): - type = pgf.Type([pgf.mkDepHypo("f", pgf.Type([pgf.mkHypo(pgf.Type([], "N", []))], "N", []))], "P", [pgf.ExprApp(pgf.ExprVar(0), pgf.ExprVar(1))]) - assert pgf.showType(["n"], type) == "(f : N -> N) -> P (f n)" + type = Type([mkDepHypo("f", Type([mkHypo(Type([], "N", []))], "N", []))], "P", [ExprApp(ExprVar(0), ExprVar(1))]) + assert showType(["n"], type) == "(f : N -> N) -> P (f n)" def test_showType_7(PGF): - type = pgf.Type([pgf.mkImplHypo("f", pgf.Type([pgf.mkHypo(pgf.Type([], "N", []))], "N", []))], "P", [pgf.ExprApp(pgf.ExprVar(0), pgf.ExprVar(1))]) - assert pgf.showType(["n"], type) == "({f} : N -> N) -> P (f n)" + type = Type([mkImplHypo("f", Type([mkHypo(Type([], "N", []))], "N", []))], "P", [ExprApp(ExprVar(0), ExprVar(1))]) + assert showType(["n"], type) == "({f} : N -> N) -> P (f n)" def test_showType_8(PGF): - type = pgf.Type([pgf.mkDepHypo("x", pgf.Type([], "N", [])), pgf.mkHypo(pgf.Type([], "P", [pgf.ExprVar(0)]))], "S", []) - assert pgf.showType(["n"], type) == "(x : N) -> P x -> S" + type = Type([mkDepHypo("x", Type([], "N", [])), mkHypo(Type([], "P", [ExprVar(0)]))], "S", []) + assert showType(["n"], type) == "(x : N) -> P x -> S" def test_showType_9(PGF): - type = pgf.Type([pgf.mkDepHypo("x", pgf.Type([], "N", [])), pgf.mkDepHypo("y", pgf.Type([], "P", [pgf.ExprVar(0)]))], "S", []) - assert pgf.showType(["n"], type) == "(x : N) -> (y : P x) -> S" + type = Type([mkDepHypo("x", Type([], "N", [])), mkDepHypo("y", Type([], "P", [ExprVar(0)]))], "S", []) + assert showType(["n"], type) == "(x : N) -> (y : P x) -> S" # expressions def test_readExpr_invalid(): - with pytest.raises(pgf.PGFError): - pgf.readExpr("->") + with pytest.raises(PGFError): + readExpr("->") # expressions: literals def test_readExpr_lint_equality(): - assert pgf.readExpr("123") == pgf.ExprLit(123) + assert readExpr("123") == ExprLit(123) def test_readExpr_lint_equality_neg(): - assert pgf.readExpr("-123") == pgf.ExprLit(-123) + assert readExpr("-123") == ExprLit(-123) def test_readExpr_lint_equality_big2(): - assert pgf.readExpr("774763251095801167872") == pgf.ExprLit(774763251095801167872) + assert readExpr("774763251095801167872") == ExprLit(774763251095801167872) def test_readExpr_lint_equality_big2_neg(): - assert pgf.readExpr("-774763251095801167872") == pgf.ExprLit(-774763251095801167872) + assert readExpr("-774763251095801167872") == ExprLit(-774763251095801167872) def test_readExpr_lint_inequality(): - assert pgf.readExpr("123") != pgf.ExprLit(456) + assert readExpr("123") != ExprLit(456) def test_readExpr_lflt_equality(): - assert pgf.readExpr("3.142") == pgf.ExprLit(3.142) + assert readExpr("3.142") == ExprLit(3.142) def test_readExpr_lflt_inequality(): - assert pgf.readExpr("3.142") != pgf.ExprLit(3) + assert readExpr("3.142") != ExprLit(3) def test_readExpr_lstr_equality(): - assert pgf.readExpr("\"abc\"") == pgf.ExprLit("abc") + assert readExpr("\"abc\"") == ExprLit("abc") def test_readExpr_lstr_inequality(): - assert pgf.readExpr("\"abc\"") != pgf.ExprLit("def") + assert readExpr("\"abc\"") != ExprLit("def") def test_readExpr_lint_str(): - assert str(pgf.readExpr("123")) == "123" + assert str(readExpr("123")) == "123" def test_readExpr_lint_str_neg(): - assert str(pgf.readExpr("-123")) == "-123" + assert str(readExpr("-123")) == "-123" def test_readExpr_lint_str_big2(): - assert str(pgf.readExpr("774763251095801167872")) == "774763251095801167872" + assert str(readExpr("774763251095801167872")) == "774763251095801167872" def test_readExpr_lint_str_big3(): - assert str(pgf.readExpr("7747632510958011678729003251095801167999")) == "7747632510958011678729003251095801167999" + assert str(readExpr("7747632510958011678729003251095801167999")) == "7747632510958011678729003251095801167999" def test_readExpr_lint_str_big2_neg(): - assert str(pgf.readExpr("-774763251095801167872")) == "-774763251095801167872" + assert str(readExpr("-774763251095801167872")) == "-774763251095801167872" def test_readExpr_lint_str_big3_neg(): - assert str(pgf.readExpr("-7747632510958011678729003251095801167999")) == "-7747632510958011678729003251095801167999" + assert str(readExpr("-7747632510958011678729003251095801167999")) == "-7747632510958011678729003251095801167999" def test_readExpr_lflt_str(): - assert str(pgf.readExpr("3.142")) == "3.142" + assert str(readExpr("3.142")) == "3.142" def test_readExpr_lstr_str_unicode(): - assert str(pgf.readExpr("\"açġħ\"")) == "\"açġħ\"" + assert str(readExpr("\"açġħ\"")) == "\"açġħ\"" def test_readExpr_lstr_null(): - assert str(pgf.ExprLit("ab\0c")) == "\"ab\\0c\"" + assert str(ExprLit("ab\0c")) == "\"ab\\0c\"" def test_readExpr_lstr_newline(): - assert str(pgf.ExprLit("ab\nc")) == "\"ab\\nc\"" + assert str(ExprLit("ab\nc")) == "\"ab\\nc\"" # expressions: functions def test_readExpr_efun_equality_1(): - assert pgf.readExpr("f") == pgf.ExprFun("f") + assert readExpr("f") == ExprFun("f") def test_readExpr_efun_equality_2(): assert \ - pgf.readExpr("f x y") == \ - pgf.ExprApp( - pgf.ExprApp( - pgf.ExprFun("f"), - pgf.ExprFun("x") + readExpr("f x y") == \ + ExprApp( + ExprApp( + ExprFun("f"), + ExprFun("x") ), - pgf.ExprFun("y") + ExprFun("y") ) def test_readExpr_efun_equality_3(): assert \ - pgf.readExpr("f (g x)") == \ - pgf.ExprApp( - pgf.ExprFun("f"), - pgf.ExprApp( - pgf.ExprFun("g"), - pgf.ExprFun("x") + readExpr("f (g x)") == \ + ExprApp( + ExprFun("f"), + ExprApp( + ExprFun("g"), + ExprFun("x") ) ) def test_readExpr_efun_equality_4(): assert \ - pgf.readExpr("f {g x}") == \ - pgf.ExprApp( - pgf.ExprFun("f"), - pgf.ExprImplArg( - pgf.ExprApp( - pgf.ExprFun("g"), - pgf.ExprFun("x") + readExpr("f {g x}") == \ + ExprApp( + ExprFun("f"), + ExprImplArg( + ExprApp( + ExprFun("g"), + ExprFun("x") ) ) ) def test_readExpr_efun_str_unicode_1(): - assert str(pgf.readExpr("'абв'")) == "'абв'" + assert str(readExpr("'абв'")) == "'абв'" @pytest.mark.skip(reason="failing") def test_readExpr_efun_str_unicode_2(): - assert str(pgf.readExpr("'аb'")) == "аb" + assert str(readExpr("'аb'")) == "аb" @pytest.mark.skip(reason="failing") def test_readExpr_efun_str_unicode_3(): - assert str(pgf.readExpr("'а\\'b'")) == "а'b" + assert str(readExpr("'а\\'b'")) == "а'b" def test_readExpr_efun_str_unicode_4(): - assert str(pgf.readExpr("'а\\'б'")) == "'а\\'б'" + assert str(readExpr("'а\\'б'")) == "'а\\'б'" # expressions: variables # def test_readExpr_evar_equality_1(): -# assert pgf.readExpr("#0") == pgf.ExprVar() -# assert pgf.readExpr("#0") == pgf.ExprVar(0) +# assert readExpr("#0") == ExprVar() +# assert readExpr("#0") == ExprVar(0) # def test_readExpr_evar_equality_2(): -# assert pgf.readExpr("#42") == pgf.ExprVar(42) +# assert readExpr("#42") == ExprVar(42) def test_readExpr_evar_str_1(): - assert str(pgf.ExprVar(0)) == "#0" + assert str(ExprVar(0)) == "#0" def test_readExpr_evar_str_2(): - assert str(pgf.ExprVar(42)) == "#42" + assert str(ExprVar(42)) == "#42" def test_showExpr_evar_1(): - assert pgf.showExpr(["x"], pgf.ExprVar(0)) == "x" + assert showExpr(["x"], ExprVar(0)) == "x" def test_showExpr_evar_2(): - assert pgf.showExpr(["x"], pgf.ExprVar(1)) == "#1" + assert showExpr(["x"], ExprVar(1)) == "#1" def test_showExpr_evar_3(): - assert pgf.showExpr(["z", "y", "x"], pgf.ExprVar(0)) == "z" + assert showExpr(["z", "y", "x"], ExprVar(0)) == "z" def test_showExpr_evar_4(): - assert pgf.showExpr(["z", "y", "x"], pgf.ExprVar(1)) == "y" + assert showExpr(["z", "y", "x"], ExprVar(1)) == "y" # expressions: lambda abstractions def test_showExpr_eabs_1(): - expr = pgf.ExprAbs(pgf.BIND_TYPE_EXPLICIT, "w", pgf.ExprVar(0)) - assert pgf.showExpr(["z", "y", "x"], expr) == "\\w->w" + expr = ExprAbs(BIND_TYPE_EXPLICIT, "w", ExprVar(0)) + assert showExpr(["z", "y", "x"], expr) == "\\w->w" def test_showExpr_eabs_2(): - expr = pgf.ExprAbs(pgf.BIND_TYPE_EXPLICIT, "v", pgf.ExprAbs(pgf.BIND_TYPE_EXPLICIT, "w", pgf.ExprVar(2))) - assert pgf.showExpr(["z", "y", "x"], expr) == "\\v,w->z" + expr = ExprAbs(BIND_TYPE_EXPLICIT, "v", ExprAbs(BIND_TYPE_EXPLICIT, "w", ExprVar(2))) + assert showExpr(["z", "y", "x"], expr) == "\\v,w->z" def test_showExpr_eabs_3(): - expr = pgf.ExprAbs(pgf.BIND_TYPE_EXPLICIT, "v", pgf.ExprAbs(pgf.BIND_TYPE_IMPLICIT, "w", pgf.ExprVar(2))) - assert pgf.showExpr(["z", "y", "x"], expr) == "\\v,{w}->z" + expr = ExprAbs(BIND_TYPE_EXPLICIT, "v", ExprAbs(BIND_TYPE_IMPLICIT, "w", ExprVar(2))) + assert showExpr(["z", "y", "x"], expr) == "\\v,{w}->z" def test_showExpr_eabs_4(): - expr = pgf.ExprAbs(pgf.BIND_TYPE_EXPLICIT, "v", pgf.ExprAbs(pgf.BIND_TYPE_IMPLICIT, "w", pgf.ExprAbs(pgf.BIND_TYPE_EXPLICIT, "z", pgf.ExprVar(0)))) - assert pgf.showExpr(["y", "x"], expr) == "\\v,{w},z->z" + expr = ExprAbs(BIND_TYPE_EXPLICIT, "v", ExprAbs(BIND_TYPE_IMPLICIT, "w", ExprAbs(BIND_TYPE_EXPLICIT, "z", ExprVar(0)))) + assert showExpr(["y", "x"], expr) == "\\v,{w},z->z" def test_showExpr_eabs_5(): - expr = pgf.ExprAbs(pgf.BIND_TYPE_EXPLICIT, "v", pgf.ExprAbs(pgf.BIND_TYPE_IMPLICIT, "w", pgf.ExprAbs(pgf.BIND_TYPE_IMPLICIT, "z", pgf.ExprVar(2)))) - assert pgf.showExpr(["y", "x"], expr) == "\\v,{w,z}->v" + expr = ExprAbs(BIND_TYPE_EXPLICIT, "v", ExprAbs(BIND_TYPE_IMPLICIT, "w", ExprAbs(BIND_TYPE_IMPLICIT, "z", ExprVar(2)))) + assert showExpr(["y", "x"], expr) == "\\v,{w,z}->v" def test_showExpr_eabs_6(): - expr = pgf.ExprAbs(pgf.BIND_TYPE_EXPLICIT, "v", pgf.ExprAbs(pgf.BIND_TYPE_IMPLICIT, "w", pgf.ExprAbs(pgf.BIND_TYPE_IMPLICIT, "z", pgf.ExprAbs(pgf.BIND_TYPE_EXPLICIT, "t", pgf.ExprVar(3))))) - assert pgf.showExpr(["y", "x"], expr) == "\\v,{w,z},t->v" + expr = ExprAbs(BIND_TYPE_EXPLICIT, "v", ExprAbs(BIND_TYPE_IMPLICIT, "w", ExprAbs(BIND_TYPE_IMPLICIT, "z", ExprAbs(BIND_TYPE_EXPLICIT, "t", ExprVar(3))))) + assert showExpr(["y", "x"], expr) == "\\v,{w,z},t->v" def test_showExpr_eabs_7(): - expr = pgf.ExprAbs(pgf.BIND_TYPE_EXPLICIT, "u", pgf.ExprAbs(pgf.BIND_TYPE_EXPLICIT, "v", pgf.ExprAbs(pgf.BIND_TYPE_IMPLICIT, "w", pgf.ExprAbs(pgf.BIND_TYPE_IMPLICIT, "z", pgf.ExprAbs(pgf.BIND_TYPE_EXPLICIT, "t", pgf.ExprVar(3)))))) - assert pgf.showExpr(["y", "x"], expr) == "\\u,v,{w,z},t->v" + expr = ExprAbs(BIND_TYPE_EXPLICIT, "u", ExprAbs(BIND_TYPE_EXPLICIT, "v", ExprAbs(BIND_TYPE_IMPLICIT, "w", ExprAbs(BIND_TYPE_IMPLICIT, "z", ExprAbs(BIND_TYPE_EXPLICIT, "t", ExprVar(3)))))) + assert showExpr(["y", "x"], expr) == "\\u,v,{w,z},t->v" def test_showExpr_eabs_8(): - expr = pgf.ExprApp(pgf.ExprFun("f"), pgf.ExprAbs(pgf.BIND_TYPE_EXPLICIT, "x", pgf.ExprVar(0))) - assert pgf.showExpr([], expr) == "f (\\x->x)" + expr = ExprApp(ExprFun("f"), ExprAbs(BIND_TYPE_EXPLICIT, "x", ExprVar(0))) + assert showExpr([], expr) == "f (\\x->x)" def test_showExpr_eabs_freshvars_1(): - expr = pgf.ExprAbs(pgf.BIND_TYPE_EXPLICIT, "v", pgf.ExprAbs(pgf.BIND_TYPE_EXPLICIT, "v", pgf.ExprVar(0))) - assert pgf.showExpr([], expr) == "\\v,v1->v1" + expr = ExprAbs(BIND_TYPE_EXPLICIT, "v", ExprAbs(BIND_TYPE_EXPLICIT, "v", ExprVar(0))) + assert showExpr([], expr) == "\\v,v1->v1" def test_showExpr_eabs_freshvars_2(): - expr = pgf.ExprAbs(pgf.BIND_TYPE_EXPLICIT, "v", pgf.ExprAbs(pgf.BIND_TYPE_EXPLICIT, "v", pgf.ExprVar(1))) - assert pgf.showExpr([], expr) == "\\v,v1->v" + expr = ExprAbs(BIND_TYPE_EXPLICIT, "v", ExprAbs(BIND_TYPE_EXPLICIT, "v", ExprVar(1))) + assert showExpr([], expr) == "\\v,v1->v" def test_showExpr_eabs_freshvars_3(): - expr = pgf.ExprAbs(pgf.BIND_TYPE_EXPLICIT, "v", pgf.ExprAbs(pgf.BIND_TYPE_EXPLICIT, "v", pgf.ExprAbs(pgf.BIND_TYPE_EXPLICIT, "v", pgf.ExprVar(1)))) - assert pgf.showExpr([], expr) == "\\v,v1,v2->v1" + expr = ExprAbs(BIND_TYPE_EXPLICIT, "v", ExprAbs(BIND_TYPE_EXPLICIT, "v", ExprAbs(BIND_TYPE_EXPLICIT, "v", ExprVar(1)))) + assert showExpr([], expr) == "\\v,v1,v2->v1" # expressions: meta variables def test_readExpr_emeta_1(): - assert pgf.readExpr("?") == pgf.ExprMeta() - assert pgf.readExpr("?") == pgf.ExprMeta(0) + assert readExpr("?") == ExprMeta() + assert readExpr("?") == ExprMeta(0) def test_readExpr_emeta_2(): - assert pgf.readExpr("?42") == pgf.ExprMeta(42) + assert readExpr("?42") == ExprMeta(42) def test_readExpr_emeta_str_1(): - assert str(pgf.readExpr("?")) == "?" + assert str(readExpr("?")) == "?" def test_readExpr_emeta_str_2(): - assert str(pgf.readExpr("?42")) == "?42" + assert str(readExpr("?42")) == "?42" # expressions: typed expressions def test_readExpr_emeta_equality(): - assert pgf.readExpr("") == pgf.ExprTyped(pgf.ExprFun("z"), pgf.readType("N")) + assert readExpr("") == ExprTyped(ExprFun("z"), readType("N")) def test_readExpr_emeta_str(): - assert str(pgf.readExpr("")) == "" + assert str(readExpr("")) == "" diff --git a/src/runtime/python/tests/test_transactions.py b/src/runtime/python/tests/test_transactions.py index 26ea56a0d..97e1b789c 100644 --- a/src/runtime/python/tests/test_transactions.py +++ b/src/runtime/python/tests/test_transactions.py @@ -2,40 +2,49 @@ import pytest from pgf import * ty = readType("(N -> N) -> P (s z)") -pi = 3.142 +prob = 3.142 -# @pytest.fixture(scope="module") -# def gr1(): -# return pgf.readPGF("../haskell/tests/basic.pgf") -# -# @pytest.fixture(scope="module") -# def gr2(gr1): -# transaction = [ -# createFunction("foo", ty, 0, pi), -# createCategory("Q", [(BIND_TYPE_EXPLICIT, "x", ty)], pi) -# ] -# return gr1.modifyPGF(transaction) -# -# @pytest.fixture(scope="module") -# def gr3(gr1): -# transaction = [ -# createFunction("bar", ty, 0, pi), -# createCategory("R", [(BIND_TYPE_EXPLICIT, "x", ty)], pi) -# ] -# return gr1.branchPGF("bar_branch", transaction) -# -# def original_functions(gr1): -# assert gr1.functions == ["c", "ind", "s", "z"] -# -# def extended_functions(gr2): -# assert gr2.functions == ["c", "foo", "ind", "s", "z"] -# -# def branched_functions(gr3): -# assert gr3.functions == ["bar", "c", "ind", "s", "z"] +@pytest.fixture(scope="module") +def gr1(): + return readPGF("../haskell/tests/basic.pgf") -def test_non_transactional(): - gr1 = readPGF("../haskell/tests/basic.pgf") +@pytest.fixture(scope="module") +def gr2(gr1): + t = gr1.newTransaction() + t.createFunction("foo", ty, 0, prob), + # t.createCategory("Q", [(BIND_TYPE_EXPLICIT, "x", ty)], prob) + assert t.commit() + return gr1 + +# gr1 + +def test_original_functions(gr1): assert gr1.functions == ["c", "ind", "s", "z"] - gr1.createFunction("foo", ty, 0, pi) - assert gr1.functions == ["c", "foo", "ind", "s", "z"] +def test_original_categories(gr1): + assert gr1.categories == ["Float","Int","N","P","S","String"] + +def test_original_function_type(gr1): + with pytest.raises(KeyError): + gr1.functionType("foo") + +# def test_original_function_prob(gr1): +# with pytest.raises(KeyError): +# gr1.functionProbability("foo") + +# gr2 + +def test_extended_functions(gr2): + assert gr2.functions == ["c", "foo", "ind", "s", "z"] + +# def test_extended_categories(gr2): +# assert gr2.categories == ["Float","Int","N","P","Q","S","String"] +# +# def test_extended_category_context(gr2): +# assert gr2.categoryContext("Q") == [(BIND_TYPE_EXPLICIT, "x", ty)] + +def test_extended_function_type(gr2): + assert gr2.functionType("foo") == ty + +# def test_extended_function_prob(gr2): +# assert gr2.functionProbability("foo") == prob diff --git a/src/runtime/python/transactions.c b/src/runtime/python/transactions.c index 8ff2e2e58..6fee73152 100644 --- a/src/runtime/python/transactions.c +++ b/src/runtime/python/transactions.c @@ -5,9 +5,43 @@ #include #include "./expr.h" #include "./ffi.h" +#include "./transactions.h" + +TransactionObject * +PGF_newTransaction(PGFObject *self, PyObject *args) +{ + PgfText *name = NULL; + // PgfText *name = PyUnicode_AsPgfText(PyUnicode_FromString("transient")); + + PgfExn err; + PgfRevision rev = pgf_clone_revision(self->db, self->revision, name, &err); + if (handleError(err) != PGF_EXN_NONE) { + return NULL; + } + + TransactionObject *trans = (TransactionObject *)pgf_TransactionType.tp_alloc(&pgf_TransactionType, 0); + trans->pgf = self; + trans->revision = rev; + + return trans; +} PyObject * -PGF_createFunction(PGFObject *self, PyObject *args) +Transaction_commit(TransactionObject *self, PyObject *args) +{ + PgfExn err; + pgf_commit_revision(self->pgf->db, self->revision, &err); + if (handleError(err) != PGF_EXN_NONE) { + return NULL; + } + + self->pgf->revision = self->revision; + + Py_RETURN_TRUE; +} + +PyObject * +Transaction_createFunction(TransactionObject *self, PyObject *args) { const char *s; Py_ssize_t size; @@ -22,7 +56,7 @@ PGF_createFunction(PGFObject *self, PyObject *args) fname->size = size; PgfExn err; - pgf_create_function(self->db, self->revision, fname, (PgfType) type, arity, prob, &marshaller, &err); + pgf_create_function(self->pgf->db, self->revision, fname, (PgfType) type, arity, prob, &marshaller, &err); PyMem_Free(fname); if (handleError(err) != PGF_EXN_NONE) { return NULL; @@ -32,7 +66,7 @@ PGF_createFunction(PGFObject *self, PyObject *args) } PyObject * -PGF_dropFunction(PGFObject *self, PyObject *args) +Transaction_dropFunction(TransactionObject *self, PyObject *args) { const char *s; Py_ssize_t size; @@ -44,7 +78,7 @@ PGF_dropFunction(PGFObject *self, PyObject *args) fname->size = size; PgfExn err; - pgf_drop_category(self->db, self->revision, fname, &err); + pgf_drop_category(self->pgf->db, self->revision, fname, &err); PyMem_Free(fname); if (handleError(err) != PGF_EXN_NONE) { return NULL; @@ -54,7 +88,7 @@ PGF_dropFunction(PGFObject *self, PyObject *args) } PyObject * -PGF_createCategory(PGFObject *self, PyObject *args) +Transaction_createCategory(TransactionObject *self, PyObject *args) { const char *s; Py_ssize_t size; @@ -70,7 +104,7 @@ PGF_createCategory(PGFObject *self, PyObject *args) PgfTypeHypo *context = NULL; PgfExn err; - pgf_create_category(self->db, self->revision, catname, n_hypos, context, prob, &marshaller, &err); + pgf_create_category(self->pgf->db, self->revision, catname, n_hypos, context, prob, &marshaller, &err); PyMem_Free(catname); if (handleError(err) != PGF_EXN_NONE) { return NULL; @@ -80,7 +114,7 @@ PGF_createCategory(PGFObject *self, PyObject *args) } PyObject * -PGF_dropCategory(PGFObject *self, PyObject *args) +Transaction_dropCategory(TransactionObject *self, PyObject *args) { const char *s; Py_ssize_t size; @@ -92,7 +126,7 @@ PGF_dropCategory(PGFObject *self, PyObject *args) catname->size = size; PgfExn err; - pgf_drop_function(self->db, self->revision, catname, &err); + pgf_drop_function(self->pgf->db, self->revision, catname, &err); PyMem_Free(catname); if (handleError(err) != PGF_EXN_NONE) { return NULL; @@ -100,3 +134,81 @@ PGF_dropCategory(PGFObject *self, PyObject *args) Py_RETURN_NONE; } + +// ---------------------------------------------------------------------------- + +// static void +// Transaction_dealloc(PGFObject* self) +// { +// Py_TYPE(self)->tp_free((PyObject*)self); +// } + +static PyGetSetDef Transaction_getseters[] = { + {NULL} /* Sentinel */ +}; + +// static PyMemberDef Transaction_members[] = { +// {NULL} /* Sentinel */ +// }; + +static PyMethodDef Transaction_methods[] = { + {"commit", (PyCFunction)Transaction_commit, METH_VARARGS, + "Commit transaction" + }, + + {"createFunction", (PyCFunction)Transaction_createFunction, METH_VARARGS, + "Create function" + }, + {"dropFunction", (PyCFunction)Transaction_dropFunction, METH_VARARGS, + "Drop function" + }, + {"createCategory", (PyCFunction)Transaction_createCategory, METH_VARARGS, + "Create category" + }, + {"dropCategory", (PyCFunction)Transaction_dropCategory, METH_VARARGS, + "Drop category" + }, + {NULL} /* Sentinel */ +}; + +PyTypeObject pgf_TransactionType = { + PyVarObject_HEAD_INIT(NULL, 0) + //0, /*ob_size*/ + "pgf.Transaction", /*tp_name*/ + sizeof(PGFObject), /*tp_basicsize*/ + 0, /*tp_itemsize*/ + 0, //(destructor)Transaction_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, /*tp_hash */ + 0, /*tp_call*/ + 0, // (reprfunc) Transaction_str, /*tp_str*/ + 0, /*tp_getattro*/ + 0, /*tp_setattro*/ + 0, /*tp_as_buffer*/ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/ + "PGF transaction", /*tp_doc*/ + 0, /*tp_traverse */ + 0, /*tp_clear */ + 0, /*tp_richcompare */ + 0, /*tp_weaklistoffset */ + 0, /*tp_iter */ + 0, /*tp_iternext */ + Transaction_methods, /*tp_methods */ + 0, //Transaction_members, /*tp_members */ + Transaction_getseters, /*tp_getset */ + 0, /*tp_base */ + 0, /*tp_dict */ + 0, /*tp_descr_get */ + 0, /*tp_descr_set */ + 0, /*tp_dictoffset */ + 0, /*tp_init */ + 0, /*tp_alloc */ + 0, /*tp_new */ +}; diff --git a/src/runtime/python/transactions.h b/src/runtime/python/transactions.h index 39b6a1e0e..18083915f 100644 --- a/src/runtime/python/transactions.h +++ b/src/runtime/python/transactions.h @@ -6,33 +6,30 @@ #include -// typedef struct { -// PyObject_HEAD -// PyObject *thing; -// } TransactionObject; +typedef struct { + PyObject_HEAD + PGFObject *pgf; // original reference, gets updated on commit + PgfRevision revision; // transient branch +} TransactionObject; -// modifyPGF -// -// branchPGF -// -// checkoutPGF +extern PyTypeObject pgf_TransactionType; + +TransactionObject * +PGF_newTransaction(PGFObject *self, PyObject *args); PyObject * -PGF_createFunction(PGFObject *self, PyObject *args); +Transaction_commit(TransactionObject *self, PyObject *args); PyObject * -PGF_dropFunction(PGFObject *self, PyObject *args); +Transaction_createFunction(TransactionObject *self, PyObject *args); PyObject * -PGF_createCategory(PGFObject *self, PyObject *args); +Transaction_dropFunction(TransactionObject *self, PyObject *args); PyObject * -PGF_dropCategory(PGFObject *self, PyObject *args); - -// setGlobalFlag -// -// setAbstractFlag - +Transaction_createCategory(TransactionObject *self, PyObject *args); +PyObject * +Transaction_dropCategory(TransactionObject *self, PyObject *args); #endif // PYPGF_TRANSACTIONS_H_