+loadHomeInterface :: SDoc -> Name -> RnM d (Module, Ifaces)
+loadHomeInterface doc_str name
+ = loadInterface doc_str (moduleName (nameModule name)) ImportBySystem
+
+loadInterface :: SDoc -> ModuleName -> WhereFrom -> RnM d (Module, Ifaces)
+loadInterface doc_str mod_name from
+ = getIfacesRn `thenRn` \ ifaces ->
+ let
+ mod_map = iImpModInfo ifaces
+ mod_info = lookupFM mod_map mod_name
+ in_map = maybeToBool mod_info
+ in
+
+ -- Issue a warning for a redundant {- SOURCE -} import
+ -- It's redundant if the moduld is in the iImpModInfo at all,
+ -- because we arrange to read all the ordinary imports before
+ -- any of the {- SOURCE -} imports
+ warnCheckRn (not (in_map && case from of {ImportByUserSource -> True; other -> False}))
+ (warnRedundantSourceImport mod_name) `thenRn_`
+
+ -- CHECK WHETHER WE HAVE IT ALREADY
+ case mod_info of {
+ Just (_, _, Just (load_mod, _, _))
+ -> -- We're read it already so don't re-read it
+ returnRn (load_mod, ifaces) ;
+
+ mod_map_result ->
+
+ -- READ THE MODULE IN
+ findAndReadIface doc_str mod_name from in_map `thenRn` \ (hi_boot_read, read_result) ->
+ case read_result of {
+ Nothing -> -- Not found, so add an empty export env to the Ifaces map
+ -- so that we don't look again
+ let
+ mod = mkVanillaModule mod_name
+ new_mod_map = addToFM mod_map mod_name (0, False, Just (mod, False, []))
+ new_ifaces = ifaces { iImpModInfo = new_mod_map }
+ in
+ setIfacesRn new_ifaces `thenRn_`
+ failWithRn (mod, new_ifaces) (noIfaceErr mod hi_boot_read) ;
+
+ -- Found and parsed!
+ Just (mod, iface) ->
+
+ -- LOAD IT INTO Ifaces
+
+ -- NB: *first* we do loadDecl, so that the provenance of all the locally-defined
+ --- names is done correctly (notably, whether this is an .hi file or .hi-boot file).
+ -- If we do loadExport first the wrong info gets into the cache (unless we
+ -- explicitly tag each export which seems a bit of a bore)
+
+ getModuleRn `thenRn` \ this_mod_nm ->
+ let
+ rd_decls = pi_decls iface
+ 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 ->
+ foldlRn (loadFixDecl mod_name) (iFixes ifaces) rd_decls `thenRn` \ new_fixities ->
+ mapRn (loadExport this_mod_nm) (pi_exports iface) `thenRn` \ avails_s ->
+ let
+ -- For an explicit user import, add to mod_map info about
+ -- the things the imported module depends on, extracted
+ -- from its usage info.
+ mod_map1 = case from of
+ ImportByUser -> addModDeps mod mod_map (pi_usages iface)
+ other -> mod_map
+
+ -- Now add info about this module
+ mod_map2 = addToFM mod_map1 mod_name mod_details
+ mod_details = (pi_mod iface, pi_orphan iface, Just (mod, hi_boot_read, concat avails_s))
+
+ new_ifaces = ifaces { iImpModInfo = mod_map2,
+ iDecls = new_decls,
+ iFixes = new_fixities,
+ iRules = new_rules,
+ iInsts = new_insts }
+ in
+ setIfacesRn new_ifaces `thenRn_`
+ returnRn (mod, new_ifaces)
+ }}
+
+addModDeps :: Module -> ImportedModuleInfo
+ -> [ImportVersion a] -> ImportedModuleInfo
+addModDeps mod mod_deps new_deps
+ = foldr add mod_deps new_deps
+ where
+ is_lib = isLibModule mod -- Don't record dependencies when importing a library module
+ add (imp_mod, version, has_orphans, _) deps
+ | is_lib && not has_orphans = deps
+ | otherwise = addToFM_C combine deps imp_mod (version, has_orphans, Nothing)
+ -- Record dependencies for modules that are
+ -- either are dependent via a non-library module
+ -- or contain orphan rules or instance decls
+
+ -- Don't ditch a module that's already loaded!!
+ combine old@(_, _, Just _) new = old
+ combine old@(_, _, Nothing) new = new
+
+loadExport :: ModuleName -> ExportItem -> RnM d [AvailInfo]
+loadExport this_mod (mod, entities)
+ | mod == this_mod = returnRn []
+ -- If the module exports anything defined in this module, just ignore it.
+ -- Reason: otherwise it looks as if there are two local definition sites
+ -- for the thing, and an error gets reported. Easiest thing is just to
+ -- filter them out up front. This situation only arises if a module
+ -- imports itself, or another module that imported it. (Necessarily,
+ -- this invoves a loop.) Consequence: if you say
+ -- module A where
+ -- import B( AType )
+ -- type AType = ...
+ --
+ -- module B( AType ) where
+ -- import {-# SOURCE #-} A( AType )
+ --
+ -- then you'll get a 'B does not export AType' message. A bit bogus
+ -- but it's a bogus thing to do!
+
+ | otherwise
+ = mapRn (load_entity mod) entities
+ where
+ new_name mod occ = mkImportedGlobalName mod occ
+
+ load_entity mod (Avail occ)
+ = new_name mod occ `thenRn` \ name ->
+ returnRn (Avail name)
+ load_entity mod (AvailTC occ occs)
+ = new_name mod occ `thenRn` \ name ->
+ mapRn (new_name mod) occs `thenRn` \ names ->
+ returnRn (AvailTC name names)
+
+
+loadFixDecl :: ModuleName -> FixityEnv
+ -> (Version, RdrNameHsDecl)
+ -> RnM d FixityEnv
+loadFixDecl mod_name fixity_env (version, FixD sig@(FixitySig rdr_name fixity loc))
+ = -- Ignore the version; when the fixity changes the version of
+ -- its 'host' entity changes, so we don't need a separate version
+ -- number for fixities
+ mkImportedGlobalName mod_name (rdrNameOcc rdr_name) `thenRn` \ name ->
+ let
+ new_fixity_env = addToNameEnv fixity_env name (FixitySig name fixity loc)
+ in
+ returnRn new_fixity_env