summaryrefslogtreecommitdiff
path: root/contrib/py-bindings/PyGF.hsc
blob: fc827e68fdcd9701071946b00983042b4d8beb15 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
{-# LANGUAGE ForeignFunctionInterface #-} 
--
-- GF Python bindings
-- Jordi Saludes, upc.edu 2010, 2011
--

module PyGF where

import PGF
import Foreign
import CString
import Foreign.C.Types
import Control.Monad
import Data.Map (keys, (!))
import Data.Char (isSpace)

#include "pygf.h"

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
    --DEBUG putStrLn $ "freeing " ++ tname ++ " at " ++ (show p)

instance Storable PGF 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

instance Storable Type 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

instance Storable Language 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

instance Storable Tree 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

-- 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
gf_printCId p = do
    c <- peek p
    newCString (showCId c)
-}

foreign export ccall gf_readPGF :: CString -> IO (Ptr PGF)
gf_readPGF path = do
  ppgf <- pyPGF
  p <- peekCString path
  readPGF p >>= poke ppgf
  return ppgf
  
foreign export ccall gf_readLanguage :: Ptr Language -> CString -> IO Bool
gf_readLanguage pt str = do
  s <- (peekCString str)
  case (readLanguage s) of
    Just x -> do
            poke pt x
            return True
    Nothing -> return False

foreign export ccall gf_startCat :: Ptr PGF -> IO (Ptr Type)
gf_startCat ppgf = do
  pgf <- peek ppgf
  pcat <- pyType
  poke pcat (startCat pgf)
  return pcat

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
  --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)

listToPy :: Storable a => IO (Ptr a) -> [a] -> IO (Ptr ()) -- opaque -- IO (Ptr (Ptr Language))
listToPy mk ls = do
    pyls <- pyList
    mapM_ (mpoke pyls)  ls
    return pyls
  where  mpoke pyl l = do
          pl <- mk
          poke pl l
          pyl << pl
       

listToPyStrings :: [String] -> IO (Ptr ())
listToPyStrings ss = do
     pyls <- pyList
     mapM_ (mpoke pyls) ss
     return pyls
  where mpoke pyl s = do
  	      cs <- newCString s
	      pcs <- pyString cs
	      pyl << pcs

              
foreign export ccall gf_showLanguage :: Ptr Language -> IO CString
gf_showLanguage plang = do
  l <- peek plang
  newCString $ showLanguage l

foreign export ccall gf_showType :: Ptr Type -> IO CString
gf_showType ptp = do
  t <- peek ptp
  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 -> IO (Ptr Language)
gf_abstractName ppgf = do
  pabs <- pyLang
  pgf <- peek ppgf
  poke pabs $ abstractName pgf
  return pabs

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 export ccall gf_unapp :: Ptr Expr -> IO (Ptr ())
foreign export ccall gf_unint :: Ptr Expr -> IO CInt
foreign export ccall gf_unstr :: Ptr Expr -> IO CString

gf_unapp pexp = do
    exp <- peek pexp
    case unApp exp of
        Just (f,args) -> do
                   puexp <- pyList
                   pf <- pyCId
                   poke pf f
                   puexp << pf
                   mapM_ (\e -> do
                              pe <- pyExpr
                              poke pe e
                              puexp << pe) args 
                   return puexp
        Nothing -> return nullPtr
gf_unint pexp = do
    exp <- peek pexp
    return $ fromIntegral $ case unInt exp of
                              Just n -> n
                              _      -> (-9)
gf_unstr pexp = do
   exp <- peek pexp
   case unStr exp of
        Just s -> newCString s
        _      -> return nullPtr

foreign export ccall gf_inferexpr :: Ptr PGF -> Ptr Expr -> IO (Ptr Type)
gf_inferexpr ppgf pexp = do
    pgf <- peek ppgf
    exp <- peek pexp
    case inferExpr pgf exp of
      Right (_,t) -> do
                 ptype <- pyType
                 poke ptype t
                 return ptype
      Left _       -> return nullPtr 


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 export ccall gf_completions :: Ptr PGF -> Ptr Language -> Ptr Type -> CString -> IO (Ptr ())
gf_completions ppgf plang pcat ctoks = do
	pgf  <- peek ppgf
	lang <- peek plang
	cat  <- peek pcat
	toks <- peekCString ctoks
	let (rpre,rs) = break isSpace (reverse toks)
	    pre = reverse rpre
	    ws = words (reverse rs)
	    state0 = initState pgf lang cat
	    completions =
	    		case loop state0 ws of
	    		     Nothing    -> []
			     Just state -> keys $ getCompletions state pre
	listToPyStrings completions
   where
        loop ps []     = Just ps
        loop ps (w:ws) =
            case nextState ps (simpleParseInput w) of
                Left _   -> Nothing
                Right ps -> loop ps ws
 	
	
foreign import ccall "newLang" pyLang :: IO (Ptr Language) 
foreign import ccall "newPGF" pyPGF :: IO (Ptr PGF) 
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 ()) 
foreign import ccall "newString" pyString :: CString -> IO (Ptr ())
foreign import ccall "append" (<<) :: Ptr () -> Ptr a -> IO ()