2 % (c) The GRASP/AQUA Project, Glasgow University, 1992-1998
4 \section[CoreUtils]{Utility functions on @Core@ syntax}
9 InScopeSet, emptyInScopeSet,
10 lookupInScope, setInScope, extendInScope, extendInScopes, isInScope,
13 Subst, TyVarSubst, IdSubst,
14 emptySubst, mkSubst, substEnv, substInScope,
15 lookupSubst, isEmptySubst, extendSubst, extendSubstList,
16 zapSubstEnv, setSubstEnv,
18 bindSubst, unBindSubst, bindSubstList, unBindSubstList,
21 substBndr, substBndrs, substTyVar, substId, substIds,
22 substAndCloneId, substAndCloneIds,
25 mkTyVarSubst, mkTopTyVarSubst,
32 #include "HsVersions.h"
35 import CoreSyn ( Expr(..), Bind(..), Note(..), CoreExpr, CoreBndr,
36 CoreRules(..), CoreRule(..), emptyCoreRules, isEmptyCoreRules
38 import CoreFVs ( exprFreeVars )
39 import Type ( Type(..), ThetaType, TyNote(..),
40 tyVarsOfType, tyVarsOfTypes, mkAppTy
44 import Var ( setVarUnique, isId )
45 import Id ( idType, setIdType )
46 import IdInfo ( zapFragileIdInfo )
47 import UniqSupply ( UniqSupply, uniqFromSupply, splitUniqSupply )
48 import Var ( Var, IdOrTyVar, Id, TyVar, isTyVar, maybeModifyIdInfo )
50 import Util ( mapAccumL, foldl2, seqList, ($!) )
53 %************************************************************************
55 \subsection{Substitutions}
57 %************************************************************************
60 type InScopeSet = VarSet
62 data Subst = Subst InScopeSet -- In scope
63 SubstEnv -- Substitution itself
64 -- INVARIANT 1: The in-scope set is a superset
65 -- of the free vars of the range of the substitution
66 -- that might possibly clash with locally-bound variables
67 -- in the thing being substituted in.
68 -- This is what lets us deal with name capture properly
69 -- It's a hard invariant to check...
70 -- There are various ways of causing it to happen:
71 -- - arrange that the in-scope set really is all the things in scope
72 -- - arrange that it's the free vars of the range of the substitution
73 -- - make it empty because all the free vars of the subst are fresh,
74 -- and hence can't possibly clash.a
76 -- INVARIANT 2: No variable is both in scope and in the domain of the substitution
77 -- Equivalently, the substitution is idempotent
84 emptyInScopeSet :: InScopeSet
85 emptyInScopeSet = emptyVarSet
91 isEmptySubst :: Subst -> Bool
92 isEmptySubst (Subst _ env) = isEmptySubstEnv env
95 emptySubst = Subst emptyVarSet emptySubstEnv
97 mkSubst :: InScopeSet -> SubstEnv -> Subst
98 mkSubst in_scope env = Subst in_scope env
100 substEnv :: Subst -> SubstEnv
101 substEnv (Subst _ env) = env
103 substInScope :: Subst -> InScopeSet
104 substInScope (Subst in_scope _) = in_scope
106 zapSubstEnv :: Subst -> Subst
107 zapSubstEnv (Subst in_scope env) = Subst in_scope emptySubstEnv
109 extendSubst :: Subst -> Var -> SubstResult -> Subst
110 extendSubst (Subst in_scope env) v r = Subst in_scope (extendSubstEnv env v r)
112 extendSubstList :: Subst -> [Var] -> [SubstResult] -> Subst
113 extendSubstList (Subst in_scope env) v r = Subst in_scope (extendSubstEnvList env v r)
115 lookupSubst :: Subst -> Var -> Maybe SubstResult
116 lookupSubst (Subst _ env) v = lookupSubstEnv env v
118 lookupInScope :: Subst -> Var -> Maybe Var
119 lookupInScope (Subst in_scope _) v = lookupVarSet in_scope v
121 isInScope :: Var -> Subst -> Bool
122 isInScope v (Subst in_scope _) = v `elemVarSet` in_scope
124 extendInScope :: Subst -> Var -> Subst
125 extendInScope (Subst in_scope env) v = Subst (extendVarSet in_scope v) env
127 extendInScopes :: Subst -> [Var] -> Subst
128 extendInScopes (Subst in_scope env) vs = Subst (foldl extendVarSet in_scope vs) env
130 -------------------------------
131 bindSubst :: Subst -> Var -> Var -> Subst
132 -- Extend with a substitution, v1 -> Var v2
133 -- and extend the in-scopes with v2
134 bindSubst (Subst in_scope env) old_bndr new_bndr
135 = Subst (in_scope `extendVarSet` new_bndr)
136 (extendSubstEnv env old_bndr subst_result)
138 subst_result | isId old_bndr = DoneEx (Var new_bndr)
139 | otherwise = DoneTy (TyVarTy new_bndr)
141 unBindSubst :: Subst -> Var -> Var -> Subst
142 -- Reverse the effect of bindSubst
143 -- If old_bndr was already in the substitution, this doesn't quite work
144 unBindSubst (Subst in_scope env) old_bndr new_bndr
145 = Subst (in_scope `delVarSet` new_bndr) (delSubstEnv env old_bndr)
147 -- And the "List" forms
148 bindSubstList :: Subst -> [Var] -> [Var] -> Subst
149 bindSubstList subst old_bndrs new_bndrs
150 = foldl2 bindSubst subst old_bndrs new_bndrs
152 unBindSubstList :: Subst -> [Var] -> [Var] -> Subst
153 unBindSubstList subst old_bndrs new_bndrs
154 = foldl2 unBindSubst subst old_bndrs new_bndrs
157 -------------------------------
158 setInScope :: Subst -- Take env part from here
161 setInScope (Subst in_scope1 env1) in_scope2
162 = ASSERT( in_scope1 `subVarSet` in_scope1 )
165 setSubstEnv :: Subst -- Take in-scope part from here
166 -> SubstEnv -- ... and env part from here
168 setSubstEnv (Subst in_scope1 _) env2 = Subst in_scope1 env2
172 %************************************************************************
174 \subsection{Type substitution}
176 %************************************************************************
179 type TyVarSubst = Subst -- TyVarSubst are expected to have range elements
180 -- (We could have a variant of Subst, but it doesn't seem worth it.)
182 -- mkTyVarSubst generates the in-scope set from
183 -- the types given; but it's just a thunk so with a bit of luck
184 -- it'll never be evaluated
185 mkTyVarSubst :: [TyVar] -> [Type] -> Subst
186 mkTyVarSubst tyvars tys = Subst (tyVarsOfTypes tys) (zip_ty_env tyvars tys emptySubstEnv)
188 -- mkTopTyVarSubst is called when doing top-level substitutions.
189 -- Here we expect that the free vars of the range of the
190 -- substitution will be empty.
191 mkTopTyVarSubst :: [TyVar] -> [Type] -> Subst
192 mkTopTyVarSubst tyvars tys = Subst emptyVarSet (zip_ty_env tyvars tys emptySubstEnv)
194 zip_ty_env [] [] env = env
195 zip_ty_env (tv:tvs) (ty:tys) env = zip_ty_env tvs tys (extendSubstEnv env tv (DoneTy ty))
198 substTy works with general Substs, so that it can be called from substExpr too.
201 substTy :: Subst -> Type -> Type
202 substTy subst ty | isEmptySubst subst = ty
203 | otherwise = subst_ty subst ty
205 substTheta :: TyVarSubst -> ThetaType -> ThetaType
206 substTheta subst theta
207 | isEmptySubst subst = theta
208 | otherwise = [(clas, map (subst_ty subst) tys) | (clas, tys) <- theta]
213 go (TyConApp tc tys) = let args = map go tys
214 in args `seqList` TyConApp tc args
215 go (NoteTy (SynNote ty1) ty2) = NoteTy (SynNote $! (go ty1)) $! (go ty2)
216 go (NoteTy (FTVNote _) ty2) = go ty2 -- Discard the free tyvar note
217 go (FunTy arg res) = (FunTy $! (go arg)) $! (go res)
218 go (NoteTy (UsgNote usg) ty2) = (NoteTy $! UsgNote usg) $! go ty2 -- Keep usage annot
219 go (AppTy fun arg) = mkAppTy (go fun) $! (go arg)
220 go ty@(TyVarTy tv) = case (lookupSubst subst tv) of
222 Just (DoneTy ty') -> ty'
224 go (ForAllTy tv ty) = case substTyVar subst tv of
225 (subst', tv') -> ForAllTy tv' $! (subst_ty subst' ty)
228 Here is where we invent a new binder if necessary.
231 substTyVar :: Subst -> TyVar -> (Subst, TyVar)
232 substTyVar subst@(Subst in_scope env) old_var
233 | old_var == new_var -- No need to clone
234 -- But we *must* zap any current substitution for the variable.
236 -- (\x.e) with id_subst = [x |-> e']
237 -- Here we must simply zap the substitution for x
239 -- The new_id isn't cloned, but it may have a different type
240 -- etc, so we must return it, not the old id
241 = (Subst (in_scope `extendVarSet` new_var)
242 (delSubstEnv env old_var),
245 | otherwise -- The new binder is in scope so
246 -- we'd better rename it away from the in-scope variables
247 -- Extending the substitution to do this renaming also
248 -- has the (correct) effect of discarding any existing
249 -- substitution for that variable
250 = (Subst (in_scope `extendVarSet` new_var)
251 (extendSubstEnv env old_var (DoneTy (TyVarTy new_var))),
254 new_var = uniqAway in_scope old_var
255 -- The uniqAway part makes sure the new variable is not already in scope
259 %************************************************************************
261 \section{Expression substitution}
263 %************************************************************************
265 This expression substituter deals correctly with name capture.
267 BUT NOTE that substExpr silently discards the
270 IdInfo attached to any binders in the expression. It's quite
271 tricky to do them 'right' in the case of mutually recursive bindings,
272 and so far has proved unnecessary.
275 substExpr :: Subst -> CoreExpr -> CoreExpr
276 substExpr subst expr | isEmptySubst subst = expr
277 | otherwise = subst_expr subst expr
279 subst_expr subst expr
282 go (Var v) = case lookupSubst subst v of
283 Just (DoneEx e') -> e'
284 Just (ContEx env' e') -> subst_expr (setSubstEnv subst env') e'
285 Nothing -> case lookupInScope subst v of
288 -- NB: we look up in the in_scope set because the variable
289 -- there may have more info. In particular, when substExpr
290 -- is called from the simplifier, the type inside the *occurrences*
291 -- of a variable may not be right; we should replace it with the
292 -- binder, from the in_scope set.
294 go (Type ty) = Type (go_ty ty)
295 go (Con con args) = Con con (map go args)
296 go (App fun arg) = App (go fun) (go arg)
297 go (Note note e) = Note (go_note note) (go e)
299 go (Lam bndr body) = Lam bndr' (subst_expr subst' body)
301 (subst', bndr') = substBndr subst bndr
303 go (Let (NonRec bndr rhs) body) = Let (NonRec bndr' (go rhs)) (subst_expr subst' body)
305 (subst', bndr') = substBndr subst bndr
307 go (Let (Rec pairs) body) = Let (Rec pairs') (subst_expr subst' body)
309 (subst', bndrs') = substBndrs subst (map fst pairs)
310 pairs' = bndrs' `zip` rhss'
311 rhss' = map (subst_expr subst' . snd) pairs
313 go (Case scrut bndr alts) = Case (go scrut) bndr' (map (go_alt subst') alts)
315 (subst', bndr') = substBndr subst bndr
317 go_alt subst (con, bndrs, rhs) = (con, bndrs', subst_expr subst' rhs)
319 (subst', bndrs') = substBndrs subst bndrs
321 go_note (Coerce ty1 ty2) = Coerce (go_ty ty1) (go_ty ty2)
324 go_ty ty = substTy subst ty
328 Substituting in binders is a rather tricky part of the whole compiler.
330 When we hit a binder we may need to
331 (a) apply the the type envt (if non-empty) to its type
332 (b) apply the type envt and id envt to its SpecEnv (if it has one)
333 (c) give it a new unique to avoid name clashes
336 substBndr :: Subst -> IdOrTyVar -> (Subst, IdOrTyVar)
338 | isTyVar bndr = substTyVar subst bndr
339 | otherwise = substId subst bndr
341 substBndrs :: Subst -> [IdOrTyVar] -> (Subst, [IdOrTyVar])
342 substBndrs subst bndrs = mapAccumL substBndr subst bndrs
345 substIds :: Subst -> [Id] -> (Subst, [Id])
346 substIds subst bndrs = mapAccumL substId subst bndrs
348 substId :: Subst -> Id -> (Subst, Id)
350 -- Returns an Id with empty unfolding and spec-env.
351 -- It's up to the caller to sort these out.
353 substId subst@(Subst in_scope env) old_id
354 = (Subst (in_scope `extendVarSet` new_id)
355 (extendSubstEnv env old_id (DoneEx (Var new_id))),
358 id_ty = idType old_id
360 -- id1 has its type zapped
361 id1 | noTypeSubst env
362 || isEmptyVarSet (tyVarsOfType id_ty) = old_id
363 -- The tyVarsOfType is cheaper than it looks
364 -- because we cache the free tyvars of the type
365 -- in a Note in the id's type itself
366 | otherwise = setIdType old_id (substTy subst id_ty)
368 -- id2 has its fragile IdInfo zapped
369 id2 = maybeModifyIdInfo zapFragileIdInfo id1
371 -- new_id is cloned if necessary
372 new_id = uniqAway in_scope id2
375 Now a variant that unconditionally allocates a new unique.
378 substAndCloneIds :: Subst -> UniqSupply -> [Id] -> (Subst, UniqSupply, [Id])
379 substAndCloneIds subst us [] = (subst, us, [])
380 substAndCloneIds subst us (b:bs) = case substAndCloneId subst us b of { (subst1, us1, b') ->
381 case substAndCloneIds subst1 us1 bs of { (subst2, us2, bs') ->
382 (subst2, us2, (b':bs')) }}
384 substAndCloneId :: Subst -> UniqSupply -> Id -> (Subst, UniqSupply, Id)
385 substAndCloneId subst@(Subst in_scope env) us old_id
386 = (Subst (in_scope `extendVarSet` new_id)
387 (extendSubstEnv env old_id (DoneEx (Var new_id))),
391 id_ty = idType old_id
392 id1 | noTypeSubst env || isEmptyVarSet (tyVarsOfType id_ty) = old_id
393 | otherwise = setIdType old_id (substTy subst id_ty)
395 id2 = maybeModifyIdInfo zapFragileIdInfo id1
396 new_id = setVarUnique id2 (uniqFromSupply us1)
397 (us1,new_us) = splitUniqSupply us
401 %************************************************************************
403 \section{Rule substitution}
405 %************************************************************************
408 substRules :: Subst -> CoreRules -> CoreRules
409 substRules subst (Rules rules rhs_fvs)
410 = Rules (map do_subst rules)
411 (subst_fvs (substEnv subst) rhs_fvs)
413 do_subst (Rule name tpl_vars lhs_args rhs)
414 = Rule name tpl_vars'
415 (map (substExpr subst') lhs_args)
416 (substExpr subst' rhs)
418 (subst', tpl_vars') = substBndrs subst tpl_vars
421 = foldVarSet (unionVarSet . subst_fv) emptyVarSet rhs_fvs
423 subst_fv fv = case lookupSubstEnv se fv of
424 Nothing -> unitVarSet fv
425 Just (DoneEx expr) -> exprFreeVars expr
426 Just (DoneTy ty) -> tyVarsOfType ty
427 Just (ContEx se' expr) -> subst_fvs se' (exprFreeVars expr)