[project @ 1997-03-14 07:52:06 by simonpj]
[ghc-hetmet.git] / ghc / compiler / rename / RnNames.lhs
index 754dfd2..276cf5a 100644 (file)
@@ -20,10 +20,10 @@ import HsBinds      ( collectTopBinders )
 import HsImpExp        ( ieName )
 import RdrHsSyn        ( RdrNameHsDecl(..), RdrName(..), RdrNameIE(..), SYN_IE(RdrNameImportDecl),
                  SYN_IE(RdrNameHsModule), SYN_IE(RdrNameFixityDecl),
-                 rdrNameOcc
+                 rdrNameOcc, ieOcc
                )
 import RnHsSyn ( RenamedHsModule(..), RenamedFixityDecl(..) )
-import RnIfaces        ( getInterfaceExports, getDeclBinders, checkUpToDate )
+import RnIfaces        ( getInterfaceExports, getDeclBinders, checkUpToDate, recordSlurp )
 import RnEnv
 import RnMonad
 import FiniteMap
@@ -83,6 +83,9 @@ getGlobalNames m@(HsModule this_mod _ exports imports _ _ mod_loc)
       exportsFromAvail this_mod exports all_avails rn_env      
                                                        `thenRn` \ (export_fn, export_env) ->
 
+       -- RECORD THAT LOCALLY DEFINED THINGS ARE AVAILABLE
+      mapRn (recordSlurp Nothing) local_avails         `thenRn_`
+
       returnRn (export_fn, Just (export_env, rn_env, local_avails))
     )                                                  `thenRn` \ (_, result) ->
     returnRn result
@@ -136,9 +139,7 @@ importsFromImportDecl (ImportDecl mod qual_only as_mod import_spec loc)
     getInterfaceExports mod                    `thenRn` \ (avails, fixities) ->
     filterImports mod import_spec avails       `thenRn` \ filtered_avails ->
     let
-       filtered_avails' = [ Avail (set_name_prov n) (map set_name_prov ns)
-                          | Avail n ns <- filtered_avails
-                          ]
+       filtered_avails' = map set_avail_prov filtered_avails
        fixities'        = [ (occ,(fixity,provenance)) | (occ,fixity) <- fixities ]
     in
     qualifyImports mod 
@@ -147,6 +148,9 @@ importsFromImportDecl (ImportDecl mod qual_only as_mod import_spec loc)
                   as_mod
                   (ExportEnv filtered_avails' fixities')
   where
+    set_avail_prov NotAvailable   = NotAvailable
+    set_avail_prov (Avail n)      = Avail (set_name_prov n) 
+    set_avail_prov (AvailTC n ns) = AvailTC (set_name_prov n) (map set_name_prov ns)
     set_name_prov name = setNameProvenance name provenance
     provenance = Imported mod loc
 \end{code}
@@ -171,11 +175,13 @@ importsFromLocalDecls rec_exp_fn (HsModule mod _ _ _ fix_decls decls _)
 
     getLocalDeclBinders avails decl
       = getDeclBinders newLocalName decl       `thenRn` \ avail ->
-       returnRn (avail : avails)
+       case avail of
+          NotAvailable -> returnRn avails              -- Instance decls and suchlike
+          other        -> returnRn (avail : avails)
 
     do_one (rdr_name, loc)
       = newLocalName rdr_name loc      `thenRn` \ name ->
-        returnRn (Avail name [])
+        returnRn (Avail name)
 \end{code}
 
 %************************************************************************
@@ -199,47 +205,36 @@ filterImports mod Nothing imports
   = returnRn imports
 
 filterImports mod (Just (want_hiding, import_items)) avails
-  =    -- Check that each import item mentions things that are actually available
-    mapRn check_import_item import_items       `thenRn_`
-
-       -- Return filtered environment; no need to filter fixities
-    returnRn (map new_avail avails)
-
+  = foldlRn (filter_item want_hiding) initial_avails import_items
   where
-    import_fm :: FiniteMap OccName RdrNameIE
-    import_fm = listToFM [(ieOcc ie, ie) | ie <- import_items]
-
-    avail_fm :: FiniteMap OccName AvailInfo
-    avail_fm = listToFM [(nameOccName name, avail) | avail@(Avail name ns) <- avails]
-
-    new_avail NotAvailable = NotAvailable
-    new_avail avail@(Avail name _)
-       | not in_import_items && want_hiding     = avail
-       | not in_import_items && not want_hiding = NotAvailable
-       | in_import_items     && want_hiding     = NotAvailable
-       | in_import_items     && not want_hiding = filtered_avail
-       where
-         maybe_import_item = lookupFM import_fm (nameOccName name)
-         in_import_items   = maybeToBool maybe_import_item
-         Just import_item  = maybe_import_item
-         filtered_avail    = filterAvail import_item avail
-
-    check_import_item  :: RdrNameIE -> RnMG ()
-    check_import_item item
-      = checkRn (maybeToBool maybe_matching_avail && sub_names_ok item avail)
-               (badImportItemErr mod item)
-     where
-       item_name            = ieOcc item
-       maybe_matching_avail = lookupFM avail_fm item_name
-       Just avail          = maybe_matching_avail
-
-    sub_names_ok (IEVar _)             _             = True
-    sub_names_ok (IEThingAbs _)                _             = True
-    sub_names_ok (IEThingAll _)                _             = True
-    sub_names_ok (IEThingWith _ wanted) (Avail _ has) = all ((`elem` has_list) . rdrNameOcc) wanted
-                                                     where
-                                                       has_list = map nameOccName has
-    sub_names_ok other1                        other2        = False
+    initial_avails | want_hiding = avails
+                  | otherwise   = []
+
+    import_fm :: FiniteMap OccName AvailInfo
+    import_fm = listToFM [ (nameOccName name, avail) 
+                        | avail <- avails,
+                          name  <- availEntityNames avail]
+
+    filter_item want_hiding avails_so_far item@(IEModuleContents _)
+      = addErrRn (badImportItemErr mod item)   `thenRn_`
+       returnRn avails_so_far
+
+    filter_item want_hiding avails_so_far item
+      | not (maybeToBool maybe_in_import_avails) ||
+       (case filtered_avail of { NotAvailable -> True; other -> False })
+      = addErrRn (badImportItemErr mod item)   `thenRn_`
+       returnRn avails_so_far
+
+      | want_hiding = returnRn (foldr hide_it [] avails_so_far)
+      | otherwise   = returnRn (filtered_avail : avails_so_far)        -- Explicit import list
+               
+      where
+       maybe_in_import_avails = lookupFM import_fm (ieOcc item)
+       Just avail             = maybe_in_import_avails
+       filtered_avail         = filterAvail item avail
+        hide_it avail avails   = case hideAvail item avail of
+                                       NotAvailable -> avails
+                                       avail'       -> avail' : avails
 \end{code}
 
 
@@ -277,8 +272,7 @@ qualifyImports this_mod qual_imp unqual_imp as_mod (ExportEnv avails fixities)
 
     mod_avail_env  = unitFM qual_mod avails
 
-    add_name name_env NotAvailable = returnRn name_env
-    add_name name_env (Avail n ns) = foldlRn add_one name_env (n : ns)
+    add_name name_env avail = foldlRn add_one name_env (availNames avail)
 
     add_one :: NameEnv -> Name -> RnMG NameEnv
     add_one env name = add_to_env addOneToNameEnvRn env occ_name name
@@ -347,10 +341,9 @@ type AvailEnv = FiniteMap OccName (RdrNameIE, AvailInfo)
 emptyAvailEnv = emptyFM
 
 unitAvailEnv :: RdrNameIE -> AvailInfo -> AvailEnv
-unitAvailEnv ie NotAvailable
-  = emptyFM
-unitAvailEnv ie avail@(Avail n ns)
-  = unitFM (nameOccName n) (ie,avail)
+unitAvailEnv ie NotAvailable   = emptyFM
+unitAvailEnv ie (AvailTC _ []) = emptyFM
+unitAvailEnv ie avail         = unitFM (nameOccName (availName avail)) (ie,avail)
 
 plusAvailEnv a1 a2
   = mapRn (addErrRn.availClashErr) (conflictsFM bad_avail a1 a2)       `thenRn_`
@@ -360,10 +353,18 @@ listToAvailEnv :: RdrNameIE -> [AvailInfo] -> RnM s d AvailEnv
 listToAvailEnv ie items
   = foldlRn plusAvailEnv emptyAvailEnv (map (unitAvailEnv ie) items)
 
-bad_avail  (ie1,Avail n1 _) (ie2,Avail n2 _) = n1 /= n2        -- Same OccName, different Name
+bad_avail  (ie1,avail1) (ie2,avail2) = availName avail1 /= availName avail2    -- Same OccName, different Name
 plus_avail (ie1,a1) (ie2,a2) = (ie1, a1 `plusAvail` a2)
 \end{code}
 
+Processing the export list.
+
+You might think that we should record things that appear in the export list as
+``occurrences'' (using addOccurrenceName), but you'd be wrong.  We do check (here)
+that they are in scope, but there is no need to slurp in their actual declaration
+(which is what addOccurrenceName forces).  Indeed, doing so would big trouble when
+compiling PrelBase, because it re-exports GHC, which includes takeMVar#, whose type
+includes ConcBase.StateAndSynchVar#, and so on...
 
 \begin{code}
 exportsFromAvail :: Module
@@ -389,16 +390,18 @@ exportsFromAvail this_mod (Just export_items) all_avails (RnEnv name_env fixity_
   where
     full_avail_env :: UniqFM AvailInfo
     full_avail_env = addListToUFM_C plusAvail emptyUFM
-                          [(name,avail) | avail@(Avail name _) <- concat (eltsFM all_avails)]
-       -- NB: full_avail_env won't contain bindings for data constructors and class ops,
-       -- which is right and proper; attempts to export them on their own will provoke an error
+                          [(name, avail) | avail <- concat (eltsFM all_avails),
+                                           name  <- availEntityNames avail 
+                          ]
+
+       -- NB: full_avail_env will contain bindings for class ops but not constructors
+       -- (see defn of availEntityNames)
 
     exports_from_item :: RdrNameIE -> RnMG AvailEnv
     exports_from_item ie@(IEModuleContents mod)
        = case lookupFM all_avails mod of
                Nothing     -> failWithRn emptyAvailEnv (modExportErr mod)
-               Just avails -> addOccurrenceNames Compulsory [n | Avail n _ <- avails]  `thenRn_`
-                              listToAvailEnv ie avails
+               Just avails -> listToAvailEnv ie avails
 
     exports_from_item ie
        | not (maybeToBool maybe_in_scope) 
@@ -416,8 +419,7 @@ exportsFromAvail this_mod (Just export_items) all_avails (RnEnv name_env fixity_
        = failWithRn emptyAvailEnv (exportItemErr ie export_avail)
 
        | otherwise     -- Phew!  It's OK!
-       = addOccurrenceName Compulsory name     `thenRn_`
-         returnRn (unitAvailEnv ie export_avail)
+       = returnRn (unitAvailEnv ie export_avail)
        where
           maybe_in_scope  = lookupNameEnv name_env (ieName ie)
          Just name       = maybe_in_scope
@@ -486,24 +488,22 @@ mk_export_fn avails
 %************************************************************************
 
 \begin{code}
-ieOcc ie = rdrNameOcc (ieName ie)
-
 badImportItemErr mod ie sty
-  = ppSep [ppStr "Module", pprModule sty mod, ppStr "does not export", ppr sty ie]
+  = ppSep [ppPStr SLIT("Module"), pprModule sty mod, ppPStr SLIT("does not export"), ppr sty ie]
 
 modExportErr mod sty
-  = ppCat [ ppStr "Unknown module in export list: module", ppPStr mod]
+  = ppCat [ ppPStr SLIT("Unknown module in export list: module"), ppPStr mod]
 
 exportItemErr export_item NotAvailable sty
-  = ppSep [ ppStr "Export item not in scope:", ppr sty export_item ]
+  = ppSep [ ppPStr SLIT("Export item not in scope:"), ppr sty export_item ]
 
 exportItemErr export_item avail sty
-  = ppHang (ppStr "Export item not fully in scope:")
-          4 (ppAboves [ppCat [ppStr "Wanted:    ", ppr sty export_item],
-                       ppCat [ppStr "Available: ", ppr sty (ieOcc export_item), pprAvail sty avail]])
+  = ppHang (ppPStr SLIT("Export item not fully in scope:"))
+          4 (ppAboves [ppCat [ppPStr SLIT("Wanted:    "), ppr sty export_item],
+                       ppCat [ppPStr SLIT("Available: "), ppr sty (ieOcc export_item), pprAvail sty avail]])
 
 availClashErr (occ_name, ((ie1,avail1), (ie2,avail2))) sty
-  = ppHang (ppCat [ppStr "Conflicting exports for local name: ", ppr sty occ_name])
+  = ppHang (ppCat [ppPStr SLIT("Conflicting exports for local name: "), ppr sty occ_name])
        4 (ppAboves [ppr sty ie1, ppr sty ie2])
 \end{code}