#include "HsVersions.h"
import CmdLineOpts ( opt_PprStyle_Debug )
-import CoreSyn ( Expr(..), Bind(..), Note(..), CoreExpr, CoreBndr,
+import CoreSyn ( Expr(..), Bind(..), Note(..), CoreExpr,
CoreRules(..), CoreRule(..),
- emptyCoreRules, isEmptyCoreRules, seqRules
+ isEmptyCoreRules, seqRules
)
import CoreFVs ( exprFreeVars, mustHaveLocalBinding )
-import TypeRep ( Type(..), TyNote(..),
- ) -- friend
+import TypeRep ( Type(..), TyNote(..) ) -- friend
import Type ( ThetaType, PredType(..), ClassContext,
- tyVarsOfType, tyVarsOfTypes, mkAppTy
+ tyVarsOfType, tyVarsOfTypes, mkAppTy, mkUTy, isUTy
)
import VarSet
import VarEnv
import Var ( setVarUnique, isId )
-import Id ( idType, setIdType, idOccInfo, zapFragileIdInfo )
+import Id ( idType, setIdType, idOccInfo, zapFragileIdInfo, maybeModifyIdInfo )
import IdInfo ( IdInfo, isFragileOcc,
specInfo, setSpecInfo,
- WorkerInfo(..), workerExists, workerInfo, setWorkerInfo, WorkerInfo
+ WorkerInfo(..), workerExists, workerInfo, setWorkerInfo, WorkerInfo,
+ lbvarInfo, LBVarInfo(..), setLBVarInfo
)
import Unique ( Uniquable(..), deriveUnique )
import UniqSet ( elemUniqSet_Directly )
import UniqSupply ( UniqSupply, uniqFromSupply, splitUniqSupply )
import Var ( Var, Id, TyVar, isTyVar )
import Outputable
-import PprCore () -- Instances
+import PprCore () -- Instances
+import UniqFM ( ufmToList ) -- Yuk (add a new op to VarEnv)
import Util ( mapAccumL, foldl2, seqList, ($!) )
+import FastTypes
\end{code}
%************************************************************************
\begin{code}
-data InScopeSet = InScope (VarEnv Var) Int#
+data InScopeSet = InScope (VarEnv Var) FastInt
-- The Int# is a kind of hash-value used by uniqAway
-- For example, it might be the size of the set
-- INVARIANT: it's not zero; we use it as a multiplier in uniqAway
extendInScopeSet (InScope in_scope n) v = InScope (extendVarEnv in_scope v v) (n +# 1#)
extendInScopeSetList :: InScopeSet -> [Var] -> InScopeSet
-extendInScopeSetList (InScope in_scope n) vs = InScope (foldl (\s v -> extendVarEnv s v v) in_scope vs)
- (case length vs of { I# l -> n +# l })
+extendInScopeSetList (InScope in_scope n) vs
+ = InScope (foldl (\s v -> extendVarEnv s v v) in_scope vs)
+ (n +# iUnbox (length vs))
modifyInScopeSet :: InScopeSet -> Var -> Var -> InScopeSet
-- Exploit the fact that the in-scope "set" is really a map
try k
#ifdef DEBUG
| k ># 1000#
- = pprPanic "uniqAway loop:" (ppr (I# k) <+> text "tries" <+> ppr var <+> int (I# n))
+ = pprPanic "uniqAway loop:" (ppr (iBox k) <+> text "tries" <+> ppr var <+> int (iBox n))
#endif
| uniq `elemUniqSet_Directly` set = try (k +# 1#)
#ifdef DEBUG
| opt_PprStyle_Debug && k ># 3#
- = pprTrace "uniqAway:" (ppr (I# k) <+> text "tries" <+> ppr var <+> int (I# n))
+ = pprTrace "uniqAway:" (ppr (iBox k) <+> text "tries" <+> ppr var <+> int (iBox n))
setVarUnique var uniq
#endif
| otherwise = setVarUnique var uniq
where
- uniq = deriveUnique orig_unique (I# (n *# k))
+ uniq = deriveUnique orig_unique (iBox (n *# k))
\end{code}
--
-- INVARIANT 2: No variable is both in scope and in the domain of the substitution
-- Equivalently, the substitution is idempotent
- --
+ -- [Sep 2000: Lies, all lies. The substitution now does contain
+ -- mappings x77 -> DoneId x77 occ
+ -- to record x's occurrence information.]
+ -- [Also watch out: the substitution can contain x77 -> DoneEx (Var x77)
+ -- Consider let x = case k of I# x77 -> ... in
+ -- let y = case k of I# x77 -> ... in ...
+ -- and suppose the body is strict in both x and y. Then the simplifier
+ -- will pull the first (case k) to the top; so the second (case k) will
+ -- cancel out, mapping x77 to, well, x77! But one is an in-Id and the
+ -- other is an out-Id. So the substitution is idempotent in the sense
+ -- that we *must not* repeatedly apply it.]
type IdSubst = Subst
\end{code}
That is added back in later. So new_id is the minimal thing it's
correct to substitute.
-* substId adds a binding (DoneVar new_id occ) to the substitution if
+* substId adds a binding (DoneId new_id occ) to the substitution if
EITHER the Id's unique has changed
OR the Id has interesting occurrence information
So in effect you can only get to interesting occurrence information
zapSubstEnv (Subst in_scope env) = Subst in_scope emptySubstEnv
extendSubst :: Subst -> Var -> SubstResult -> Subst
-extendSubst (Subst in_scope env) v r = Subst in_scope (extendSubstEnv env v r)
+extendSubst (Subst in_scope env) v r = UASSERT( case r of { DoneTy ty -> not (isUTy ty) ; _ -> True } )
+ Subst in_scope (extendSubstEnv env v r)
extendSubstList :: Subst -> [Var] -> [SubstResult] -> Subst
-extendSubstList (Subst in_scope env) v r = Subst in_scope (extendSubstEnvList env v r)
+extendSubstList (Subst in_scope env) v r = UASSERT( all (\ r1 -> case r1 of { DoneTy ty -> not (isUTy ty) ; _ -> True }) r )
+ Subst in_scope (extendSubstEnvList env v r)
lookupSubst :: Subst -> Var -> Maybe SubstResult
lookupSubst (Subst _ env) v = lookupSubstEnv env v
setSubstEnv (Subst in_scope1 _) env2 = Subst in_scope1 env2
\end{code}
+Pretty printing, for debugging only
+
+\begin{code}
+instance Outputable SubstResult where
+ ppr (DoneEx e) = ptext SLIT("DoneEx") <+> ppr e
+ ppr (DoneId v _) = ptext SLIT("DoneId") <+> ppr v
+ ppr (ContEx _ e) = ptext SLIT("ContEx") <+> ppr e
+ ppr (DoneTy t) = ptext SLIT("DoneTy") <+> ppr t
+
+instance Outputable SubstEnv where
+ ppr se = brackets (fsep (punctuate comma (map ppr_elt (ufmToList (substEnvEnv se)))))
+ where
+ ppr_elt (uniq,sr) = ppr uniq <+> ptext SLIT("->") <+> ppr sr
+
+instance Outputable Subst where
+ ppr (Subst (InScope in_scope _) se)
+ = ptext SLIT("<InScope =") <+> braces (fsep (map ppr (rngVarEnv in_scope)))
+ $$ ptext SLIT(" Subst =") <+> ppr se <> char '>'
+\end{code}
%************************************************************************
%* *
mkTopTyVarSubst tyvars tys = Subst emptyInScopeSet (zip_ty_env tyvars tys emptySubstEnv)
zip_ty_env [] [] env = env
-zip_ty_env (tv:tvs) (ty:tys) env = zip_ty_env tvs tys (extendSubstEnv env tv (DoneTy ty))
+zip_ty_env (tv:tvs) (ty:tys) env = UASSERT( not (isUTy ty) )
+ zip_ty_env tvs tys (extendSubstEnv env tv (DoneTy ty))
\end{code}
substTy works with general Substs, so that it can be called from substExpr too.
where
go (TyConApp tc tys) = let args = map go tys
in args `seqList` TyConApp tc args
+
+ go (PredTy p) = PredTy $! (substPred subst p)
+
go (NoteTy (SynNote ty1) ty2) = NoteTy (SynNote $! (go ty1)) $! (go ty2)
go (NoteTy (FTVNote _) ty2) = go ty2 -- Discard the free tyvar note
- go (NoteTy (UsgNote usg) ty2) = (NoteTy $! UsgNote usg) $! go ty2 -- Keep usage annot
- go (NoteTy (UsgForAll uv) ty2) = (NoteTy $! UsgForAll uv) $! go ty2 -- Keep uvar bdr
- go (NoteTy (IPNote nm) ty2) = (NoteTy $! IPNote nm) $! go ty2 -- Keep ip note
go (FunTy arg res) = (FunTy $! (go arg)) $! (go res)
go (AppTy fun arg) = mkAppTy (go fun) $! (go arg)
go (ForAllTy tv ty) = case substTyVar subst tv of
(subst', tv') -> ForAllTy tv' $! (subst_ty subst' ty)
+
+ go (UsageTy u ty) = mkUTy (go u) $! (go ty)
\end{code}
Here is where we invent a new binder if necessary.
-- id2 has its IdInfo zapped
id2 = zapFragileIdInfo id1
- -- new_id is cloned if necessary
- new_id = uniqAway in_scope id2
+ -- id3 has its LBVarInfo zapped
+ id3 = maybeModifyIdInfo (\ info -> go info (lbvarInfo info)) id2
+ where go info (LBVarInfo u@(TyVarTy _)) = Just $ setLBVarInfo info $
+ LBVarInfo (subst_ty subst u)
+ go info _ = Nothing
+ -- new_id is cloned if necessary
+ new_id = uniqAway in_scope id3
-- Extend the substitution if the unique has changed,
-- or there's some useful occurrence information
-- See the notes with substTyVar for the delSubstEnv