[project @ 2005-02-23 13:46:43 by simonpj]
[ghc-hetmet.git] / ghc / compiler / main / TidyPgm.lhs
index aaedea4..ee4b5bb 100644 (file)
@@ -8,10 +8,10 @@ module TidyPgm( tidyCorePgm, tidyCoreExpr ) where
 
 #include "HsVersions.h"
 
-import CmdLineOpts     ( DynFlag(..), dopt )
+import CmdLineOpts     ( DynFlags, DynFlag(..), dopt )
 import CoreSyn
 import CoreUnfold      ( noUnfolding, mkTopUnfolding )
-import CoreFVs         ( ruleLhsFreeIds, ruleRhsFreeVars, exprSomeFreeVars )
+import CoreFVs         ( ruleLhsFreeIds, exprSomeFreeVars )
 import CoreTidy                ( tidyExpr, tidyVarOcc, tidyIdRules )
 import PprCore                 ( pprIdRules )
 import CoreLint                ( showPass, endPass )
@@ -40,7 +40,6 @@ import HscTypes               ( HscEnv(..), NameCache( nsUniqs ),
                        )
 import Maybes          ( orElse )
 import ErrUtils                ( showPass, dumpIfSet_core )
-import UniqFM          ( mapUFM )
 import UniqSupply      ( splitUniqSupply, uniqFromSupply )
 import List            ( partition )
 import Maybe           ( isJust )
@@ -128,13 +127,14 @@ tidyCorePgm hsc_env
        ; showPass dflags "Tidy Core"
 
        ; let omit_iface_prags = dopt Opt_OmitInterfacePragmas dflags
-       ; let ext_ids   = findExternalSet   omit_iface_prags binds_in orphans_in
+       ; let ext_ids   = findExternalSet   omit_iface_prags binds_in
        ; let ext_rules = findExternalRules omit_iface_prags binds_in orphans_in ext_ids
                -- findExternalRules filters ext_rules to avoid binders that 
                -- aren't externally visible; but the externally-visible binders 
                -- are computed (by findExternalSet) assuming that all orphan
-               -- rules are exported.  So in fact we may export more than we
-               -- need.  (It's a sort of mutual recursion.)
+               -- rules are exported (they get their Exported flag set in the desugarer)
+               -- So in fact we may export more than we need. 
+               -- (It's a sort of mutual recursion.)
 
        -- We also make sure to avoid any exported binders.  Consider
        --      f{-u1-} = 1     -- Local decl
@@ -156,7 +156,7 @@ tidyCorePgm hsc_env
                -- The type environment is a convenient source of such things.
 
        ; (final_env, tidy_binds)
-               <- tidyTopBinds mod nc_var ext_ids init_env binds_in
+               <- tidyTopBinds dflags mod nc_var ext_ids init_env binds_in
 
        ; let tidy_rules = tidyIdRules final_env ext_rules
 
@@ -272,25 +272,29 @@ findExternalRules :: Bool   -- Omit interface pragmas
 findExternalRules omit_iface_prags binds orphan_rules ext_ids
   | omit_iface_prags = []
   | otherwise
-  = filter needed_rule (orphan_rules ++ local_rules)
+  = filter (not . internal_rule) (orphan_rules ++ local_rules)
   where
     local_rules  = [ rule
                   | id <- bindersOfBinds binds,
                     id `elemVarEnv` ext_ids,
                     rule <- idCoreRules id
                   ]
-    needed_rule (id, rule)
-       =  not (isBuiltinRule rule)
+    internal_rule (IdCoreRule id is_orphan rule)
+       =  isBuiltinRule rule
                -- We can't print builtin rules in interface files
                -- Since they are built in, an importing module
                -- will have access to them anyway
 
-       && not (any internal_id (varSetElems (ruleLhsFreeIds rule)))
+       || (not is_orphan && internal_id id)
+               -- Rule for an Id in this module; internal if the
+               -- Id is not exported
+
+       || any internal_id (varSetElems (ruleLhsFreeIds rule))
                -- Don't export a rule whose LHS mentions an Id that
                -- is completely internal (i.e. not visible to an
                -- importing module)
 
-    internal_id id = isLocalId id && not (id `elemVarEnv` ext_ids)
+    internal_id id = not (id `elemVarEnv` ext_ids)
 \end{code}
 
 %************************************************************************
@@ -300,24 +304,14 @@ findExternalRules omit_iface_prags binds orphan_rules ext_ids
 %************************************************************************
 
 \begin{code}
-findExternalSet :: Bool -- omit interface pragmas
-               -> [CoreBind] -> [IdCoreRule]
+findExternalSet :: Bool                -- Omit interface pragmas
+               -> [CoreBind]
                -> IdEnv Bool   -- In domain => external
                                -- Range = True <=> show unfolding
        -- Step 1 from the notes above
-findExternalSet omit_iface_prags binds orphan_rules
-  = foldr find init_needed binds
+findExternalSet omit_iface_prags binds
+  = foldr find emptyVarEnv binds
   where
-    orphan_rule_ids :: IdSet
-    orphan_rule_ids = unionVarSets [ ruleRhsFreeVars rule 
-                                  | (_, rule) <- orphan_rules]
-    init_needed :: IdEnv Bool
-    init_needed = mapUFM (\_ -> False) orphan_rule_ids
-       -- The mapUFM is a bit cheesy.  It is a cheap way
-       -- to turn the set of orphan_rule_ids, which we use to initialise
-       -- the sweep, into a mapping saying 'don't expose unfolding'    
-       -- (When we come to the binding site we may change our mind, of course.)
-
     find (NonRec id rhs) needed
        | need_id needed id = addExternal omit_iface_prags (id,rhs) needed
        | otherwise         = needed
@@ -406,38 +400,40 @@ addExternal omit_iface_prags (id,rhs) needed
 --
 --   * subst_env: A Var->Var mapping that substitutes the new Var for the old
 
-tidyTopBinds :: Module
+tidyTopBinds :: DynFlags
+            -> Module
             -> IORef NameCache -- For allocating new unique names
             -> IdEnv Bool      -- Domain = Ids that should be external
                                -- True <=> their unfolding is external too
             -> TidyEnv -> [CoreBind]
             -> IO (TidyEnv, [CoreBind])
-tidyTopBinds mod nc_var ext_ids tidy_env []
+tidyTopBinds dflags mod nc_var ext_ids tidy_env []
   = return (tidy_env, [])
 
-tidyTopBinds mod nc_var ext_ids tidy_env (b:bs)
-  = do { (tidy_env1, b')  <- tidyTopBind  mod nc_var ext_ids tidy_env b
-       ; (tidy_env2, bs') <- tidyTopBinds mod nc_var ext_ids tidy_env1 bs
+tidyTopBinds dflags mod nc_var ext_ids tidy_env (b:bs)
+  = do { (tidy_env1, b')  <- tidyTopBind  dflags mod nc_var ext_ids tidy_env b
+       ; (tidy_env2, bs') <- tidyTopBinds dflags mod nc_var ext_ids tidy_env1 bs
        ; return (tidy_env2, b':bs') }
 
 ------------------------
-tidyTopBind :: Module
+tidyTopBind  :: DynFlags
+            -> Module
             -> IORef NameCache -- For allocating new unique names
             -> IdEnv Bool      -- Domain = Ids that should be external
                                -- True <=> their unfolding is external too
             -> TidyEnv -> CoreBind
             -> IO (TidyEnv, CoreBind)
 
-tidyTopBind mod nc_var ext_ids tidy_env1@(occ_env1,subst1) (NonRec bndr rhs)
+tidyTopBind dflags mod nc_var ext_ids tidy_env1@(occ_env1,subst1) (NonRec bndr rhs)
   = do { (occ_env2, name') <- tidyTopName mod nc_var ext_ids occ_env1 bndr
        ; let   { (bndr', rhs') = tidyTopPair ext_ids tidy_env2 caf_info name' (bndr, rhs)
                ; subst2        = extendVarEnv subst1 bndr bndr'
                ; tidy_env2     = (occ_env2, subst2) }
        ; return (tidy_env2, NonRec bndr' rhs') }
   where
-    caf_info = hasCafRefs subst1 (idArity bndr) rhs
+    caf_info = hasCafRefs dflags subst1 (idArity bndr) rhs
 
-tidyTopBind mod nc_var ext_ids tidy_env1@(occ_env1,subst1) (Rec prs)
+tidyTopBind dflags mod nc_var ext_ids tidy_env1@(occ_env1,subst1) (Rec prs)
   = do { (occ_env2, names') <- tidyTopNames mod nc_var ext_ids occ_env1 bndrs
        ; let   { prs'      = zipWith (tidyTopPair ext_ids tidy_env2 caf_info)
                                      names' prs
@@ -450,7 +446,7 @@ tidyTopBind mod nc_var ext_ids tidy_env1@(occ_env1,subst1) (Rec prs)
        -- the CafInfo for a recursive group says whether *any* rhs in
        -- the group may refer indirectly to a CAF (because then, they all do).
     caf_info 
-       | or [ mayHaveCafRefs (hasCafRefs subst1 (idArity bndr) rhs)
+       | or [ mayHaveCafRefs (hasCafRefs dflags subst1 (idArity bndr) rhs)
             | (bndr,rhs) <- prs ] = MayHaveCafRefs
        | otherwise                = NoCafRefs
 
@@ -625,13 +621,13 @@ it as a CAF.  In these cases however, we would need to use an additional
 CAF list to keep track of non-collectable CAFs.  
 
 \begin{code}
-hasCafRefs  :: VarEnv Var -> Arity -> CoreExpr -> CafInfo
-hasCafRefs p arity expr 
+hasCafRefs  :: DynFlags -> VarEnv Var -> Arity -> CoreExpr -> CafInfo
+hasCafRefs dflags p arity expr 
   | is_caf || mentions_cafs = MayHaveCafRefs
   | otherwise              = NoCafRefs
  where
   mentions_cafs = isFastTrue (cafRefs p expr)
-  is_caf = not (arity > 0 || rhsIsStatic expr)
+  is_caf = not (arity > 0 || rhsIsStatic dflags expr)
   -- NB. we pass in the arity of the expression, which is expected
   -- to be calculated by exprArity.  This is because exprArity
   -- knows how much eta expansion is going to be done by 
@@ -647,13 +643,13 @@ cafRefs p (Var id)
        Just id' -> fastBool (mayHaveCafRefs (idCafInfo id'))
        Nothing  -> fastBool False
 
-cafRefs p (Lit l)           = fastBool False
-cafRefs p (App f a)         = fastOr (cafRefs p f) (cafRefs p) a
-cafRefs p (Lam x e)         = cafRefs p e
-cafRefs p (Let b e)         = fastOr (cafRefss p (rhssOfBind b)) (cafRefs p) e
-cafRefs p (Case e bndr alts) = fastOr (cafRefs p e) (cafRefss p) (rhssOfAlts alts)
-cafRefs p (Note n e)        = cafRefs p e
-cafRefs p (Type t)          = fastBool False
+cafRefs p (Lit l)             = fastBool False
+cafRefs p (App f a)           = fastOr (cafRefs p f) (cafRefs p) a
+cafRefs p (Lam x e)           = cafRefs p e
+cafRefs p (Let b e)           = fastOr (cafRefss p (rhssOfBind b)) (cafRefs p) e
+cafRefs p (Case e bndr _ alts) = fastOr (cafRefs p e) (cafRefss p) (rhssOfAlts alts)
+cafRefs p (Note n e)          = cafRefs p e
+cafRefs p (Type t)            = fastBool False
 
 cafRefss p []    = fastBool False
 cafRefss p (e:es) = fastOr (cafRefs p e) (cafRefss p) es