@@ -10,7 +10,6 @@ module Control.Distributed.Process.Internal.Closure.TH
10import Prelude hiding (lookup)
10import Prelude hiding (lookup)
11import Data.ByteString.Lazy (ByteString)
11import Data.ByteString.Lazy (ByteString)
12import Data.Binary (encode, decode)
12import Data.Binary (encode, decode)
13−import Data.Typeable (typeOf, Typeable, TypeRep)
14import Data.Accessor ((^=))
13import Data.Accessor ((^=))
15import Control.Applicative ((<$>))
14import Control.Applicative ((<$>))
16import Language.Haskell.TH
15import Language.Haskell.TH
@@ -46,11 +45,12 @@ import Control.Distributed.Process.Internal.Types
46 , StaticLabel(..)
45 , StaticLabel(..)
48 , ProcessId
47 , ProcessId
51 , Identifier(ProcessIdentifier)
49 , Identifier(ProcessIdentifier)
52 , remoteTableLabel
50 , remoteTableLabel
53− , remoteTableSender
51+ , remoteTableDict
52+ , SerializableDict(..)
53+ , RuntimeSerializableSupport(..)
55import Control.Distributed.Process.Internal.Dynamic (Dynamic, toDyn)
55import Control.Distributed.Process.Internal.Dynamic (Dynamic, toDyn)
56import Control.Distributed.Process.Internal.MessageT (sendMessage)
56import Control.Distributed.Process.Internal.MessageT (sendMessage)
@@ -64,10 +64,13 @@ import Control.Distributed.Process.Internal.MessageT (sendMessage)
64remotable :: [Name] -> Q [Dec]
64remotable :: [Name] -> Q [Dec]
65remotable ns = do
65remotable ns = do
66 (closures, inserts) <- unzip <$> mapM generateDefs ns
66 (closures, inserts) <- unzip <$> mapM generateDefs ns
67− rtable <- createMetaData (concat inserts)
67+ rtable <- createMetaData inserts
68 return $ concat closures ++ rtable
68 return $ concat closures ++ rtable
70-- | Create a closure
70-- | Create a closure
72+-- If @f :: a -> b@ then @mkClosure :: a -> Closure b@. Make sure to pass 'f'
73+-- as an argument to 'remotable' too.
71mkClosure :: Name -> Q Exp
74mkClosure :: Name -> Q Exp
72mkClosure = varE . closureName
75mkClosure = varE . closureName
@@ -90,26 +93,18 @@ createMetaData is =
91-- Moreover, if b is of the form Process c, then additionally create
94-- Moreover, if b is of the form Process c, then additionally create
92-- 3. registerSender (Process c) (send :: ProcessId -> c -> Process ())
95-- 3. registerSender (Process c) (send :: ProcessId -> c -> Process ())
93−generateDefs :: Name -> Q ([Dec], [Q Exp])
96+generateDefs :: Name -> Q ([Dec], Q Exp)
94generateDefs n = do
97generateDefs n = do
98+ serializableDict <- [t| SerializableDict |]
95 mType <- getType n
99 mType <- getType n
96 case mType of
100 case mType of
97 Just (origName, ArrowT `AppT` arg `AppT` res) -> do
101 Just (origName, ArrowT `AppT` arg `AppT` res) -> do
98 (closure, label) <- generateClosure origName (return arg) (return res)
102 (closure, label) <- generateClosure origName (return arg) (return res)
99 let decoder = generateDecoder origName (return res)
103 let decoder = generateDecoder origName (return res)
100 insert = [| registerLabel $(stringE label) (toDyn $decoder) |]
104 insert = [| registerLabel $(stringE label) (toDyn $decoder) |]
101−
105+ return (closure, insert)
102− -- Generate special closure to support 'call'
106+ Just (origName, sdict `AppT` a) | sdict == serializableDict ->
103− mResult <- processResult res
107+ return ([], [| registerSerializableDict $(varE n) |])
104− insert' <- case mResult of
108− let sender = generateSender result
110− [| registerSender $(typeToTypeRep res) (toDyn $sender) |]
112− return (closure, insert : insert')
114 fail $ "remotable: " ++ show n ++ " is not a function"
109 fail $ "remotable: " ++ show n ++ " is not a function"
@@ -125,25 +120,10 @@ generateClosure n arg res = do
125 label :: String
120 label :: String
126 label = show $ n
121 label = show $ n
128−-- | If 't' is of the form 'Process b', return 'Just b'
129−processResult :: Type -> Q (Maybe (Q Type))
131− process <- [t| Process |]
133− p `AppT` a | p == process -> return . Just . return $ a
136-- | Generate the decoder (see 'generateDefs')
123-- | Generate the decoder (see 'generateDefs')
137generateDecoder :: Name -> Q Type -> Q Exp
124generateDecoder :: Name -> Q Type -> Q Exp
138generateDecoder n res = [| $(varE n) . decode :: ByteString -> $res |]
125generateDecoder n res = [| $(varE n) . decode :: ByteString -> $res |]
140−-- | Generate the sender. This is necessary to support 'call'
141−generateSender :: Q Type -> Q Exp
143− -- This duplicates the functionality of 'Process.send', but gets the TH out
144− -- of the mutually recursive module cycle
145− [| (\pid msg -> procMsg $ sendMessage (ProcessIdentifier pid) (CallReply msg)) :: ProcessId -> $tp -> Process () |]
147-- | The name for the function that generates the closure
127-- | The name for the function that generates the closure
148closureName :: Name -> Name
128closureName :: Name -> Name
149closureName n = mkName $ nameBase n ++ "__closure"
129closureName n = mkName $ nameBase n ++ "__closure"
@@ -151,16 +131,25 @@ closureName n = mkName $ nameBase n ++ "__closure"
151registerLabel :: String -> Dynamic -> RemoteTable -> RemoteTable
131registerLabel :: String -> Dynamic -> RemoteTable -> RemoteTable
152registerLabel label dyn = remoteTableLabel label ^= Just dyn
132registerLabel label dyn = remoteTableLabel label ^= Just dyn
154−registerSender :: TypeRep -> Dynamic -> RemoteTable -> RemoteTable
134+registerSerializableDict :: forall a. SerializableDict a -> RemoteTable -> RemoteTable
155−registerSender typ dyn = remoteTableSender typ ^= Just dyn
135+registerSerializableDict (SerializableDict label) =
136+ -- TODO: Code duplication with Process
137+ let send :: ProcessId -> a -> Process ()
138+ send pid a = procMsg $ sendMessage (ProcessIdentifier pid) a
140+ ret :: ByteString -> Process a
141+ ret = return . decode
143+ rss = RuntimeSerializableSupport {
144+ rssSend = toDyn send
145+ , rssReturn = toDyn ret
147+ in remoteTableDict label ^= Just rss
157--------------------------------------------------------------------------------
149--------------------------------------------------------------------------------
158-- Generic Template Haskell auxiliary functions --
150-- Generic Template Haskell auxiliary functions --
159--------------------------------------------------------------------------------
151--------------------------------------------------------------------------------
161−typeToTypeRep :: Type -> Q Exp
162−typeToTypeRep tp = [| typeOf (undefined :: $(return tp)) |]
164-- | Compose a set of expressions
153-- | Compose a set of expressions
165compose :: [Q Exp] -> Q Exp
154compose :: [Q Exp] -> Q Exp
166compose [] = [| id |]
155compose [] = [| id |]