[project @ 2000-03-23 17:45:17 by simonpj]
[ghc-hetmet.git] / ghc / compiler / main / MkIface.lhs
index 056880e..6851765 100644 (file)
@@ -22,7 +22,7 @@ import TcInstUtil     ( InstInfo(..) )
 
 import CmdLineOpts
 import Id              ( Id, idType, idInfo, omitIfaceSigForId, isUserExportedId,
-                         getIdSpecialisation
+                         idSpecialisation
                        )
 import Var             ( isId )
 import VarSet
@@ -33,11 +33,11 @@ import IdInfo               ( IdInfo, StrictnessInfo(..), ArityInfo, InlinePragInfo(..), inli
                          cafInfo, ppCafInfo, specInfo,
                          cprInfo, ppCprInfo, pprInlinePragInfo,
                          occInfo, OccInfo(..),
-                         workerExists, workerInfo, ppWorkerInfo
+                         workerExists, workerInfo, ppWorkerInfo, WorkerInfo(..)
                        )
 import CoreSyn         ( CoreExpr, CoreBind, Bind(..), rulesRules, rulesRhsFreeVars )
 import CoreFVs         ( exprSomeFreeVars, ruleSomeLhsFreeVars, ruleSomeFreeVars )
-import CoreUnfold      ( calcUnfoldingGuidance, okToUnfoldInHiFile, couldBeSmallEnoughToInline )
+import CoreUnfold      ( okToUnfoldInHiFile, couldBeSmallEnoughToInline )
 import Module          ( moduleString, pprModule, pprModuleName )
 import Name            ( isLocallyDefined, isWiredInName, nameRdrName, nameModule,
                          Name, NamedThing(..)
@@ -76,6 +76,10 @@ We then have one-function-per-block-of-interface-stuff, e.g.,
 @ifaceExportList@ produces the @__exports__@ section; it appends
 to the handle provided by @startIface@.
 
+NOTE: ALWAYS remember that ghc-iface.lprl rewrites the interface file,
+so you have to keep it in synch with the code below. Otherwise you'll
+lose the happiest years of your life, believe me...  -- SUP
+
 \begin{code}
 startIface  :: Module -> InterfaceDetails
            -> IO (Maybe Handle) -- Nothing <=> don't do an interface
@@ -86,13 +90,14 @@ ifaceDecls :: Maybe Handle
           -> [Id]              -- Ids used at code-gen time; they have better pragma info!
           -> [CoreBind]        -- In dependency order, later depend on earlier
           -> [ProtoCoreRule]   -- Rules
+          -> [Deprecation Name]
           -> IO ()
 
 endIface    :: Maybe Handle -> IO ()
 \end{code}
 
 \begin{code}
-startIface mod (has_orphans, import_usages, ExportEnv avails fixities _)
+startIface mod (InterfaceDetails has_orphans import_usages (ExportEnv avails fixities _) _)
   = case opt_ProduceHi of
       Nothing -> return Nothing ; -- not producing any .hi file
 
@@ -115,12 +120,14 @@ endIface (Just if_hdl)    = hPutStr if_hdl "\n" >> hClose if_hdl
 
 
 \begin{code}
-ifaceDecls Nothing tycons classes inst_info final_ids simplified rules = return ()
+ifaceDecls Nothing tycons classes inst_info final_ids simplified rules _ = return ()
 ifaceDecls (Just hdl)
           tycons classes
           inst_infos
-          final_ids binds
+          final_ids
+          binds
           orphan_rules         -- Rules defined locally for an Id that is *not* defined locally
+          deprecations
   | null_decls = return ()              
        --  You could have a module with just (re-)exports/instances in it
   | otherwise
@@ -130,30 +137,34 @@ ifaceDecls (Just hdl)
     ifaceBinds hdl (inst_ids `unionVarSet` orphan_rule_ids)
               final_ids binds                  >>= \ emitted_ids ->
     ifaceRules hdl orphan_rules emitted_ids    >>
-    return ()
+    ifaceDeprecations hdl deprecations
   where
      orphan_rule_ids = unionVarSets [ ruleSomeFreeVars interestingId rule 
                                    | ProtoCoreRule _ _ rule <- orphan_rules]
 
-     null_decls = null binds      && 
-                 null tycons     &&
-                 null classes    && 
-                 isEmptyBag inst_infos &&
-                 null orphan_rules
+     null_decls = null binds           && 
+                 null tycons           &&
+                 null classes          && 
+                 isEmptyBag inst_infos &&
+                 null orphan_rules     &&
+                 null deprecations
 \end{code}
 
 \begin{code}
+ifaceImports :: Handle -> VersionInfo Name -> IO ()
 ifaceImports if_hdl import_usages
   = hPutCol if_hdl upp_uses (sortLt lt_imp_vers import_usages)
   where
-    upp_uses (m, mv, has_orphans, whats_imported)
+    upp_uses (m, mv, has_orphans, is_boot, whats_imported)
       = hsep [ptext SLIT("import"), pprModuleName m, 
-             int mv, pp_orphan,
+             int mv, pp_orphan, pp_boot,
              upp_import_versions whats_imported
        ] <> semi
       where
        pp_orphan | has_orphans = ptext SLIT("!")
                  | otherwise   = empty
+        pp_boot   | is_boot     = ptext SLIT("@")
+                  | otherwise   = empty
 
        -- Importing the whole module is indicated by an empty list
     upp_import_versions Everything = empty
@@ -162,6 +173,7 @@ ifaceImports if_hdl import_usages
     upp_import_versions (Specifically nvs)
       = dcolon <+> hsep [ hsep [ppr_unqual_name n, int v] | (n,v) <- sort_versions nvs ]
 
+{- SUP: What's this??
 ifaceModuleDeps if_hdl [] = return ()
 ifaceModuleDeps if_hdl mod_deps
   = let 
@@ -172,7 +184,9 @@ ifaceModuleDeps if_hdl mod_deps
     in 
     printForIface if_hdl (ptext SLIT("__depends") <+> vcat lines <> ptext SLIT(" ;")) >>
     hPutStr if_hdl "\n"
+-}
 
+ifaceExports :: Handle -> Avails -> IO ()
 ifaceExports if_hdl [] = return ()
 ifaceExports if_hdl avails
   = hPutCol if_hdl do_one_module (fmToList export_fm)
@@ -193,35 +207,50 @@ ifaceExports if_hdl avails
                hsep (map upp_avail (sortLt lt_avail avails))
          ] <> semi
 
+ifaceFixities :: Handle -> Fixities -> IO ()
 ifaceFixities if_hdl [] = return ()
 ifaceFixities if_hdl fixities 
   = hPutCol if_hdl upp_fixity fixities
 
+ifaceRules :: Handle -> [ProtoCoreRule] -> IdSet -> IO ()
 ifaceRules if_hdl rules emitted
-  | null orphan_rule_pretties && null local_id_pretties
+  |  opt_OmitInterfacePragmas  -- Don't emit rules if we are suppressing
+                               -- interface pragmas
+  || (null orphan_rule_pretties && null local_id_pretties)
   = return ()
   | otherwise
-  = do printForIface if_hdl (vcat [
+  = printForIface if_hdl (vcat [
                ptext SLIT("{-## __R"),
-
                vcat orphan_rule_pretties,
-
                vcat local_id_pretties,
-
                ptext SLIT("##-}")
-          ])
-       
-       return ()
+       ])
   where
     orphan_rule_pretties =  [ pprCoreRule (Just fn) rule
                            | ProtoCoreRule _ fn rule <- rules
                            ]
     local_id_pretties = [ pprCoreRule (Just fn) rule
                        | fn <- varSetElems emitted, 
-                         rule <- rulesRules (getIdSpecialisation fn),
+                         rule <- rulesRules (idSpecialisation fn),
                          all (`elemVarSet` emitted) (varSetElems (ruleSomeLhsFreeVars interestingId rule))
-                               -- Spit out a rule only if all its lhs free vars are eemitted
+                               -- Spit out a rule only if all its lhs free vars are emitted
+                               -- This is a good reason not to do it when we emit the Id itself
                        ]
+
+ifaceDeprecations :: Handle -> [Deprecation Name] -> IO ()
+ifaceDeprecations if_hdl [] = return ()
+ifaceDeprecations if_hdl deprecations
+  = printForIface if_hdl (vcat [
+               ptext SLIT("{-## __D"),
+               vcat [ pprIE ie <+> doubleQuotes (ppr txt) <> semi | Deprecation ie txt <- deprecations ],
+               ptext SLIT("##-}")
+       ])
+  where
+    pprIE (IEVar            n   ) = ppr n
+    pprIE (IEThingAbs       n   ) = ppr n
+    pprIE (IEThingAll       n   ) = hcat [ppr n, text "(..)"]
+    pprIE (IEThingWith      n ns) = ppr n <> parens (hcat (punctuate comma (map ppr ns)))
+    pprIE (IEModuleContents _   ) = empty
 \end{code}
 
 %************************************************************************
@@ -333,7 +362,7 @@ ifaceId get_idinfo needed_ids is_rec id rhs
     work_info     = workerInfo core_idinfo
     has_worker    = workerExists work_info
     wrkr_pretty   = ppWorkerInfo work_info
-    Just work_id  = work_info
+    HasWorker work_id wrap_arity = work_info
 
 
     ------------  Occ info  --------------
@@ -358,7 +387,7 @@ ifaceId get_idinfo needed_ids is_rec id rhs
                  rhs_is_small           &&     -- Small enough
                  okToUnfoldInHiFile rhs        -- No casms etc
 
-    rhs_is_small = couldBeSmallEnoughToInline (calcUnfoldingGuidance opt_UF_HiFileThreshold rhs)
+    rhs_is_small = couldBeSmallEnoughToInline opt_UF_HiFileThreshold rhs
 
     ------------  Specialisations --------------
     spec_info   = specInfo core_idinfo
@@ -384,12 +413,8 @@ ifaceId get_idinfo needed_ids is_rec id rhs
     ------------ Sanity checking --------------
        -- The arity of a wrapper function should match its strictness,
        -- or else an importing module will get very confused indeed.
-       -- [later: actually all that is necessary is for strictness to exceed arity]
-    arity_matches_strictness
-       = not has_worker ||
-         case strict_info of
-           StrictnessInfo ds _ -> length ds >= arityLowerBound arity_info
-           other               -> True
+    arity_matches_strictness = not has_worker || 
+                              wrap_arity == arityLowerBound arity_info
     
 interestingId id = isId id && isLocallyDefined id &&
                   not (omitIfaceSigForId id)
@@ -654,7 +679,7 @@ lt_lexical :: NamedThing a => a -> a -> Bool
 lt_lexical a1 a2 = getName a1 `lt_name` getName a2
 
 lt_imp_vers :: ImportVersion a -> ImportVersion a -> Bool
-lt_imp_vers (m1,_,_,_) (m2,_,_,_) = m1 < m2
+lt_imp_vers (m1,_,_,_,_) (m2,_,_,_,_) = m1 < m2
 
 sort_versions vs = sortLt lt_vers vs