g2-0.2.0.0: src/G2/Language/Monad/Support.hs
{-# LANGUAGE FunctionalDependencies #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE UndecidableInstances #-}
module G2.Language.Monad.Support ( StateT
, StateM
, StateNGT
, StateNG
, NameGenT
, NameGenM
, NamingM (..)
, ExprEnvM (..)
, ExState (..)
, FullState (..)
, runStateM
, execStateM
, runNamingM
, runNamingT
, runExprEnvM
, runStateMInNamingM
, runStateNG
, execStateNG
, readRecord
, withNG
, mapCurrExpr
, insertPC
, insertPCStateNG
, mapMAccumB ) where
import Control.Monad.Identity
import qualified Control.Monad.State.Lazy as SM
import G2.Language.Naming
import qualified G2.Language.PathConds as PC
import G2.Language.Syntax
import G2.Language.Support
import G2.Language.TypeClasses
-- | A wrapper for `State`, allowing it to be used as a monadic context.
type StateT t m a = SM.StateT (State t, Bindings) m a
type StateM t a = StateT t Identity a
type StateNGT t m a = SM.StateT (State t, NameGen) m a
type StateNG t a = StateNGT t Identity a
-- | A wrapper for `NameGen`, allowing it to be used as a monadic context.
type NameGenT m a = SM.StateT NameGen m a
type NameGenM a = NameGenT Identity a
-- | A wrapper for `ExprEnv`, allowing it to be used as a monadic context.
type EET m a = SM.StateT ExprEnv m a
type EEM a = EET Identity a
-- instance SM.MonadState (State t, Bindings) (SM.State (State t, Bindings)) where
-- state f = StateM (SM.state f)
-- instance SM.MonadState (State t, NameGen) (SM.State (State t, NameGen)) where
-- state f = StateNG (SM.state f)
-- instance SM.MonadState NameGen (SM.State NameGen) where
-- state f = NameGenM (SM.state f)
-- We split the State Monad into two pieces, so we can use it in the
-- initialization stage of G2 (in this stage, we do not have an entire State.
-- See G2.Initialization.Types), or so that we can just use it with smaller
-- pieces of a state.
class Monad m => NamingM s m | m -> s where
nameGen :: m NameGen
putNameGen :: NameGen -> m ()
class Monad m => ExprEnvM s m | m -> s where
exprEnv :: m ExprEnv
putExprEnv :: ExprEnv -> m ()
-- | Allows access to certain basic components of a state.
class (ExprEnvM s m, NamingM s m) => ExState s m | m -> s where
typeEnv :: m TypeEnv
putTypeEnv :: TypeEnv -> m ()
knownValues :: m KnownValues
putKnownValues :: KnownValues -> m ()
typeClasses :: m TypeClasses
putTypeClasses :: TypeClasses -> m ()
-- Extends `ExState`, allowing access to a more complete set of the
-- components in the `State`.
class ExState s m => FullState s m | m -> s where
currExpr :: m CurrExpr
putCurrExpr :: CurrExpr -> m ()
pathConds :: m PathConds
putPathConds :: PathConds -> m ()
inputNames :: m [Name]
fixedInputs :: m [Expr]
instance Monad m => NamingM NameGen (SM.StateT NameGen m) where
nameGen = SM.get
putNameGen = SM.put
instance Monad m => NamingM (State t, Bindings) (SM.StateT (State t, Bindings) m) where
nameGen = readRecord (\(_, b) -> name_gen b)
putNameGen = rep_name_genM
instance Monad m => NamingM (State t, NameGen) (SM.StateT (State t, NameGen) m) where
nameGen = readRecord (\(_, ng) -> ng)
putNameGen = rep_name_genNG
instance ExprEnvM (State t, Bindings) (SM.State (State t, Bindings)) where
exprEnv = readRecord (\(s, _) -> expr_env s)
putExprEnv = rep_expr_envM
instance ExprEnvM (State t, NameGen) (SM.State (State t, NameGen)) where
exprEnv = readRecord (\(s, _) -> expr_env s)
putExprEnv = rep_expr_envNG
instance ExState (State t, Bindings) (SM.State (State t, Bindings)) where
typeEnv = readRecord (\(s, _) -> type_env s)
putTypeEnv = rep_type_envM
knownValues = readRecord (\(s, _) -> known_values s)
putKnownValues = rep_known_valuesM
typeClasses = readRecord (\(s, _) -> type_classes s)
putTypeClasses = rep_type_classesM
instance ExState (State t, NameGen) (SM.State (State t, NameGen)) where
typeEnv = readRecord (\(s, _) -> type_env s)
putTypeEnv = rep_type_envNG
knownValues = readRecord (\(s, _) -> known_values s)
putKnownValues = rep_known_valuesNG
typeClasses = readRecord (\(s, _) -> type_classes s)
putTypeClasses = rep_type_classesNG
instance FullState (State t, Bindings) (SM.State (State t, Bindings)) where
currExpr = readRecord (\(s, _) -> curr_expr s)
putCurrExpr = rep_curr_exprM
pathConds = readRecord (\(s, _) -> path_conds s)
putPathConds = rep_path_condsM
inputNames = readRecord (\(_, b) -> input_names b)
fixedInputs = readRecord (\(_,b) -> fixed_inputs b)
runStateM :: StateM t a -> State t -> Bindings -> (a, (State t, Bindings))
runStateM s s' b = SM.runState s (s', b)
execStateM :: StateM t a -> State t -> Bindings -> (State t, Bindings)
execStateM s = (\lh_s b -> snd (runStateM s lh_s b))
runStateNG :: StateNG t a -> State t -> NameGen -> (a, (State t, NameGen))
runStateNG s s' ng = SM.runState s (s', ng)
execStateNG :: StateNG t a -> State t -> NameGen -> (State t, NameGen)
execStateNG s = (\lh_s ng -> snd (runStateNG s lh_s ng))
runNamingT :: NameGenT m a -> NameGen -> m (a, NameGen)
runNamingT s = SM.runStateT s
runNamingM :: NameGenM a -> NameGen -> (a, NameGen)
runNamingM s = SM.runState s
runExprEnvM :: EEM a -> ExprEnv -> (a, ExprEnv)
runExprEnvM s = SM.runState s
runStateMInNamingM :: (Monad m, NamingM s m) => StateNG t a -> State t -> m (a, State t)
runStateMInNamingM m s = do
ng <- nameGen
let (a, (s', ng')) = runStateNG m s ng
putNameGen ng'
return (a, s')
readRecord :: SM.MonadState s m => (s -> r) -> m r
readRecord f = return . f =<< SM.get
rep_expr_envM :: ExprEnv -> StateM t ()
rep_expr_envM eenv = do
(s,b) <- SM.get
SM.put $ (s {expr_env = eenv}, b)
rep_expr_envNG :: ExprEnv -> StateNG t ()
rep_expr_envNG eenv = do
(s,b) <- SM.get
SM.put $ (s {expr_env = eenv}, b)
rep_type_envM :: TypeEnv -> StateM t ()
rep_type_envM tenv = do
(s,b) <- SM.get
SM.put $ (s {type_env = tenv}, b)
rep_type_envNG :: TypeEnv -> StateNG t ()
rep_type_envNG tenv = do
(s,b) <- SM.get
SM.put $ (s {type_env = tenv}, b)
withNG :: NamingM s m => (NameGen -> (a, NameGen)) -> m a
withNG f = do
ng <- nameGen
let (a, ng') = f ng
putNameGen ng'
return a
rep_name_genM :: Monad m => NameGen -> StateT t m ()
rep_name_genM ng = do
(s,b) <- SM.get
SM.put $ (s, b {name_gen = ng})
rep_name_genNG :: Monad m => NameGen -> StateNGT t m ()
rep_name_genNG ng = do
(s, _) <- SM.get
SM.put $ (s, ng)
rep_known_valuesM :: KnownValues -> StateM t ()
rep_known_valuesM kv = do
(s, b) <- SM.get
SM.put $ (s {known_values = kv}, b)
rep_known_valuesNG :: KnownValues -> StateNG t ()
rep_known_valuesNG kv = do
(s, b) <- SM.get
SM.put $ (s {known_values = kv}, b)
rep_type_classesM :: TypeClasses -> StateM t ()
rep_type_classesM tc = do
(s, b) <- SM.get
SM.put $ (s {type_classes = tc}, b)
rep_type_classesNG :: TypeClasses -> StateNG t ()
rep_type_classesNG tc = do
(s, b) <- SM.get
SM.put $ (s {type_classes = tc}, b)
rep_curr_exprM :: CurrExpr -> StateM t ()
rep_curr_exprM ce = do
(s, b) <- SM.get
SM.put $ (s {curr_expr = ce}, b)
mapCurrExpr :: FullState s m => (Expr -> m Expr) -> m ()
mapCurrExpr f = do
(CurrExpr er e) <- currExpr
e' <- f e
putCurrExpr (CurrExpr er e')
rep_path_condsM :: PathConds -> StateM t ()
rep_path_condsM pc = do
(s, b) <- SM.get
SM.put $ (s {path_conds = pc}, b)
insertPC :: FullState s m => PathCond -> m ()
insertPC pc = do
pcs <- pathConds
putPathConds $ PC.insert pc pcs
insertPCStateNG :: PathCond -> StateNG t ()
insertPCStateNG pc = do
(s@(State { path_conds = pcs }), ng) <- SM.get
SM.put (s { path_conds = PC.insert pc pcs}, ng)
mapMAccumB :: Monad m => (a -> b -> m (a, c)) -> a -> [b] -> m (a, [c])
mapMAccumB _ a [] = do
return (a, [])
mapMAccumB f a (x:xs) = do
(a', res) <- f a x
(a'', res2) <- mapMAccumB f a' xs
return $ (a'', res:res2)