module GHC.Core.Tidy (
tidyExpr, tidyRules, tidyUnfolding
) where
#include "HsVersions.h"
import GHC.Prelude
import GHC.Core
import GHC.Core.Seq ( seqUnfolding )
import GHC.Types.Id
import GHC.Types.Id.Info
import GHC.Types.Demand ( zapDmdEnvSig )
import GHC.Core.Type ( tidyType, tidyVarBndr )
import GHC.Core.Coercion ( tidyCo )
import GHC.Types.Var
import GHC.Types.Var.Env
import GHC.Types.Unique (getUnique)
import GHC.Types.Unique.FM
import GHC.Types.Name hiding (tidyNameOcc)
import GHC.Types.SrcLoc
import GHC.Types.Tickish
import GHC.Data.Maybe
import Data.List (mapAccumL)
tidyBind :: TidyEnv
-> CoreBind
-> (TidyEnv, CoreBind)
tidyBind env (NonRec bndr rhs)
= tidyLetBndr env env bndr =: \ (env', bndr') ->
(env', NonRec bndr' (tidyExpr env' rhs))
tidyBind env (Rec prs)
= let
(bndrs, rhss) = unzip prs
(env', bndrs') = mapAccumL (tidyLetBndr env') env bndrs
in
map (tidyExpr env') rhss =: \ 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 env (Coercion co) = Coercion (tidyCo env co)
tidyExpr _ (Lit lit) = Lit lit
tidyExpr env (App f a) = App (tidyExpr env f) (tidyExpr env a)
tidyExpr env (Tick t e) = Tick (tidyTickish env t) (tidyExpr env e)
tidyExpr env (Cast e co) = Cast (tidyExpr env e) (tidyCo 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 env') alts)
tidyExpr env (Lam b e)
= tidyBndr env b =: \ (env', b) ->
Lam b (tidyExpr env' e)
tidyAlt :: TidyEnv -> CoreAlt -> CoreAlt
tidyAlt env (Alt con vs rhs)
= tidyBndrs env vs =: \ (env', vs) ->
(Alt con vs (tidyExpr env' rhs))
tidyTickish :: TidyEnv -> CoreTickish -> CoreTickish
tidyTickish env (Breakpoint ext ix ids)
= Breakpoint ext ix (map (tidyVarOcc env) ids)
tidyTickish _ other_tickish = other_tickish
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 }
tidyNameOcc :: TidyEnv -> Name -> Name
tidyNameOcc (_, var_env) n = case lookupUFM_Directly var_env (getUnique 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 = tidyVarBndr env var
| otherwise = tidyIdBndr env var
tidyBndrs :: TidyEnv -> [Var] -> (TidyEnv, [Var])
tidyBndrs env vars = mapAccumL tidyBndr env vars
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)
mult' = tidyType env (idMult id)
name' = mkInternalName (idUnique id) occ' noSrcSpan
id' = mkLocalIdWithInfo name' mult' ty' new_info
var_env' = extendVarEnv var_env id id'
new_info = vanillaIdInfo `setOccInfo` occInfo old_info
`setUnfoldingInfo` new_unf
`setOneShotInfo` oneShotInfo old_info
old_info = idInfo id
old_unf = unfoldingInfo old_info
new_unf = zapUnfolding old_unf
in
((tidy_env', var_env'), id')
}
tidyLetBndr :: TidyEnv
-> TidyEnv
-> Id -> (TidyEnv, Id)
tidyLetBndr rec_tidy_env env@(tidy_env, var_env) id
= case tidyOccName tidy_env (getOccName id) of { (tidy_env', occ') ->
let
ty' = tidyType env (idType id)
mult' = tidyType env (idMult id)
name' = mkInternalName (idUnique id) occ' noSrcSpan
details = idDetails id
id' = mkLocalVar details name' mult' ty' new_info
var_env' = extendVarEnv var_env id id'
old_info = idInfo id
new_info = vanillaIdInfo
`setOccInfo` occInfo old_info
`setArityInfo` arityInfo old_info
`setStrictnessInfo` zapDmdEnvSig (strictnessInfo old_info)
`setDemandInfo` demandInfo old_info
`setInlinePragInfo` inlinePragInfo old_info
`setUnfoldingInfo` new_unf
old_unf = unfoldingInfo old_info
new_unf | isStableUnfolding old_unf = tidyUnfolding rec_tidy_env old_unf old_unf
| otherwise = zapUnfolding old_unf
in
((tidy_env', var_env'), id') }
tidyUnfolding :: TidyEnv -> Unfolding -> Unfolding -> Unfolding
tidyUnfolding tidy_env df@(DFunUnfolding { df_bndrs = bndrs, df_args = args }) _
= df { df_bndrs = bndrs', df_args = map (tidyExpr tidy_env') args }
where
(tidy_env', bndrs') = tidyBndrs tidy_env bndrs
tidyUnfolding tidy_env
unf@(CoreUnfolding { uf_tmpl = unf_rhs, uf_src = src })
unf_from_rhs
| isStableSource src
= seqIt $ unf { uf_tmpl = tidyExpr tidy_env unf_rhs }
| otherwise
= unf_from_rhs
where seqIt unf = seqUnfolding unf `seq` unf
tidyUnfolding _ unf _ = unf
(=:) :: a -> (a -> b) -> b
m =: k = m `seq` k m