lhc-0.10: src/Grin/Stage2/Rename.hs
module Grin.Stage2.Rename
( rename
) where
import Control.Monad.State.Strict
import qualified Data.Map as Map
import Grin.Stage2.Types
rename :: Grin -> Grin
rename grin = evalState (renameGrin grin) emptyState
where emptyState = S { stateUnique = 1
, stateSubst = Map.empty }
type M a = State S a
-- The substitution map could just as easily be a reader.
data S = S { stateUnique :: !Int
, stateSubst :: Map.Map Renamed Renamed
}
renameGrin :: Grin -> M Grin
renameGrin grin
= do mapM_ (bind . nodeName) (grinNodes grin)
mapM_ (bind . cafName) (grinCAFs grin)
forM_ (grinFunctions grin) $ \func -> do bind (funcDefName func)
mapM_ bind (funcDefArgs func)
defs <- mapM renameFuncDef (grinFunctions grin)
nodes <- mapM renameNode (grinNodes grin)
cafs <- mapM renameCAF (grinCAFs grin)
entryPoint <- newName (grinEntryPoint grin)
newUnique <- gets stateUnique
return Grin { grinNodes = nodes
, grinCAFs = cafs
, grinFunctions = defs
, grinEntryPoint = entryPoint
, grinUnique = newUnique }
renameFuncDef :: FuncDef -> M FuncDef
renameFuncDef def
= do name <- newName (funcDefName def)
args <- mapM newName (funcDefArgs def)
body <- renameExpression (funcDefBody def)
return FuncDef{ funcDefName = name
, funcDefReturns = funcDefReturns def
, funcDefArgs = args
, funcDefBody = body }
renameExpression :: Expression -> M Expression
renameExpression (e1 :>>= binds :-> e2)
= do e1' <- renameExpression e1
binds' <- mapM bind binds
e2' <- renameExpression e2
return (e1' :>>= binds' :-> e2')
renameExpression (Application fn args)
= liftM2 Application (newName fn) (mapM newName args)
renameExpression (Case scrut alts)
= do scrut' <- newName scrut
alts' <- mapM renameAlt alts
return $ Case scrut' alts'
renameExpression (Fetch nth ptr)
= liftM (Fetch nth) (newName ptr)
renameExpression (Store args)
= liftM Store (mapM newName args)
renameExpression (StoreHole size)
= return $ StoreHole size
renameExpression (Unit args)
= liftM Unit (mapM newName args)
renameExpression (Constant val)
= liftM Constant (renameValue val)
renameAlt :: Alt -> M Alt
renameAlt (cond :> branch)
= do cond' <- renameValue cond
branch' <- renameExpression branch
return (cond' :> branch')
renameValue :: Value -> M Value
renameValue (Node node nt missing_args)
= do node' <- newName node
return $ Node node' nt missing_args
renameValue value = return value
renameNode :: NodeDef -> M NodeDef
renameNode node
= do name <- newName (nodeName node)
return node{nodeName = name}
renameCAF :: CAF -> M CAF
renameCAF caf
= do name <- newName (cafName caf)
value <- renameValue (cafValue caf)
return CAF{ cafName = name
, cafValue = value }
bind :: Renamed -> M Renamed
bind name | isBuiltin name || isExternal name
= return name
bind name
= do uid <- newUnique
s <- get
when (name `Map.member` stateSubst s) $ error $ "Grin.Stage2.Rename.bind: Duplication of (supposedly) unique identifier: " ++ show name
let newName = genNewName name uid
put s { stateSubst = Map.insert name newName (stateSubst s) }
return newName
newName :: Renamed -> M Renamed
newName oldName | isBuiltin oldName || isExternal oldName = return oldName
newName oldName@(Aliased (-1) _) = return oldName
newName oldName
= do subst <- gets stateSubst
case Map.lookup oldName subst of
Nothing -> error $ "Grin.Stage2.Rename.newName: Unbound variable: " ++ show oldName
Just new -> return new
newUnique :: M Int
newUnique = do s <- get
let unique = stateUnique s
put s{stateUnique = unique + 1}
return unique
genNewName (Aliased _uid name) uid = Aliased uid name
genNewName (Anonymous _uid) uid = Anonymous uid
genNewName other _uid = other