module Control.Distributed.Session.Eval (
evalSession,
evalSessionEq,
evalSessionEq'
) where
import Control.SessionTypes
import Control.SessionTypes.Indexed
import Control.SessionTypes.Types
import Control.Distributed.Session.STChannel
import Control.Distributed.Session.Session
import qualified Control.Distributed.Process as P
import Control.Distributed.Process.Serializable
import Data.Proxy (Proxy(..))
import qualified Prelude as PL
type SendPortST s = RemoveRecv (SendInsInt s)
type RecvPortST s = RemoveSend (RecvInsInt s)
type MapRecvPortST xs = MapRemoveSend (MapRecvInsInt xs)
evalSession :: forall s r a. HasConstraint Serializable s => Session s r a -> SessionInfo -> P.Process a
evalSession sess si =
let st = runSession sess (Just si)
(sp', rp') = toSTChanBi (utchan si) (Proxy :: Proxy (SendInsInt s)) (Proxy :: Proxy (RecvInsInt s))
in PL.fmap fst $ runSTChannelT (eval st) (sp', rp')
eval :: HasConstraint Serializable s => STTerm P.Process s r a ->
STChannelT P.Process (SendPortST s :*: RecvPortST s)
(SendPortST r :*: RecvPortST r)
a
eval (Send a r) = do
sendSTChanM a
eval r
eval (Recv r) = do
a <- recvSTChanM
eval (r a)
eval s@(Sel1 _) = unFoldSelect 0 s
eval s@(Sel2 _) = unFoldSelect 0 s
eval o@(OffS _ _) = do
x <- recvSTChanM
unFoldOffer x o
eval o@(OffZ _) = do
x <- recvSTChanM
unFoldOffer x o
eval (Rec s) = do
recChanM
eval s
eval (Weaken s) = do
wkChanM
eval s
eval (Var s) = do
varChanM
eval s
eval (Lift m) = do
st <- lift m
eval st
eval (Ret a) = do
return a
evalSessionEq :: Session s s a -> P.Process a
evalSessionEq sess = do
let st = runSession sess Nothing
evalST st
where
evalST :: STTerm P.Process s s a -> P.Process a
evalST (Ret a) = PL.return a
evalST (Lift m) = m PL.>>= evalST
evalSessionEq' :: Session s s a -> SessionInfo -> P.Process a
evalSessionEq' sess si = do
let st = runSession sess (Just si)
evalST st
where
evalST :: STTerm P.Process s s a -> P.Process a
evalST (Ret a) = PL.return a
evalST (Lift m) = m PL.>>= evalST
unFoldSelect :: (s ~ 'Cap ctx (Sel xs), HasConstraint Serializable s) =>
Int -> STTerm P.Process s r a ->
STChannelT P.Process (SendPortST s :*: RecvPortST s)
(SendPortST r :*: RecvPortST r)
a
unFoldSelect k (Sel1 s) = sel1ChanM >> sendSTChanM k >> eval s
unFoldSelect k (Sel2 s) = sel2ChanM >> unFoldSelect (k + 1) s
unFoldOffer :: (s ~ 'Cap ctx (Off xs), HasConstraint Serializable s) => Int -> STTerm P.Process s r a ->
STChannelT P.Process (SendPortST s :*: 'Cap (MapRecvPortST ctx) (Off (MapRecvPortST xs)))
(SendPortST r :*: RecvPortST r)
a
unFoldOffer _ (OffZ s) = off1ChanM >> eval s
unFoldOffer 0 (OffS s _) = off1ChanM >> eval s
unFoldOffer n (OffS _ xs) = off2ChanM >> unFoldOffer (n 1) xs
type family MapSendInsInt ss where
MapSendInsInt '[] = '[]
MapSendInsInt (s ': xs) = (Int :!> SendInsIntST s) ': MapSendInsInt xs
type family MapSendInsInt' ss where
MapSendInsInt' '[] = '[]
MapSendInsInt' (s ': xs) = SendInsIntST s ': MapSendInsInt' xs
type family SendInsInt c where
SendInsInt ('Cap ctx s) = 'Cap (MapSendInsInt' ctx) (SendInsIntST s)
type family SendInsIntCtx ctx where
SendInsIntCtx '[] = '[]
SendInsIntCtx (s ': ctx) = SendInsIntST s ': SendInsIntCtx ctx
type family SendInsIntST s where
SendInsIntST (a :!> r) = a :!> (SendInsIntST r)
SendInsIntST (a :?> r) = a :?> SendInsIntST r
SendInsIntST (Sel xs) = Sel (MapSendInsInt xs)
SendInsIntST (Off xs) = Off (MapSendInsInt' xs)
SendInsIntST (R s) = R (SendInsIntST s)
SendInsIntST (Wk s) = Wk (SendInsIntST s)
SendInsIntST V = V
SendInsIntST Eps = Eps
type family MapRecvInsInt ss where
MapRecvInsInt '[] = '[]
MapRecvInsInt (s ': xs) = RecvInsIntST s ': MapRecvInsInt xs
type family RecvInsInt c where
RecvInsInt ('Cap ctx s) = 'Cap (MapRecvInsInt ctx) (RecvInsIntST s)
type family RecvInsIntST s where
RecvInsIntST (a :!> r) = a :!> RecvInsIntST r
RecvInsIntST (a :?> r) = a :?> RecvInsIntST r
RecvInsIntST (Sel xs) = Sel (MapRecvInsInt xs)
RecvInsIntST (Off xs) = Int :?> (Off (MapRecvInsInt xs))
RecvInsIntST (R s) = R (RecvInsIntST s)
RecvInsIntST (Wk s) = Wk (RecvInsIntST s)
RecvInsIntST V = V
RecvInsIntST Eps = Eps