{-# LANGUAGE OverloadedStrings #-}
module Monad where
import Agda.IR
import Agda.Interaction.Base (IOTCM)
import Agda.TypeChecking.Monad (TCMT)
import Control.Concurrent
import Server.ResponseController (ResponseController)
import qualified Server.ResponseController as ResponseController
import Server.CommandController (CommandController)
import qualified Server.CommandController as CommandController
import Control.Monad.Reader
import Data.Text (Text, pack)
--------------------------------------------------------------------------------
data Env = Env
{ envLogChan :: Chan Text,
envCommandController :: CommandController,
envResponseChan :: Chan Response,
envResponseController :: ResponseController,
envDevMode :: Bool
}
createInitEnv :: Bool -> IO Env
createInitEnv devMode =
Env <$> newChan
<*> CommandController.new
<*> newChan
<*> ResponseController.new
<*> pure devMode
--------------------------------------------------------------------------------
-- | OUR monad
type ServerM m = ReaderT Env m
runServerM :: Env -> ServerM m a -> m a
runServerM = flip runReaderT
--------------------------------------------------------------------------------
writeLog :: (Monad m, MonadIO m) => Text -> ServerM m ()
writeLog msg = do
chan <- asks envLogChan
liftIO $ writeChan chan msg
writeLog' :: (Monad m, MonadIO m, Show a) => a -> ServerM m ()
writeLog' x = do
chan <- asks envLogChan
liftIO $ writeChan chan $ pack $ show x
-- | Provider
provideCommand :: (Monad m, MonadIO m) => IOTCM -> ServerM m ()
provideCommand iotcm = do
controller <- asks envCommandController
liftIO $ CommandController.put controller iotcm
-- | Consumter
consumeCommand :: (Monad m, MonadIO m) => Env -> m IOTCM
consumeCommand env = liftIO $ CommandController.take (envCommandController env)
waitUntilResponsesSent :: (Monad m, MonadIO m) => ServerM m ()
waitUntilResponsesSent = do
controller <- asks envResponseController
liftIO $ ResponseController.setCheckpointAndWait controller
signalCommandFinish :: (Monad m, MonadIO m) => ServerM m ()
signalCommandFinish = do
writeLog "[Command] Finished"
-- send `ResponseEnd`
env <- ask
liftIO $ writeChan (envResponseChan env) ResponseEnd
-- allow the next Command to be consumed
liftIO $ CommandController.release (envCommandController env)
sendResponse :: (Monad m, MonadIO m) => Env -> Response -> TCMT m ()
sendResponse env reaction = do
liftIO $ writeChan (envResponseChan env) reaction