From 3bb29951703b58a8713a4839ef19d7eaefc13ad5 Mon Sep 17 00:00:00 2001 From: "jordi.saludes" Date: Thu, 22 Jul 2010 13:23:27 +0000 Subject: [PATCH] Refactored py-bindings using Storable. --- contrib/py-bindings/Makefile | 21 ++-- contrib/py-bindings/PyGF.hsc | 107 +++++++++++++++++--- contrib/py-bindings/gfmodule.c | 175 ++++++++++++++------------------- contrib/py-bindings/mtest.c | 65 ------------ contrib/py-bindings/pygf.h | 26 ++++- 5 files changed, 199 insertions(+), 195 deletions(-) delete mode 100644 contrib/py-bindings/mtest.c diff --git a/contrib/py-bindings/Makefile b/contrib/py-bindings/Makefile index fb2668ac5..bcf78e572 100644 --- a/contrib/py-bindings/Makefile +++ b/contrib/py-bindings/Makefile @@ -4,16 +4,17 @@ cbind=../c-bindings pythoninc=/usr/include/python2.5 debug= #-optc '-DDEBUG=1' exdir=../../examples/tutorial/embedded -conf: - ln -s $(cbind)/PGFFFI.hs - ln -s $(cbind)/pgf.h + build: gf.so -gf.so: PGFFFI.hs gfmodule.c Query.pgf +gf.so: PyGF.hs gfmodule.c Query.pgf ghc $(import) --make -fglasgow-exts -O2 -no-hs-main -c $< ghc -O2 --make -fglasgow-exts -no-hs-main -optl '-shared' \ - -optc '-DMODULE=PGFFFI' $(debug) -optc '-I$(pythoninc)' -o $@ \ + -optc '-DMODULE=$(basename $<)' $(debug) -optc '-I$(pythoninc)' -o $@ \ $(filter-out %.pgf, $^) + + + clean: rm -f *.hi *.o rm -f *_stub.* @@ -21,7 +22,7 @@ clean: superclean: make clean - rm -f PGFFFI.hs pgf.h Query.pgf + rm -f Query.pgf rm -f gf.so rm -f mtest @@ -29,10 +30,4 @@ PyGF.hs: PyGF.hsc hsc2hs -I$(pythoninc) $< Query.pgf: - gf --make $(exdir)/QueryEng.gf $(exdir)/QuerySpa.gf - -mtest: PyGF.hs mtest.c Query.pgf - ghc $(import) --make -fglasgow-exts -O2 -no-hs-main -c $< - ghc -O2 --make -fglasgow-exts -no-hs-main \ - -optc '-DMODULE=PyGF' -optc '-I$(pythoninc)' -o $@ \ - $(filter-out %.pgf, $^) \ No newline at end of file + gf --make $(exdir)/QueryEng.gf $(exdir)/QuerySpa.gf \ No newline at end of file diff --git a/contrib/py-bindings/PyGF.hsc b/contrib/py-bindings/PyGF.hsc index 2b44e96c9..27c87b1a0 100644 --- a/contrib/py-bindings/PyGF.hsc +++ b/contrib/py-bindings/PyGF.hsc @@ -5,15 +5,17 @@ import PGF import Foreign import CString import Foreign.C.Types +import Control.Monad #include "pygf.h" --- type PyPtr = Ptr Py freeSp :: String -> Ptr a -> IO () freeSp tname p = do + --DEBUG putStrLn $ "about to free pointer " ++ tname ++ " at " ++ (show p) sp <- (#peek PyGF, sp) p + --DEBUG putStrLn "peeked" freeStablePtr sp - putStrLn $ "freeing " ++ tname ++ " at " ++ (show p) + --DEBUG putStrLn $ "freeing " ++ tname ++ " at " ++ (show p) instance Storable PGF where sizeOf _ = (#size PyGF) @@ -55,12 +57,31 @@ instance Storable Tree where sp <- (#peek PyGF, sp) p deRefStablePtr sp +-- It is CId the same as Tree? + +{- instance Storable CId where + sizeOf _ = (#size PyGF) + alignment _ = alignment (undefined::CInt) + poke p o = do + sp <- newStablePtr o + (#poke PyGF, sp) p sp + peek p = do + sp <- (#peek PyGF, sp) p + deRefStablePtr sp +-} + foreign export ccall gf_freePGF :: Ptr PGF -> IO () foreign export ccall gf_freeType :: Ptr Type -> IO () foreign export ccall gf_freeLanguage :: Ptr Language -> IO () +foreign export ccall gf_freeTree :: Ptr Tree -> IO () +foreign export ccall gf_freeExpr :: Ptr Expr -> IO () +foreign export ccall gf_freeCId :: Ptr CId -> IO () gf_freePGF = freeSp "pgf" gf_freeType = freeSp "type" gf_freeLanguage = freeSp "language" +gf_freeTree = freeSp "tree" +gf_freeExpr = freeSp "expression" +gf_freeCId = freeSp "CId" {-foreign export ccall gf_printCId :: Ptr CId-> IO CString @@ -68,6 +89,7 @@ gf_printCId p = do c <- peek p newCString (showCId c) -} + foreign export ccall gf_readPGF :: Ptr PGF -> CString -> IO () gf_readPGF pt path = do p <- (peekCString path) @@ -88,29 +110,37 @@ gf_startCat ppgf pcat= do pgf <- peek ppgf poke pcat (startCat pgf) -foreign export ccall gf_parse :: Ptr PGF -> Ptr Language -> Ptr Type -> CString -> IO (Ptr Tree) +foreign export ccall gf_parse :: Ptr PGF -> Ptr Language -> Ptr Type -> CString -> IO (Ptr ()) gf_parse ppgf plang pcat input = do p <- peek ppgf c <- peek pcat i <- peekCString input l <- peek plang let parsed = parse p l c i - -- putStrLn $ (show $ length parsed) ++ " parsings" - listToArray $ parsed + --DEBUG putStrLn $ (show $ length parsed) ++ " parsings" + listToPy pyTree parsed foreign export ccall gf_showExpr :: Ptr Expr -> IO CString gf_showExpr pexpr = do e <- peek pexpr newCString (showExpr [] e) -listToArray :: Storable a => [a] -> IO (Ptr a) -listToArray list = do - buf <- mallocBytes $ (#size PyGF) * (length list + 1) - sequence $ zipWith (dpoke buf) [0..] list - return buf - where - dpoke buf n x = do - pokeElemOff buf n x +listToPy :: Storable a => IO (Ptr a) -> [a] -> IO (Ptr ()) -- opaque -- IO (Ptr (Ptr Language)) +listToPy mk ls = do + let bufl = length ls + 1 + -- buf <- mallocBytes $ (#size PyGF) * bufl + pyls <- pyList + -- pokeElemOff buf (length ls) nullPtr + mapM_ (mpoke pyls) ls + return pyls + where mpoke pyl l = do + pl <- mk + poke pl l + pyl << pl + + +-- foreign export ccall "gf_freeArray" free :: Ptr a -> IO () + foreign export ccall gf_showLanguage :: Ptr Language -> IO CString gf_showLanguage plang = do @@ -120,4 +150,53 @@ gf_showLanguage plang = do foreign export ccall gf_showType :: Ptr Type -> IO CString gf_showType ptp = do t <- peek ptp - newCString $ showType [] t \ No newline at end of file + newCString $ showType [] t + +foreign export ccall gf_showPrintName :: Ptr PGF -> Ptr Language -> Ptr CId -> IO CString +gf_showPrintName ppgf plang pcid = do + pgf <- peek ppgf + lang <- peek plang + cid <- peek pcid + newCString (showPrintName pgf lang cid) + +foreign export ccall gf_abstractName :: Ptr PGF -> Ptr Language -> IO () +gf_abstractName ppgf pabs = do + pgf <- peek ppgf + poke pabs $ abstractName pgf + +foreign export ccall gf_linearize :: Ptr PGF -> Ptr Language -> Ptr Tree -> IO CString +gf_linearize ppgf plang ptree = do + pgf <- peek ppgf + lang <- peek plang + tree <- peek ptree + newCString $ linearize pgf lang tree + +foreign export ccall gf_languageCode :: Ptr PGF -> Ptr Language -> IO CString +gf_languageCode ppgf plang = do + pgf <- peek ppgf + lang <- peek plang + case languageCode pgf lang of + Just s -> newCString s + Nothing -> return nullPtr + +foreign export ccall gf_languages :: Ptr PGF -> IO (Ptr ()) -- (Ptr (Ptr Language)) +gf_languages ppgf = do + pgf <- peek ppgf + listToPy pyLang $ languages pgf + +foreign export ccall gf_categories :: Ptr PGF -> IO (Ptr ()) +gf_categories ppgf = do + pgf <- peek ppgf + listToPy pyCId $ categories pgf + +foreign export ccall gf_showCId :: Ptr CId -> IO CString +gf_showCId pcid = do + cid <- peek pcid + newCString $ showCId cid + + +foreign import ccall "newLang" pyLang :: IO (Ptr Language) +foreign import ccall "newTree" pyTree :: IO (Ptr Tree) +foreign import ccall "newCId" pyCId :: IO (Ptr CId) +foreign import ccall "newList" pyList :: IO (Ptr ()) +foreign import ccall "append" (<<) :: Ptr () -> Ptr a -> IO () diff --git a/contrib/py-bindings/gfmodule.c b/contrib/py-bindings/gfmodule.c index cc6db6f64..ba933ee76 100644 --- a/contrib/py-bindings/gfmodule.c +++ b/contrib/py-bindings/gfmodule.c @@ -1,63 +1,9 @@ // GF Python bindings -// Jordi Saludes 2010 +// Jordi Saludes, upc.edu 2010 // #include -#include "pgf.h" - -#define NEWOBJECT(OBJ, GFTYPE) typedef struct {\ - PyObject_HEAD \ - GFTYPE obj; \ -} OBJ; -#define NEWTYPE(TYPE,NAME,OBJECT,DOC) static PyTypeObject TYPE = {\ - PyObject_HEAD_INIT(NULL)\ - 0, /*ob_size*/\ - NAME, /*tp_name*/\ - sizeof(OBJECT), /*tp_basicsize*/\ - 0, /*tp_itemsize*/\ - 0, /*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, /*tp_str*/\ - 0, /*tp_getattro*/\ - 0, /*tp_setattro*/\ - 0, /*tp_as_buffer*/\ - Py_TPFLAGS_DEFAULT, /*tp_flags*/\ - DOC, /* tp_doc */\ -}; -#define NEWGF(OBJ,GFTYPE,TYPE,NAME,DOC) NEWOBJECT(OBJ,GFTYPE) \ -NEWTYPE(TYPE,NAME,OBJ,DOC) - -#ifdef DEBUG -#define DEALLOCFN(delname,t,cb,cbname) static void \ -delname(t *self){ cb(self->obj);\ - printf("gf_%s has been called for stable pointer 0x%x\n", cbname, self->obj);\ - self->ob_type->tp_free((PyObject*)self); } -#else -#define DEALLOCFN(delname,t,cb,cbname) static void \ -delname(t *self){ cb(self->obj);\ - self->ob_type->tp_free((PyObject*)self); } -#endif - -#ifdef DEBUG -#define REPRCB(cbid,t,gfcb) static PyObject* \ -cbid(t *self) { \ - const char *str = gfcb(self->obj); \ - return PyString_FromFormat("0x%x: %s", self->obj, str); } -#else -#define REPRCB(cbid,t,gfcb) static PyObject* \ -cbid(t *self) { \ - const char *str = gfcb(self->obj); \ - return PyString_FromString(str); } -#endif +#include "pygf.h" /* utilities */ @@ -85,14 +31,14 @@ NEWGF(Tree,GF_Tree,TreeType,"gf.tree","gf tree") DEALLOCFN(CId_dealloc, CId, gf_freeCId, "freeCId") -static PyObject* +/* static PyObject* CId_repr(CId *self) { char* str_cid = gf_showCId(self->obj); PyObject* repr = PyString_FromString(str_cid); free(str_cid); return repr; -} + } */ @@ -101,11 +47,13 @@ CId_repr(CId *self) DEALLOCFN(PGF_dealloc, PGFModule, gf_freePGF, "freePGF") + static PyObject* pgf_repr(PGFModule *self) { - GF_Language lang = gf_abstractName(self->obj); - const char* abs = gf_showLanguage(lang); - gf_freeLanguage(lang); + Lang lang; + gf_abstractName(self, &lang); + const char* abs = gf_showLanguage(&lang); + gf_freeLanguage(&lang); return PyString_FromFormat("", abs, self->obj); } @@ -117,36 +65,40 @@ startCategory(PyObject *self, PyObject *noarg) gfType *cat; if (!checkType(self, &PGFType)) return NULL; cat = (gfType*)gfTypeType.tp_new(&gfTypeType,NULL,NULL); - cat->obj = gf_startCat(((PGFModule*)self)->obj); + gf_startCat((PGFModule*)self, cat); return cat; } -static PyObject* +inline static PyObject* categories(PGFModule* self) { - PyObject* cats = PyList_New(0); - GF_CId *p = gf_categories(self->obj); + /* PyObject* cats = PyList_New(0); + GF_CId *p = gf_categories(self); while (*p) { CId* c = (CId*)CIdType.tp_new(&CIdType,NULL,NULL); c->obj = *(p++); PyList_Append(cats, (PyObject*)c); Py_DECREF(c); //? } - return cats; + return cats; */ + return gf_categories(self); } -static PyObject* +inline static PyObject* languages(PGFModule* self) { - PyObject *langs = PyList_New(0); - GF_Language *p = gf_languages(self->obj); + /* PyObject *langs = PyList_New(0); + PyGF **p = gf_languages(self); + // PyGF *q = p; while (*p) { - Lang* l = (Lang*)LangType.tp_new(&LangType,NULL,NULL); - l->obj = *(p++); - PyList_Append(langs, (PyObject*)l); - Py_DECREF(l); //?? - } - return langs; + printf("sp: %x\n", (*p)->sp); + //Lang* l = (Lang*)LangType.tp_new(&LangType,NULL,NULL); + //l->obj = (p++)->sp; + PyList_Append(langs, (PyObject*)(*(p++))); + // Py_DECREF(*(p++)); //?? + } + // gf_freeArray(q); */ + return gf_languages(self); } static PyObject* @@ -155,7 +107,7 @@ languageCode(PGFModule *self, PyObject *args) Lang *lang; if (!PyArg_ParseTuple(args, "O", &lang)) return NULL; - char* scode = gf_languageCode(self->obj, lang->obj); + char* scode = gf_languageCode(self, lang); if (scode) { PyObject* result = PyString_FromString(scode); free(scode); @@ -176,17 +128,17 @@ linearize(PGFModule *self, PyObject *args) return NULL; if (!checkType(lang,&LangType)) return NULL; if (!checkType(tree,&TreeType)) return NULL; - char* c_lin = gf_linearize(self->obj, lang->obj, tree->obj); + char* c_lin = gf_linearize(self, lang, tree); return PyString_FromString(c_lin); } static Lang* abstractName(PGFModule* self) { - Lang* abs = (Lang*)LangType.tp_new(&LangType,NULL,NULL); + Lang* abs_name = (Lang*)LangType.tp_new(&LangType,NULL,NULL); if (!checkType(self,&PGFType)) return NULL; - abs->obj = gf_abstractName(self->obj); - return abs; + gf_abstractName(self, abs_name); + return abs_name; } @@ -197,7 +149,7 @@ printName(PGFModule *self, PyObject *args) CId* id; if (!PyArg_ParseTuple(args, "OO", &lang, &id)) return NULL; - char *pname = gf_showPrintName(self->obj, lang->obj, id->obj); + char *pname = gf_showPrintName(self, lang, id); PyObject* result = PyString_FromString(pname); free(pname); return result; @@ -207,24 +159,23 @@ printName(PGFModule *self, PyObject *args) static PyObject* parse(PyObject *self, PyObject *args, PyObject *kws) { - PyObject *lang_pyob, *cat_pyob = NULL; - GF_PGF pgf; - GF_Language lang; - GF_Type cat; + PyObject *lang, *cat = NULL; + //GF_PGF pgf; + // GF_Language lang; + // GF_Type cat; char *lexed; static char *kwlist[] = {"lexed", "lang", "cat", NULL}; if (!PyArg_ParseTupleAndKeywords(args, kws, "sO|O", kwlist, - &lexed, &lang_pyob, &cat_pyob)) + &lexed, &lang, &cat)) return NULL; - if (!checkType(self, &PGFType)) return NULL; - if (!checkType(lang_pyob, &LangType)) return NULL; - if (cat_pyob) { - if (!checkType(cat_pyob, &gfTypeType)) return NULL; - cat = ((gfType*)cat_pyob)->obj; + if (!checkType(self, &PGFType)) return NULL; + if (!checkType(lang, &LangType)) return NULL; + if (cat) { + if (!checkType(cat, &gfTypeType)) return NULL; } else { - cat = startCategory(self,NULL)->obj; + cat = (PyObject*)startCategory(self,NULL); } - pgf = ((PGFModule*)self)->obj; + /* pgf = ((PGFModule*)self)->obj; lang = ((Lang*)lang_pyob)->obj; PyObject *parsed = PyList_New(0); GF_Tree *p = gf_parse(pgf,lang,cat,lexed); @@ -235,12 +186,13 @@ parse(PyObject *self, PyObject *args, PyObject *kws) expr->obj = *(p++); PyList_Append(parsed, (PyObject*)expr); Py_DECREF(expr); //?? - /* char *str = gf_showExpr(exp); - puts(str); - free(str); */ + // char *str = gf_showExpr(exp); + //puts(str); + //free(str); } while (*p); - } - return parsed; + } + return parsed; */ + return gf_parse(self, lang, cat, lexed); } static PGFModule* @@ -252,7 +204,7 @@ readPGF(PyObject *self, PyObject *args) return NULL; pgf = (PGFModule*)PGFType.tp_new(&PGFType,NULL,NULL); if (!pgf) return NULL; - pgf->obj = gf_readPGF(path); + gf_readPGF(pgf, path); return pgf; } @@ -270,7 +222,7 @@ static PyMethodDef pgf_methods[] = { {NULL, NULL, 0, NULL} /* Sentinel */ }; - +REPRCB(CId_repr, CId, gf_showCId) /* Language methods, constructor and destructor */ @@ -287,7 +239,7 @@ readLang(PyObject *self, PyObject *args) return NULL; l = (Lang*)LangType.tp_new(&LangType,NULL,NULL); if(!l) return NULL; - l->obj = gf_readLanguage(langName); + gf_readLanguage(l,langName); return l; } @@ -348,7 +300,7 @@ initgf(void) static char *argv[] = {"gf.so", 0}, **argv_ = argv; static int argc = 1; gf_init (&argc, &argv_); - hs_add_root (__stginit_PGFFFI); + hs_add_root (__stginit_PyGF); #define ADDTYPE(t) Py_INCREF(&t);\ PyModule_AddObject(m, "gf", (PyObject *)&t); @@ -359,3 +311,22 @@ PyModule_AddObject(m, "gf", (PyObject *)&t); ADDTYPE(TreeType) ADDTYPE(ExprType) } + + +inline Lang* newLang() { + return (Lang*)LangType.tp_new(&LangType,NULL,NULL); +} + +inline Tree* newTree() { + return (Tree*)TreeType.tp_new(&TreeType,NULL,NULL); +} + +inline CId* newCId() { + return (CId*)CIdType.tp_new(&CIdType,NULL,NULL); +} + +inline PyObject* newList() { return PyList_New(0); } + +void append(PyObject* l, PyObject* ob) { + PyList_Append(l, ob); +} diff --git a/contrib/py-bindings/mtest.c b/contrib/py-bindings/mtest.c deleted file mode 100644 index 58d582389..000000000 --- a/contrib/py-bindings/mtest.c +++ /dev/null @@ -1,65 +0,0 @@ -/* GF C Bindings - Copyright (C) 2008-2009 Kevin Kofler - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, see . -*/ - -#include -#include -#include "pygf.h" -//#include "gf_lexing.h" - -PyGF pgf, lang, cat; - -int main(int argc, char *argv[]) -{ - int has_lang; - gf_init(&argc, &argv); - printf("Passed init\n"); - gf_readPGF(&pgf, "Query.pgf"); - printf("passed readPGF\n"); - if (!gf_readLanguage(&lang, "QueryEng")) - return 1; - printf("passed readLanguage: %s\n", gf_showLanguage(&lang)); - gf_startCat(&pgf, &cat); - printf("passed startcat: %s\n", gf_showType(&cat)); - // char *lexed = gf_stringOp("lextext")("Is 2 prime"); - char lexed[] = "is 23 odd"; - PyGF *result = gf_parse(&pgf, &lang, &cat, &lexed); - int k; - for (k = 0; result[k].sp ; k++) { - char *str = gf_showExpr(&result[k]); - puts(str); - free(str); - printf("next: 0x%x\n",result[k+1].sp); - } - /* // free(lexed); - PyGF *p = result; - if (result[0]) { - int k = 0; - do { - printf("tree %d\n",++k); - char *str = gf_showExpr(*(p++)); - puts(str); - free(str); - } while (*p && k < 5); - } else - puts("no match"); - gf_freeTrees(result); */ - gf_freeType(&cat); - gf_freeLanguage(&lang); - gf_freePGF(&pgf); - gf_exit(); - return 0; -} diff --git a/contrib/py-bindings/pygf.h b/contrib/py-bindings/pygf.h index 3a63090ca..101674dfa 100644 --- a/contrib/py-bindings/pygf.h +++ b/contrib/py-bindings/pygf.h @@ -32,6 +32,7 @@ typedef struct { HsStablePtr sp; } PyGF; + #define NEWOBJECT(OBJ, GFTYPE) typedef struct {\ PyObject_HEAD \ GFTYPE obj; \ @@ -65,4 +66,27 @@ typedef struct { NEWTYPE(TYPE,NAME,OBJ,DOC) -NEWOBJECT(CID, GF_CId) +// NEWOBJECT(CID, GF_CId) + +#ifdef DEBUG +#define DEALLOCFN(delname,t,cb,cbname) static void \ +delname(t *self){ cb(self);\ + printf("gf_%s has been called for stable pointer 0x%x\n", cbname, self->obj);\ + self->ob_type->tp_free((PyObject*)self); } +#else +#define DEALLOCFN(delname,t,cb,cbname) static void \ +delname(t *self){ cb(self);\ + self->ob_type->tp_free((PyObject*)self); } +#endif + +#ifdef DEBUG +#define REPRCB(cbid,t,gfcb) static PyObject* \ +cbid(t *self) { \ + const char *str = gfcb(self); \ + return PyString_FromFormat("0x%x: %s", self->obj, str); } +#else +#define REPRCB(cbid,t,gfcb) static PyObject* \ +cbid(t *self) { \ + const char *str = gfcb(self); \ + return PyString_FromString(str); } +#endif