[project @ 2001-01-18 12:54:16 by simonmar]
[ghc-hetmet.git] / ghc / compiler / rename / Rename.lhs
index fefa9dc..af9ccc6 100644 (file)
@@ -22,20 +22,23 @@ import RnMonad
 import RnExpr          ( rnExpr )
 import RnNames         ( getGlobalNames, exportsFromAvail )
 import RnSource                ( rnSourceDecls, rnTyClDecl, rnIfaceRuleDecl, rnInstDecl )
-import RnIfaces                ( slurpImpDecls, mkImportInfo, 
+import RnIfaces                ( slurpImpDecls, mkImportInfo, recordLocalSlurps,
                          getInterfaceExports, closeDecls,
                          RecompileRequired, outOfDate, recompileRequired
                        )
 import RnHiFiles       ( readIface, removeContext, loadInterface,
-                         loadExports, loadFixDecls, loadDeprecs )
-import RnEnv           ( availsToNameSet, availName, 
-                         emptyAvailEnv, unitAvailEnv, availEnvElts, plusAvailEnv, groupAvails,
-                         warnUnusedImports, warnUnusedLocalBinds, warnUnusedModules,
-                         lookupOrigNames, lookupSrcName, newGlobalName, unQualInScope
+                         loadExports, loadFixDecls, loadDeprecs,
+                         tryLoadInterface )
+import RnEnv           ( availsToNameSet, availName, mkIfaceGlobalRdrEnv,
+                         emptyAvailEnv, unitAvailEnv, availEnvElts, 
+                         plusAvailEnv, groupAvails, warnUnusedImports, 
+                         warnUnusedLocalBinds, warnUnusedModules, 
+                         lookupOrigNames, lookupSrcName, 
+                         newGlobalName, unQualInScope
                        )
 import Module           ( Module, ModuleName, WhereFrom(..),
                          moduleNameUserString, moduleName,
-                         moduleEnvElts, lookupModuleEnv
+                         moduleEnvElts
                        )
 import Name            ( Name, NamedThing(..), getSrcLoc,
                          nameIsLocalOrFrom, nameOccName, nameModule,
@@ -52,7 +55,8 @@ import PrelNames      ( mAIN_Name, pREL_MAIN_Name, pRELUDE_Name,
                        )
 import PrelInfo                ( derivingOccurrences )
 import Type            ( funTyCon )
-import ErrUtils                ( dumpIfSet, showPass, printErrorsAndWarnings, errorsFound )
+import ErrUtils                ( dumpIfSet, dumpIfSet_dyn, showPass, 
+                         printErrorsAndWarnings, errorsFound )
 import Bag             ( bagToList )
 import FiniteMap       ( FiniteMap, fmToList, emptyFM, lookupFM, 
                          addToFM_C, elemFM, addToFM
@@ -70,6 +74,7 @@ import HscTypes               ( PersistentCompilerState, HomeIfaceTable, HomeSymbolTable,
                          Provenance(..), ImportReason(..), initialVersionInfo,
                          Deprecations(..), lookupDeprec, lookupIface
                         )
+import CmStaticInfo    ( GhciMode(..) )
 import List            ( partition, nub )
 \end{code}
 
@@ -101,25 +106,51 @@ renameExpr :: DynFlags
           -> HomeIfaceTable -> HomeSymbolTable
           -> PersistentCompilerState 
           -> Module -> RdrNameHsExpr
-          -> IO (PersistentCompilerState, Maybe (PrintUnqualified, (RenamedHsExpr, [RenamedHsDecl])))
+          -> IO ( PersistentCompilerState, 
+                  Maybe (PrintUnqualified, (RenamedHsExpr, [RenamedHsDecl]))
+                 )
 
 renameExpr dflags hit hst pcs this_module expr
-  | Just iface <- lookupModuleEnv hit this_module
-  = do { let rdr_env      = mi_globals iface
-       ; let print_unqual = unQualInScope rdr_env
-         
-       ; renameSource dflags hit hst pcs this_module $
-         initRnMS rdr_env emptyLocalFixityEnv SourceMode (rnExpr expr) `thenRn` \ (e,fvs) -> 
-         closeDecls [] fvs                                             `thenRn` \ decls ->
-         doptRn Opt_D_dump_rn                                          `thenRn` \ dump_rn ->
-         ioToRnM (dumpIfSet dump_rn "Renamer:" (ppr e))                `thenRn_`
+  = do { renameSource dflags hit hst pcs this_module $
+         tryLoadInterface doc (moduleName this_module) ImportByUser 
+                                               `thenRn` \ (iface, maybe_err) ->
+         case maybe_err of {
+           Just msg -> ioToRnM (printErrs alwaysQualify 
+                                (ptext SLIT("failed to load interface for") 
+                                 <+> quotes (ppr this_module) 
+                                 <>  char ':' <+> msg)) `thenRn_`
+                       returnRn Nothing;
+           Nothing -> 
+
+         let rdr_env      = mi_globals iface
+             print_unqual = unQualInScope rdr_env
+         in 
+         initRnMS rdr_env emptyLocalFixityEnv CmdLineMode (rnExpr expr)        
+                                               `thenRn` \ (e,fvs) -> 
+
+         checkErrsRn                           `thenRn` \ no_errs_so_far ->
+         if not no_errs_so_far then
+               -- Found errors already, so exit now
+               doDump e [] `thenRn_` 
+               returnRn Nothing
+         else
+
+         lookupOrigNames implicit_occs                 `thenRn` \ implicit_names ->
+         slurpImpDecls (fvs `plusFV` implicit_names)   `thenRn` \ decls ->
+
+         doDump e decls  `thenRn_`
          returnRn (Just (print_unqual, (e, decls)))
-       }
-
-  | otherwise
-  = do { printErrs alwaysQualify (ptext SLIT("renameExpr: Bad module context") <+> ppr this_module)
-       ; return (pcs, Nothing)
-       }
+       }}
+  where
+     implicit_occs = string_occs
+     doc = text "context for compiling expression"
+
+     doDump :: RenamedHsExpr -> [RenamedHsDecl] -> RnMG (Either IOError ())
+     doDump e decls = 
+       getDOptsRn  `thenRn` \ dflags ->
+       ioToRnM (dumpIfSet_dyn dflags Opt_D_dump_rn "Renamer:" 
+                       (vcat (ppr e : map ppr decls)))
 \end{code}
 
 
@@ -194,6 +225,18 @@ rename this_module contents@(HsModule _ _ exports imports local_decls mod_deprec
        -- CHECK THAT main IS DEFINED, IF REQUIRED
     checkMain this_module local_gbl_env                `thenRn_`
 
+       -- EXIT IF ERRORS FOUND
+       -- We exit here if there are any errors in the source, *before*
+       -- we attempt to slurp the decls from the interfaces, otherwise
+       -- the slurped decls may get lost when we return up the stack
+       -- to hscMain/hscExpr.
+    checkErrsRn                                        `thenRn` \ no_errs_so_far ->
+    if not no_errs_so_far then
+       -- Found errors already, so exit now
+        rnDump [] rn_local_decls               `thenRn_` 
+       returnRn Nothing
+    else
+
        -- SLURP IN ALL THE NEEDED DECLARATIONS
     implicitFVs mod_name rn_local_decls        `thenRn` \ implicit_fvs -> 
     let
@@ -205,13 +248,7 @@ rename this_module contents@(HsModule _ _ exports imports local_decls mod_deprec
     traceRn (text "Source FVs:" <+> fsep (map ppr (nameSetToList slurp_fvs)))  `thenRn_`
     slurpImpDecls slurp_fvs            `thenRn` \ rn_imp_decls ->
 
-       -- EXIT IF ERRORS FOUND
     rnDump rn_imp_decls rn_local_decls         `thenRn_` 
-    checkErrsRn                                        `thenRn` \ no_errs_so_far ->
-    if not no_errs_so_far then
-       -- Found errors already, so exit now
-       returnRn Nothing
-    else
 
        -- GENERATE THE VERSION/USAGE INFO
     mkImportInfo mod_name imports                      `thenRn` \ my_usages ->
@@ -297,17 +334,17 @@ implicitFVs mod_name decls
        -- generate code
     implicit_occs = string_occs ++ foldr ((++) . get) implicit_main decls
 
-       -- Virtually every program has error messages in it somewhere
-    string_occs = [unpackCString_RDR, unpackCStringFoldr_RDR, 
-                  unpackCStringUtf8_RDR, eqString_RDR]
 
-    get (TyClD (TyData _ _ _ _ _ _ (Just deriv_classes) _ _ _))
-       = concat (map get_deriv deriv_classes)
-    get other = []
+    get (TyClD (TyData {tcdDerivs = Just deriv_classes})) = concat (map get_deriv deriv_classes)
+    get other                                            = []
 
     get_deriv cls = case lookupUFM derivingOccurrences cls of
                        Nothing   -> []
                        Just occs -> occs
+
+-- Virtually every program has error messages in it somewhere
+string_occs = [unpackCString_RDR, unpackCStringFoldr_RDR, 
+              unpackCStringUtf8_RDR, eqString_RDR]
 \end{code}
 
 \begin{code}
@@ -358,7 +395,7 @@ fixitiesFromLocalDecls gbl_env decls
     getFixities acc (FixD fix)
       = fix_decl acc fix
 
-    getFixities acc (TyClD (ClassDecl _ _ _ _ sigs _ _ _ ))
+    getFixities acc (TyClD (ClassDecl { tcdSigs = sigs}))
       = foldlRn fix_decl acc [sig | FixSig sig <- sigs]
                -- Get fixities from class decl sigs too.
     getFixities acc other_decl
@@ -416,7 +453,8 @@ rnDeprecs gbl_env Nothing decls
 %************************************************************************
 
 \begin{code}
-checkOldIface :: DynFlags
+checkOldIface :: GhciMode
+              -> DynFlags
              -> HomeIfaceTable -> HomeSymbolTable
              -> PersistentCompilerState
              -> FilePath
@@ -425,7 +463,14 @@ checkOldIface :: DynFlags
              -> IO (PersistentCompilerState, Bool, (RecompileRequired, Maybe ModIface))
                                -- True <=> errors happened
 
-checkOldIface dflags hit hst pcs iface_path source_unchanged maybe_iface
+checkOldIface ghci_mode dflags hit hst pcs iface_path source_unchanged maybe_iface
+
+  -- If the source has changed and we're in interactive mode, avoid reading
+  -- an interface; just return the one we might have been supplied with.
+  | ghci_mode == Interactive && not source_unchanged
+  = return (pcs, False, (outOfDate, maybe_iface))
+
+  | otherwise
   = runRn dflags hit hst pcs (panic "Bogus module") $
     case maybe_iface of
        Just old_iface -> -- Use the one we already have
@@ -486,7 +531,7 @@ loadOldIface parsed_iface
                               mi_boot = False, mi_orphan = pi_orphan iface, 
                               mi_fixities = fix_env, mi_deprecs = deprec_env,
                               mi_decls   = decls,
-                              mi_globals = panic "No mi_globals in old interface"
+                              mi_globals = mkIfaceGlobalRdrEnv avails
                    }
     in
     returnRn mod_iface
@@ -563,8 +608,21 @@ closeIfaceDecls dflags hit hst pcs
        needed = unionManyNameSets (map ruleDeclFVs rule_decls) `unionNameSets`
                 unionManyNameSets (map instDeclFVs inst_decls) `unionNameSets`
                 unionManyNameSets (map tyClDeclFVs tycl_decls)
+       local_names    = foldl add emptyNameSet tycl_decls
+       add names decl = addListToNameSet names (map fst (tyClDeclSysNames decl ++ tyClDeclNames decl))
     in
-    closeDecls decls needed
+       -- Record that we have now got declarations for local_names
+    recordLocalSlurps local_names      `thenRn_`
+
+       -- Do the transitive closure
+    lookupOrigNames implicit_occs      `thenRn` \ implicit_names ->
+    closeDecls decls (needed `plusFV` implicit_names) `thenRn` \closed_decls ->
+    rnDump [] closed_decls `thenRn_`
+    returnRn closed_decls
+  where
+    implicit_occs = string_occs        -- Data type decls with record selectors,
+                               -- which may appear in the decls, need unpackCString
+                               -- and friends. It's easier to just grab them right now.
 \end{code}
 
 %*********************************************************
@@ -668,7 +726,10 @@ reportUnusedNames my_mod_iface unqual imports avail_env
     minimal_imports1 = foldr add_name     minimal_imports0 defined_and_used
     minimal_imports  = foldr add_inst_mod minimal_imports1 inst_mods
     
-    add_name (n,NonLocalDef (UserImport m _ _)) acc = addToFM_C plusAvailEnv acc (moduleName (nameModule n))
+       -- We've carefully preserved the provenance so that we can
+       -- construct minimal imports that import the name by (one of)
+       -- the same route(s) as the programmer originally did.
+    add_name (n,NonLocalDef (UserImport m _ _)) acc = addToFM_C plusAvailEnv acc (moduleName m)
                                                                (unitAvailEnv (mk_avail n))
     add_name (n,other_prov)                    acc = acc
 
@@ -711,22 +772,26 @@ warnDeprecations this_mod export_avails my_deprecs used_names
        pit     = iPIT ifaces
        deprecs = [ (n,txt)
                   | n <- nameSetToList used_names,
+                   not (nameIsLocalOrFrom this_mod n),
                     Just txt <- [lookup_deprec hit pit n] ]
+       -- nameIsLocalOrFrom: don't complain about locally defined names
+       -- For a start, we may be exporting a deprecated thing
+       -- Also we may use a deprecated thing in the defn of another
+       -- deprecated things.  We may even use a deprecated thing in
+       -- the defn of a non-deprecated thing, when changing a module's 
+       -- interface
     in                   
     mapRn_ warnDeprec deprecs
 
   where
-    export_mods = nub [ moduleName (nameModule name) 
+    export_mods = nub [ moduleName mod
                      | avail <- export_avails,
-                       let name = availName avail,
-                       not (nameIsLocalOrFrom this_mod name) ]
+                       let mod = nameModule (availName avail),
+                       mod /= this_mod ]
   
     load_home m = loadInterface (text "Check deprecations for" <+> ppr m) m ImportBySystem
 
     lookup_deprec hit pit n
-       | nameIsLocalOrFrom this_mod n
-       = lookupDeprec my_deprecs n 
-       | otherwise
        = case lookupIface hit pit n of
                Just iface -> lookupDeprec (mi_deprecs iface) n
                Nothing    -> pprPanic "warnDeprecations:" (ppr n)