[project @ 2004-02-26 14:49:05 by simonpj]
[ghc-hetmet.git] / ghc / compiler / rename / RnNames.lhs
index 656d131..37399d2 100644 (file)
@@ -54,7 +54,7 @@ import SrcLoc         ( noSrcLoc, Located(..), mkGeneralSrcSpan,
 import BasicTypes      ( DeprecTxt )
 import ListSetOps      ( removeDups )
 import Util            ( sortLt, notNull, isSingleton )
-import List            ( partition, insert )
+import List            ( partition )
 import IO              ( openFile, IOMode(..) )
 \end{code}
 
@@ -192,7 +192,9 @@ importsFromImportDecl this_mod
 
     let
        -- Compute new transitive dependencies
-       orphans | is_orph   = insert imp_mod_name (dep_orphs deps)
+
+       orphans | is_orph   = ASSERT( not (imp_mod_name `elem` dep_orphs deps) )
+                             imp_mod_name : dep_orphs deps
                | otherwise = dep_orphs deps
 
        (dependent_mods, dependent_pkgs) 
@@ -208,8 +210,8 @@ importsFromImportDecl this_mod
           =    -- Imported module is from another package
                -- Dump the dependent modules
                -- Add the package imp_mod comes from to the dependent packages
-               -- from imp_mod
-            ([], insert (mi_package iface) (dep_pkgs deps))
+            ASSERT( not (mi_package iface `elem` dep_pkgs deps) )
+            ([], mi_package iface : dep_pkgs deps)
 
        not_self (m, _) = m /= this_mod_name
 
@@ -403,33 +405,37 @@ filterImports :: ModIface
              -> ImportSpec                     -- The span for the entire import decl
              -> Maybe (Bool, [Located (IE RdrName)])   -- Import spec; True => hiding
              -> [AvailInfo]                    -- What's available
-             -> RnM (AvailEnv,                 -- What's imported
-                     GlobalRdrEnv)             -- ...in two forms
+             -> RnM (AvailEnv,                 -- What's imported (qualified or unqualified)
+                     GlobalRdrEnv)             -- Same again, but in GRE form
 
        -- Complains if import spec mentions things that the module doesn't export
         -- Warns/informs if import spec contains duplicates.
+                       
 mkGenericRdrEnv imp_spec avails
   = mkGlobalRdrEnv [ GRE { gre_name = name, gre_prov = Imported [imp_spec] False }
                   | avail <- avails, name <- availNames avail ]
-                       
+
 filterImports iface imp_spec Nothing total_avails
-  = returnM (mkAvailEnv total_avails, mkGenericRdrEnv imp_spec total_avails)
+  = returnM (mkAvailEnv total_avails, 
+            mkGenericRdrEnv imp_spec total_avails)
 
 filterImports iface imp_spec (Just (want_hiding, import_items)) total_avails
-  = mapAndUnzipM (addLocM get_item) import_items       `thenM` \ (avails, gres) ->
+  = mapAndUnzipM (addLocM get_item) import_items       `thenM` \ (avails_s, gres) ->
     let
-       all_avails = foldr plusAvailEnv     emptyAvailEnv     avails
-       rdr_env    = foldr plusGlobalRdrEnv emptyGlobalRdrEnv gres
+       avails = concat avails_s
     in
     if not want_hiding then
-       returnM (all_avails, rdr_env)
+      return (mkAvailEnv avails,
+             foldr plusGlobalRdrEnv emptyGlobalRdrEnv gres)
     else
-    let        -- Hide stuff in all_avails
-          hidden = availsToNameSet (availEnvElts all_avails)
-          keep n = not (n `elemNameSet` hidden)
-          pruned_avails = pruneAvails keep total_avails
-    in
-    returnM (mkAvailEnv pruned_avails, mkGenericRdrEnv imp_spec pruned_avails)
+      let
+       hidden = availsToNameSet avails
+       keep n = not (n `elemNameSet` hidden)
+       pruned_avails = pruneAvails keep total_avails
+      in
+      return (mkAvailEnv pruned_avails,
+             mkGenericRdrEnv imp_spec pruned_avails)
+
   where
     import_fm :: OccEnv AvailInfo
     import_fm = mkOccEnv [ (nameOccName name, avail) 
@@ -440,12 +446,12 @@ filterImports iface imp_spec (Just (want_hiding, import_items)) total_avails
        -- in an import list map to TcOccs, not VarOccs.
 
     bale_out item = addErr (badImportItemErr iface imp_spec item)      `thenM_`
-                   returnM (emptyAvailEnv, emptyGlobalRdrEnv)
+                   returnM ([], emptyGlobalRdrEnv)
 
-    succeed_with :: Bool -> AvailInfo -> RnM (AvailEnv, GlobalRdrEnv)
+    succeed_with :: Bool -> AvailInfo -> RnM ([AvailInfo], GlobalRdrEnv)
     succeed_with all_explicit avail
       = do { loc <- getSrcSpanM
-          ; returnM (unitAvailEnv avail, 
+          ; returnM ([avail], 
                      mkGlobalRdrEnv (map (mk_gre loc) (availNames avail))) }
       where
        mk_gre loc name = GRE { gre_name = name, 
@@ -454,7 +460,7 @@ filterImports iface imp_spec (Just (want_hiding, import_items)) total_avails
        explicit name = all_explicit || name == main_name
        main_name = availName avail
 
-    get_item :: IE RdrName -> RnM (AvailEnv, GlobalRdrEnv)
+    get_item :: IE RdrName -> RnM ([AvailInfo], GlobalRdrEnv)
        -- Empty result for a bad item.
        -- Singleton result is typical case.
        -- Can have two when we are hiding, and mention C which might be
@@ -474,10 +480,11 @@ filterImports iface imp_spec (Just (want_hiding, import_items)) total_avails
 
     get_item item@(IEThingAbs n)
       | want_hiding    -- hiding( C ) 
-                       -- Here the 'C' can be a data constructor *or* a type/class
+                       -- Here the 'C' can be a data constructor 
+                       -- *or* a type/class, or even both
       = case catMaybes [check_item item, check_item (IEVar data_n)] of
          []     -> bale_out item
-         avails -> returnM (mkAvailEnv avails, emptyGlobalRdrEnv)
+         avails -> returnM (avails, emptyGlobalRdrEnv)
                        -- The GlobalRdrEnv result is irrelevant when hiding
       where
        data_n = setRdrNameSpace n srcDataName
@@ -565,9 +572,8 @@ type ExportAccum    -- The type of the accumulating parameter of
                        -- the main worker function in exportsFromAvail
      = ([ModuleName],          -- 'module M's seen so far
        ExportOccMap,           -- Tracks exported occurrence names
-       AvailEnv)               -- The accumulated exported stuff, kept in an env
-                               --   so we can common-up related AvailInfos
-emptyExportAccum = ([], emptyOccEnv, emptyAvailEnv) 
+       NameSet)                -- The accumulated exported stuff
+emptyExportAccum = ([], emptyOccEnv, emptyNameSet) 
 
 type ExportOccMap = OccEnv (Name, IE RdrName)
        -- Tracks what a particular exported OccName
@@ -578,7 +584,7 @@ type ExportOccMap = OccEnv (Name, IE RdrName)
 
 exportsFromAvail :: Bool  -- False => no 'module M(..) where' header at all
                 -> Maybe [Located (IE RdrName)] -- Nothing => no explicit export list
-                -> RnM Avails
+                -> RnM NameSet
        -- Complains if two distinct exports have same OccName
         -- Warns about identical exports.
        -- Complains about exports items not in scope
@@ -601,33 +607,27 @@ exportsFromAvail explicit_mod exports
        exports_from_avail real_exports rdr_env imports }
 
 
-exports_from_avail Nothing rdr_env
-                  imports@(ImportAvails { imp_env = entity_avail_env })
+exports_from_avail Nothing rdr_env imports
  =     -- Export all locally-defined things
        -- We do this by filtering the global RdrEnv,
-       -- keeping only things that are (a) qualified,
-       -- (b) locally defined, (c) a 'main' name
-       -- Then we look up in the entity-avail-env
-   return [ lookupAvailEnv entity_avail_env name
-         | gre <- globalRdrEnvElts rdr_env,
-           isLocalGRE gre,
-           let name = gre_name gre,
-           isNothing (nameParent_maybe name)   -- Main things only
-         ]
+       -- keeping only things that are locally-defined
+   return (mkNameSet [ gre_name gre 
+                    | gre <- globalRdrEnvElts rdr_env,
+                      isLocalGRE gre ])
 
 exports_from_avail (Just export_items) rdr_env
                   (ImportAvails { imp_qual = mod_avail_env, 
                                   imp_env  = entity_avail_env }) 
   = foldlM (exports_from_litem) emptyExportAccum
-           export_items                        `thenM` \ (_, _, export_avail_map) ->
-    returnM (nameEnvElts export_avail_map)
+           export_items                        `thenM` \ (_, _, exports) ->
+    returnM exports
 
   where
     exports_from_litem :: ExportAccum -> Located (IE RdrName) -> RnM ExportAccum
     exports_from_litem acc = addLocM (exports_from_item acc)
 
     exports_from_item :: ExportAccum -> IE RdrName -> RnM ExportAccum
-    exports_from_item acc@(mods, occs, avails) ie@(IEModuleContents mod)
+    exports_from_item acc@(mods, occs, exports) ie@(IEModuleContents mod)
        | mod `elem` mods       -- Duplicate export of M
        = do { warn_dup_exports <- doptM Opt_WarnDuplicateExports ;
               warnIf warn_dup_exports (dupModuleExport mod) ;
@@ -640,23 +640,19 @@ exports_from_avail (Just export_items) rdr_env
 
            Just avail_env
                -> let
-                       mod_avails = [ filtered_avail
-                                    | avail <- availEnvElts avail_env,
-                                      let mb_avail = filter_unqual rdr_env avail,
-                                      isJust mb_avail,
-                                      let Just filtered_avail = mb_avail]
-                                               
-                       avails' = foldl addAvail avails mod_avails
+                       new_exports = [ name | avail <- availEnvElts avail_env,
+                                              name  <- availNames avail,
+                                              inScopeUnqual rdr_env name ]
                   in
+
                -- This check_occs not only finds conflicts between this item
                -- and others, but also internally within this item.  That is,
                -- if 'M.x' is in scope in several ways, we'll have several
                -- members of mod_avails with the same OccName.
+                  check_occs ie occs new_exports       `thenM` \ occs' ->
+                  returnM (mod:mods, occs', addListToNameSet exports new_exports)
 
-                  foldlM (check_occs ie) occs mod_avails       `thenM` \ occs' ->
-                  returnM (mod:mods, occs', avails')
-
-    exports_from_item acc@(mods, occs, avails) ie
+    exports_from_item acc@(mods, occs, exports) ie
        = lookupGlobalOccRn (ieName ie)                 `thenM` \ name -> 
          if isUnboundName name then
                returnM acc     -- Avoid error cascade
@@ -675,41 +671,34 @@ exports_from_avail (Just export_items) rdr_env
            Just export_avail ->        
 
                -- Phew!  It's OK!  Now to check the occurrence stuff!
-         checkForDodgyExport ie avail                          `thenM_`
-          check_occs ie occs export_avail                      `thenM` \ occs' ->
-         returnM (mods, occs', addAvail avails export_avail)
+       
+         let 
+             new_exports = availNames export_avail 
+         in
+         checkForDodgyExport ie new_exports            `thenM_`
+          check_occs ie occs new_exports               `thenM` \ occs' ->
+         returnM (mods, occs', addListToNameSet exports new_exports)
          }
 
 
 -------------------------------
-filter_unqual :: GlobalRdrEnv -> AvailInfo -> Maybe AvailInfo
--- Filter the Avail by what's in scope unqualified
-filter_unqual env (Avail n)
-  | in_scope env n = Just (Avail n)
-  | otherwise     = Nothing
-filter_unqual env (AvailTC n ns)
-  | not (null ns') = Just (AvailTC n ns')
-  | otherwise     = Nothing
-  where
-    ns' = filter (in_scope env) ns
-
-in_scope :: GlobalRdrEnv -> Name -> Bool
+inScopeUnqual :: GlobalRdrEnv -> Name -> Bool
 -- Checks whether the Name is in scope unqualified, 
 -- regardless of whether it's ambiguous or not
-in_scope env n = any unQualOK (lookupGRE_Name env n)
+inScopeUnqual env n = any unQualOK (lookupGRE_Name env n)
 
 -------------------------------
-checkForDodgyExport :: IE RdrName -> AvailInfo -> RnM ()
-checkForDodgyExport (IEThingAll tc) (AvailTC _ [n]) = addWarn (dodgyExportWarn tc)
+checkForDodgyExport :: IE RdrName -> [Name] -> RnM ()
+checkForDodgyExport (IEThingAll tc) [n] = addWarn (dodgyExportWarn tc)
   -- This occurs when you import T(..), but
   -- only export T abstractly.  The single [n]
   -- in the AvailTC is the type or class itself
 checkForDodgyExport _ _ = return ()
 
 -------------------------------
-check_occs :: IE RdrName -> ExportOccMap -> AvailInfo -> RnM ExportOccMap
-check_occs ie occs avail 
-  = foldlM check occs (availNames avail)
+check_occs :: IE RdrName -> ExportOccMap -> [Name] -> RnM ExportOccMap
+check_occs ie occs names
+  = foldlM check occs names
   where
     check occs name
       = case lookupOccEnv occs name_occ of