module Tip.Pass.UniqLocals where
import Tip.Core
import Tip.Scope as Scope
import Tip.Fresh
import Control.Monad
import Control.Monad.State
import Control.Applicative
import qualified Data.Traversable as T
import qualified Data.Map as M
import qualified Data.Set as S
uniqLocals :: forall a . Name a => Theory a -> Fresh (Theory a)
uniqLocals thy
= fmap declsToTheory
. mapM (flip evalStateT M.empty . T.traverse uq)
. theoryDecls
$ thy
where
nonlocals = M.keys (types scp) ++ M.keys (Scope.globals scp)
scp = scope thy
uq :: a -> StateT (M.Map a a) Fresh a
uq a | a `elem` nonlocals = do return a
| otherwise = do mb <- gets (M.lookup a)
case mb of
Nothing -> do b <- lift (refresh a)
modify (M.insert a b)
return b
Just b -> do return b