From dcac7254f3fc24cde44af516374b0b3ce3881481 Mon Sep 17 00:00:00 2001 From: "jordi.saludes" Date: Tue, 27 Jul 2010 15:42:48 +0000 Subject: [PATCH] Added 'functions' and 'functionType' to py-bindings. --- contrib/py-bindings/PyGF.hsc | 21 +++++++++++++ contrib/py-bindings/gfmodule.c | 55 ++++++++++++++++++++-------------- contrib/py-bindings/test.py | 12 +++++++- 3 files changed, 64 insertions(+), 24 deletions(-) diff --git a/contrib/py-bindings/PyGF.hsc b/contrib/py-bindings/PyGF.hsc index 7b9991f3e..fc99d1a7d 100644 --- a/contrib/py-bindings/PyGF.hsc +++ b/contrib/py-bindings/PyGF.hsc @@ -1,4 +1,6 @@ {-# LANGUAGE ForeignFunctionInterface #-} +-- GF Python bindings -- Jordi Saludes, upc.edu 2010 + module PyGF where import PGF @@ -226,8 +228,27 @@ gf_inferexpr ppgf pexp ptype = do let Right (_,t) = inferExpr pgf exp poke ptype t + +foreign export ccall gf_functions :: Ptr PGF -> IO (Ptr ()) +gf_functions ppgf = do + pgf <- peek ppgf + listToPy pyCId $ functions pgf + +foreign export ccall gf_functiontype :: Ptr PGF -> Ptr CId -> IO (Ptr Type) +gf_functiontype ppgf pcid = do + pgf <- peek ppgf + cid <- peek pcid + case functionType pgf cid of + Just t -> do + ptp <- pyType + poke ptp t + return ptp + _ -> return nullPtr + + foreign import ccall "newLang" pyLang :: IO (Ptr Language) foreign import ccall "newTree" pyTree :: IO (Ptr Tree) +foreign import ccall "newgfType" pyType :: IO (Ptr Type) foreign import ccall "newCId" pyCId :: IO (Ptr CId) foreign import ccall "newExpr" pyExpr :: IO (Ptr Expr) foreign import ccall "newList" pyList :: IO (Ptr ()) diff --git a/contrib/py-bindings/gfmodule.c b/contrib/py-bindings/gfmodule.c index 8491f2eb5..98c65ce47 100644 --- a/contrib/py-bindings/gfmodule.c +++ b/contrib/py-bindings/gfmodule.c @@ -32,16 +32,6 @@ NEWGF(Tree,GF_Tree,TreeType,"gf.tree","gf tree") DEALLOCFN(CId_dealloc, CId, gf_freeCId, "freeCId") -/* static PyObject* -CId_repr(CId *self) -{ - char* str_cid = gf_showCId(self->obj); - PyObject* repr = PyString_FromString(str_cid); - free(str_cid); - return repr; - } */ - - /* PGF methods, constructor and destructor */ @@ -62,21 +52,28 @@ startCategory(PGF *self, PyObject *noarg) gfType *cat; if (!checkType(self, &PGFType)) return NULL; cat = (gfType*)gfTypeType.tp_new(&gfTypeType,NULL,NULL); - gf_startCat((PGF*)self, cat); + gf_startCat(self, cat); return cat; } -inline static PyObject* +/* inline static PyObject* categories(PGF* self) { return gf_categories(self); } +inline static PyObject* +functions(PGF* self) +{ + return gf_functions(self); + } + inline static PyObject* languages(PGF* self) { return gf_languages(self); } +*/ static PyObject* languageCode(PGF *self, PyObject *args) @@ -134,6 +131,22 @@ printName(PGF *self, PyObject *args) return result; } +static gfType* +functiontype(PGF *self, PyObject* args) +{ + CId* cid; + gfType* gftp; + if (!PyArg_ParseTuple(args, "O", &cid)) + return NULL; + if (!checkType(cid,&CIdType)) { + PyErr_Format(PyExc_TypeError, "Must be a gf identifier."); + return NULL; + } + // gftp = (gfType)gfTypeType.tp_new(&gfTypeType,NULL,NULL); + return gf_functiontype(self, cid); + // return gftp; +} + static PyObject* parse(PGF *self, PyObject *args, PyObject *kws) @@ -176,17 +189,19 @@ readPGF(PyObject *self, PyObject *args) } } -//Todo: repr + static PyMethodDef pgf_methods[] = { {"parse", (PyCFunction)parse, METH_VARARGS|METH_KEYWORDS,"Parse a string."}, {"lin", (PyCFunction)linearize, METH_VARARGS,"Linearize tree."}, {"lang_code", (PyCFunction)languageCode, METH_VARARGS,"Get the language code."}, {"print_name", (PyCFunction)printName, METH_VARARGS,"Get the print name for a id."}, + {"fun_type", (PyCFunction)functiontype, METH_VARARGS,"Get the type of a fun expression."}, {"startcat", (PyCFunction)startCategory, METH_NOARGS,"Get the start category."}, - {"categories", (PyCFunction)categories, METH_NOARGS,"Get all categories."}, + {"categories", (PyCFunction)gf_categories, METH_NOARGS,"Get all categories."}, + {"functions", (PyCFunction)gf_functions, METH_NOARGS,"Get all functions."}, {"abstract", (PyCFunction)abstractName, METH_NOARGS,"Get the module abstract name."}, - {"languages", (PyCFunction)languages, METH_NOARGS,"Get the module languages."}, + {"languages", (PyCFunction)gf_languages, METH_NOARGS,"Get the module languages."}, {NULL, NULL, 0, NULL} /* Sentinel */ }; @@ -256,18 +271,12 @@ infer_expr(Expr *self, PyObject* args) { } gfType* gftp = (gfType*)gfTypeType.tp_new(&gfTypeType,NULL,NULL); gf_inferexpr(pgf, self, gftp); - return gftp; + return (PyObject*)gftp; } -/* todo: Is Tree == Expr ? - -static PyMethodDef tree_methods[] = { - {"unapply", (PyCFunction)unapp, METH_NOARGS, "Unapply a tree."}, - {NULL, NULL, 0, NULL} // * Sentinel * // -}; -*/ +/* todo: Is Tree == Expr ? */ static PyMethodDef expr_methods[] = { {"unapply", (PyCFunction)unapp, METH_NOARGS, "Unapply an expression."}, diff --git a/contrib/py-bindings/test.py b/contrib/py-bindings/test.py index 04adb2c29..8b1bc9443 100644 --- a/contrib/py-bindings/test.py +++ b/contrib/py-bindings/test.py @@ -72,7 +72,16 @@ class TestPgfInfo(unittest.TestCase): for lang in 'QueryEng QuerySpa'.split(): l = gf.read_language(lang) self.assertEqual(rmprefix(l),lang) - + def test_functions(self): + pgf = self.pgf() + self.assertTrue('Even' in [`f` for f in pgf.functions()]) + def test_function_types(self): + pgf = self.pgf() + gftypes = dict((`f`,`pgf.fun_type(f)`) for f in pgf.functions()) + for p in "Prime : Object -> Question; Yes : Answer".split(';'): + lhs,rhs = [s.strip() for s in p.split(':')] + self.assertEqual(gftypes[lhs],rhs) + class TestParsing(unittest.TestCase): def setUp(self): self.lexed = samples @@ -154,5 +163,6 @@ class TestUnapplyExpr(unittest.TestCase): if type(uexp) != type(2) and type(uexp) != type('2'): exp = uexp[1] + if __name__ == '__main__': unittest.main()