2 % (c) The GRASP/AQUA Project, Glasgow University, 1992-1996
4 \section[DefUtils]{Miscellaneous Utility functions}
6 >#include "HsVersions.h"
9 > strip, stripAtom, stripCaseAlts, freeVars, renameExprs, rebindExpr,
10 > atom2expr, newDefId, newTmpId, deforestable, foldrSUs,
11 > mkDefLetrec, subst, freeTyVars, union, consistent, RenameResult(..),
17 > import Def2Core -- tmp, for traces
23 > import Type ( cloneTyVar, mkTyVarTy, applyTypeEnvToTy,
24 > extractTyVarsFromTy, TyVar, SigmaType(..)
25 > IF_ATTACK_PRAGMAS(COMMA cmpTyVar)
27 > import Literal ( Literal ) -- for Eq Literal
29 > import Id ( mkIdWithNewUniq, mkSysLocal, applyTypeEnvToId,
30 > getIdInfo, toplevelishId, idType, Id )
34 > import PrimOp ( PrimOp ) -- for Eq PrimOp
36 > import SrcLoc ( mkUnknownSrcLoc )
39 -----------------------------------------------------------------------------
42 Implementation of the strip function. Strip is the identity on
43 expressions (recursing into subterms), but replaces each label with
44 its left hand side. The result is a term with no labels.
46 > strip :: DefExpr -> DefExpr
48 > strip e' = case e' of
49 > Var (DefArgExpr e) -> panic "DefUtils(strip): Var (DefExpr _)"
50 > Var (Label l e) -> l
51 > Var (DefArgVar v) -> e'
53 > Con c ts es -> Con c ts (map stripAtom es)
54 > Prim op ts es -> Prim op ts (map stripAtom es)
55 > Lam vs e -> Lam vs (strip e)
56 > CoTyLam alpha e -> CoTyLam alpha (strip e)
57 > App e v -> App (strip e) (stripAtom v)
58 > CoTyApp e t -> CoTyApp (strip e) t
59 > Case e ps -> Case (strip e) (stripCaseAlts ps)
60 > Let (NonRec v e) e' -> Let (NonRec v (strip e)) (strip e')
62 > Let (Rec [ (v, strip e) | (v,e) <- bs ]) (strip e)
63 > SCC l e -> SCC l (strip e)
65 > stripAtom :: DefAtom -> DefAtom
66 > stripAtom (VarArg v) = VarArg (stripArg v)
67 > stripAtom (LitArg l) = LitArg l -- XXX
69 > stripArg :: DefBindee -> DefBindee
70 > stripArg (DefArgExpr e) = DefArgExpr (strip e)
71 > stripArg (Label l e) = panic "DefUtils(stripArg): Label _ _"
72 > stripArg (DefArgVar v) = panic "DefUtils(stripArg): DefArgVar _ _"
74 > stripCaseAlts (AlgAlts as def)
75 > = AlgAlts (map stripAlgAlt as) (stripDefault def)
76 > stripCaseAlts (PrimAlts as def)
77 > = PrimAlts (map stripPrimAlt as) (stripDefault def)
79 > stripAlgAlt (c, vs, e) = (c, vs, strip e)
80 > stripPrimAlt (l, e) = (l, strip e)
82 > stripDefault NoDefault = NoDefault
83 > stripDefault (BindDefault v e) = BindDefault v (strip e)
85 -----------------------------------------------------------------------------
86 \subsection{Free Variables}
88 Find the free variables of an expression. With labels, we descend
89 into the left side since this is the only sensible thing to do.
90 Strictly speaking, for a term (Label l e), freeVars l == freeVars e,
91 but l is guranteed to be finite so we choose that one.
93 > freeVars :: DefExpr -> [Id]
94 > freeVars e = free e []
96 > free e fvs = case e of
97 > Var (DefArgExpr e) ->
98 > panic "DefUtils(free): Var (DefExpr _)"
99 > Var (Label l e) -> free l fvs
101 > | v `is_elem` fvs -> fvs
102 > | otherwise -> v : fvs
103 > where { is_elem = isIn "freeVars(deforest)" }
105 > Con c ts es -> foldr freeAtom fvs es
106 > Prim op ts es -> foldr freeAtom fvs es
107 > Lam vs e -> free' vs (free e fvs)
108 > CoTyLam alpha e -> free e fvs
109 > App e v -> free e (freeAtom v fvs)
110 > CoTyApp e t -> free e fvs
111 > Case e ps -> free e (freeCaseAlts ps fvs)
112 > Let (NonRec v e) e' -> free e (free' [v] (free e' fvs))
113 > Let (Rec bs) e -> free' vs (foldr free (free e fvs) es)
114 > where (vs,es) = unzip bs
115 > SCC l e -> free e fvs
117 > free' :: [Id] -> [Id] -> [Id]
118 > free' vs fvs = filter (\x -> notElem x vs) fvs
120 > freeAtom (VarArg (DefArgExpr e)) fvs = free e fvs
121 > freeAtom (VarArg (Label l e)) fvs
122 > = panic "DefUtils(free): VarArg (Label _ _)"
123 > freeAtom (VarArg (DefArgVar v)) fvs
124 > = panic "DefUtils(free): VarArg (DefArgVar _ _)"
125 > freeAtom (LitArg l) fvs = fvs
127 > freeCaseAlts (AlgAlts as def) fvs
128 > = foldr freeAlgAlt (freeDefault def fvs) as
129 > freeCaseAlts (PrimAlts as def) fvs
130 > = foldr freePrimAlt (freeDefault def fvs) as
132 > freeAlgAlt (c, vs, e) fvs = free' vs (free e fvs)
133 > freePrimAlt (l, e) fvs = free e fvs
135 > freeDefault NoDefault fvs = fvs
136 > freeDefault (BindDefault v e) fvs = free' [v] (free e fvs)
138 -----------------------------------------------------------------------------
139 \subsection{Free Type Variables}
141 > freeTyVars :: DefExpr -> [TyVar]
142 > freeTyVars e = free e []
144 > free e tvs = case e of
145 > Var (DefArgExpr e) ->
146 > panic "DefUtils(freeVars): Var (DefExpr _)"
147 > Var (Label l e) -> free l tvs
148 > Var (DefArgVar id) -> freeId id tvs
150 > Con c ts es -> foldr freeTy (foldr freeAtom tvs es) ts
151 > Prim op ts es -> foldr freeTy (foldr freeAtom tvs es) ts
152 > Lam vs e -> foldr freeId (free e tvs) vs
153 > CoTyLam alpha e -> filter (/= alpha) (free e tvs)
154 > App e v -> free e (freeAtom v tvs)
155 > CoTyApp e t -> free e (freeTy t tvs)
156 > Case e ps -> free e (freeCaseAlts ps tvs)
157 > Let (NonRec v e) e' -> free e (freeId v (free e' tvs))
158 > Let (Rec bs) e -> foldr freeBind (free e tvs) bs
159 > SCC l e -> free e tvs
161 > freeId id tvs = extractTyVarsFromTy (idType id) `union` tvs
162 > freeTy t tvs = extractTyVarsFromTy t `union` tvs
163 > freeBind (v,e) tvs = freeId v (free e tvs)
165 > freeAtom (VarArg (DefArgExpr e)) tvs = free e tvs
166 > freeAtom (VarArg (Label l e)) tvs
167 > = panic "DefUtils(freeVars): VarArg (Label _ _)"
168 > freeAtom (VarArg (DefArgVar v)) tvs
169 > = panic "DefUtils(freeVars): VarArg (DefArgVar _ _)"
170 > freeAtom (LitArg l) tvs = tvs -- XXX
172 > freeCaseAlts (AlgAlts as def) tvs
173 > = foldr freeAlgAlt (freeDefault def tvs) as
174 > freeCaseAlts (PrimAlts as def) tvs
175 > = foldr freePrimAlt (freeDefault def tvs) as
177 > freeAlgAlt (c, vs, e) tvs = foldr freeId (free e tvs) vs
178 > freePrimAlt (l, e) tvs = free e tvs
180 > freeDefault NoDefault tvs = tvs
181 > freeDefault (BindDefault v e) tvs = freeId v (free e tvs)
183 -----------------------------------------------------------------------------
184 \subsection{Rebinding variables in an expression}
186 Here is the code that renames all the bound variables in an expression
187 with new uniques. Free variables are left unchanged.
189 > rebindExpr :: DefExpr -> UniqSM DefExpr
190 > rebindExpr e = uniqueExpr nullIdEnv nullTyVarEnv e
192 > uniqueExpr :: IdEnv Id -> TypeEnv -> DefExpr -> UniqSM DefExpr
195 > Var (DefArgVar v) ->
196 > returnUs (Var (DefArgVar (lookup v p)))
199 > uniqueExpr p t l `thenUs` \l ->
200 > uniqueExpr p t e `thenUs` \e ->
201 > returnUs (mkLabel l e)
203 > Var (DefArgExpr _) ->
204 > panic "DefUtils(uniqueExpr): Var(DefArgExpr _)"
210 > mapUs (uniqueAtom p t) es `thenUs` \es ->
211 > returnUs (Con c (map (applyTypeEnvToTy t) ts) es)
214 > mapUs (uniqueAtom p t) es `thenUs` \es ->
215 > returnUs (Prim op (map (applyTypeEnvToTy t) ts) es)
218 > mapUs (newVar t) vs `thenUs` \vs' ->
219 > uniqueExpr (growIdEnvList p (zip vs vs')) t e `thenUs` \e ->
220 > returnUs (Lam vs' e)
223 > getUnique `thenUs` \u ->
224 > let v' = cloneTyVar v u
225 > t' = addOneToTyVarEnv t v (mkTyVarTy v') in
226 > uniqueExpr p t' e `thenUs` \e ->
227 > returnUs (CoTyLam v' e)
230 > uniqueExpr p t e `thenUs` \e ->
231 > uniqueAtom p t v `thenUs` \v ->
235 > uniqueExpr p t e `thenUs` \e ->
236 > returnUs (CoTyApp e (applyTypeEnvToTy t ty))
239 > uniqueExpr p t e `thenUs` \e ->
240 > uniqueAlts alts `thenUs` \alts ->
241 > returnUs (Case e alts)
243 > uniqueAlts (AlgAlts as d) =
244 > mapUs uniqueAlgAlt as `thenUs` \as ->
245 > uniqueDefault d `thenUs` \d ->
246 > returnUs (AlgAlts as d)
247 > uniqueAlts (PrimAlts as d) =
248 > mapUs uniquePrimAlt as `thenUs` \as ->
249 > uniqueDefault d `thenUs` \d ->
250 > returnUs (PrimAlts as d)
252 > uniqueAlgAlt (c, vs, e) =
253 > mapUs (newVar t) vs `thenUs` \vs' ->
254 > uniqueExpr (growIdEnvList p (zip vs vs')) t e
256 > returnUs (c, vs', e)
257 > uniquePrimAlt (l, e) =
258 > uniqueExpr p t e `thenUs` \e ->
261 > uniqueDefault NoDefault = returnUs NoDefault
262 > uniqueDefault (BindDefault v e) =
263 > newVar t v `thenUs` \v' ->
264 > uniqueExpr (addOneToIdEnv p v v') t e `thenUs` \e ->
265 > returnUs (BindDefault v' e)
267 > Let (NonRec v e) e' ->
268 > uniqueExpr p t e `thenUs` \e ->
269 > newVar t v `thenUs` \v' ->
270 > uniqueExpr (addOneToIdEnv p v v') t e' `thenUs` \e' ->
271 > returnUs (Let (NonRec v' e) e')
274 > let (vs,es) = unzip ds in
275 > mapUs (newVar t) vs `thenUs` \vs' ->
276 > let p' = growIdEnvList p (zip vs vs') in
277 > mapUs (uniqueExpr p' t) es `thenUs` \es ->
278 > uniqueExpr p' t e `thenUs` \e ->
279 > returnUs (Let (Rec (zip vs' es)) e)
282 > uniqueExpr p t e `thenUs` \e ->
286 > uniqueAtom :: IdEnv Id -> TypeEnv -> DefAtom -> UniqSM DefAtom
287 > uniqueAtom p t (LitArg l) = returnUs (LitArg l) -- XXX
288 > uniqueAtom p t (VarArg v) =
289 > uniqueArg p t v `thenUs` \v ->
290 > returnUs (VarArg v)
292 > uniqueArg p t (DefArgVar v) =
293 > panic "DefUtils(uniqueArg): DefArgVar _ _"
294 > uniqueArg p t (DefArgExpr e) =
295 > uniqueExpr p t e `thenUs` \e ->
296 > returnUs (DefArgExpr e)
297 > uniqueArg p t (Label l e) =
298 > panic "DefUtils(uniqueArg): Label _ _"
300 We shouldn't need to apply the type environment to free variables,
301 since their types can only contain type variables that are free in the
302 expression as a whole (?)
304 > lookup :: Id -> IdEnv Id -> Id
306 > case lookupIdEnv p id of
308 > Just new_id -> new_id
310 > newVar :: TypeEnv -> Id -> UniqSM Id
312 > getUnique `thenUs` \u ->
313 > returnUs (mkIdWithNewUniq (applyTypeEnvToId t id) u)
315 -----------------------------------------------------------------------------
316 \subsection{Detecting Renamings}
318 The function `renameExprs' takes two expressions and returns True if
319 they are renamings of each other. The variables in the list `fs' are
320 excluded from the renaming process (i.e. if any of these variables
321 are present in one expression, they cannot be renamed in the other
324 We only allow renaming of sysLocal ids - ie. not top-level, imported
325 or otherwise global ids.
329 > | IsRenaming [(Id,Id)]
330 > | InconsistentRenaming [(Id,Id)]
332 > renameExprs :: DefExpr -> DefExpr -> UniqSM RenameResult
335 > [] -> returnUs NotRenaming
336 > [r] -> if not (consistent r) then
337 > d2c (strip u) `thenUs` \u ->
338 > d2c (strip u') `thenUs` \u' ->
339 > trace ("failed consistency check:\n" ++
340 > ppShow 80 (ppr PprDebug u) ++ "\n" ++
341 > ppShow 80 (ppr PprDebug u'))
342 > (returnUs (InconsistentRenaming r))
344 > trace "Renaming!" (returnUs (IsRenaming r))
345 > _ -> panic "DefUtils(renameExprs)"
347 Check that we have a consistent renaming. A renaming is consistent if
348 each time variable x in expression 1 is renamed, it is renamed to the
351 > consistent :: [(Id,Id)] -> Bool
352 > consistent rs = and [ y == y' | (x,y) <- rs, (x',y') <- rs, x == x' ]
354 > checkConsistency :: [(Id,Id)] -> [[(Id,Id)]] -> [[(Id,Id)]]
355 > checkConsistency bound free = [ r' | r <- free, r' <- check r ]
357 > check r | they're_consistent = [frees]
360 > (bounds,frees) = partition (\(a,b) -> a `elem` lbound) r
361 > (lbound,rbound) = unzip bound
362 > they're_consistent = consistent (bound ++ bounds)
364 Renaming composition operator.
366 > (....) :: [[a]] -> [[a]] -> [[a]]
367 > r .... r' = [ xs ++ xs' | xs <- r, xs' <- r' ]
369 The class of identifiers which can be renamed. It is sensible to
370 disallow renamings of deforestable ids, but the top-level ones are a
371 bit iffy. Ideally, we should allow renaming of top-level ids, but the
372 current scheme allows us to leave out the top-level ids from the
373 argument lists of new function definitions. (we still have the
374 shadowed ones to worry about..)
376 Main renaming function. Returns a list of renamings made while
377 comparing the expressions.
379 > ren :: DefExpr -> DefExpr -> [[(Id,Id)]]
381 > -- renaming or identical cases --
384 > -- same variable, no renaming
385 > ren (Var (DefArgVar x)) t@(Var (DefArgVar y))
386 > | x == y = [[(x,y)]]
387 > | isArgId x && isArgId y = [[(x,y)]]
389 > -- if we're doing matching, use the next rule,
390 > -- and delete the second clause in the above rule.
392 > ren (Var (DefArgVar x)) t
393 > | okToRename x && all (not. deforestable) (freeVars t)
397 > ren (Lit l) (Lit l') | l == l'
399 > ren (Con c ts es) (Con c' ts' es') | c == c'
400 > = foldr (....) [[]] (zipWith renAtom es es')
401 > ren (Prim op ts es) (Prim op' ts' es') | op == op'
402 > = foldr (....) [[]] (zipWith renAtom es es')
403 > ren (Lam vs e) (Lam vs' e')
404 > = checkConsistency (zip vs vs') (ren e e')
405 > ren (CoTyLam vs e) (CoTyLam vs' e')
407 > ren (App e v) (App e' v')
408 > = ren e e' .... renAtom v v'
409 > ren (CoTyApp e t) (CoTyApp e' t')
411 > ren (Case e alts) (Case e' alts')
412 > = ren e e' .... renAlts alts alts'
413 > ren (Let (NonRec v a) b) (Let (NonRec v' a') b')
414 > = ren a a' .... (checkConsistency [(v,v')] (ren b b'))
415 > ren (Let (Rec ds) e) (Let (Rec ds') e')
416 > = checkConsistency (zip vs vs')
417 > (ren e e' .... (foldr (....) [[]] (zipWith ren es es')))
418 > where (vs ,es ) = unzip ds
419 > (vs',es') = unzip ds'
423 > ren (Var (Label l e)) e' = ren l e'
424 > ren e (Var (Label l e')) = ren e l
428 > ren (Var (DefArgExpr _)) _
429 > = panic "DefUtils(ren): Var (DefArgExpr _)"
430 > ren _ (Var (DefArgExpr _))
431 > = panic "DefUtils(ren): Var (DefArgExpr _)"
439 > renAtom (VarArg (DefArgExpr e)) (VarArg (DefArgExpr e'))
441 > -- XXX shouldn't need the next two
442 > renAtom (LitArg l) (LitArg l') | l == l' = [[]]
443 > renAtom (VarArg (DefArgVar v)) _ =
444 > panic "DefUtils(renAtom): VarArg (DefArgVar _ _)"
445 > renAtom _ (VarArg (DefArgVar v)) =
446 > panic "DefUtils(renAtom): VarArg (DefArgVar _ _)"
447 > renAtom (VarArg (Label _ _)) _ =
448 > panic "DefUtils(renAtom): VarArg (Label _ _)"
449 > renAtom e (VarArg (Label l e')) =
450 > panic "DefUtils(renAtom): VarArg (Label _ _)"
454 Renamings of case alternatives doesn't allow reordering, but that
455 should be Ok (we don't ever change the ordering anyway).
457 > renAlts (AlgAlts as dflt) (AlgAlts as' dflt')
458 > = foldr (....) [[]] (zipWith renAlgAlt as as') .... renDefault dflt dflt'
459 > renAlts (PrimAlts as dflt) (PrimAlts as' dflt')
460 > = foldr (....) [[]] (zipWith renPrimAlt as as') .... renDefault dflt dflt'
463 > renAlgAlt (c,vs,e) (c',vs',e') | c == c'
464 > = checkConsistency (zip vs vs') (ren e e')
467 > renPrimAlt (l,e) (l',e') | l == l' = ren e e'
468 > renPrimAlt _ _ = []
470 > renDefault NoDefault NoDefault = [[]]
471 > renDefault (BindDefault v e) (BindDefault v' e')
472 > = checkConsistency [(v,v')] (ren e e')
474 -----------------------------------------------------------------------------
476 > atom2expr :: DefAtom -> DefExpr
477 > atom2expr (VarArg (DefArgExpr e)) = e
478 > atom2expr (VarArg (Label l e)) = mkLabel l e
479 > -- XXX next two should be illegal
480 > atom2expr (LitArg l) = Lit l
481 > atom2expr (VarArg (DefArgVar v)) =
482 > panic "DefUtils(atom2expr): VarArg (DefArgVar _)"
484 > expr2atom = VarArg . DefArgExpr
486 -----------------------------------------------------------------------------
487 Grab a new Id and tag it as coming from the Deforester.
489 > newDefId :: Type -> UniqSM Id
491 > getUnique `thenUs` \u ->
492 > returnUs (mkSysLocal SLIT("def") u t mkUnknownSrcLoc)
494 > newTmpId :: Type -> UniqSM Id
496 > getUnique `thenUs` \u ->
497 > returnUs (mkSysLocal SLIT("tmp") u t mkUnknownSrcLoc)
499 -----------------------------------------------------------------------------
500 Check whether an Id was given a `DEFOREST' annotation by the programmer.
502 > deforestable :: Id -> Bool
504 > case getInfo (getIdInfo id) of
506 > Don'tDeforest -> False
508 -----------------------------------------------------------------------------
509 Filter for free variables to abstract from new functions.
512 > = (not . deforestable) id
513 > && (not . toplevelishId) id
515 -----------------------------------------------------------------------------
517 > foldrSUs f c [] = returnUs c
518 > foldrSUs f c (x:xs)
519 > = foldrSUs f c xs `thenUs` \xs' ->
522 -----------------------------------------------------------------------------
524 > mkDefLetrec [] e = e
525 > mkDefLetrec bs e = Let (Rec bs) e
527 -----------------------------------------------------------------------------
530 > subst :: [(Id,DefExpr)]
534 > subst p e' = sub e'
537 > sub e' = case e' of
538 > Var (DefArgExpr e) -> panic "DefExpr(sub): Var (DefArgExpr _)"
539 > Var (Label l e) -> panic "DefExpr(sub): Var (Label _ _)"
540 > Var (DefArgVar v) ->
541 > case lookupIdEnv p' v of
542 > Just e -> rebindExpr e `thenUs` \e -> returnUs e
543 > Nothing -> returnUs e'
544 > Lit l -> returnUs e'
545 > Con c ts es -> mapUs substAtom es `thenUs` \es ->
546 > returnUs (Con c ts es)
547 > Prim op ts es -> mapUs substAtom es `thenUs` \es ->
548 > returnUs (Prim op ts es)
549 > Lam vs e -> sub e `thenUs` \e ->
550 > returnUs (Lam vs e)
551 > CoTyLam alpha e -> sub e `thenUs` \e ->
552 > returnUs (CoTyLam alpha e)
553 > App e v -> sub e `thenUs` \e ->
554 > substAtom v `thenUs` \v ->
556 > CoTyApp e t -> sub e `thenUs` \e ->
557 > returnUs (CoTyApp e t)
558 > Case e ps -> sub e `thenUs` \e ->
559 > substCaseAlts ps `thenUs` \ps ->
560 > returnUs (Case e ps)
561 > Let (NonRec v e) e'
562 > -> sub e `thenUs` \e ->
563 > sub e' `thenUs` \e' ->
564 > returnUs (Let (NonRec v e) e')
565 > Let (Rec bs) e -> sub e `thenUs` \e ->
566 > mapUs substBind bs `thenUs` \bs ->
567 > returnUs (Let (Rec bs) e)
570 > sub e `thenUs` \e ->
572 > SCC l e -> sub e `thenUs` \e ->
575 > substAtom (VarArg v) =
576 > substArg v `thenUs` \v ->
577 > returnUs (VarArg v)
578 > substAtom (LitArg l) =
579 > returnUs (LitArg l) -- XXX
581 > substArg (DefArgExpr e) =
582 > sub e `thenUs` \e ->
583 > returnUs (DefArgExpr e)
584 > substArg e@(Label _ _) =
585 > panic "DefExpr(substArg): Label _ _"
586 > substArg e@(DefArgVar v) = -- XXX
587 > case lookupIdEnv p' v of
588 > Just e -> rebindExpr e `thenUs` \e ->
589 > returnUs (DefArgExpr e)
590 > Nothing -> returnUs e
592 > substCaseAlts (AlgAlts as def) =
593 > mapUs substAlgAlt as `thenUs` \as ->
594 > substDefault def `thenUs` \def ->
595 > returnUs (AlgAlts as def)
596 > substCaseAlts (PrimAlts as def) =
597 > mapUs substPrimAlt as `thenUs` \as ->
598 > substDefault def `thenUs` \def ->
599 > returnUs (PrimAlts as def)
601 > substAlgAlt (c, vs, e) =
602 > sub e `thenUs` \e ->
603 > returnUs (c, vs, e)
604 > substPrimAlt (l, e) =
605 > sub e `thenUs` \e ->
608 > substDefault NoDefault =
610 > substDefault (BindDefault v e) =
611 > sub e `thenUs` \e ->
612 > returnUs (BindDefault v e)
614 -----------------------------------------------------------------------------
618 > | x `is_elem` ys = union xs ys
619 > | otherwise = x : union xs ys
620 > where { is_elem = isIn "union(deforest)" }