[project @ 2004-12-30 22:14:59 by simonpj]
[ghc-hetmet.git] / ghc / compiler / simplCore / SimplEnv.lhs
index e7792e8..8a3841f 100644 (file)
@@ -21,7 +21,7 @@ module SimplEnv (
        SimplEnv, mkSimplEnv, extendIdSubst, extendTvSubst, 
        zapSubstEnv, setSubstEnv, 
        getInScope, setInScope, setInScopeSet, modifyInScope, addNewInScopeIds,
-       getRules,
+       getRules, refineSimplEnv,
 
        SimplSR(..), mkContEx, substId, 
 
@@ -39,55 +39,31 @@ module SimplEnv (
 #include "HsVersions.h"
 
 import SimplMonad      
-import Rules           ( RuleBase, emptyRuleBase )
-import Id              ( Id, idType, idOccInfo, idInlinePragma, idUnfolding, setIdUnfolding )
+import Id              ( Id, idType, idOccInfo, idUnfolding, setIdUnfolding )
 import IdInfo          ( IdInfo, vanillaIdInfo, occInfo, setOccInfo, specInfo, setSpecInfo,
                          arityInfo, setArityInfo, workerInfo, setWorkerInfo, 
                          unfoldingInfo, setUnfoldingInfo, 
                          unknownArity, workerExists
                            )
 import CoreSyn
-import CoreUtils       ( needsCaseBinding, exprIsTrivial )
+import Rules           ( RuleBase )
+import CoreUtils       ( needsCaseBinding )
 import PprCore         ()      -- Instances
 import CostCentre      ( CostCentreStack, subsumedCCS )
 import Var     
 import VarEnv
-import VarSet          ( isEmptyVarSet )
+import VarSet          ( isEmptyVarSet, elemVarSetByKey, mkVarSet )
 import OrdList
 
 import qualified CoreSubst     ( Subst, mkSubst, substExpr, substRules, substWorker )
 import qualified Type          ( substTy, substTyVarBndr )
 
-import Type             ( Type, TvSubst(..), TvSubstEnv, isUnLiftedType, seqType, tyVarsOfType )
-import UniqSupply      ( uniqsFromSupply, uniqFromSupply, splitUniqSupply,
-                         UniqSupply
-                       )
-import FiniteMap
-import BasicTypes      ( TopLevelFlag, isTopLevel, isLoopBreaker,
-                         Activation, isActive, isAlwaysActive,
-                         OccInfo(..), isOneOcc, isFragileOcc
-                       )
-import CmdLineOpts     ( SimplifierSwitch(..), SimplifierMode(..),
-                         DynFlags, DynFlag(..), dopt, 
-                         opt_PprStyle_Debug, opt_HistorySize, opt_SimplNoPreInlining, opt_RulesOff
-                       )
-import Unique          ( Unique )
+import Type             ( Type, TvSubst(..), TvSubstEnv, composeTvSubst,
+                         isUnLiftedType, seqType, tyVarsOfType )
+import BasicTypes      ( OccInfo(..), isFragileOcc )
+import CmdLineOpts     ( SimplifierMode(..) )
 import Util            ( mapAccumL )
 import Outputable
-import FastTypes
-import FastString
-import Maybes          ( expectJust )
-
-import GLAEXTS         ( indexArray# )
-
-#if __GLASGOW_HASKELL__ < 503
-import PrelArr  ( Array(..) )
-#else
-import GHC.Arr  ( Array(..) )
-#endif
-
-import Array           ( array, (//) )
-
 \end{code}
 
 %************************************************************************
@@ -328,6 +304,34 @@ getRules :: SimplEnv -> RuleBase
 getRules = seExtRules
 \end{code}
 
+               GADT stuff
+
+Given an idempotent substitution, generated by the unifier, use it to 
+refine the environment
+
+\begin{code}
+refineSimplEnv :: SimplEnv -> TvSubstEnv -> [OutTyVar] -> SimplEnv
+-- The TvSubstEnv is the refinement, and it refines OutTyVars into OutTypes
+refineSimplEnv env@(SimplEnv { seTvSubst = tv_subst, seInScope = in_scope })
+              refine_tv_subst tvs
+  = env { seTvSubst = composeTvSubst in_scope refine_tv_subst tv_subst,
+         seInScope = in_scope' }
+  where
+    in_scope' 
+       | all bound_here (varEnvKeys refine_tv_subst) = in_scope
+               -- The tvs are the tyvars bound here.  If only they 
+               -- are refined, there's no need to do anything 
+       | otherwise = mapInScopeSet refine_id in_scope
+
+    bound_here uniq = elemVarSetByKey uniq tv_set
+    tv_set = mkVarSet tvs
+
+    refine_id v        -- Only refine its type; any rules will get
+                       -- refined if they are used (I hope)
+       | isId v    = setIdType v (Type.substTy refine_subst (idType v))
+       | otherwise = v
+    refine_subst = TvSubst in_scope refine_tv_subst
+\end{code}
 
 %************************************************************************
 %*                                                                     *
@@ -361,7 +365,6 @@ substId (SimplEnv { seInScope = in_scope, seIdSubst = ids }) v
     refine v = case lookupInScope in_scope v of
                 Just v' -> v'
                 Nothing -> WARN( True, ppr v ) v       -- This is an error!
-       
 \end{code}
 
 
@@ -391,7 +394,7 @@ simplBinder :: SimplEnv -> InBinder -> SimplM (SimplEnv, OutBinder)
 simplBinder env bndr
   | isTyVar bndr  = do { let (env', tv) = substTyVarBndr env bndr
                        ; seqTyVar tv `seq` return (env', tv) }
-  | otherwise     = do { let (env', id) = substIdBndr False env env bndr
+  | otherwise     = do { let (env', id) = substIdBndr env bndr
                        ; seqId id `seq` return (env', id) }
 
 -------------
@@ -412,7 +415,7 @@ simplLamBndr env bndr
   | otherwise                                  = seqId id2 `seq` return (env', id2)
   where
     old_unf = idUnfolding bndr
-    (env', id1) = substIdBndr False env env bndr
+    (env', id1) = substIdBndr env bndr
     id2 = id1 `setIdUnfolding` substUnfolding env old_unf
 
 -------------
@@ -426,48 +429,21 @@ seqId id = seqType (idType id)    `seq`
 \end{code}
 
 \begin{code}
--- substBndr and friends are used when doing expression substitution only
--- In this case we can *preserve* occurrence information, and indeed we *want*
--- to do so else lose useful occ info in rules. 
-
-substBndr :: SimplEnv -> Var -> (SimplEnv, Var)
-substBndr subst bndr
-  | isTyVar bndr  = substTyVarBndr subst bndr
-  | otherwise     = substIdBndr True {- keep fragile info -} subst subst bndr
-
-substBndrs :: SimplEnv -> [Var] -> (SimplEnv, [Var])
-substBndrs subst bndrs = mapAccumL substBndr subst bndrs
-
-substRecBndrs :: SimplEnv -> [Id] -> (SimplEnv, [Id])
--- Substitute a mutually recursive group
-substRecBndrs subst bndrs 
-  = (new_subst, new_bndrs)
-  where
-       -- Here's the reason we need to pass rec_subst to substIdBndr
-    (new_subst, new_bndrs) = mapAccumL (substIdBndr True {- keep fragile info -} new_subst) 
-                                      subst bndrs
-\end{code}
-
-
-\begin{code}
-substIdBndr :: Bool            -- True <=> keep fragile info
-        -> SimplEnv            -- Substitution to use for the IdInfo
-        -> SimplEnv -> Id      -- Substitition and Id to transform
-        -> (SimplEnv, Id)      -- Transformed pair
+substIdBndr :: SimplEnv -> Id  -- Substitition and Id to transform
+           -> (SimplEnv, Id)   -- Transformed pair
 
 -- Returns with:
 --     * Unique changed if necessary
 --     * Type substituted
 --     * Unfolding zapped
 --     * Rules, worker, lbvar info all substituted 
---     * Occurrence info zapped if is_fragile_occ returns True
+--     * Fragile occurrence info zapped
 --     * The in-scope set extended with the returned Id
 --     * The substitution extended with a DoneId if unique changed
 --       In this case, the var in the DoneId is the same as the
 --       var returned
 
-substIdBndr keep_fragile rec_env 
-           env@(SimplEnv { seInScope = in_scope, seIdSubst = id_subst})
+substIdBndr env@(SimplEnv { seInScope = in_scope, seIdSubst = id_subst})
            old_id
   = (env { seInScope = in_scope `extendInScopeSet` new_id,
           seIdSubst = new_subst }, new_id)
@@ -481,7 +457,7 @@ substIdBndr keep_fragile rec_env
        -- new_id has the right IdInfo
        -- The lazy-set is because we're in a loop here, with 
        -- rec_env, when dealing with a mutually-recursive group
-    new_id = maybeModifyIdInfo (substIdInfo keep_fragile rec_env) id2
+    new_id = maybeModifyIdInfo (substIdInfo env) id2
 
        -- Extend the substitution if the unique has changed
        -- See the notes with substTyVarBndr for the delSubstEnv
@@ -570,33 +546,24 @@ simplIdInfo :: SimplEnv -> IdInfo -> IdInfo
   -- Used by the simplifier to compute new IdInfo for a let(rec) binder,
   -- subsequent to simplLetId having zapped its IdInfo
 simplIdInfo env old_info
-  = case substIdInfo False env old_info of 
+  = case substIdInfo env old_info of 
        Just new_info -> new_info
        Nothing       -> old_info
 
-substIdInfo :: Bool    -- True <=> keep even fragile info
-           -> SimplEnv
+substIdInfo :: SimplEnv
            -> IdInfo
            -> Maybe IdInfo
--- The keep_fragile flag is True when we are running a simple expression
--- substitution that preserves all structure, so that arity and occurrence
--- info are unaffected.  The False state is used more often.
---
 -- Substitute the 
 --     rules
 --     worker info
 -- Zap the unfolding 
--- If keep_fragile then
---     keep OccInfo
---     keep Arity
--- else
---     keep only 'robust' OccInfo
---     zap Arity
+-- Keep only 'robust' OccInfo
+-- Zap Arity
 -- 
 -- Seq'ing on the returned IdInfo is enough to cause all the 
 -- substitutions to happen completely
 
-substIdInfo keep_fragile env info
+substIdInfo env info
   | nothing_to_do = Nothing
   | otherwise     = Just (info `setOccInfo`              (if keep_occ then old_occ else NoOccInfo)
                               `setArityInfo`     (if keep_arity then old_arity else unknownArity)
@@ -612,8 +579,8 @@ substIdInfo keep_fragile env info
                    not (workerExists old_wrkr) &&
                    not (hasUnfolding (unfoldingInfo info))
     
-    keep_occ   = keep_fragile || not (isFragileOcc old_occ)
-    keep_arity = keep_fragile || old_arity == unknownArity
+    keep_occ   = not (isFragileOcc old_occ)
+    keep_arity = old_arity == unknownArity
     old_arity = arityInfo info
     old_occ   = occInfo info
     old_rules = specInfo info