%
% (c) The University of Glasgow 2006
% (c) The AQUA Project, Glasgow University, 19961998
%
This module contains "tidying" code for *nested* expressions, bindings, rules.
The code for *toplevel* bindings is in TidyPgm.
\begin{code}
module CoreTidy (
tidyExpr, tidyVarOcc, tidyRule, tidyRules
) where
#include "HsVersions.h"
import CoreSyn
import CoreArity
import Id
import IdInfo
import TcType( tidyType, tidyTyVarBndr )
import Var
import VarEnv
import UniqFM
import Name hiding (tidyNameOcc)
import SrcLoc
import Maybes
import Data.List
\end{code}
%************************************************************************
%* *
\subsection{Tidying expressions, rules}
%* *
%************************************************************************
\begin{code}
tidyBind :: TidyEnv
-> CoreBind
-> (TidyEnv, CoreBind)
tidyBind env (NonRec bndr rhs)
= tidyLetBndr env (bndr,rhs) =: \ (env', bndr') ->
(env', NonRec bndr' (tidyExpr env' rhs))
tidyBind env (Rec prs)
= mapAccumL tidyLetBndr env prs =: \ (env', bndrs') ->
map (tidyExpr env') (map snd prs) =: \ rhss' ->
(env', Rec (zip bndrs' rhss'))
tidyExpr :: TidyEnv -> CoreExpr -> CoreExpr
tidyExpr env (Var v) = Var (tidyVarOcc env v)
tidyExpr env (Type ty) = Type (tidyType env ty)
tidyExpr _ (Lit lit) = Lit lit
tidyExpr env (App f a) = App (tidyExpr env f) (tidyExpr env a)
tidyExpr env (Note n e) = Note (tidyNote env n) (tidyExpr env e)
tidyExpr env (Cast e co) = Cast (tidyExpr env e) (tidyType env co)
tidyExpr env (Let b e)
= tidyBind env b =: \ (env', b') ->
Let b' (tidyExpr env' e)
tidyExpr env (Case e b ty alts)
= tidyBndr env b =: \ (env', b) ->
Case (tidyExpr env e) b (tidyType env ty)
(map (tidyAlt b env') alts)
tidyExpr env (Lam b e)
= tidyBndr env b =: \ (env', b) ->
Lam b (tidyExpr env' e)
tidyAlt :: CoreBndr -> TidyEnv -> CoreAlt -> CoreAlt
tidyAlt _case_bndr env (con, vs, rhs)
= tidyBndrs env vs =: \ (env', vs) ->
(con, vs, tidyExpr env' rhs)
tidyNote :: TidyEnv -> Note -> Note
tidyNote _ note = note
tidyRules :: TidyEnv -> [CoreRule] -> [CoreRule]
tidyRules _ [] = []
tidyRules env (rule : rules)
= tidyRule env rule =: \ rule ->
tidyRules env rules =: \ rules ->
(rule : rules)
tidyRule :: TidyEnv -> CoreRule -> CoreRule
tidyRule _ rule@(BuiltinRule {}) = rule
tidyRule env rule@(Rule { ru_bndrs = bndrs, ru_args = args, ru_rhs = rhs,
ru_fn = fn, ru_rough = mb_ns })
= tidyBndrs env bndrs =: \ (env', bndrs) ->
map (tidyExpr env') args =: \ args ->
rule { ru_bndrs = bndrs, ru_args = args,
ru_rhs = tidyExpr env' rhs,
ru_fn = tidyNameOcc env fn,
ru_rough = map (fmap (tidyNameOcc env')) mb_ns }
\end{code}
%************************************************************************
%* *
\subsection{Tidying nontoplevel binders}
%* *
%************************************************************************
\begin{code}
tidyNameOcc :: TidyEnv -> Name -> Name
tidyNameOcc (_, var_env) n = case lookupUFM var_env n of
Nothing -> n
Just v -> idName v
tidyVarOcc :: TidyEnv -> Var -> Var
tidyVarOcc (_, var_env) v = lookupVarEnv var_env v `orElse` v
tidyBndr :: TidyEnv -> Var -> (TidyEnv, Var)
tidyBndr env var
| isTyCoVar var = tidyTyVarBndr env var
| otherwise = tidyIdBndr env var
tidyBndrs :: TidyEnv -> [Var] -> (TidyEnv, [Var])
tidyBndrs env vars = mapAccumL tidyBndr env vars
tidyLetBndr :: TidyEnv -> (Id, CoreExpr) -> (TidyEnv, Var)
tidyLetBndr env (id,rhs)
= ((tidy_env,new_var_env), final_id)
where
((tidy_env,var_env), new_id) = tidyIdBndr env id
final_id = new_id `setIdInfo` new_info
idinfo = idInfo id
new_info = idInfo new_id
`setArityInfo` exprArity rhs
`setStrictnessInfo` strictnessInfo idinfo
`setDemandInfo` demandInfo idinfo
`setInlinePragInfo` inlinePragInfo idinfo
new_var_env = extendVarEnv var_env id final_id
tidyIdBndr :: TidyEnv -> Id -> (TidyEnv, Id)
tidyIdBndr env@(tidy_env, var_env) id
=
case tidyOccName tidy_env (getOccName id) of { (tidy_env', occ') ->
let
ty' = tidyType env (idType id)
name' = mkInternalName (idUnique id) occ' noSrcSpan
id' = mkLocalIdWithInfo name' ty' new_info
var_env' = extendVarEnv var_env id id'
new_info = vanillaIdInfo `setOccInfo` occInfo old_info
old_info = idInfo id
in
((tidy_env', var_env'), id')
}
\end{code}
Note [Tidy IdInfo]
~~~~~~~~~~~~~~~~~~
All nested Ids now have the same IdInfo, namely vanillaIdInfo, which
should save some space; except that we preserve occurrence info for
two reasons:
(a) To make printing tidy core nicer
(b) Because we tidy RULES and InlineRules, which may then propagate
via
the benefit of that occurrence analysis when we use the rule or
or inline the function. In particular, it's vital not to lose
loopbreaker info, else we get an infinite inlining loop
Note that tidyLetBndr puts more IdInfo back.
\begin{code}
(=:) :: a -> (a -> b) -> b
m =: k = m `seq` k m
\end{code}