[project @ 2000-11-01 17:15:28 by simonpj]
[ghc-hetmet.git] / ghc / compiler / main / MkIface.lhs
index c837f4c..8540f9f 100644 (file)
@@ -23,8 +23,7 @@ import TcHsSyn                ( TypecheckedRuleDecl )
 import HscTypes                ( VersionInfo(..), IfaceDecls(..), ModIface(..), ModDetails(..),
                          TyThing(..), DFunId, TypeEnv, isTyClThing, Avails,
                          WhatsImported(..), GenAvailInfo(..), 
-                         ImportVersion, AvailInfo, Deprecations(..), 
-                         ModuleLocation(..)
+                         ImportVersion, AvailInfo, Deprecations(..)
                        )
 
 import CmdLineOpts
@@ -42,10 +41,9 @@ import CoreSyn               ( CoreExpr, CoreBind, Bind(..), CoreRule(..), IdCoreRule,
 import CoreFVs         ( exprSomeFreeVars, ruleSomeLhsFreeVars, ruleSomeFreeVars )
 import CoreUnfold      ( okToUnfoldInHiFile, mkTopUnfolding, neverUnfold, unfoldingTemplate, noUnfolding )
 import Name            ( isLocallyDefined, getName, 
-                         Name, NamedThing(..),
-                         plusNameEnv, lookupNameEnv, emptyNameEnv, mkNameEnv,
-                         extendNameEnv, lookupNameEnv_NF, nameEnvElts
+                         Name, NamedThing(..)
                        )
+import Name    -- Env
 import OccName         ( pprOccName )
 import TyCon           ( TyCon, getSynTyConDefn, isSynTyCon, isNewTyCon, isAlgTyCon,
                          tyConTheta, tyConTyVars, tyConDataCons, tyConFamilySize
@@ -55,8 +53,7 @@ import FieldLabel     ( fieldLabelType )
 import Type            ( splitSigmaTy, tidyTopType, deNoteType )
 import SrcLoc          ( noSrcLoc )
 import Outputable
-import Module          ( ModuleName, moduleName )
-import Finder          ( findModule )
+import Module          ( ModuleName )
 
 import List            ( partition )
 import IO              ( IOMode(..), openFile, hClose )
@@ -84,6 +81,14 @@ mkModDetails type_env dfun_ids tidy_binds stg_ids orphan_rules
        --      a) keeping the types and classes
        --      b) removing all Ids, and Ids with correct IdInfo
        --              gotten from the bindings
+       -- From (b) we keep only those Ids with Global names, plus Ids
+       --          accessible from them (notably via unfoldings)
+       -- This truncates the type environment to include only the 
+       -- exported Ids and things needed from them, which saves space
+       --
+       -- However, we do keep things like constructors, which should not appear 
+       -- in interface files, because they are needed by importing modules when
+       -- using the compilation manager
     new_type_env = mkNameEnv [(getName tycl, tycl) | tycl <- orig_type_env, isTyClThing tycl]
                        `plusNameEnv`
                   mkNameEnv [(idName id, AnId id) | id <- final_ids]
@@ -121,16 +126,13 @@ mkModDetailsFromIface type_env dfun_ids rules
 completeIface :: Maybe ModIface                -- The old interface, if we have it
              -> ModIface               -- The new one, minus the decls and versions
              -> ModDetails             -- The ModDetails for this module
-             -> Maybe (ModIface, SDoc) -- The new one, complete with decls and versions
+             -> (ModIface, Maybe SDoc) -- The new one, complete with decls and versions
                                        -- The SDoc is a debug document giving differences
                                        -- Nothing => no change
 
        -- NB: 'Nothing' means that even the usages havn't changed, so there's no
        --     need to write a new interface file.  But even if the usages have
        --     changed, the module version may not have.
-       --
-       -- The IO in the type is solely for debug output
-       -- In particular, dumping a record of what has changed
 completeIface maybe_old_iface new_iface mod_details 
   = addVersionInfo maybe_old_iface (new_iface { mi_decls = new_decls })
   where
@@ -139,7 +141,7 @@ completeIface maybe_old_iface new_iface mod_details
                              dcl_rules = rule_dcls }
 
      inst_dcls   = map ifaceInstance (md_insts mod_details)
-     ty_cls_dcls = map ifaceTyCls (nameEnvElts (md_types mod_details))
+     ty_cls_dcls = foldNameEnv ifaceTyCls [] (md_types mod_details)
      rule_dcls   = map ifaceRule (md_rules mod_details)
 \end{code}
 
@@ -151,19 +153,21 @@ completeIface maybe_old_iface new_iface mod_details
 %************************************************************************
 
 \begin{code}
-ifaceTyCls :: TyThing -> RenamedTyClDecl
-ifaceTyCls (AClass clas)
-  = ClassDecl (toHsContext sc_theta)
-             (getName clas)
-             (toHsTyVars clas_tyvars)
-             (toHsFDs clas_fds)
-             (map toClassOpSig op_stuff)
-             EmptyMonoBinds
-             [] noSrcLoc
+ifaceTyCls :: TyThing -> [RenamedTyClDecl] -> [RenamedTyClDecl]
+ifaceTyCls (AClass clas) so_far
+  = cls_decl : so_far
   where
-     (clas_tyvars, clas_fds, sc_theta, _, op_stuff) = classExtraBigSig clas
+    cls_decl = ClassDecl (toHsContext sc_theta)
+                        (getName clas)          
+                        (toHsTyVars clas_tyvars)
+                        (toHsFDs clas_fds)
+                        (map toClassOpSig op_stuff)
+                        EmptyMonoBinds
+                        [] noSrcLoc
+
+    (clas_tyvars, clas_fds, sc_theta, _, op_stuff) = classExtraBigSig clas
 
-     toClassOpSig (sel_id, def_meth)
+    toClassOpSig (sel_id, def_meth)
        = ASSERT(sel_tyvars == clas_tyvars)
          ClassOpSig (getName sel_id) (Just def_meth') (toHsType op_ty) noSrcLoc
        where
@@ -173,22 +177,26 @@ ifaceTyCls (AClass clas)
                         GenDefMeth -> GenDefMeth
                         DefMeth id -> DefMeth (getName id)
 
-ifaceTyCls (ATyCon tycon)
-  | isSynTyCon tycon
-  = TySynonym (getName tycon)(toHsTyVars tyvars) (toHsType ty) noSrcLoc
+ifaceTyCls (ATyCon tycon) so_far
+  = ty_decl : so_far
+  
   where
-    (tyvars, ty) = getSynTyConDefn tycon
-
-ifaceTyCls (ATyCon tycon)
-  | isAlgTyCon tycon
-  = TyData new_or_data (toHsContext (tyConTheta tycon))
-          (getName tycon)
-          (toHsTyVars tyvars)
-          (map ifaceConDecl (tyConDataCons tycon))
-          (tyConFamilySize tycon)
-          Nothing noSrcLoc (panic "gen1") (panic "gen2")
-  where
-    tyvars = tyConTyVars tycon
+    ty_decl | isSynTyCon tycon
+           = TySynonym (getName tycon)(toHsTyVars tyvars) 
+                       (toHsType syn_ty) noSrcLoc
+
+           | isAlgTyCon tycon
+           = TyData new_or_data (toHsContext (tyConTheta tycon))
+                    (getName tycon)      
+                    (toHsTyVars tyvars)
+                    (map ifaceConDecl (tyConDataCons tycon))
+                    (tyConFamilySize tycon)
+                    Nothing noSrcLoc (panic "gen1") (panic "gen2")
+
+           | otherwise = pprPanic "ifaceTyCls" (ppr tycon)
+
+    tyvars      = tyConTyVars tycon
+    (_, syn_ty) = getSynTyConDefn tycon
     new_or_data | isNewTyCon tycon = NewType
                | otherwise        = DataType
 
@@ -215,11 +223,12 @@ ifaceTyCls (ATyCon tycon)
     mk_field strict_mark field_label
        = ([getName field_label], mk_bang_ty strict_mark (fieldLabelType field_label))
 
-ifaceTyCls (ATyCon tycon) = pprPanic "ifaceTyCls" (ppr tycon)
-
-ifaceTyCls (AnId id) 
-  = IfaceSig (getName id) (toHsType id_type) hs_idinfo noSrcLoc
+ifaceTyCls (AnId id) so_far
+  | omitIfaceSigForId id = so_far
+  | otherwise           = iface_sig : so_far
   where
+    iface_sig = IfaceSig (getName id) (toHsType id_type) hs_idinfo noSrcLoc
+
     id_type = idType id
     id_info = idInfo id
 
@@ -329,17 +338,11 @@ bindsToIds needed_ids codegen_ids binds
        | otherwise                  = emitted
 
     go needed (NonRec id rhs : binds) emitted
-       | need_id needed id
-       = if omitIfaceSigForId id then
-           go (needed `delVarSet` id) binds (id:emitted)
-         else
-           go ((needed `unionVarSet` extras) `delVarSet` id)
-              binds
-              (new_id:emitted)
-       | otherwise
-       = go needed binds emitted
+       | need_id needed id = go new_needed binds (new_id:emitted)
+       | otherwise         = go needed     binds emitted
        where
          (new_id, extras) = mkFinalId codegen_ids False id rhs
+         new_needed       = (needed `unionVarSet` extras) `delVarSet` id
 
        -- Recursive groups are a bit more of a pain.  We may only need one to
        -- start with, but it may call out the next one, and so on.  So we
@@ -372,12 +375,15 @@ bindsToIds needed_ids codegen_ids binds
 
 \begin{code}
 mkFinalId :: IdSet             -- The Ids with arity info from the code generator
-         -> Bool                       -- True <=> recursive, so don't include unfolding
+         -> Bool               -- True <=> recursive, so don't include unfolding
          -> Id
          -> CoreExpr           -- The Id's right hand side
-         -> (Id, IdSet)                -- The emitted id, plus any *extra* needed Ids
+         -> (Id, IdSet)        -- The emitted id, plus any *extra* needed Ids
 
 mkFinalId codegen_ids is_rec id rhs
+  | omitIfaceSigForId id 
+  = (id, emptyVarSet)          -- An optimisation for top-level constructors and suchlike
+  | otherwise
   = (id `setIdInfo` new_idinfo, new_needed_ids)
   where
     core_idinfo = idInfo id
@@ -514,7 +520,7 @@ getRules orphan_rules binds emitted
 \begin{code}
 addVersionInfo :: Maybe ModIface               -- The old interface, read from M.hi
               -> ModIface                      -- The new interface decls
-              -> Maybe (ModIface, SDoc)        -- Nothing => no change; no need to write new Iface
+              -> (ModIface, Maybe SDoc)        -- Nothing => no change; no need to write new Iface
                                                -- Just mi => Here is the new interface to write
                                                --            with correct version numbers
 
@@ -524,7 +530,7 @@ addVersionInfo :: Maybe ModIface            -- The old interface, read from M.hi
 
 addVersionInfo Nothing new_iface
 -- No old interface, so definitely write a new one!
-  = Just (new_iface, text "No old interface available")
+  = (new_iface, Just (text "No old interface available"))
 
 addVersionInfo (Just old_iface@(ModIface { mi_version = old_version, 
                                           mi_decls   = old_decls,
@@ -533,10 +539,10 @@ addVersionInfo (Just old_iface@(ModIface { mi_version = old_version,
                                     mi_fixities = new_fixities })
 
   | no_output_change && no_usage_change
-  = Nothing
+  = (old_iface, Nothing)
 
   | otherwise          -- Add updated version numbers
-  = Just (final_iface, pp_tc_diffs)
+  = (final_iface, Just pp_tc_diffs)
        
   where
     final_iface = new_iface { mi_version = new_version }
@@ -605,11 +611,8 @@ diffDecls old_vers old_fixities new_fixities old new
 %************************************************************************
 
 \begin{code}
-writeIface :: FilePath -> Maybe ModIface -> IO ()
-writeIface hi_path Nothing
-  = return ()
-
-writeIface hi_path (Just mod_iface)
+writeIface :: FilePath -> ModIface -> IO ()
+writeIface hi_path mod_iface
   = do { if_hdl <- openFile hi_path WriteMode
        ; printForIface if_hdl (pprIface mod_iface)
        ; hClose if_hdl
@@ -628,14 +631,13 @@ pprIface iface
        , vcat (map pprExport (mi_exports iface))
        , vcat (map pprUsage (mi_usages iface))
 
-       , pprIfaceDecls (vers_decls version_info) 
-                       (mi_fixities iface)
-                       (mi_decls iface)
-
+       , pprFixities (mi_fixities iface) (dcl_tycl decls)
+       , pprIfaceDecls (vers_decls version_info) decls
        , pprDeprecs (mi_deprecs iface)
        ]
   where
     version_info = mi_version iface
+    decls       = mi_decls iface
     exp_vers     = vers_exports version_info
     rule_vers   = vers_rules version_info
 
@@ -653,20 +655,17 @@ pprExport :: (ModuleName, Avails) -> SDoc
 pprExport (mod, items)
  = hsep [ ptext SLIT("__export "), ppr mod, hsep (map pp_avail items) ] <> semi
   where
-    ppr_name :: Name -> SDoc   -- Print the occurrence name only
-    ppr_name n = ppr (nameOccName n)
-
     pp_avail :: AvailInfo -> SDoc
-    pp_avail (Avail name)      = ppr_name name
-    pp_avail (AvailTC name []) = empty
-    pp_avail (AvailTC name ns) = hcat [ppr_name name, bang, pp_export ns']
-                               where
-                                 bang | name `elem` ns = empty
-                                      | otherwise      = char '|'
-                                 ns' = filter (/= name) ns
+    pp_avail (Avail name)                   = pprOcc name
+    pp_avail (AvailTC n [])                 = empty
+    pp_avail (AvailTC n (n':ns)) | n==n'     = pprOcc n                    <> pp_export ns
+                                | otherwise = pprOcc n <> char '|' <> pp_export (n':ns)
     
     pp_export []    = empty
-    pp_export names = braces (hsep (map ppr_name names))
+    pp_export names = braces (hsep (map pprOcc names))
+
+pprOcc :: Name -> SDoc -- Print the occurrence name only
+pprOcc n = pprOccName (nameOccName n)
 \end{code}
 
 
@@ -687,7 +686,7 @@ pprUsage (m, has_orphans, is_boot, whats_imported)
     pp_versions NothingAtAll                       = empty
     pp_versions (Everything v)                     = dcolon <+> int v
     pp_versions (Specifically vm ve nvs vr) = dcolon <+> int vm <+> pp_export_version ve <+> int vr 
-                                             <+> hsep [ ppr n <+> int v | (n,v) <- nvs ]
+                                             <+> hsep [ pprOcc n <+> int v | (n,v) <- nvs ]
 
        -- HACK for the moment: print the export-list version even if
        -- we don't use it, so that syntax of interface files doesn't change
@@ -696,27 +695,27 @@ pprUsage (m, has_orphans, is_boot, whats_imported)
 \end{code}
 
 \begin{code}
-pprIfaceDecls version_map fixity_map decls
+pprIfaceDecls version_map decls
   = vcat [ vcat [ppr i <+> semi | i <- dcl_insts decls]
         , vcat (map ppr_decl (dcl_tycl decls))
         , pprRules (dcl_rules decls)
         ]
   where
-    ppr_decl d  = (ppr_vers d <+> ppr d <> semi) $$ ppr_fixes d
+    ppr_decl d  = ppr_vers d <+> ppr d <> semi
 
        -- Print the version for the decl
     ppr_vers d = case lookupNameEnv version_map (tyClDeclName d) of
                   Nothing -> empty
                   Just v  -> int v
-
-       -- Print fixities relevant to the decl
-    ppr_fixes d = vcat [ ppr fix <+> ppr n <> semi
-                      | (n,_) <- tyClDeclNames d, 
-                        Just fix <- [lookupNameEnv fixity_map n]
-                      ]
 \end{code}
 
 \begin{code}
+pprFixities fixity_map decls
+  = hsep [ ppr fix <+> ppr n 
+        | d <- decls, 
+          (n,_) <- tyClDeclNames d, 
+          Just fix <- [lookupNameEnv fixity_map n]] <> semi
+
 pprRules []    = empty
 pprRules rules = hsep [ptext SLIT("{-## __R"), vcat (map ppr rules), ptext SLIT("##-}")]
 
@@ -729,5 +728,5 @@ pprDeprecs deprecs   = ptext SLIT("{-## __D") <+> guts <+> ptext SLIT("##-}")
 
 pp_deprecs env = vcat (punctuate semi (map pp_deprec (nameEnvElts env)))
               where
-                pp_deprec (name, txt) = pprOccName (nameOccName name) <+> ptext txt
+                pp_deprec (name, txt) = pprOcc name <+> ptext txt
 \end{code}