module Test.StateMachine.Internal.Types.Environment
( Environment(..)
, EnvironmentError(..)
, emptyEnvironment
, insertConcrete
, reifyDynamic
, reifyEnvironment
, reify
) where
import Data.Dynamic
(Dynamic, Proxy(Proxy), TypeRep, Typeable,
dynTypeRep, fromDynamic, toDyn, typeRep)
import Data.Map
(Map)
import qualified Data.Map as M
import Test.StateMachine.Types
newtype Environment =
Environment {
unEnvironment :: Map Var Dynamic
} deriving (Show)
data EnvironmentError =
EnvironmentValueNotFound !Var
| EnvironmentTypeError !TypeRep !TypeRep
deriving (Eq, Ord, Show)
emptyEnvironment :: Environment
emptyEnvironment =
Environment M.empty
insertConcrete :: Symbolic a -> Concrete a -> Environment -> Environment
insertConcrete (Symbolic k) (Concrete v) =
Environment . M.insert k (toDyn v) . unEnvironment
reifyDynamic :: forall a. Typeable a => Dynamic -> Either EnvironmentError (Concrete a)
reifyDynamic dyn =
case fromDynamic dyn of
Nothing ->
Left $ EnvironmentTypeError (typeRep (Proxy :: Proxy a)) (dynTypeRep dyn)
Just x ->
Right $ Concrete x
reifyEnvironment :: Environment -> (forall a. Symbolic a -> Either EnvironmentError (Concrete a))
reifyEnvironment (Environment vars) (Symbolic n) =
case M.lookup n vars of
Nothing ->
Left $ EnvironmentValueNotFound n
Just dyn ->
reifyDynamic dyn
reify :: HTraversable t => Environment -> t Symbolic b -> Either EnvironmentError (t Concrete b)
reify vars =
htraverse (reifyEnvironment vars)