[project @ 2001-10-16 14:08:26 by simonmar]
[ghc-hetmet.git] / ghc / compiler / compMan / CompManager.lhs
index 56d8325..1ddddfd 100644 (file)
@@ -16,10 +16,12 @@ module CompManager (
     cmGetContext, -- :: CmState -> IO String
 
 #ifdef GHCI
-    cmRunStmt,   --  :: CmState -> DynFlags -> String -> IO (CmState, [Name])
+    cmInfoThing,  -- :: CmState -> DynFlags -> String -> IO (Maybe TyThing)
 
-    cmTypeOfExpr, --  :: CmState -> DynFlags -> String
-                 --  -> IO (CmState, Maybe String)
+    cmRunStmt,   -- :: CmState -> DynFlags -> String -> IO (CmState, [Name])
+
+    cmTypeOfExpr, -- :: CmState -> DynFlags -> String
+                 -- -> IO (CmState, Maybe String)
 
     cmTypeOfName, -- :: CmState -> Name -> IO (Maybe String)
 
@@ -34,17 +36,21 @@ where
 
 import CmLink
 import CmTypes
-import CmStaticInfo    ( GhciMode(..) )
 import DriverPipeline
 import DriverFlags     ( getDynFlags )
 import DriverPhases
 import DriverUtil
 import Finder
+#ifdef GHCI
+import HscMain         ( initPersistentCompilerState, hscThing )
+#else
 import HscMain         ( initPersistentCompilerState )
+#endif
 import HscTypes
 import RnEnv           ( unQualInScope )
 import Id              ( idType, idName )
-import Name            ( Name, NamedThing(..), nameRdrName )
+import Name            ( Name, NamedThing(..), nameRdrName, nameModule,
+                         isHomePackageName )
 import NameEnv
 import RdrName         ( lookupRdrEnv, emptyRdrEnv )
 import Module
@@ -53,13 +59,15 @@ import Type         ( tidyType )
 import VarEnv          ( emptyTidyEnv )
 import UniqFM
 import Unique          ( Uniquable )
-import Digraph         ( SCC(..), stronglyConnComp, flattenSCC )
+import Digraph         ( SCC(..), stronglyConnComp, flattenSCC, flattenSCCs )
 import ErrUtils                ( showPass )
+import SysTools                ( cleanTempFilesExcept )
 import Util
-import TmpFiles
 import Outputable
+import BasicTypes      ( Fixity, defaultFixity )
 import Panic
 import CmdLineOpts     ( DynFlags(..) )
+
 import IOExts
 
 #ifdef GHCI
@@ -142,7 +150,7 @@ cmInit mode = do
 cmSetContext :: CmState -> String -> IO CmState
 cmSetContext cmstate str
    = do let mn = mkModuleName str
-           modules_loaded = [ (name_of_summary s, ms_mod s)  | s <- mg cmstate ]
+           modules_loaded = [ (name_of_summary s, ms_mod s) | s <- mg cmstate ]
 
         m <- case lookup mn modules_loaded of
                Just m  -> return m
@@ -168,6 +176,34 @@ moduleNameToModule mn
        Just (m,_) -> return m
 
 -----------------------------------------------------------------------------
+-- cmInfoThing: convert a String to a TyThing
+
+-- A string may refer to more than one TyThing (eg. a constructor,
+-- and type constructor), so we return a list of all the possible TyThings.
+
+#ifdef GHCI
+cmInfoThing :: CmState -> DynFlags -> String 
+       -> IO (CmState, PrintUnqualified, [(TyThing,Fixity)])
+cmInfoThing cmstate dflags id
+   = do (new_pcs, things) <- hscThing dflags hst hit pcs icontext id
+       let pairs = map (\x -> (x, getFixity new_pcs (getName x))) things
+       return (cmstate{ pcs=new_pcs }, unqual, pairs)
+   where 
+     CmState{ hst=hst, hit=hit, pcs=pcs, pls=pls, ic=icontext } = cmstate
+     unqual = getUnqual pcs hit icontext
+
+     getFixity :: PersistentCompilerState -> Name -> Fixity
+     getFixity pcs name
+       | Just iface  <- lookupModuleEnv iface_table (nameModule name),
+         Just fixity <- lookupNameEnv (mi_fixities iface) name
+         = fixity
+       | otherwise
+         = defaultFixity
+       where iface_table | isHomePackageName name = hit
+                         | otherwise              = pcs_PIT pcs
+#endif
+
+-----------------------------------------------------------------------------
 -- cmRunStmt:  Run a statement/expr.
 
 #ifdef GHCI
@@ -238,19 +274,23 @@ cmTypeOfExpr cmstate dflags expr
 
        case maybe_stuff of
           Nothing -> return (new_cmstate, Nothing)
-          Just (_, ty, _) ->
-            let pit = pcs_PIT pcs
-                modname = moduleName (ic_module ic)
-                tidy_ty = tidyType emptyTidyEnv ty
-                str = case lookupIfaceByModName hit pit modname of
-                         Nothing    -> showSDoc (ppr tidy_ty)
-                         Just iface -> showSDocForUser unqual (ppr tidy_ty)
-                            where unqual = unQualInScope (mi_globals iface)
-            in return (new_cmstate, Just str)
+          Just (_, ty, _) -> return (new_cmstate, Just str)
+            where 
+               str = showSDocForUser unqual (ppr tidy_ty)
+               unqual  = getUnqual pcs hit ic
+               tidy_ty = tidyType emptyTidyEnv ty
    where
        CmState{ hst=hst, hit=hit, pcs=pcs, ic=ic } = cmstate
 #endif
 
+getUnqual pcs hit ic
+   = case lookupIfaceByModName hit pit modname of
+       Nothing    -> alwaysQualify
+       Just iface -> unQualInScope (mi_globals iface)
+ where
+    pit = pcs_PIT pcs
+    modname = moduleName (ic_module ic)
+
 -----------------------------------------------------------------------------
 -- cmTypeOfName: returns a string representing the type of a name.
 
@@ -259,15 +299,11 @@ cmTypeOfName :: CmState -> Name -> IO (Maybe String)
 cmTypeOfName CmState{ hit=hit, pcs=pcs, ic=ic } name
  = case lookupNameEnv (ic_type_env ic) name of
        Nothing -> return Nothing
-       Just (AnId id) -> 
-          let pit = pcs_PIT pcs
-              modname = moduleName (ic_module ic)
-              ty = tidyType emptyTidyEnv (idType id)
-              str = case lookupIfaceByModName hit pit modname of
-                       Nothing    -> showSDoc (ppr ty)
-                       Just iface -> showSDocForUser unqual (ppr ty)
-                          where unqual = unQualInScope (mi_globals iface)
-          in return (Just str)
+       Just (AnId id) -> return (Just str)
+          where
+            unqual = getUnqual pcs hit ic
+            ty = tidyType emptyTidyEnv (idType id)
+            str = showSDocForUser unqual (ppr ty)
 
        _ -> panic "cmTypeOfName"
 #endif
@@ -344,12 +380,12 @@ cmUnload state@CmState{ gmode=mode, pls=pls, pcs=pcs } dflags
 -- 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
@@ -369,9 +405,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
@@ -420,7 +458,7 @@ cmLoadModule cmstate1 rootname
 
        -- unload any modules which aren't going to be re-linked this
        -- time around.
-       pls2 <- unload ghci_mode dflags stable_linkables pls1
+       pls2 <- CmLink.unload ghci_mode dflags stable_linkables pls1
 
         -- We could at this point detect cycles which aren't broken by
         -- a source-import, and complain immediately, but it seems better
@@ -444,9 +482,13 @@ cmLoadModule cmstate1 rootname
 
         let threaded2 = CmThreaded pcs1 hst1 hit1
 
+       -- clean up between compilations
+       let cleanup = cleanTempFilesExcept verb 
+                         (ppFilesFromSummaries (flattenSCCs upsweep_these))
+
         (upsweep_complete_success, threaded3, modsUpswept, newLis)
            <- upsweep_mods ghci_mode dflags valid_linkables reachable_from 
-                           threaded2 upsweep_these
+                           threaded2 cleanup upsweep_these
 
         let ui3 = add_to_ui valid_linkables newLis
         let (CmThreaded pcs3 hst3 hit3) = threaded3
@@ -513,33 +555,43 @@ cmLoadModule cmstate1 rootname
 
 
 -- Finish up after a cmLoad.
---
+
+-- If the link failed, unload everything and return.
+cmLoadFinish ok (LinkFailed pls) hst hit ui mods ghci_mode pcs = do
+  dflags <- getDynFlags
+  new_pls <- CmLink.unload ghci_mode dflags [] pls 
+  new_state <- cmInit ghci_mode
+  return (new_state{ pcs=pcs, pls=new_pls }, False, [])
+
 -- Empty the interactive context and set the module context to the topmost
 -- newly loaded module, or the Prelude if none were loaded.
-cmLoadFinish ok linkresult hst hit ui mods ghci_mode pcs
-  = do case linkresult of {
-          LinkErrs _ _ -> panic "cmLoadModule: link failed (2)";
-          LinkOK pls   -> do
-
-       def_mod <- readIORef defaultCurrentModule
+cmLoadFinish ok (LinkOK pls) hst hit ui mods ghci_mode pcs
+  = do def_mod <- readIORef defaultCurrentModule
        let current_mod = case mods of 
                                []    -> def_mod
                                (x:_) -> ms_mod x
 
                   new_ic = emptyInteractiveContext current_mod
 
-           new_cmstate = CmState{ hst=hst, hit=hit, 
-                                  ui=ui, mg=mods,
-                                  gmode=ghci_mode, pcs=pcs, 
-                                 pls=pls,
+           new_cmstate = CmState{ hst=hst, hit=hit, ui=ui, mg=mods,
+                                  gmode=ghci_mode, pcs=pcs, pls=pls,
                                  ic = new_ic }
            mods_loaded = map (moduleNameUserString.name_of_summary) mods
 
        return (new_cmstate, ok, mods_loaded)
-    }
 
+-- used to fish out the preprocess output files for the purposes
+-- of cleaning up.
 ppFilesFromSummaries summaries
-  = [ fn | Just fn <- map (ml_hspp_file . ms_location) summaries ]
+  = [ fn | Just fn <- map toPpFile summaries ]
+  where
+   toPpFile sum
+     | hspp /= ml_hs_file loc = hspp
+     | otherwise              = Nothing
+    where
+      loc  = ms_location sum
+      hspp = ml_hspp_file loc
+
 
 -----------------------------------------------------------------------------
 -- getValidLinkables
@@ -639,7 +691,13 @@ getValidLinkable old_linkables objects_allowed new_linkables summary
            src_date = ms_hs_date summary
 
           valid_linkable
-             =  filter (\l -> linkableTime l > src_date) linkable
+             =  filter (\l -> linkableTime l >= src_date) linkable
+               -- why '>=' rather than '>' above?  If the filesystem stores
+               -- times to the nearset second, we may occasionally find that
+               -- the object & source have the same modification time, 
+               -- especially if the source was automatically generated
+               -- and compiled.  Using >= is slightly unsafe, but it matches
+               -- make's behaviour.
 
        return (valid_linkable ++ new_linkables)
 
@@ -762,6 +820,7 @@ upsweep_mods :: GhciMode
              -> UnlinkedImage         -- valid linkables
              -> (ModuleName -> [ModuleName])  -- to construct downward closures
              -> CmThreaded            -- PCS & HST & HIT
+            -> IO ()                 -- how to clean up unwanted tmp files
              -> [SCC ModSummary]      -- mods to do (the worklist)
                                       -- ...... RETURNING ......
              -> IO (Bool{-complete success?-},
@@ -769,17 +828,17 @@ upsweep_mods :: GhciMode
                     [ModSummary],     -- mods which succeeded
                     [Linkable])       -- new linkables
 
-upsweep_mods ghci_mode dflags oldUI reachable_from threaded 
+upsweep_mods ghci_mode dflags oldUI reachable_from threaded cleanup
      []
    = return (True, threaded, [], [])
 
-upsweep_mods ghci_mode dflags oldUI reachable_from threaded 
+upsweep_mods ghci_mode dflags oldUI reachable_from threaded cleanup
      ((CyclicSCC ms):_)
    = do hPutStrLn stderr ("Module imports form a cycle for modules:\n\t" ++
                           unwords (map (moduleNameUserString.name_of_summary) ms))
         return (False, threaded, [], [])
 
-upsweep_mods ghci_mode dflags oldUI reachable_from threaded 
+upsweep_mods ghci_mode dflags oldUI reachable_from threaded cleanup
      ((AcyclicSCC mod):mods)
    = do --case threaded of
         --   CmThreaded pcsz hstz hitz
@@ -788,12 +847,16 @@ upsweep_mods ghci_mode dflags oldUI reachable_from threaded
         (threaded1, maybe_linkable) 
            <- upsweep_mod ghci_mode dflags oldUI threaded mod 
                           (reachable_from (name_of_summary mod))
+
+       -- remove unwanted tmp files between compilations
+       cleanup
+
         case maybe_linkable of
            Just linkable 
               -> -- No errors; do the rest
                  do (restOK, threaded2, modOKs, linkables) 
                        <- upsweep_mods ghci_mode dflags oldUI reachable_from 
-                                       threaded1 mods
+                                       threaded1 cleanup mods
                     return (restOK, threaded2, mod:modOKs, linkable:linkables)
            Nothing -- we got a compilation error; give up now
               -> return (False, threaded1, [], [])
@@ -889,10 +952,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]
@@ -1019,8 +1081,8 @@ summariseFile file
 
         let (path, basename, ext) = splitFilename3 file
 
-       Just (mod, location)
-          <- mkHomeModuleLocn mod_name (path ++ '/':basename) (Just file)
+       (mod, location)
+          <- mkHomeModuleLocn mod_name (path ++ '/':basename) file
 
         src_timestamp
            <- case ml_hs_file location of 
@@ -1040,14 +1102,7 @@ summarise mod location old_summary
    = do let hs_fn = unJust "summarise" (ml_hs_file location)
 
         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;
-            };
-
+           Nothing -> noHsFileErr mod;
            Just src_fn -> do
 
         src_timestamp <- getModificationTime src_fn