[project @ 1999-12-02 13:43:07 by simonmar]
[ghc-hetmet.git] / ghc / compiler / rename / RnIfaces.lhs
index 8298af0..55091bb 100644 (file)
@@ -13,7 +13,8 @@ module RnIfaces (
 
        checkUpToDate,
 
-       getDeclBinders, getDeclSysBinders
+       getDeclBinders, getDeclSysBinders,
+       removeContext           -- removeContext probably belongs somewhere else
     ) where
 
 #include "HsVersions.h"
@@ -21,6 +22,7 @@ module RnIfaces (
 import CmdLineOpts     ( opt_NoPruneDecls, opt_IgnoreIfacePragmas )
 import HsSyn           ( HsDecl(..), TyClDecl(..), InstDecl(..), IfaceSig(..), 
                          HsType(..), ConDecl(..), IE(..), ConDetails(..), Sig(..),
+                         ForeignDecl(..), ForKind(..), isDynamic,
                          FixitySig(..), RuleDecl(..),
                          isClassOpSig
                        )
@@ -29,7 +31,7 @@ import RdrHsSyn               ( RdrNameHsDecl, RdrNameInstDecl, RdrNameTyClDecl, RdrNameRuleD
                          extractHsTyRdrNames
                        )
 import RnEnv           ( mkImportedGlobalName, newImportedBinder, mkImportedGlobalFromRdrName,
-                         lookupOccRn,
+                         lookupOccRn, lookupImplicitOccRn,
                          pprAvail,
                          availName, availNames, addAvailToNameSet,
                          FreeVars, emptyFVs
@@ -64,6 +66,7 @@ import Outputable
 import Unique          ( Unique )
 import StringBuffer     ( StringBuffer, hGetStringBuffer )
 import FastString      ( mkFastString )
+import ErrUtils         ( Message )
 import Lex
 import Outputable
 
@@ -79,9 +82,19 @@ import List  ( nub )
 %*********************************************************
 
 \begin{code}
-loadHomeInterface :: SDoc -> Name -> RnM d (Module, Ifaces)
+loadHomeInterface :: SDoc -> Name -> RnM d Ifaces
 loadHomeInterface doc_str name
-  = loadInterface doc_str (moduleName (nameModule name)) ImportBySystem
+  = loadInterface doc_str (moduleName (nameModule name)) ImportBySystem                `thenRn` \ (_, ifaces) ->
+    returnRn ifaces
+
+loadOrphanModules :: [ModuleName] -> RnM d ()
+loadOrphanModules mods
+  | null mods = returnRn ()
+  | otherwise = traceRn (text "Loading orphan modules:" <+> fsep (map pprModuleName mods))     `thenRn_` 
+               mapRn_ load mods        `thenRn_`
+               returnRn ()
+  where
+    load mod = loadInterface (pprModuleName mod <+> ptext SLIT("is a orphan-instance module")) mod ImportBySystem
 
 loadInterface :: SDoc -> ModuleName -> WhereFrom -> RnM d (Module, Ifaces)
 loadInterface doc_str mod_name from
@@ -137,7 +150,9 @@ loadInterface doc_str mod_name from
     in
     foldlRn (loadDecl mod)          (iDecls ifaces) rd_decls           `thenRn` \ new_decls ->
     foldlRn (loadInstDecl mod)      (iInsts ifaces) (pi_insts iface)   `thenRn` \ new_insts ->
-    foldlRn (loadRule mod)          (iRules ifaces) (pi_rules iface)   `thenRn` \ new_rules -> 
+    (if (opt_IgnoreIfacePragmas) 
+       then returnRn emptyBag
+       else foldlRn (loadRule mod)  (iRules ifaces) (pi_rules iface))  `thenRn` \ new_rules -> 
     foldlRn (loadFixDecl mod_name)   (iFixes ifaces) rd_decls                  `thenRn` \ new_fixities ->
     mapRn   (loadExport this_mod_nm) (pi_exports iface)                        `thenRn` \ avails_s ->
     let
@@ -408,7 +423,7 @@ checkEntityUsage mod decls ((occ_name,old_vers) : rest)
     case lookupNameEnv decls name of
 
        Nothing       ->        -- We used it before, but it ain't there now
-                         putDocRn (sep [ptext SLIT("No longer exported:"), ppr name])
+                         traceRn (sep [ptext SLIT("No longer exported:"), ppr name])
                          `thenRn_` returnRn False
 
        Just (new_vers,_,_,_)   -- It's there, but is it up to date?
@@ -418,7 +433,7 @@ checkEntityUsage mod decls ((occ_name,old_vers) : rest)
 
                | otherwise
                        -- Out of date, so bale out
-               -> putDocRn (sep [ptext SLIT("Out of date:"), ppr name])  `thenRn_`
+               -> traceRn (sep [ptext SLIT("Out of date:"), ppr name])  `thenRn_`
                   returnRn False
 \end{code}
 
@@ -444,13 +459,9 @@ importDecl name
     if name `elemNameSet` already_slurped then
        returnRn Nothing        -- Already dealt with
     else
-       getModuleRn             `thenRn` \ this_mod ->
-       let
-         mod = moduleName (nameModule name)
-       in
-       if mod == this_mod then         -- Don't bring in decls from
+       if isLocallyDefined name then   -- Don't bring in decls from
                                        -- the renamed module's own interface file
-                 addWarnRn (importDeclWarn mod name) `thenRn_`
+                 addWarnRn (importDeclWarn name) `thenRn_`
                  returnRn Nothing
        else
        getNonWiredInDecl name
@@ -460,7 +471,7 @@ importDecl name
 getNonWiredInDecl :: Name -> RnMG (Maybe (Module, RdrNameHsDecl))
 getNonWiredInDecl needed_name 
   = traceRn doc_str                            `thenRn_`
-    loadHomeInterface doc_str needed_name      `thenRn` \ (_, ifaces) ->
+    loadHomeInterface doc_str needed_name      `thenRn` \ ifaces ->
     case lookupNameEnv (iDecls ifaces) needed_name of
 
       Just (version,avail,_,decl)
@@ -530,36 +541,47 @@ getInterfaceExports mod_name from
 \begin{code}
 getImportedInstDecls :: NameSet -> RnMG [(Module,RdrNameHsDecl)]
 getImportedInstDecls gates
-  =    -- First load any orphan-instance modules that aren't aready loaded
+  =            -- First, load any orphan-instance modules that aren't aready loaded
        -- Orphan-instance modules are recorded in the module dependecnies
-    getIfacesRn                                                `thenRn` \ ifaces ->
+    getIfacesRn                                        `thenRn` \ ifaces ->
     let
        orphan_mods =
          [mod | (mod, (_, True, Nothing)) <- fmToList (iImpModInfo ifaces)]
     in
-    traceRn (text "Loading orphan modules" <+> fsep (map pprModuleName orphan_mods))
-    `thenRn_` mapRn_ load_it orphan_mods       `thenRn_`
+    loadOrphanModules orphan_mods                      `thenRn_` 
 
        -- Now we're ready to grab the instance declarations
        -- Find the un-gated ones and return them, 
        -- removing them from the bag kept in Ifaces
-    getIfacesRn                                                `thenRn` \ ifaces ->
+    getIfacesRn                                        `thenRn` \ ifaces ->
     let
        (decls, new_insts) = selectGated gates (iInsts ifaces)
     in
     setIfacesRn (ifaces { iInsts = new_insts })                `thenRn_`
 
     traceRn (sep [text "getImportedInstDecls:", 
-                 nest 4 (fsep (map ppr (nameSetToList gates))),
-                 text "Slurped" <+> int (length decls)
-                                <+> text "instance declarations"]) `thenRn_`
+                 nest 4 (fsep (map ppr gate_list)),
+                 text "Slurped" <+> int (length decls) <+> text "instance declarations",
+                 nest 4 (vcat (map ppr_brief_inst_decl decls))])       `thenRn_`
     returnRn decls
   where
-    load_it mod = loadInterface (doc_str mod) mod ImportBySystem
-    doc_str mod = sep [pprModuleName mod, ptext SLIT("is a orphan-instance module")]
+    gate_list      = nameSetToList gates
+
+    load_home gate | isLocallyDefined gate
+                  = returnRn ()
+                  | otherwise
+                  = loadHomeInterface (ppr gate <+> text "is an instance gate") gate   `thenRn_`
+                    returnRn ()
+
+ppr_brief_inst_decl (mod, InstD (InstDecl inst_ty _ _ _ _))
+  = case inst_ty of
+       HsForAllTy _ _ tau -> ppr tau
+       other              -> ppr inst_ty
 
 getImportedRules :: RnMG [(Module,RdrNameHsDecl)]
-getImportedRules
+getImportedRules 
+  | opt_IgnoreIfacePragmas = returnRn []
+  | otherwise
   = getIfacesRn        `thenRn` \ ifaces ->
     let
        gates              = iSlurp ifaces      -- Anything at all that's been slurped
@@ -571,6 +593,7 @@ getImportedRules
     returnRn decls
 
 selectGated gates decl_bag
+       -- Select only those decls whose gates are *all* in 'gates'
 #ifdef DEBUG
   | opt_NoPruneDecls   -- Just to try the effect of not gating at all
   = (foldrBag (\ (_,d) ds -> d:ds) [] decl_bag, emptyBag)      -- Grab them all
@@ -592,7 +615,7 @@ lookupFixity name
        Nothing                  -> returnRn defaultFixity
 
   | otherwise  -- Imported
-  = loadHomeInterface doc name         `thenRn` \ (_, ifaces) ->
+  = loadHomeInterface doc name         `thenRn` \ ifaces ->
     case lookupNameEnv (iFixes ifaces) name of
        Just (FixitySig _ fix _) -> returnRn fix 
        Nothing                  -> returnRn defaultFixity
@@ -640,7 +663,7 @@ For (1) it is slightly harmful to record @B.f@ in @A@'s usages,
 because a change in @B.f@'s version will provoke full recompilation of @A@,
 producing an identical @A.o@,
 and @A.hi@ differing only in its usage-version of @B.f@
-(which isn't used by any importer).
+(and this usage-version info isn't used by any importer).
 
 For (2), because of the tricky @B.h@ question above,
 we ensure that @A.hi@ is touched
@@ -673,19 +696,30 @@ getImportVersions this_mod exports
                -- mv_map2 adds the version numbers of things exported individually
        mv_map2 = foldr add_mv mv_map1 imp_names
 
-       -- Build the result list by adding info for each module, 
-       -- *omitting*   (a) library modules
-       --              (b) source-imported modules
+       -- Build the result list by adding info for each module.
+       -- For (a) library modules
+       --     (b) source-imported modules
+       -- we do something special.  We don't want to record detailed usage information.
+       -- Indeed we don't want to record them at all unless they contain orphans,
+       -- which we must never lose track of.
        mk_version_info mod_name (version, has_orphans, cts) so_far
-          | omit cts  = so_far -- Don't record usage info for this module
-          | otherwise = (mod_name, version, has_orphans, whats_imported) : so_far
+          | lib_or_source_imported && not has_orphans
+          = so_far     -- Don't record any usage info for this module
+          
+          | lib_or_source_imported     -- Has orphans; record the module but not
+                                       -- detailed version information for the imports
+          = (mod_name, version, has_orphans, Specifically []) : so_far
+
+          | otherwise 
+          = (mod_name, version, has_orphans, whats_imported) : so_far
           where
             whats_imported = case lookupFM mv_map2 mod_name of
                                Just wi -> wi
                                Nothing -> Specifically []
 
-       omit (Just (mod, boot_import, _)) = isLibModule mod || boot_import
-       omit Nothing                      = False
+            lib_or_source_imported = case cts of
+                                       Just (mod, boot_import, _) -> isLibModule mod || boot_import
+                                       Nothing                    -> False
     in
     returnRn (foldFM mk_version_info [] mod_map)
   where
@@ -753,7 +787,7 @@ getDeclBinders new_name (TyClD (TySynonym tycon _ _ src_loc))
   = new_name tycon src_loc             `thenRn` \ tycon_name ->
     returnRn (Just (AvailTC tycon_name [tycon_name]))
 
-getDeclBinders new_name (TyClD (ClassDecl _ cname _ sigs _ _ _ _ _ src_loc))
+getDeclBinders new_name (TyClD (ClassDecl _ cname _ _ sigs _ _ _ _ _ src_loc))
   = new_name cname src_loc                     `thenRn` \ class_name ->
 
        -- Record the names for the class ops
@@ -770,11 +804,25 @@ getDeclBinders new_name (SigD (IfaceSig var ty prags src_loc))
     returnRn (Just (Avail var_name))
 
 getDeclBinders new_name (FixD _)  = returnRn Nothing
-getDeclBinders new_name (ForD _)  = returnRn Nothing
+
+    -- foreign declarations
+getDeclBinders new_name (ForD (ForeignDecl nm kind _ dyn _ loc))
+  | binds_haskell_name kind dyn
+  = new_name nm loc                `thenRn` \ name ->
+    returnRn (Just (Avail name))
+
+  | otherwise -- a foreign export
+  = lookupImplicitOccRn nm `thenRn_` 
+    returnRn Nothing
+
 getDeclBinders new_name (DefD _)  = returnRn Nothing
 getDeclBinders new_name (InstD _) = returnRn Nothing
 getDeclBinders new_name (RuleD _) = returnRn Nothing
 
+binds_haskell_name (FoImport _) _   = True
+binds_haskell_name FoLabel      _   = True
+binds_haskell_name FoExport  ext_nm = isDynamic ext_nm
+
 ----------------
 getConFieldNames new_name (ConDecl con _ _ (RecCon fielddecls) src_loc : rest)
   = mapRn (\n -> new_name n src_loc) (con:fields)      `thenRn` \ cfs ->
@@ -795,7 +843,7 @@ getConFieldNames new_name (ConDecl con _ _ condecl src_loc : rest)
 
 getConFieldNames new_name [] = returnRn []
 
-getClassOpNames new_name (ClassOpSig op _ _ src_loc) = new_name op src_loc
+getClassOpNames new_name (ClassOpSig op _ _ _ src_loc) = new_name op src_loc
 \end{code}
 
 @getDeclSysBinders@ gets the implicit binders introduced by a decl.
@@ -808,7 +856,7 @@ and the dict fun of an instance decl, because both of these have
 bindings of their own elsewhere.
 
 \begin{code}
-getDeclSysBinders new_name (TyClD (ClassDecl _ cname _ sigs _ _ tname dname snames src_loc))
+getDeclSysBinders new_name (TyClD (ClassDecl _ cname _ _ sigs _ _ tname dname snames src_loc))
   = new_name dname src_loc                             `thenRn` \ datacon_name ->
     new_name tname src_loc                             `thenRn` \ tycon_name ->
     sequenceRn [new_name n src_loc | n <- snames]      `thenRn` \ scsel_names ->
@@ -893,12 +941,8 @@ readIface the_mod file_path
                  PFailed err                    -> failWithRn Nothing err 
                  POk _  (PIface mod_nm iface) ->
                    warnCheckRn (mod_nm == moduleName the_mod)
-                       (hsep [ ptext SLIT("Something is amiss; requested module name")
-                       , pprModule the_mod
-                       , ptext SLIT("differs from name found in the interface file ")
-                       , pprModuleName mod_nm
-                       ])
-                   `thenRn_` returnRn (Just (the_mod, iface))
+                               (hiModuleNameMismatchWarn the_mod mod_nm) `thenRn_`
+                   returnRn (Just (the_mod, iface))
 
         Left err
          | isDoesNotExistError err -> returnRn Nothing
@@ -932,16 +976,24 @@ getDeclWarn name loc
   = sep [ptext SLIT("Failed to find (optional) interface decl for") <+> quotes (ppr name),
         ptext SLIT("desired at") <+> ppr loc]
 
-importDeclWarn mod name
+importDeclWarn name
   = sep [ptext SLIT(
     "Compiler tried to import decl from interface file with same name as module."), 
         ptext SLIT(
     "(possible cause: module name clashes with interface file already in scope.)")
        ] $$
-    hsep [ptext SLIT("Interface:"), quotes (pprModuleName mod), 
-         comma, ptext SLIT("name:"), quotes (ppr name)]
+    hsep [ptext SLIT("name:"), quotes (ppr name)]
 
 warnRedundantSourceImport mod_name
   = ptext SLIT("Unnecessary {- SOURCE -} in the import of module")
           <+> quotes (pprModuleName mod_name)
+
+hiModuleNameMismatchWarn :: Module -> ModuleName -> Message
+hiModuleNameMismatchWarn requested_mod mod_nm = 
+    hsep [ ptext SLIT("Something is amiss; requested module name")
+        , pprModule requested_mod
+        , ptext SLIT("differs from name found in the interface file ")
+        , pprModuleName mod_nm
+        ]
+
 \end{code}