packages feed

berp-0.0.1: src/Berp/Interpreter/Monad.hs

-----------------------------------------------------------------------------
-- |
-- Module      : Berp.Interpreter.Monad
-- Copyright   : (c) 2010 Bernie Pope
-- License     : BSD-style
-- Maintainer  : florbitous@gmail.com
-- Stability   : experimental
-- Portability : ghc
--
-- Monad type and routines for the interpreter.
--
-----------------------------------------------------------------------------

module Berp.Interpreter.Monad (Repl, runRepl, withInputState) where

import Exception (ExceptionMonad (..))
import qualified MonadUtils as MU (MonadIO, liftIO)
import Control.Monad.Trans as MT (MonadIO (..))
import Control.Monad.State.Strict (StateT (..), evalStateT, gets, mapStateT) 
import GHC (GhcT, runGhcT)
import HscTypes (liftGhcT)
import System.Console.Haskeline as Haskeline (defaultSettings)
import System.Console.Haskeline.IO (initializeInput, InputState)
import Berp.Compile.Monad (Compile, runCompileMonad)

type Repl a = GhcT (StateT ReplState Compile) a

data ReplState = ReplState { repl_inputState :: !InputState }

runRepl :: Maybe FilePath -> Repl a -> IO a
runRepl filePath comp = do
   initInputState <- initializeInput defaultSettings
   let initReplState = ReplState { repl_inputState = initInputState }
   runCompileMonad $ (flip evalStateT) initReplState $ runGhcT filePath comp

withInputState :: (InputState -> Repl a) -> Repl a
withInputState f = do
   state <- liftGhcT $ gets repl_inputState
   f state

-- Ugliness because GHC has its own MonadIO class
instance MU.MonadIO m => MonadIO (GhcT m) where
   liftIO = MU.liftIO

instance MonadIO m => MU.MonadIO (StateT s m) where
   liftIO = MT.liftIO

instance ExceptionMonad m => ExceptionMonad (StateT s m) where
    gcatch f h = StateT $ \s -> gcatch (runStateT f s) (\e -> runStateT (h e) s)
    gblock = mapStateT gblock
    gunblock = mapStateT gunblock