[project @ 2001-01-25 17:32:42 by simonpj]
[ghc-hetmet.git] / ghc / compiler / coreSyn / Subst.lhs
index d9d9279..1866956 100644 (file)
@@ -37,31 +37,33 @@ module Subst (
 #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}
 
 
@@ -72,7 +74,7 @@ import Util           ( mapAccumL, foldl2, seqList, ($!) )
 %************************************************************************
 
 \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
@@ -87,8 +89,9 @@ extendInScopeSet :: InScopeSet -> Var -> InScopeSet
 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
@@ -131,17 +134,17 @@ uniqAway (InScope set n) var
     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}
 
 
@@ -168,7 +171,17 @@ data Subst = Subst InScopeSet              -- In scope
        --
        -- 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}
@@ -180,7 +193,7 @@ The general plan about the substitution and in-scope set for Ids is as follows
   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
@@ -232,10 +245,12 @@ zapSubstEnv :: Subst -> Subst
 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
@@ -321,6 +336,25 @@ setSubstEnv :: Subst               -- Take in-scope part from here
 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}
 
 %************************************************************************
 %*                                                                     *
@@ -345,7 +379,8 @@ mkTopTyVarSubst :: [TyVar] -> [Type] -> Subst
 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.
@@ -374,11 +409,11 @@ subst_ty subst ty
   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)
@@ -388,6 +423,8 @@ subst_ty subst ty
                                        
     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.
@@ -531,9 +568,14 @@ substId subst@(Subst in_scope env) old_id
        -- 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