module Control.SessionTypes.Interactive (
interactive,
interactiveStep
) where
import Control.SessionTypes.STTerm
import Control.SessionTypes.Types
import qualified Control.SessionTypes.Indexed as I
import Control.SessionTypes.MonadSession
import Control.Monad.Trans.Maybe (MaybeT(..), runMaybeT)
import Control.Monad.IO.Class (MonadIO, liftIO)
import Data.Proxy (Proxy (..))
import Data.Typeable (Typeable, typeRep)
import Text.Read (readMaybe)
interactive :: (MonadIO m, HasConstraints '[Read, Show, Typeable] s, Show a) => STTerm m s r a -> m a
interactive (Send _ r) = interactive r
interactive r@(Recv c) = do
liftIO $ putStr $ "Enter value of type " ++ typeShow r ++ ": "
ma <- liftIO $ fmap readMaybe getLine
case ma of
Nothing -> interactive r
Just a -> interactive $ c a
where typeShow :: forall m ctx a r k b. Typeable a => STTerm m ('Cap ctx (a :?> r)) k b -> String
typeShow _ = show $ typeRep (Proxy :: Proxy a)
interactive (Sel1 s) = interactive s
interactive (Sel2 r) = interactive r
interactive (OffZ s) = interactive s
interactive (OffS s xs) = do
liftIO $ putStr $ "(L)eft or (R)ight: "
lr <- liftIO getLine
case lr of
"L" -> interactive s
"Left" -> interactive s
"R" -> interactive xs
"Right" -> interactive xs
_ -> do
liftIO $ putStrLn "Invalid option"
interactive (OffS s xs)
interactive (Rec s) = interactive s
interactive (Weaken s) = interactive s
interactive (Var s) = interactive s
interactive (Lift m) = m >>= interactive
interactive (Ret a) = return a
interactiveStep :: (MonadIO m, HasConstraints '[Read, Show, Typeable] s, Show a) => STTerm m s r a -> m (Maybe a)
interactiveStep st = runMaybeT (interactiveStep' st)
interactiveStep' :: (MonadIO m, HasConstraints '[Read, Show, Typeable] s, Show a) => STTerm m s r a -> MaybeT m a
interactiveStep' s@(Send a r) = do
printST s
waitStep
interactiveStep' r
interactiveStep' s@(Recv r) = do
printST s
ma <- liftIO $ fmap readMaybe getLine
case ma of
Nothing -> interactiveStep' s
Just a -> waitStep >> interactiveStep' (r a)
interactiveStep' s@(Sel1 r) = do
printST s
waitStep
interactiveStep' r
interactiveStep' s@(Sel2 r) = do
printST s
waitStep
interactiveStep' r
interactiveStep' (OffZ r) = interactiveStep' r
interactiveStep' s@(OffS r xs) = do
printST s
lr <- liftIO getLine
if lr `elem` ["L","Left"]
then waitStep >> interactiveStep' r
else if lr `elem` ["R","Right"]
then waitStep >> interactiveStep' xs
else do
liftIO $ putStrLn "Invalid option"
interactiveStep' (OffS s xs)
interactiveStep' s@(Rec r) = do
printST s
waitStep
interactiveStep' r
interactiveStep' s@(Weaken r) = do
printST s
waitStep
interactiveStep' r
interactiveStep' s@(Var r) = do
printST s
waitStep
interactiveStep' r
interactiveStep' s@(Lift m) = do
printST s
waitStep
MaybeT $ m >>= \st -> runMaybeT $ interactiveStep' st
interactiveStep' s@(Ret a) = do
printST s
return a
printST :: (MonadIO m, HasConstraints [Typeable, Show] s, Show a) => STTerm m s r a -> MaybeT m ()
printST (Send a _) = liftIO $ putStrLn $ "> Send value " ++ show a
printST r@(Recv _) = liftIO $ putStr $ "?> Enter value of type " ++ typeShow r ++ ": "
where typeShow :: forall m ctx a r k b. Typeable a => STTerm m ('Cap ctx (a :?> r)) k b -> String
typeShow _ = show $ typeRep (Proxy :: Proxy a)
printST (Sel1 _) = liftIO $ putStrLn "> Select1"
printST (Sel2 _) = liftIO $ putStrLn "> Select2"
printST (OffZ _) = return ()
printST (OffS _ _) = liftIO $ putStr $ "?> (L)eft or (R)ight: "
printST (Rec _) = liftIO $ putStrLn "> Recurse"
printST (Weaken _) = liftIO $ putStrLn "> Weaken"
printST (Var _) = liftIO $ putStrLn "> Var"
printST (Lift _) = liftIO $ putStrLn $ "> Lifted"
printST (Ret a) = liftIO $ putStrLn $ "> Returned: " ++ show a
waitStep :: MonadIO m => MaybeT m ()
waitStep = do
liftIO $ putStrLn "?> Press n to continue or q to quit."
line <- liftIO $ getLine
case line of
"n" -> return ()
"q" -> MaybeT $ return Nothing
_ -> waitStep