diff --git a/src/runtime/haskell/tests/transactions.hs b/src/runtime/haskell/tests/transactions.hs index e9582f544..94cd91a80 100644 --- a/src/runtime/haskell/tests/transactions.hs +++ b/src/runtime/haskell/tests/transactions.hs @@ -36,6 +36,8 @@ main = do ,TestCase (assertEqual "new function type" (Just ty) (functionType gr2 "foo")) ,TestCase (assertEqual "old function prob" (-log 0) (functionProbability gr1 "foo")) ,TestCase (assertEqual "new function prob" pi (functionProbability gr2 "foo")) + ,TestCase (assertEqual "old category prob" (-log 0) (categoryProbability gr1 "Q")) + ,TestCase (assertEqual "new category prob" pi (categoryProbability gr2 "Q")) ] performMajorGC diff --git a/src/runtime/python/expr.c b/src/runtime/python/expr.c index ca5682545..b32c5cd9d 100644 --- a/src/runtime/python/expr.c +++ b/src/runtime/python/expr.c @@ -36,7 +36,7 @@ Type_init(TypeObject *self, PyObject *args, PyObject *kwds) } for (Py_ssize_t i = 0; i < PyList_Size(exprs); i++) { if (!PyObject_TypeCheck(PyList_GetItem(exprs, i), &pgf_ExprType)) { - PyErr_SetString(PyExc_TypeError, "invalid expression in Type_init"); + PyErr_SetString(PyExc_TypeError, "invalid expression in Type initialisation"); return -1; } // Py_INCREF(&exprs[i]); @@ -353,7 +353,7 @@ Expr_unpack(ExprObject *self, PyObject *fargs) for (;;) { if (PyObject_TypeCheck(expr, &pgf_ExprAbsType)) { ExprAbsObject *eabs = (ExprAbsObject *) expr; - PyObject* res = + PyObject* res = Py_BuildValue("OOOO", eabs->bind_type, eabs->name, eabs->body, args); Py_DECREF(args); return res; diff --git a/src/runtime/python/pypgf.c b/src/runtime/python/pypgf.c index 3f20217d4..a24ab7f08 100644 --- a/src/runtime/python/pypgf.c +++ b/src/runtime/python/pypgf.c @@ -18,6 +18,22 @@ PGF_dealloc(PGFObject *self) Py_TYPE(self)->tp_free(self); } +static PyObject * +PGF_writeToFile(PGFObject *self, PyObject *args) +{ + const char *fpath; + if (!PyArg_ParseTuple(args, "s", &fpath)) + return NULL; + + PgfExn err; + pgf_write_pgf(fpath, self->db, self->revision, &err); + if (handleError(err) != PGF_EXN_NONE) { + return NULL; + } + + Py_RETURN_NONE; +} + typedef struct { PgfItor fn; PGFObject *grammar; @@ -262,6 +278,26 @@ PGF_functionIsConstructor(PGFObject *self, PyObject *args) return PyBool_FromLong(isCon); } +static PyObject * +PGF_categoryProbability(PGFObject *self, PyObject *args) +{ + const char *s; + Py_ssize_t size; + if (!PyArg_ParseTuple(args, "s#", &s, &size)) + return NULL; + + PgfText *catname = CString_AsPgfText(s, size); + + PgfExn err; + prob_t prob = pgf_category_prob(self->db, self->revision, catname, &err); + FreePgfText(catname); + if (handleError(err) != PGF_EXN_NONE) { + return NULL; + } + + return PyFloat_FromDouble((double)prob); +} + static PyObject * PGF_functionProbability(PGFObject *self, PyObject *args) { @@ -307,6 +343,9 @@ static PyMemberDef PGF_members[] = { }; static PyMethodDef PGF_methods[] = { + {"writeToFile", (PyCFunction)PGF_writeToFile, METH_VARARGS, + "Writes PGF to file"}, + {"categoryContext", (PyCFunction)PGF_categoryContext, METH_VARARGS, "Returns the context for a given category" }, @@ -319,6 +358,9 @@ static PyMethodDef PGF_methods[] = { {"functionIsConstructor", (PyCFunction)PGF_functionIsConstructor, METH_VARARGS, "Checks whether a function is a constructor" }, + {"categoryProbability", (PyCFunction)PGF_categoryProbability, METH_VARARGS, + "Returns the probability of a category" + }, {"functionProbability", (PyCFunction)PGF_functionProbability, METH_VARARGS, "Returns the probability of a function" }, diff --git a/src/runtime/python/tests/test_basic.py b/src/runtime/python/tests/test_basic.py index 918ad2a32..75df99a0c 100644 --- a/src/runtime/python/tests/test_basic.py +++ b/src/runtime/python/tests/test_basic.py @@ -77,6 +77,12 @@ def test_newNGF_existing(NGF): with pytest.raises(FileExistsError): newNGF("empty", "./basic.ngf") +# writePGF + +def test_writePGF(PGF): + PGF.writeToFile("./copy.pgf") + os.remove("./copy.pgf") # cleanup + # abstract syntax def test_abstractName(PGF): diff --git a/src/runtime/python/tests/test_transactions.py b/src/runtime/python/tests/test_transactions.py index a7dfda7c0..65b20b1e3 100644 --- a/src/runtime/python/tests/test_transactions.py +++ b/src/runtime/python/tests/test_transactions.py @@ -70,6 +70,11 @@ def test_original_function_prob(gr1): # gr1.functionProbability("foo") assert gr1.functionProbability("foo") == float('inf') +def test_original_category_prob(gr1): + # with pytest.raises(KeyError): + # gr1.categoryProbability("Q") + assert gr1.categoryProbability("Q") == float('inf') + # gr2 def test_extended_functions(gr2): @@ -89,6 +94,9 @@ def test_extended_function_prob(gr2): # assert gr2.functionProbability("foo") == prob assert math.isclose(gr2.functionProbability("foo"), prob, rel_tol=1e-06) +def test_extended_category_prob(gr2): + assert gr2.categoryProbability("Q") == prob + # gr3 def test_branched_functions(gr3):