fibon-0.2.0: lib/Fibon/ConfigMonad.hs
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
module Fibon.ConfigMonad (
FlagParameter(..)
, FlagConfig(..)
, Configuration
, ConfigState(..)
, ConfigMonad
, done
, append
, replace
, setTimeout
, runWithInitialFlags
, collectExtraStatsFrom
, noExtraStats
, useGhcDir
, useGhcInPlaceDir
, getEnv
)
where
import Control.Monad.State
import qualified Data.Map as Map
import Fibon.FlagConfig
import Fibon.Timeout
import System.FilePath
data FlagParameter =
ConfigureFlags
| BuildFlags
| RunFlags
deriving (Show, Eq, Ord, Enum)
newtype GenConfigMonad a = CM {
configState :: (State (ConfigState ConfigMap) a)
}
deriving (Monad)
data ConfigState a = ConfigState {
flags :: a
, limit :: Timeout
, extraStatsFile :: Maybe FilePath
, environment :: [(String, String)]
}
type ConfigMap = Map.Map FlagParameter [String]
type ConfigMonad = GenConfigMonad ()
type Configuration = ConfigState FlagConfig
done :: ConfigMonad
done = CM (return ())
replace :: FlagParameter -> String -> ConfigMonad
replace p f = CM $
modify $ (\c -> c {flags = Map.insert p [f] (flags c)})
append :: FlagParameter -> String -> ConfigMonad
append p f = CM $
modify $ (\c -> c {flags = Map.insertWith (flip (++)) p as (flags c)})
where as = words f
setTimeout :: Timeout -> ConfigMonad
setTimeout t = CM $
modify $ (\c -> c {limit = t})
collectExtraStatsFrom :: FilePath -> ConfigMonad
collectExtraStatsFrom f = CM $
modify $ (\c -> c {extraStatsFile = Just f})
noExtraStats :: ConfigMonad
noExtraStats = CM $
modify $ (\c -> c {extraStatsFile = Nothing})
useGhcDir :: FilePath -> ConfigMonad
useGhcDir dir = do
append ConfigureFlags $ "--with-ghc="++(dir </> "ghc")
append ConfigureFlags $ "--with-ghc-pkg="++(dir </> "ghc-pkg")
useGhcInPlaceDir :: FilePath -> ConfigMonad
useGhcInPlaceDir dir = do
append ConfigureFlags $ "--with-ghc="++(dir </> "ghc-stage2")
append ConfigureFlags $ "--with-ghc-pkg="++(dir </> "ghc-pkg")
getEnv :: String -> GenConfigMonad (Maybe String)
getEnv s = CM $ do
e <- gets environment
return (lookup s e)
runWithInitialFlags :: FlagConfig -> [(String, String)] -> ConfigMonad -> Configuration
runWithInitialFlags fc progEnv cm = toConfig finalState
where
startState = ConfigState {
flags = fromFlagConfig fc
, limit = Infinity
, extraStatsFile = Nothing
, environment = progEnv
}
finalState = execState (configState cm) startState
toConfig :: (ConfigState ConfigMap) -> Configuration
toConfig state = state {
flags =
FlagConfig {
configureFlags = Map.findWithDefault [] ConfigureFlags configMap
, buildFlags = Map.findWithDefault [] BuildFlags configMap
, runFlags = Map.findWithDefault [] RunFlags configMap
}
}
where
configMap = flags state
fromFlagConfig :: FlagConfig -> ConfigMap
fromFlagConfig fc =
Map.insert ConfigureFlags (configureFlags fc) $
Map.insert BuildFlags (buildFlags fc) $
Map.insert RunFlags (runFlags fc) $
Map.empty