2 % (c) The GRASP/AQUA Project, Glasgow University, 1992-1998
4 Taken quite directly from the Peyton Jones/Lester paper.
8 exprFreeVars, exprsFreeVars,
9 exprSomeFreeVars, exprsSomeFreeVars,
10 idRuleVars, idFreeVars, ruleSomeFreeVars, ruleSomeLhsFreeVars,
12 CoreExprWithFVs, CoreBindWithFVs, freeVars, freeVarsOf,
15 #include "HsVersions.h"
18 import Id ( Id, idFreeTyVars, getIdSpecialisation )
20 import Var ( IdOrTyVar, isId )
21 import Name ( isLocallyDefined )
22 import Type ( tyVarsOfType, Type )
23 import Util ( mapAndUnzip )
26 %************************************************************************
28 \section{Finding the free variables of an expression}
30 %************************************************************************
32 This function simply finds the free variables of an expression.
33 So far as type variables are concerned, it only finds tyvars that are
35 * free in type arguments,
36 * free in the type of a binder,
38 but not those that are free in the type of variable occurrence.
41 exprFreeVars :: CoreExpr -> IdOrTyVarSet -- Find all locally-defined free Ids or tyvars
42 exprFreeVars = exprSomeFreeVars isLocallyDefined
44 exprsFreeVars :: [CoreExpr] -> IdOrTyVarSet
45 exprsFreeVars = foldr (unionVarSet . exprFreeVars) emptyVarSet
47 exprSomeFreeVars :: InterestingVarFun -- Says which Vars are interesting
50 exprSomeFreeVars fv_cand e = expr_fvs e fv_cand emptyVarSet
52 exprsSomeFreeVars :: InterestingVarFun -- Says which Vars are interesting
55 exprsSomeFreeVars fv_cand = foldr (unionVarSet . exprSomeFreeVars fv_cand) emptyVarSet
57 type InterestingVarFun = IdOrTyVar -> Bool -- True <=> interesting
62 type FV = InterestingVarFun
63 -> IdOrTyVarSet -- In scope
64 -> IdOrTyVarSet -- Free vars
66 union :: FV -> FV -> FV
67 union fv1 fv2 fv_cand in_scope = fv1 fv_cand in_scope `unionVarSet` fv2 fv_cand in_scope
70 noVars fv_cand in_scope = emptyVarSet
72 -- At a variable occurrence, add in any free variables of its rule rhss
73 -- Curiously, we gather the Id's free *type* variables from its binding
74 -- site, but its free *rule-rhs* variables from its usage sites. This
75 -- is a little weird. The reason is that the former is more efficient,
76 -- but the latter is more fine grained, and a makes a difference when
77 -- a variable mentions itself one of its own rule RHSs
78 oneVar :: IdOrTyVar -> FV
79 oneVar var fv_cand in_scope
80 = foldVarSet add_rule_var var_itself_set (idRuleVars var)
82 var_itself_set | keep_it fv_cand in_scope var = unitVarSet var
83 | otherwise = emptyVarSet
84 add_rule_var var set | keep_it fv_cand in_scope var = extendVarSet set var
87 someVars :: IdOrTyVarSet -> FV
88 someVars vars fv_cand in_scope
89 = filterVarSet (keep_it fv_cand in_scope) vars
91 keep_it fv_cand in_scope var
92 | var `elemVarSet` in_scope = False
97 addBndr :: CoreBndr -> FV -> FV
98 addBndr bndr fv fv_cand in_scope
99 | isId bndr = inside_fvs `unionVarSet` someVars (idFreeTyVars bndr) fv_cand in_scope
100 | otherwise = inside_fvs
102 inside_fvs = fv fv_cand (in_scope `extendVarSet` bndr)
104 addBndrs :: [CoreBndr] -> FV -> FV
105 addBndrs bndrs fv = foldr addBndr fv bndrs
110 expr_fvs :: CoreExpr -> FV
112 expr_fvs (Type ty) = someVars (tyVarsOfType ty)
113 expr_fvs (Var var) = oneVar var
114 expr_fvs (Con con args) = foldr (union . expr_fvs) noVars args
115 expr_fvs (Note _ expr) = expr_fvs expr
116 expr_fvs (App fun arg) = expr_fvs fun `union` expr_fvs arg
117 expr_fvs (Lam bndr body) = addBndr bndr (expr_fvs body)
119 expr_fvs (Case scrut bndr alts)
120 = expr_fvs scrut `union` addBndr bndr (foldr (union . alt_fvs) noVars alts)
122 alt_fvs (con, bndrs, rhs) = addBndrs bndrs (expr_fvs rhs)
124 expr_fvs (Let (NonRec bndr rhs) body)
125 = expr_fvs rhs `union` addBndr bndr (expr_fvs body)
127 expr_fvs (Let (Rec pairs) body)
128 = addBndrs bndrs (foldr (union . expr_fvs) (expr_fvs body) rhss)
130 (bndrs,rhss) = unzip pairs
136 idRuleVars ::Id -> IdOrTyVarSet
137 idRuleVars id = rulesRhsFreeVars (getIdSpecialisation id)
139 idFreeVars :: Id -> IdOrTyVarSet
140 idFreeVars id = idRuleVars id `unionVarSet` idFreeTyVars id
142 rulesSomeFreeVars :: InterestingVarFun -> CoreRules -> IdOrTyVarSet
143 rulesSomeFreeVars interesting (Rules rules _)
144 = foldr (unionVarSet . ruleSomeFreeVars interesting) emptyVarSet rules
146 ruleSomeFreeVars :: InterestingVarFun -> CoreRule -> IdOrTyVarSet
147 ruleSomeFreeVars interesting (Rule _ tpl_vars tpl_args rhs)
148 = rule_fvs interesting emptyVarSet
150 rule_fvs = addBndrs tpl_vars $
151 foldr (union . expr_fvs) (expr_fvs rhs) tpl_args
153 ruleSomeLhsFreeVars :: InterestingVarFun -> CoreRule -> IdOrTyVarSet
154 ruleSomeLhsFreeVars fn (Rule _ tpl_vars tpl_args rhs)
155 = foldl delVarSet (exprsSomeFreeVars fn tpl_args) tpl_vars
159 %************************************************************************
161 \section[freevars-everywhere]{Attaching free variables to every sub-expression}
163 %************************************************************************
165 The free variable pass annotates every node in the expression with its
166 NON-GLOBAL free variables and type variables.
169 type CoreBindWithFVs = AnnBind Id IdOrTyVarSet
170 type CoreExprWithFVs = AnnExpr Id IdOrTyVarSet
171 -- Every node annotated with its free variables,
172 -- both Ids and TyVars
174 freeVarsOf :: CoreExprWithFVs -> IdSet
175 freeVarsOf (free_vars, _) = free_vars
178 aFreeVar = unitVarSet
179 unionFVs = unionVarSet
181 filters :: IdOrTyVar -> IdOrTyVarSet -> IdOrTyVarSet
183 -- (b `filters` s) removes the binder b from the free variable set s,
185 -- (a) the free variables of b's type
186 -- (b) the idSpecVars of b
188 -- This is really important for some lambdas:
189 -- In (\x::a -> x) the only mention of "a" is in the binder.
192 -- let x::a = b in ...
193 -- we should really note that "a" is free in this expression.
194 -- It'll be pinned inside the /\a by the binding for b, but
195 -- it seems cleaner to make sure that a is in the free-var set
196 -- when it is mentioned.
198 -- This also shows up in recursive bindings. Consider:
199 -- /\a -> letrec x::a = x in E
200 -- Now, there are no explicit free type variables in the RHS of x,
201 -- but nevertheless "a" is free in its definition. So we add in
202 -- the free tyvars of the types of the binders, and include these in the
203 -- free vars of the group, attached to the top level of each RHS.
205 -- This actually happened in the defn of errorIO in IOBase.lhs:
206 -- errorIO (ST io) = case (errorIO# io) of
209 -- bottom = bottom -- Never evaluated
211 filters b s | isId b = (s `delVarSet` b) `unionFVs` idFreeVars b
212 | otherwise = s `delVarSet` b
216 %************************************************************************
218 \subsection{Free variables (and types)}
220 %************************************************************************
223 freeVars :: CoreExpr -> CoreExprWithFVs
228 -- ToDo: insert motivating example for why we *need*
229 -- to include the idSpecVars in the FV list.
230 -- Actually [June 98] I don't think it's necessary
231 -- fvs = fvs_v `unionVarSet` idSpecVars v
233 fvs | isLocallyDefined v = aFreeVar v
236 freeVars (Con con args)
237 = (foldr (unionFVs . freeVarsOf) noFVs args2, AnnCon con args2)
239 args2 = map freeVars args
241 freeVars (Lam b body)
242 = (b `filters` freeVarsOf body', AnnLam b body')
244 body' = freeVars body
246 freeVars (App fun arg)
247 = (freeVarsOf fun2 `unionFVs` freeVarsOf arg2, AnnApp fun2 arg2)
252 freeVars (Case scrut bndr alts)
253 = ((bndr `filters` alts_fvs) `unionFVs` freeVarsOf scrut2,
254 AnnCase scrut2 bndr alts2)
256 scrut2 = freeVars scrut
258 (alts_fvs_s, alts2) = mapAndUnzip fv_alt alts
259 alts_fvs = foldr1 unionFVs alts_fvs_s
261 fv_alt (con,args,rhs) = (foldr filters (freeVarsOf rhs2) args,
266 freeVars (Let (NonRec binder rhs) body)
267 = (freeVarsOf rhs2 `unionFVs` body_fvs,
268 AnnLet (AnnNonRec binder rhs2) body2)
271 body2 = freeVars body
272 body_fvs = binder `filters` freeVarsOf body2
274 freeVars (Let (Rec binds) body)
275 = (foldl delVarSet group_fvs binders,
276 -- The "filters" part may have added one of the binders
277 -- via the idSpecVars part, so we must delete it again
278 AnnLet (AnnRec (binders `zip` rhss2)) body2)
280 (binders, rhss) = unzip binds
282 rhss2 = map freeVars rhss
283 all_fvs = foldr (unionFVs . fst) body_fvs rhss2
284 group_fvs = foldr filters all_fvs binders
286 body2 = freeVars body
287 body_fvs = freeVarsOf body2
289 freeVars (Note (Coerce to_ty from_ty) expr)
290 = (freeVarsOf expr2 `unionFVs` tfvs1 `unionFVs` tfvs2,
291 AnnNote (Coerce to_ty from_ty) expr2)
293 expr2 = freeVars expr
294 tfvs1 = tyVarsOfType from_ty
295 tfvs2 = tyVarsOfType to_ty
297 freeVars (Note other_note expr)
298 = (freeVarsOf expr2, AnnNote other_note expr2)
300 expr2 = freeVars expr
302 freeVars (Type ty) = (tyVarsOfType ty, AnnType ty)