[project @ 2001-06-27 11:14:07 by simonmar]
[ghc-hetmet.git] / ghc / compiler / compMan / CompManager.lhs
index 001a44d..24a53b8 100644 (file)
@@ -9,7 +9,7 @@ module CompManager (
 
     cmLoadModule, -- :: CmState -> FilePath -> IO (CmState, [String])
 
-    cmUnload,    -- :: CmState -> IO CmState
+    cmUnload,    -- :: CmState -> DynFlags -> IO CmState
 
     cmSetContext, -- :: CmState -> String -> IO CmState
 
@@ -34,7 +34,6 @@ where
 
 import CmLink
 import CmTypes
-import CmStaticInfo    ( GhciMode(..) )
 import DriverPipeline
 import DriverFlags     ( getDynFlags )
 import DriverPhases
@@ -55,8 +54,8 @@ import UniqFM
 import Unique          ( Uniquable )
 import Digraph         ( SCC(..), stronglyConnComp, flattenSCC )
 import ErrUtils                ( showPass )
+import SysTools                ( cleanTempFilesExcept )
 import Util
-import TmpFiles
 import Outputable
 import Panic
 import CmdLineOpts     ( DynFlags(..) )
@@ -326,15 +325,17 @@ cmInfo cmstate str
 -- Unload the compilation manager's state: everything it knows about the
 -- current collection of modules in the Home package.
 
-cmUnload :: CmState -> IO CmState
-cmUnload state 
+cmUnload :: CmState -> DynFlags -> IO CmState
+cmUnload state@CmState{ gmode=mode, pls=pls, pcs=pcs } dflags
  = do -- Throw away the old home dir cache
       emptyHomeDirCache
-      -- Throw away the HIT and the HST
-      return state{ hst=new_hst, hit=new_hit, ui=emptyUI }
-   where
-     CmState{ hst=hst, hit=hit } = state
-     (new_hst, new_hit) = retainInTopLevelEnvs [] (hst,hit)
+
+      -- Unload everything the linker knows about
+      new_pls <- CmLink.unload mode dflags [] pls 
+
+      -- Start with a fresh CmState, but keep the PersistentCompilerState
+      new_state <- cmInit mode
+      return new_state{ pcs=pcs, pls=new_pls }
 
 -----------------------------------------------------------------------------
 -- The real business of the compilation manager: given a system state and
@@ -342,12 +343,12 @@ cmUnload state
 -- the system state at the same time.
 
 cmLoadModule :: CmState 
-             -> FilePath
+             -> [FilePath]
              -> IO (CmState,           -- new state
                    Bool,               -- was successful
                    [String])           -- list of modules loaded
 
-cmLoadModule cmstate1 rootname
+cmLoadModule cmstate1 rootnames
    = do -- version 1's are the original, before downsweep
         let pls1      = pls    cmstate1
         let pcs1      = pcs    cmstate1
@@ -367,9 +368,11 @@ cmLoadModule cmstate1 rootname
 
        showPass dflags "Chasing dependencies"
         when (verb >= 1 && ghci_mode == Batch) $
-           hPutStrLn stderr (progName ++ ": chasing modules from: " ++ rootname)
+           hPutStrLn stderr (showSDoc (hcat [
+            text progName, text ": chasing modules from: ",
+            hcat (punctuate comma (map text rootnames))]))
 
-        (mg2unsorted, a_root_is_Main) <- downsweep [rootname] mg1
+        (mg2unsorted, a_root_is_Main) <- downsweep rootnames mg1
         let mg2unsorted_names = map name_of_summary mg2unsorted
 
         -- reachable_from follows source as well as normal imports
@@ -388,6 +391,9 @@ cmLoadModule cmstate1 rootname
        -- See getValidLinkables below for details.
        valid_linkables <- getValidLinkables ui1 mg2unsorted_names 
                                mg2_with_srcimps
+       -- when (verb >= 2) $
+        --    putStrLn (showSDoc (text "Valid linkables:" 
+        --                      <+> ppr valid_linkables))
 
         -- Figure out a stable set of modules which can be retained
         -- the top level envs, to avoid upsweeping them.  Goes to a
@@ -489,13 +495,14 @@ cmLoadModule cmstate1 rootname
               let mods_to_zap_names 
                      = findPartiallyCompletedCycles modsDone_names 
                          mg2_with_srcimps
-              let (hst4, hit4, ui4)
-                     = removeFromTopLevelEnvs mods_to_zap_names (hst3,hit3,ui3)
-
               let mods_to_keep
                      = filter ((`notElem` mods_to_zap_names).name_of_summary) 
                          modsDone
 
+              let (hst4, hit4, ui4)
+                     = retainInTopLevelEnvs (map name_of_summary mods_to_keep) 
+                                            (hst3,hit3,ui3)
+
              -- clean up after ourselves
              cleanTempFilesExcept verb (ppFilesFromSummaries mods_to_keep)
 
@@ -569,7 +576,10 @@ getValidLinkablesSCC old_linkables all_home_mods new_linkables scc0
          scc             = flattenSCC scc0
           scc_names       = map name_of_summary scc
          home_module m   = m `elem` all_home_mods && m `notElem` scc_names
-          scc_allhomeimps = nub (filter home_module (concatMap ms_allimps scc))
+          scc_allhomeimps = nub (filter home_module (concatMap ms_imps scc))
+               -- NOTE: ms_imps, not ms_allimps above.  We don't want to
+               -- force a module's SOURCE imports to be already compiled for
+               -- its object linkable to be valid.
 
          has_object m = case findModuleLinkable_maybe new_linkables m of
                            Nothing -> False
@@ -610,8 +620,7 @@ getValidLinkable old_linkables objects_allowed new_linkables summary
                    Just l | not (isObjectLinkable l) || stillThere l 
                                -> old_linkable
                                -- ToDo: emit a warning if not (stillThere l)
-                          | otherwise
-                               -> Nothing
+                    other -> Nothing
 
           -- make sure that if we had an old disk linkable around, that it's
           -- still there on the disk (in case we need to re-link it).
@@ -636,7 +645,6 @@ getValidLinkable old_linkables objects_allowed new_linkables summary
        return (valid_linkable ++ new_linkables)
 
 
-
 maybe_getFileLinkable :: ModuleName -> FilePath -> IO (Maybe Linkable)
 maybe_getFileLinkable mod_name obj_fn
    = do obj_exist <- doesFileExist obj_fn
@@ -820,10 +828,10 @@ upsweep_mod ghci_mode dflags oldUI threaded1 summary1 reachable_inc_me
           -- in interactive mode, all home modules below us *must* have an
           -- interface in the HIT.  We never demand-load home interfaces in
           -- interactive mode.
-            (hst1_strictDC, hit1_strictDC)
+            (hst1_strictDC, hit1_strictDC, [])
                = ASSERT(ghci_mode == Batch || 
                        all (`elemUFM` hit1) reachable_only)
-                retainInTopLevelEnvs reachable_only (hst1,hit1)
+                retainInTopLevelEnvs reachable_only (hst1,hit1,[])
 
             old_linkable 
                = unJust "upsweep_mod:old_linkable" maybe_old_linkable
@@ -855,22 +863,14 @@ upsweep_mod ghci_mode dflags oldUI threaded1 summary1 reachable_inc_me
              -> do let threaded2 = CmThreaded pcs2 hst1 hit1
                     return (threaded2, Nothing)
 
--- Remove unwanted modules from the top level envs (HST, HIT, UI).
-removeFromTopLevelEnvs :: [ModuleName]
-                       -> (HomeSymbolTable, HomeIfaceTable, UnlinkedImage)
-                       -> (HomeSymbolTable, HomeIfaceTable, UnlinkedImage)
-removeFromTopLevelEnvs zap_these (hst, hit, ui)
-   = (delListFromUFM hst zap_these,
-      delListFromUFM hit zap_these,
-      filterModuleLinkables (`notElem` zap_these) ui
-     )
-
+-- Filter modules in the top level envs (HST, HIT, UI).
 retainInTopLevelEnvs :: [ModuleName]
-                        -> (HomeSymbolTable, HomeIfaceTable)
-                        -> (HomeSymbolTable, HomeIfaceTable)
-retainInTopLevelEnvs keep_these (hst, hit)
+                        -> (HomeSymbolTable, HomeIfaceTable, UnlinkedImage)
+                        -> (HomeSymbolTable, HomeIfaceTable, UnlinkedImage)
+retainInTopLevelEnvs keep_these (hst, hit, ui)
    = (retainInUFM hst keep_these,
-      retainInUFM hit keep_these
+      retainInUFM hit keep_these,
+      filterModuleLinkables (`elem` keep_these) ui
      )
      where
         retainInUFM :: Uniquable key => UniqFM elt -> [key] -> UniqFM elt
@@ -890,10 +890,9 @@ downwards_closure_of_module summaries root
 
          res = simple_transitive_closure (map toEdge summaries) [root]
      in
-         --trace (showSDoc (text "DC of mod" <+> ppr root
-         --                 <+> text "=" <+> ppr res)) (
+--         trace (showSDoc (text "DC of mod" <+> ppr root
+--                          <+> text "=" <+> ppr res)) $
          res
-         --)
 
 -- Calculate transitive closures from a set of roots given an adjacency list
 simple_transitive_closure :: Eq a => [(a,[a])] -> [a] -> [a]
@@ -952,7 +951,7 @@ downsweep rootNm old_summaries
      where
        getRootSummary :: FilePath -> IO ModSummary
        getRootSummary file
-          | haskellish_file file
+          | haskellish_src_file file
           = do exists <- doesFileExist file
                if exists then summariseFile file else do
                throwDyn (CmdLineError ("can't find file `" ++ file ++ "'"))    
@@ -1016,14 +1015,13 @@ downsweep rootNm old_summaries
 summariseFile :: FilePath -> IO ModSummary
 summariseFile file
    = do hspp_fn <- preprocess file
-        modsrc <- readFile hspp_fn
+        (srcimps,imps,mod_name) <- getImportsFromFile hspp_fn
 
-        let (srcimps,imps,mod_name) = getImports modsrc
-           (path, basename, ext) = splitFilename3 file
+        let (path, basename, ext) = splitFilename3 file
 
        Just (mod, location)
-          <- mkHomeModuleLocn mod_name (path ++ '/':basename) file
-          
+          <- mkHomeModuleLocn mod_name (path ++ '/':basename) (Just file)
+
         src_timestamp
            <- case ml_hs_file location of 
                  Nothing     -> noHsFileErr mod_name
@@ -1037,13 +1035,22 @@ summariseFile file
 summarise :: Module -> ModuleLocation -> Maybe ModSummary
         -> IO (Maybe ModSummary)
 summarise mod location old_summary
-   | isHomeModule mod
+   | not (isHomeModule mod) = return Nothing
+   | otherwise
    = do let hs_fn = unJust "summarise" (ml_hs_file location)
 
-        src_timestamp
-           <- case ml_hs_file location of 
-                 Nothing     -> noHsFileErr mod
-                 Just src_fn -> getModificationTime src_fn
+        case ml_hs_file location of {
+           Nothing -> do {
+               dflags <- getDynFlags;
+               when (verbosity dflags >= 1) $
+                   hPutStrLn stderr ("WARNING: module `" ++ 
+                       moduleUserString mod ++ "' has no source file.");
+               return Nothing;
+            };
+
+           Just src_fn -> do
+
+        src_timestamp <- getModificationTime src_fn
 
        -- return the cached summary if the source didn't change
        case old_summary of {
@@ -1051,23 +1058,22 @@ summarise mod location old_summary
           _ -> do
 
         hspp_fn <- preprocess hs_fn
-        modsrc <- readFile hspp_fn
-        let (srcimps,imps,mod_name) = getImports modsrc
+        (srcimps,imps,mod_name) <- getImportsFromFile hspp_fn
 
        when (mod_name /= moduleName mod) $
                throwDyn (ProgramError 
-                  (showSDoc (text modsrc
+                  (showSDoc (text hs_fn
                              <>  text ": file name does not match module name"
                              <+> quotes (ppr (moduleName mod)))))
 
         return (Just (ModSummary mod location{ml_hspp_file=Just hspp_fn} 
                                  srcimps imps src_timestamp))
         }
+      }
 
-   | otherwise = return Nothing
 
 noHsFileErr mod
-  = panic (showSDoc (text "no source file for module" <+> quotes (ppr mod)))
+  = throwDyn (CmdLineError (showSDoc (text "no source file for module" <+> quotes (ppr mod))))
 
 packageModErr mod
   = throwDyn (CmdLineError (showSDoc (text "module" <+>