-- Please, see the file LICENSE for copyright and license information. A monad to keep an environment with hylomorphism definitions and throwing errors. >module HFusion.Internal.FuseEnvironment( > clearFuseEnv, > insertFuseEnv, > deleteFuseEnv, > lookupFuseEnv, > fuseFuseEnv, > renameFuseEnv, > toListFuseEnv, > runEnv, > env2FusionState, > Binds, > emptyBinds, > Env) where > import HFusion.Internal.HsSyn(Variable(..)) > import HFusion.Internal.Utils(newVarGen) > import Control.Monad.State(State,StateT(..),get,put,evalStateT) > import Control.Monad.Error(throwError,ErrorT) > import Control.Monad.Trans(lift) > import Data.Map(empty,Map,insert,lookup,delete,toList) > import HFusion.Internal.Utils(VarGen) > import HFusion.Internal.HyloFace > import List(elemIndex) > import HFusion.Internal.FuseFace(fusionar,HyloT,getNames,renameHT) > import Prelude(maybe,Int,Monad(..),(.),error,id,($), > show,fst,Either(..),either,foldr,flip) data Key a = SingleKey a | KeyList [a] > type Binds = (Map [Variable] HyloT,Map Variable [Variable]) > type Env a = StateT Binds (ErrorT FusionError (State VarGen)) a > emptyBinds :: Binds > emptyBinds = (empty,empty) > env2FusionState :: Env a -> FusionState a > env2FusionState m = evalStateT m emptyBinds > runEnv :: Env a -> Either FusionError a > runEnv = runFusionState newVarGen . env2FusionState > clearFuseEnv :: Env () > clearFuseEnv = put emptyBinds > insertFuseEnv :: HyloT -> Env () > insertFuseEnv h = do (mh,mv)<-get;put (insert names h mh,foldr (flip insert names) mv names) > where names = getNames h > deleteFuseEnv :: Variable -> Env () > deleteFuseEnv v = do (mh,mv)<-get > maybe (return ()) (\ns -> put (delete ns mh,foldr delete mv ns)) (Data.Map.lookup v mv) > lookupFuseEnv :: Variable -> Env HyloT > lookupFuseEnv v = do (mh,mv)<-get > maybe err (maybe err return . flip Data.Map.lookup mh) (Data.Map.lookup v mv) > where err = throwError (NotFound (show v)) > fuseFuseEnv :: [Variable] -> Variable -> Int -> Variable -> Env HyloT > fuseFuseEnv names v1 ia v2 = > do h1<-lookupFuseEnv v1 > h2<-lookupFuseEnv v2 > let getIndex v h = maybe (error "fuseFuseEnv: this should not happen.") id $ elemIndex v (getNames h) > (_,h3)<-lift (fusionar names h1 (getIndex v1 h1) ia h2 (getIndex v2 h2)) > insertFuseEnv h3 > return h3 > renameFuseEnv :: Variable -> Variable -> Env (HyloT,HyloT) > renameFuseEnv v1 v2 = do h1<-lookupFuseEnv v1 > h2<-lookupFuseEnv v2 > let getIndex v h = maybe (error "fuseFuseEnv: this should not happen.") id $ elemIndex v (getNames h) > lift (renameHT h1 h2) > toListFuseEnv :: Env [([Variable],HyloT)] > toListFuseEnv = get >>= return . toList . fst