@@ -47,6 +47,7 @@ import Data.Binary (encode, decode)
47import qualified Data.Map as Map (insert)
47import qualified Data.Map as Map (insert)
48import Data.Dynamic (toDyn)
48import Data.Dynamic (toDyn)
49import Control.Applicative ((<$>))
49import Control.Applicative ((<$>))
50+import Control.Monad (join)
50import Language.Haskell.TH
51import Language.Haskell.TH
51 ( -- Q monad and operations
52 ( -- Q monad and operations
@@ -77,7 +78,11 @@ import Control.Distributed.Process.Internal.Types
77 ( RemoteTable
78 ( RemoteTable
78 , Closure(..)
79 , Closure(..)
79 , Static(..)
80 , Static(..)
85+import Control.Distributed.Process (send, unClosure)
82--------------------------------------------------------------------------------
87--------------------------------------------------------------------------------
83-- Top-level API --
88-- Top-level API --
@@ -87,9 +92,9 @@ import Control.Distributed.Process.Internal.Types
87-- of functions
92-- of functions
88remotable :: [Name] -> Q [Dec]
93remotable :: [Name] -> Q [Dec]
89remotable ns = do
94remotable ns = do
90− (closures, decoders, inserts) <- unzip3 <$> mapM process ns
95+ (closures, inserts) <- unzip <$> mapM generateDefs ns
91− rtable <- createMetaData inserts
96+ rtable <- createMetaData (concat inserts)
92− return $ concat closures ++ concat decoders ++ rtable
97+ return $ concat closures ++ rtable
94-- | Create a closure
99-- | Create a closure
95mkClosure :: Name -> Q Exp
100mkClosure :: Name -> Q Exp
@@ -110,22 +115,36 @@ createMetaData is =
111-- Given an (f :: a -> b) in module M, create:
116-- Given an (f :: a -> b) in module M, create:
112-- 1. f__closure :: a -> Closure b,
117-- 1. f__closure :: a -> Closure b,
113−-- 2. f__dec :: ByteString -> b
114−-- 3. Map.insert "M.f" (toDyn f__dec)
118+-- 2. Map.insert "M.f" (toDyn ((f . enc) :: ByteString -> b))
120+-- Moreover, if b is of the form Process c, then additionally create
121+-- 3. Map.insert "M.f__call" (... :: ByteString -> Process ())
122+-- (see 'generateCallClosure')
115−process :: Name -> Q ([Dec], [Dec], Q Exp)
123+generateDefs :: Name -> Q ([Dec], [Q Exp])
116−process n = do
124+generateDefs n = do
117 mType <- getType n
125 mType <- getType n
118 case mType of
126 case mType of
119 Just (origName, ArrowT `AppT` arg `AppT` res) -> do
127 Just (origName, ArrowT `AppT` arg `AppT` res) -> do
120 (closure, label) <- generateClosure origName (return arg) (return res)
128 (closure, label) <- generateClosure origName (return arg) (return res)
121− decoder <- generateDecoder origName (return res)
129+ let decoder = generateDecoder origName (return res)
122− let decoderE = varE (decoderName n)
130+ insert = [| Map.insert $(stringE label) (toDyn $decoder) |]
132+ -- Generate special closure to support 'call'
133+ mResult <- processResult res
134+ insert' <- case mResult of
138+ let encoder = generateCallClosure origName (return result)
139+ label' = label ++ "__call"
123− insert = [| Map.insert $(stringE label) (toDyn $decoderE) |]
141+ [| Map.insert $(stringE label') (toDyn $encoder) |]
124− return (closure, decoder, insert)
143+ return (closure, insert : insert')
126 fail $ "remotable: " ++ show n ++ " is not a function"
145 fail $ "remotable: " ++ show n ++ " is not a function"
128−-- | Generate the closure creator (see 'process')
147+-- | Generate the closure creator (see 'generateDefs')
129generateClosure :: Name -> Q Type -> Q Type -> Q ([Dec], String)
148generateClosure :: Name -> Q Type -> Q Type -> Q ([Dec], String)
130generateClosure n arg res = do
149generateClosure n arg res = do
131 closure <- sequence
150 closure <- sequence
@@ -137,12 +156,26 @@ generateClosure n arg res = do
137 label :: String
156 label :: String
138 label = show $ n
157 label = show $ n
159+-- | If 't' is of the form 'Process b', return 'Just b'
160+processResult :: Type -> Q (Maybe Type)
162+ process <- [t| Process |]
164+ p `AppT` a | p == process -> return $ Just a
140−-- | Generate the decoder (see 'process')
167+-- | Generate the decoder (see 'generateDefs')
141−generateDecoder :: Name -> Q Type -> Q [Dec]
168+generateDecoder :: Name -> Q Type -> Q Exp
142−generateDecoder n res = do
169+generateDecoder n res = [| $(varE n) . decode :: ByteString -> $res |]
143− sequence [ sigD (decoderName n) [t| ByteString -> $res |]
170+
144− , sfnD (decoderName n) [| $(varE n) . decode |]
171+-- | Generate the call-closure. This is necessary to support 'call'
172+generateCallClosure :: Name -> Q Type -> Q Exp
173+generateCallClosure n t =
175+ let (cl, them) = decode env :: (Closure (Process $t), ProcessId)
176+ join (unClosure cl) >>= send them . CallReply
177+ ) :: ByteString -> Process ()
147-- | The name for the function that generates the closure
180-- | The name for the function that generates the closure
148closureName :: Name -> Name
181closureName :: Name -> Name