bd59e15253640a34bbeed777b830791c2ed389fc
[ghc.git] / compiler / basicTypes / VarEnv.hs
1 {-
2 (c) The University of Glasgow 2006
3 (c) The GRASP/AQUA Project, Glasgow University, 1992-1998
4 -}
5
6 module VarEnv (
7 -- * Var, Id and TyVar environments (maps)
8 VarEnv, IdEnv, TyVarEnv, CoVarEnv, TyCoVarEnv,
9
10 -- ** Manipulating these environments
11 emptyVarEnv, unitVarEnv, mkVarEnv, mkVarEnv_Directly,
12 elemVarEnv, varEnvElts, varEnvKeys, varEnvToList,
13 extendVarEnv, extendVarEnv_C, extendVarEnv_Acc, extendVarEnv_Directly,
14 extendVarEnvList,
15 plusVarEnv, plusVarEnv_C, plusVarEnv_CD, alterVarEnv,
16 delVarEnvList, delVarEnv, delVarEnv_Directly,
17 minusVarEnv, intersectsVarEnv,
18 lookupVarEnv, lookupVarEnv_NF, lookupWithDefaultVarEnv,
19 mapVarEnv, zipVarEnv,
20 modifyVarEnv, modifyVarEnv_Directly,
21 isEmptyVarEnv, foldVarEnv, foldVarEnv_Directly,
22 elemVarEnvByKey, lookupVarEnv_Directly,
23 filterVarEnv, filterVarEnv_Directly, restrictVarEnv,
24 partitionVarEnv,
25
26 -- * Deterministic Var environments (maps)
27 DVarEnv,
28
29 -- ** Manipulating these environments
30 emptyDVarEnv,
31 extendDVarEnv,
32 lookupDVarEnv,
33 foldDVarEnv,
34
35 -- * The InScopeSet type
36 InScopeSet,
37
38 -- ** Operations on InScopeSets
39 emptyInScopeSet, mkInScopeSet, delInScopeSet,
40 extendInScopeSet, extendInScopeSetList, extendInScopeSetSet,
41 getInScopeVars, lookupInScope, lookupInScope_Directly,
42 unionInScope, elemInScopeSet, uniqAway,
43 varSetInScope,
44
45 -- * The RnEnv2 type
46 RnEnv2,
47
48 -- ** Operations on RnEnv2s
49 mkRnEnv2, rnBndr2, rnBndrs2, rnBndr2_var,
50 rnOccL, rnOccR, inRnEnvL, inRnEnvR, rnOccL_maybe, rnOccR_maybe,
51 rnBndrL, rnBndrR, nukeRnEnvL, nukeRnEnvR, rnSwap,
52 delBndrL, delBndrR, delBndrsL, delBndrsR,
53 addRnInScopeSet,
54 rnEtaL, rnEtaR,
55 rnInScope, rnInScopeSet, lookupRnInScope,
56 rnEnvL, rnEnvR,
57
58 -- * TidyEnv and its operation
59 TidyEnv,
60 emptyTidyEnv
61 ) where
62
63 import OccName
64 import Var
65 import VarSet
66 import UniqFM
67 import UniqDFM
68 import Unique
69 import Util
70 import Maybes
71 import Outputable
72 import StaticFlags
73
74 {-
75 ************************************************************************
76 * *
77 In-scope sets
78 * *
79 ************************************************************************
80 -}
81
82 -- | A set of variables that are in scope at some point
83 -- "Secrets of the Glasgow Haskell Compiler inliner" Section 3. provides
84 -- the motivation for this abstraction.
85 data InScopeSet = InScope (VarEnv Var) {-# UNPACK #-} !Int
86 -- The (VarEnv Var) is just a VarSet. But we write it like
87 -- this to remind ourselves that you can look up a Var in
88 -- the InScopeSet. Typically the InScopeSet contains the
89 -- canonical version of the variable (e.g. with an informative
90 -- unfolding), so this lookup is useful.
91 --
92 -- INVARIANT: the VarEnv maps (the Unique of) a variable to
93 -- a variable with the same Unique. (This was not
94 -- the case in the past, when we had a grevious hack
95 -- mapping var1 to var2.
96 --
97 -- The Int is a kind of hash-value used by uniqAway
98 -- For example, it might be the size of the set
99 -- INVARIANT: it's not zero; we use it as a multiplier in uniqAway
100
101 instance Outputable InScopeSet where
102 ppr (InScope s _) = text "InScope"
103 <+> braces (fsep (map (ppr . Var.varName) (varSetElems s)))
104 -- In-scope sets get big, and with -dppr-debug
105 -- the output is overwhelming
106
107 emptyInScopeSet :: InScopeSet
108 emptyInScopeSet = InScope emptyVarSet 1
109
110 getInScopeVars :: InScopeSet -> VarEnv Var
111 getInScopeVars (InScope vs _) = vs
112
113 mkInScopeSet :: VarEnv Var -> InScopeSet
114 mkInScopeSet in_scope = InScope in_scope 1
115
116 extendInScopeSet :: InScopeSet -> Var -> InScopeSet
117 extendInScopeSet (InScope in_scope n) v = InScope (extendVarEnv in_scope v v) (n + 1)
118
119 extendInScopeSetList :: InScopeSet -> [Var] -> InScopeSet
120 extendInScopeSetList (InScope in_scope n) vs
121 = InScope (foldl (\s v -> extendVarEnv s v v) in_scope vs)
122 (n + length vs)
123
124 extendInScopeSetSet :: InScopeSet -> VarEnv Var -> InScopeSet
125 extendInScopeSetSet (InScope in_scope n) vs
126 = InScope (in_scope `plusVarEnv` vs) (n + sizeUFM vs)
127
128 delInScopeSet :: InScopeSet -> Var -> InScopeSet
129 delInScopeSet (InScope in_scope n) v = InScope (in_scope `delVarEnv` v) n
130
131 elemInScopeSet :: Var -> InScopeSet -> Bool
132 elemInScopeSet v (InScope in_scope _) = v `elemVarEnv` in_scope
133
134 -- | Look up a variable the 'InScopeSet'. This lets you map from
135 -- the variable's identity (unique) to its full value.
136 lookupInScope :: InScopeSet -> Var -> Maybe Var
137 lookupInScope (InScope in_scope _) v = lookupVarEnv in_scope v
138
139 lookupInScope_Directly :: InScopeSet -> Unique -> Maybe Var
140 lookupInScope_Directly (InScope in_scope _) uniq
141 = lookupVarEnv_Directly in_scope uniq
142
143 unionInScope :: InScopeSet -> InScopeSet -> InScopeSet
144 unionInScope (InScope s1 _) (InScope s2 n2)
145 = InScope (s1 `plusVarEnv` s2) n2
146
147 varSetInScope :: VarSet -> InScopeSet -> Bool
148 varSetInScope vars (InScope s1 _) = vars `subVarSet` s1
149
150 -- | @uniqAway in_scope v@ finds a unique that is not used in the
151 -- in-scope set, and gives that to v.
152 uniqAway :: InScopeSet -> Var -> Var
153 -- It starts with v's current unique, of course, in the hope that it won't
154 -- have to change, and thereafter uses a combination of that and the hash-code
155 -- found in the in-scope set
156 uniqAway in_scope var
157 | var `elemInScopeSet` in_scope = uniqAway' in_scope var -- Make a new one
158 | otherwise = var -- Nothing to do
159
160 uniqAway' :: InScopeSet -> Var -> Var
161 -- This one *always* makes up a new variable
162 uniqAway' (InScope set n) var
163 = try 1
164 where
165 orig_unique = getUnique var
166 try k
167 | debugIsOn && (k > 1000)
168 = pprPanic "uniqAway loop:" (ppr k <+> text "tries" <+> ppr var <+> int n)
169 | uniq `elemVarSetByKey` set = try (k + 1)
170 | debugIsOn && opt_PprStyle_Debug && (k > 3)
171 = pprTrace "uniqAway:" (ppr k <+> text "tries" <+> ppr var <+> int n)
172 setVarUnique var uniq
173 | otherwise = setVarUnique var uniq
174 where
175 uniq = deriveUnique orig_unique (n * k)
176
177 {-
178 ************************************************************************
179 * *
180 Dual renaming
181 * *
182 ************************************************************************
183 -}
184
185 -- | When we are comparing (or matching) types or terms, we are faced with
186 -- \"going under\" corresponding binders. E.g. when comparing:
187 --
188 -- > \x. e1 ~ \y. e2
189 --
190 -- Basically we want to rename [@x@ -> @y@] or [@y@ -> @x@], but there are lots of
191 -- things we must be careful of. In particular, @x@ might be free in @e2@, or
192 -- y in @e1@. So the idea is that we come up with a fresh binder that is free
193 -- in neither, and rename @x@ and @y@ respectively. That means we must maintain:
194 --
195 -- 1. A renaming for the left-hand expression
196 --
197 -- 2. A renaming for the right-hand expressions
198 --
199 -- 3. An in-scope set
200 --
201 -- Furthermore, when matching, we want to be able to have an 'occurs check',
202 -- to prevent:
203 --
204 -- > \x. f ~ \y. y
205 --
206 -- matching with [@f@ -> @y@]. So for each expression we want to know that set of
207 -- locally-bound variables. That is precisely the domain of the mappings 1.
208 -- and 2., but we must ensure that we always extend the mappings as we go in.
209 --
210 -- All of this information is bundled up in the 'RnEnv2'
211 data RnEnv2
212 = RV2 { envL :: VarEnv Var -- Renaming for Left term
213 , envR :: VarEnv Var -- Renaming for Right term
214 , in_scope :: InScopeSet } -- In scope in left or right terms
215
216 -- The renamings envL and envR are *guaranteed* to contain a binding
217 -- for every variable bound as we go into the term, even if it is not
218 -- renamed. That way we can ask what variables are locally bound
219 -- (inRnEnvL, inRnEnvR)
220
221 mkRnEnv2 :: InScopeSet -> RnEnv2
222 mkRnEnv2 vars = RV2 { envL = emptyVarEnv
223 , envR = emptyVarEnv
224 , in_scope = vars }
225
226 addRnInScopeSet :: RnEnv2 -> VarEnv Var -> RnEnv2
227 addRnInScopeSet env vs
228 | isEmptyVarEnv vs = env
229 | otherwise = env { in_scope = extendInScopeSetSet (in_scope env) vs }
230
231 rnInScope :: Var -> RnEnv2 -> Bool
232 rnInScope x env = x `elemInScopeSet` in_scope env
233
234 rnInScopeSet :: RnEnv2 -> InScopeSet
235 rnInScopeSet = in_scope
236
237 -- | Retrieve the left mapping
238 rnEnvL :: RnEnv2 -> VarEnv Var
239 rnEnvL = envL
240
241 -- | Retrieve the right mapping
242 rnEnvR :: RnEnv2 -> VarEnv Var
243 rnEnvR = envR
244
245 rnBndrs2 :: RnEnv2 -> [Var] -> [Var] -> RnEnv2
246 -- ^ Applies 'rnBndr2' to several variables: the two variable lists must be of equal length
247 rnBndrs2 env bsL bsR = foldl2 rnBndr2 env bsL bsR
248
249 rnBndr2 :: RnEnv2 -> Var -> Var -> RnEnv2
250 -- ^ @rnBndr2 env bL bR@ goes under a binder @bL@ in the Left term,
251 -- and binder @bR@ in the Right term.
252 -- It finds a new binder, @new_b@,
253 -- and returns an environment mapping @bL -> new_b@ and @bR -> new_b@
254 rnBndr2 env bL bR = fst $ rnBndr2_var env bL bR
255
256 rnBndr2_var :: RnEnv2 -> Var -> Var -> (RnEnv2, Var)
257 -- ^ Similar to 'rnBndr2' but returns the new variable as well as the
258 -- new environment
259 rnBndr2_var (RV2 { envL = envL, envR = envR, in_scope = in_scope }) bL bR
260 = (RV2 { envL = extendVarEnv envL bL new_b -- See Note
261 , envR = extendVarEnv envR bR new_b -- [Rebinding]
262 , in_scope = extendInScopeSet in_scope new_b }, new_b)
263 where
264 -- Find a new binder not in scope in either term
265 new_b | not (bL `elemInScopeSet` in_scope) = bL
266 | not (bR `elemInScopeSet` in_scope) = bR
267 | otherwise = uniqAway' in_scope bL
268
269 -- Note [Rebinding]
270 -- If the new var is the same as the old one, note that
271 -- the extendVarEnv *deletes* any current renaming
272 -- E.g. (\x. \x. ...) ~ (\y. \z. ...)
273 --
274 -- Inside \x \y { [x->y], [y->y], {y} }
275 -- \x \z { [x->x], [y->y, z->x], {y,x} }
276
277 rnBndrL :: RnEnv2 -> Var -> (RnEnv2, Var)
278 -- ^ Similar to 'rnBndr2' but used when there's a binder on the left
279 -- side only.
280 rnBndrL (RV2 { envL = envL, envR = envR, in_scope = in_scope }) bL
281 = (RV2 { envL = extendVarEnv envL bL new_b
282 , envR = envR
283 , in_scope = extendInScopeSet in_scope new_b }, new_b)
284 where
285 new_b = uniqAway in_scope bL
286
287 rnBndrR :: RnEnv2 -> Var -> (RnEnv2, Var)
288 -- ^ Similar to 'rnBndr2' but used when there's a binder on the right
289 -- side only.
290 rnBndrR (RV2 { envL = envL, envR = envR, in_scope = in_scope }) bR
291 = (RV2 { envR = extendVarEnv envR bR new_b
292 , envL = envL
293 , in_scope = extendInScopeSet in_scope new_b }, new_b)
294 where
295 new_b = uniqAway in_scope bR
296
297 rnEtaL :: RnEnv2 -> Var -> (RnEnv2, Var)
298 -- ^ Similar to 'rnBndrL' but used for eta expansion
299 -- See Note [Eta expansion]
300 rnEtaL (RV2 { envL = envL, envR = envR, in_scope = in_scope }) bL
301 = (RV2 { envL = extendVarEnv envL bL new_b
302 , envR = extendVarEnv envR new_b new_b -- Note [Eta expansion]
303 , in_scope = extendInScopeSet in_scope new_b }, new_b)
304 where
305 new_b = uniqAway in_scope bL
306
307 rnEtaR :: RnEnv2 -> Var -> (RnEnv2, Var)
308 -- ^ Similar to 'rnBndr2' but used for eta expansion
309 -- See Note [Eta expansion]
310 rnEtaR (RV2 { envL = envL, envR = envR, in_scope = in_scope }) bR
311 = (RV2 { envL = extendVarEnv envL new_b new_b -- Note [Eta expansion]
312 , envR = extendVarEnv envR bR new_b
313 , in_scope = extendInScopeSet in_scope new_b }, new_b)
314 where
315 new_b = uniqAway in_scope bR
316
317 delBndrL, delBndrR :: RnEnv2 -> Var -> RnEnv2
318 delBndrL rn@(RV2 { envL = env, in_scope = in_scope }) v
319 = rn { envL = env `delVarEnv` v, in_scope = in_scope `extendInScopeSet` v }
320 delBndrR rn@(RV2 { envR = env, in_scope = in_scope }) v
321 = rn { envR = env `delVarEnv` v, in_scope = in_scope `extendInScopeSet` v }
322
323 delBndrsL, delBndrsR :: RnEnv2 -> [Var] -> RnEnv2
324 delBndrsL rn@(RV2 { envL = env, in_scope = in_scope }) v
325 = rn { envL = env `delVarEnvList` v, in_scope = in_scope `extendInScopeSetList` v }
326 delBndrsR rn@(RV2 { envR = env, in_scope = in_scope }) v
327 = rn { envR = env `delVarEnvList` v, in_scope = in_scope `extendInScopeSetList` v }
328
329 rnOccL, rnOccR :: RnEnv2 -> Var -> Var
330 -- ^ Look up the renaming of an occurrence in the left or right term
331 rnOccL (RV2 { envL = env }) v = lookupVarEnv env v `orElse` v
332 rnOccR (RV2 { envR = env }) v = lookupVarEnv env v `orElse` v
333
334 rnOccL_maybe, rnOccR_maybe :: RnEnv2 -> Var -> Maybe Var
335 -- ^ Look up the renaming of an occurrence in the left or right term
336 rnOccL_maybe (RV2 { envL = env }) v = lookupVarEnv env v
337 rnOccR_maybe (RV2 { envR = env }) v = lookupVarEnv env v
338
339 inRnEnvL, inRnEnvR :: RnEnv2 -> Var -> Bool
340 -- ^ Tells whether a variable is locally bound
341 inRnEnvL (RV2 { envL = env }) v = v `elemVarEnv` env
342 inRnEnvR (RV2 { envR = env }) v = v `elemVarEnv` env
343
344 lookupRnInScope :: RnEnv2 -> Var -> Var
345 lookupRnInScope env v = lookupInScope (in_scope env) v `orElse` v
346
347 nukeRnEnvL, nukeRnEnvR :: RnEnv2 -> RnEnv2
348 -- ^ Wipe the left or right side renaming
349 nukeRnEnvL env = env { envL = emptyVarEnv }
350 nukeRnEnvR env = env { envR = emptyVarEnv }
351
352 rnSwap :: RnEnv2 -> RnEnv2
353 -- ^ swap the meaning of left and right
354 rnSwap (RV2 { envL = envL, envR = envR, in_scope = in_scope })
355 = RV2 { envL = envR, envR = envL, in_scope = in_scope }
356
357 {-
358 Note [Eta expansion]
359 ~~~~~~~~~~~~~~~~~~~~
360 When matching
361 (\x.M) ~ N
362 we rename x to x' with, where x' is not in scope in
363 either term. Then we want to behave as if we'd seen
364 (\x'.M) ~ (\x'.N x')
365 Since x' isn't in scope in N, the form (\x'. N x') doesn't
366 capture any variables in N. But we must nevertheless extend
367 the envR with a binding [x' -> x'], to support the occurs check.
368 For example, if we don't do this, we can get silly matches like
369 forall a. (\y.a) ~ v
370 succeeding with [a -> v y], which is bogus of course.
371
372
373 ************************************************************************
374 * *
375 Tidying
376 * *
377 ************************************************************************
378 -}
379
380 -- | When tidying up print names, we keep a mapping of in-scope occ-names
381 -- (the 'TidyOccEnv') and a Var-to-Var of the current renamings
382 type TidyEnv = (TidyOccEnv, VarEnv Var)
383
384 emptyTidyEnv :: TidyEnv
385 emptyTidyEnv = (emptyTidyOccEnv, emptyVarEnv)
386
387 {-
388 ************************************************************************
389 * *
390 \subsection{@VarEnv@s}
391 * *
392 ************************************************************************
393 -}
394
395 type VarEnv elt = UniqFM elt
396 type IdEnv elt = VarEnv elt
397 type TyVarEnv elt = VarEnv elt
398 type TyCoVarEnv elt = VarEnv elt
399 type CoVarEnv elt = VarEnv elt
400
401 emptyVarEnv :: VarEnv a
402 mkVarEnv :: [(Var, a)] -> VarEnv a
403 mkVarEnv_Directly :: [(Unique, a)] -> VarEnv a
404 zipVarEnv :: [Var] -> [a] -> VarEnv a
405 unitVarEnv :: Var -> a -> VarEnv a
406 alterVarEnv :: (Maybe a -> Maybe a) -> VarEnv a -> Var -> VarEnv a
407 extendVarEnv :: VarEnv a -> Var -> a -> VarEnv a
408 extendVarEnv_C :: (a->a->a) -> VarEnv a -> Var -> a -> VarEnv a
409 extendVarEnv_Acc :: (a->b->b) -> (a->b) -> VarEnv b -> Var -> a -> VarEnv b
410 extendVarEnv_Directly :: VarEnv a -> Unique -> a -> VarEnv a
411 plusVarEnv :: VarEnv a -> VarEnv a -> VarEnv a
412 extendVarEnvList :: VarEnv a -> [(Var, a)] -> VarEnv a
413
414 lookupVarEnv_Directly :: VarEnv a -> Unique -> Maybe a
415 filterVarEnv_Directly :: (Unique -> a -> Bool) -> VarEnv a -> VarEnv a
416 delVarEnv_Directly :: VarEnv a -> Unique -> VarEnv a
417 partitionVarEnv :: (a -> Bool) -> VarEnv a -> (VarEnv a, VarEnv a)
418 restrictVarEnv :: VarEnv a -> VarSet -> VarEnv a
419 delVarEnvList :: VarEnv a -> [Var] -> VarEnv a
420 delVarEnv :: VarEnv a -> Var -> VarEnv a
421 minusVarEnv :: VarEnv a -> VarEnv b -> VarEnv a
422 intersectsVarEnv :: VarEnv a -> VarEnv a -> Bool
423 plusVarEnv_C :: (a -> a -> a) -> VarEnv a -> VarEnv a -> VarEnv a
424 plusVarEnv_CD :: (a -> a -> a) -> VarEnv a -> a -> VarEnv a -> a -> VarEnv a
425 mapVarEnv :: (a -> b) -> VarEnv a -> VarEnv b
426 modifyVarEnv :: (a -> a) -> VarEnv a -> Var -> VarEnv a
427 varEnvElts :: VarEnv a -> [a]
428 varEnvKeys :: VarEnv a -> [Unique]
429 varEnvToList :: VarEnv a -> [(Unique, a)]
430
431 isEmptyVarEnv :: VarEnv a -> Bool
432 lookupVarEnv :: VarEnv a -> Var -> Maybe a
433 filterVarEnv :: (a -> Bool) -> VarEnv a -> VarEnv a
434 lookupVarEnv_NF :: VarEnv a -> Var -> a
435 lookupWithDefaultVarEnv :: VarEnv a -> a -> Var -> a
436 elemVarEnv :: Var -> VarEnv a -> Bool
437 elemVarEnvByKey :: Unique -> VarEnv a -> Bool
438 foldVarEnv :: (a -> b -> b) -> b -> VarEnv a -> b
439 foldVarEnv_Directly :: (Unique -> a -> b -> b) -> b -> VarEnv a -> b
440
441 elemVarEnv = elemUFM
442 elemVarEnvByKey = elemUFM_Directly
443 alterVarEnv = alterUFM
444 extendVarEnv = addToUFM
445 extendVarEnv_C = addToUFM_C
446 extendVarEnv_Acc = addToUFM_Acc
447 extendVarEnv_Directly = addToUFM_Directly
448 extendVarEnvList = addListToUFM
449 plusVarEnv_C = plusUFM_C
450 plusVarEnv_CD = plusUFM_CD
451 delVarEnvList = delListFromUFM
452 delVarEnv = delFromUFM
453 minusVarEnv = minusUFM
454 intersectsVarEnv e1 e2 = not (isEmptyVarEnv (e1 `intersectUFM` e2))
455 plusVarEnv = plusUFM
456 lookupVarEnv = lookupUFM
457 filterVarEnv = filterUFM
458 lookupWithDefaultVarEnv = lookupWithDefaultUFM
459 mapVarEnv = mapUFM
460 mkVarEnv = listToUFM
461 mkVarEnv_Directly= listToUFM_Directly
462 emptyVarEnv = emptyUFM
463 varEnvElts = eltsUFM
464 varEnvKeys = keysUFM
465 varEnvToList = ufmToList
466 unitVarEnv = unitUFM
467 isEmptyVarEnv = isNullUFM
468 foldVarEnv = foldUFM
469 foldVarEnv_Directly = foldUFM_Directly
470 lookupVarEnv_Directly = lookupUFM_Directly
471 filterVarEnv_Directly = filterUFM_Directly
472 delVarEnv_Directly = delFromUFM_Directly
473 partitionVarEnv = partitionUFM
474
475 restrictVarEnv env vs = filterVarEnv_Directly keep env
476 where
477 keep u _ = u `elemVarSetByKey` vs
478
479 zipVarEnv tyvars tys = mkVarEnv (zipEqual "zipVarEnv" tyvars tys)
480 lookupVarEnv_NF env id = case lookupVarEnv env id of
481 Just xx -> xx
482 Nothing -> panic "lookupVarEnv_NF: Nothing"
483
484 {-
485 @modifyVarEnv@: Look up a thing in the VarEnv,
486 then mash it with the modify function, and put it back.
487 -}
488
489 modifyVarEnv mangle_fn env key
490 = case (lookupVarEnv env key) of
491 Nothing -> env
492 Just xx -> extendVarEnv env key (mangle_fn xx)
493
494 modifyVarEnv_Directly :: (a -> a) -> UniqFM a -> Unique -> UniqFM a
495 modifyVarEnv_Directly mangle_fn env key
496 = case (lookupUFM_Directly env key) of
497 Nothing -> env
498 Just xx -> addToUFM_Directly env key (mangle_fn xx)
499
500 -- Deterministic VarEnv
501 -- See Note [Deterministic UniqFM] in UniqDFM for explanation why we need
502 -- DVarEnv.
503
504 type DVarEnv elt = UniqDFM elt
505
506 emptyDVarEnv :: DVarEnv a
507 emptyDVarEnv = emptyUDFM
508
509 extendDVarEnv :: DVarEnv a -> Var -> a -> DVarEnv a
510 extendDVarEnv = addToUDFM
511
512 lookupDVarEnv :: DVarEnv a -> Var -> Maybe a
513 lookupDVarEnv = lookupUDFM
514
515 foldDVarEnv :: (a -> b -> b) -> b -> DVarEnv a -> b
516 foldDVarEnv = foldUDFM