-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathRE.hs
139 lines (120 loc) · 3.99 KB
/
RE.hs
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
{-# LANGUAGE ForeignFunctionInterface #-}
module RE where
import System.Plugins.Load
import System.Plugins.Make
import Data.Map
import Data.Maybe
import System.Directory
import System.FileLock
import Control.Monad.Trans.State
import Control.Monad.IO.Class
import Foreign
import Foreign.StablePtr
import Foreign.Ptr
import Foreign.C.Types
import Foreign.C.String
import Foreign.Marshal.Array
import RETypes
type CallbackFunctionType = Ptr () -> CString -> CInt -> Ptr CString -> IO CInt
foreign import ccall "dynamic" mkCallbackFunctionType :: FunPtr CallbackFunctionType -> CallbackFunctionType
foreign export ccall c_start :: CString -> IO (Ptr ())
foreign export ccall c_stop :: Ptr () -> IO ()
foreign export ccall c_ruleExists :: Ptr () -> CString -> IO CInt
foreign export ccall c_execRule :: Ptr () -> CString -> CInt -> Ptr CString -> Ptr () -> FunPtr CallbackFunctionType -> IO CInt
wrapCallbackFunction :: FunPtr CallbackFunctionType -> Ptr () -> Callback
wrapCallbackFunction cb cbSt fn ps = do
fnCString <- newCString fn
psCString <- mapM newCString ps
psArray <- newArray psCString
CInt errcode <- mkCallbackFunctionType cb cbSt fnCString (length ps) psArray
psCString' <- peekArray (length ps) psArray
ps' <- mapM peekCString psCString'
mapM free psCString'
free psArray
return (fromIntegral errcode, ps')
c_start :: CString -> IO (Ptr ())
c_start cobj = do
obj <- peekCString cobj
reSt <- hsStart obj
reStStablePtr <- newStablePtr reSt
let reStPtr = castStablePtrToPtr reStStablePtr
return reStPtr
c_stop :: Ptr () -> IO ()
c_stop reStPtr = do
let reStStablePtr = castPtrToStablePtr reStPtr
-- reSt <- deRefStablePtr reStStablePtr
freeStablePtr reStStablePtr
c_ruleExists :: Ptr () -> CString -> IO CInt
c_ruleExists reStPtr rnCString = do
let reStStablePtr = castPtrToStablePtr reStPtr
reSt <- deRefStablePtr reStStablePtr
rn <- peekCString rnCString
ret <- evalStateT (hsRuleExists rn) reSt
return (CInt (if ret then 1 else 0))
c_execRule :: Ptr () -> CString -> CInt -> Ptr CString -> Ptr () -- callback state
-> FunPtr CallbackFunctionType -> IO CInt
c_execRule reStPtr rnCString (CInt n) psArray cbSt cb = do
let cbHs = wrapCallbackFunction cb cbSt
let reStStablePtr = castPtrToStablePtr reStPtr
reSt <- deRefStablePtr reStStablePtr
rn <- peekCString rnCString
psCString <- peekArray (fromIntegral n) psArray
ps <- mapM peekCString psCString
(errcode, ps') <- evalStateT (hsExecRule rn ps) (cbHs, reSt)
mapM free psCString
psCString' <- mapM newCString ps'
pokeArray psArray psCString'
return (CInt (fromInteger (toInteger errcode)))
remake :: String -> String -> IO Bool
remake objhs objo = do
hstime <- getModificationTime objhs
exist <- doesFileExist objo
if exist
then do
otime <- getModificationTime objo
return (otime <= hstime)
else
return True
hsMake :: String -> IO ()
hsMake obj = do
let objhs = obj ++ ".hs"
let objo = obj ++ ".o"
rem <- remake objhs objo
if rem
then do
withFileLock objhs Exclusive (\_ -> do
rem <- remake objhs objo
if rem
then do
putStrLn "recompiling"
make objhs ["-dynamic", "-fPIC"]
return ()
else
return ())
else
return ()
hsLoad :: String -> IO Module
hsLoad obj = do
h <- load_ (obj ++ ".o") [] "irods"
case h of
LoadSuccess m _ -> return m
LoadFailure msg -> error (show msg)
hsStart :: String -> IO ReState
hsStart obj = do
hsMake obj
m <- hsLoad obj
return (ReState m empty)
hsStop :: ReState -> IO ()
hsStop state = return ()
hsRuleExists :: String -> StateT ReState IO Bool
hsRuleExists rn = do
ReState m props <- get
rm <- liftIO (loadFunction m rn)
return (isJust rm)
hsExecRule :: String -> [ParamType] -> RE (ErrorCode, [ParamType])
hsExecRule rn ps = do
(_, ReState m props) <- get
rm <- liftIO (loadFunction m rn)
case rm of
Just r -> (r :: RuleType) ps
Nothing -> return (0 - 1, ps)