[project @ 2000-11-21 15:00:57 by simonmar]
[ghc-hetmet.git] / ghc / compiler / compMan / CompManager.lhs
index ba72c97..16b139d 100644 (file)
@@ -5,7 +5,9 @@
 
 \begin{code}
 module CompManager ( cmInit, cmLoadModule,
-                     cmGetExpr, cmRunExpr,
+#ifdef GHCI
+                     cmGetExpr, cmTypeExpr, cmRunExpr,
+#endif
                      CmState, emptyCmState  -- abstract
                    )
 where
@@ -15,32 +17,40 @@ where
 import CmLink
 import CmTypes
 import HscTypes
-import HscMain         ( hscExpr )
-import Interpreter     ( HValue )
 import Module          ( ModuleName, moduleName,
-                         isModuleInThisPackage, moduleEnvElts,
+                         isHomeModule, moduleEnvElts,
                          moduleNameUserString )
 import CmStaticInfo    ( PackageConfigInfo, GhciMode(..) )
 import DriverPipeline
 import GetImports
 import HscTypes                ( HomeSymbolTable, HomeIfaceTable, 
                          PersistentCompilerState, ModDetails(..) )
+import Type            ( Type )
 import Name            ( lookupNameEnv )
-import RdrName
 import Module
 import PrelNames       ( mainName )
 import HscMain         ( initPersistentCompilerState )
-import Finder          ( findModule, emptyHomeDirCache )
+import Finder
 import UniqFM          ( emptyUFM, lookupUFM, addToUFM, delListFromUFM,
                          UniqFM, listToUFM )
 import Unique          ( Uniquable )
 import Digraph         ( SCC(..), stronglyConnComp )
+import DriverFlags     ( getDynFlags )
+import DriverPhases
 import DriverUtil      ( BarfKind(..), splitFilename3 )
-import CmdLineOpts     ( DynFlags )
+import ErrUtils                ( showPass )
 import Util
 import Outputable
 import Panic           ( panic )
 
+#ifdef GHCI
+import CmdLineOpts     ( DynFlags(..) )
+import Interpreter     ( HValue )
+import HscMain         ( hscExpr, hscTypeExpr )
+import RdrName
+import PrelGHC         ( unsafeCoerce# )
+#endif
+
 -- lang
 import Exception       ( throwDyn )
 
@@ -48,10 +58,9 @@ import Exception     ( throwDyn )
 import Time             ( ClockTime )
 import Directory        ( getModificationTime, doesFileExist )
 import IO
+import Monad
 import List            ( nub )
 import Maybe           ( catMaybes, fromMaybe, isJust )
-
-import PrelGHC         ( unsafeCoerce# )
 \end{code}
 
 
@@ -60,6 +69,7 @@ cmInit :: PackageConfigInfo -> GhciMode -> IO CmState
 cmInit raw_package_info gmode
    = emptyCmState raw_package_info gmode
 
+#ifdef GHCI
 cmGetExpr :: CmState
          -> DynFlags
           -> ModuleName
@@ -67,7 +77,7 @@ cmGetExpr :: CmState
           -> IO (CmState, Maybe HValue)
 cmGetExpr cmstate dflags modname expr
    = do (new_pcs, maybe_unlinked_iexpr) <- 
-          hscExpr dflags hst hit pcs (mkModuleInThisPackage modname) expr
+          hscExpr dflags hst hit pcs (mkHomeModule modname) expr
         case maybe_unlinked_iexpr of
           Nothing     -> return (cmstate{ pcs=new_pcs }, Nothing)
           Just uiexpr -> do
@@ -79,11 +89,25 @@ cmGetExpr cmstate dflags modname expr
        CmState{ pcs=pcs, pcms=pcms, pls=pls } = cmstate
        PersistentCMState{ hst=hst, hit=hit } = pcms
 
+cmTypeExpr :: CmState
+         -> DynFlags
+          -> ModuleName
+          -> String
+          -> IO (CmState, Maybe Type)
+cmTypeExpr cmstate dflags modname expr
+   = do (new_pcs, expr_type) <- 
+          hscTypeExpr dflags hst hit pcs (mkHomeModule modname) expr
+        return (cmstate{ pcs=new_pcs }, expr_type)
+   where
+       CmState{ pcs=pcs, pcms=pcms, pls=pls } = cmstate
+       PersistentCMState{ hst=hst, hit=hit } = pcms
+
 -- The HValue should represent a value of type IO () (Perhaps IO a?)
 cmRunExpr :: HValue -> IO ()
 cmRunExpr hval
    = do unsafeCoerce# hval :: IO ()
        -- putStrLn "done."
+#endif
 
 -- Persistent state just for CM, excluding link & compile subsystems
 data PersistentCMState
@@ -143,8 +167,10 @@ the system state at the same time.
 
 \begin{code}
 cmLoadModule :: CmState 
-             -> ModuleName
-             -> IO (CmState, Maybe ModuleName)
+             -> FilePath
+             -> IO (CmState,           -- new state
+                   Bool,               -- was successful
+                   [ModuleName])       -- list of modules loaded
 
 cmLoadModule cmstate1 rootname
    = do -- version 1's are the original, before downsweep
@@ -159,12 +185,6 @@ cmLoadModule cmstate1 rootname
         let pcii      = pci   pcms1 -- this never changes
         let ghci_mode = gmode pcms1 -- ToDo: fix!
 
-        -- During upsweep, look at new summaries to see if source has
-        -- changed.  Here's a function to pass down; it takes a new
-        -- summary.
-        let source_changed :: ModSummary -> Bool
-            source_changed = summary_indicates_source_changed mg1
-
         -- Do the downsweep to reestablish the module graph
         -- then generate version 2's by removing from HIT,HST,UI any
         -- modules in the old MG which are not in the new one.
@@ -172,7 +192,11 @@ cmLoadModule cmstate1 rootname
         -- Throw away the old home dir cache
         emptyHomeDirCache
 
-        hPutStr stderr "cmLoadModule: downsweep begins\n"
+       dflags <- getDynFlags
+        let verb = verbosity dflags
+
+       showPass dflags "Chasing dependencies"
+
         mg2unsorted <- downsweep [rootname]
 
         let modnames1   = map name_of_summary mg1
@@ -192,8 +216,8 @@ cmLoadModule cmstate1 rootname
         let reachable_from :: ModuleName -> [ModuleName]
             reachable_from = downwards_closure_of_module mg2unsorted
 
-        hPutStrLn stderr "after tsort:\n"
-        hPutStrLn stderr (showSDoc (vcat (map ppr mg2)))
+        --hPutStrLn stderr "after tsort:\n"
+        --hPutStrLn stderr (showSDoc (vcat (map ppr mg2)))
 
         -- Because we don't take into account source imports when doing
         -- the topological sort, there shouldn't be any cycles in mg2.
@@ -206,7 +230,7 @@ cmLoadModule cmstate1 rootname
         let threaded2 = CmThreaded pcs1 hst2 hit2
 
         (upsweep_complete_success, threaded3, modsDone, newLis)
-           <- upsweep_mods ghci_mode ui2 reachable_from source_changed threaded2 mg2
+           <- upsweep_mods ghci_mode ui2 reachable_from threaded2 mg2
 
         let ui3 = add_to_ui ui2 newLis
         let (CmThreaded pcs3 hst3 hit3) = threaded3
@@ -222,10 +246,12 @@ cmLoadModule cmstate1 rootname
 
          then 
            -- Easy; just relink it all.
-           do hPutStrLn stderr "UPSWEEP COMPLETELY SUCCESSFUL"
+           do when (verb >= 2) $ 
+               hPutStrLn stderr "Upsweep completely successful."
               linkresult 
-                 <- link ghci_mode (any exports_main (moduleEnvElts hst3)) 
-                         newLis pls1
+                 <- link ghci_mode dflags 
+                       (any exports_main (moduleEnvElts hst3)) 
+                        newLis pls1
               case linkresult of
                  LinkErrs _ _
                     -> panic "cmLoadModule: link failed (1)"
@@ -235,13 +261,14 @@ cmLoadModule cmstate1 rootname
                                                           pci=pcii, gmode=ghci_mode }
                           let cmstate3 
                                  = CmState { pcms=pcms3, pcs=pcs3, pls=pls3 }
-                          return (cmstate3, Just rootname)
+                          return (cmstate3, True, map name_of_summary modsDone)
 
          else 
            -- Tricky.  We need to back out the effects of compiling any
            -- half-done cycles, both so as to clean up the top level envs
            -- and to avoid telling the interactive linker to link them.
-           do hPutStrLn stderr "UPSWEEP PARTIALLY SUCCESSFUL"
+           do when (verb >= 2) $
+               hPutStrLn stderr "Upsweep partially successful."
 
               let modsDone_names
                      = map name_of_summary modsDone
@@ -256,9 +283,10 @@ cmLoadModule cmstate1 rootname
               -- we could get the relevant linkables by filtering newLis, but
               -- it seems easier to drag them out of the updated, cleaned-up UI
               let linkables_to_link 
-                     = map (findModuleLinkable ui4) mods_to_keep_names
+                     = map (unJust "linkables_to_link" . findModuleLinkable_maybe ui4)
+                           mods_to_keep_names
 
-              linkresult <- link ghci_mode False linkables_to_link pls1
+              linkresult <- link ghci_mode dflags False linkables_to_link pls1
               case linkresult of
                  LinkErrs _ _
                     -> panic "cmLoadModule: link failed (2)"
@@ -268,40 +296,8 @@ cmLoadModule cmstate1 rootname
                                                           pci=pcii, gmode=ghci_mode }
                           let cmstate4 
                                  = CmState { pcms=pcms4, pcs=pcs3, pls=pls4 }
-                          return (cmstate4, 
-                                  -- choose rather arbitrarily who to return
-                                  if null mods_to_keep then Nothing 
-                                     else Just (last mods_to_keep_names))
-
-
--- Given a bunch of old summaries and a new summary, try and
--- find the corresponding old summary, and, if found, compare
--- its source timestamp with that of the new summary.  If in
--- doubt say True.
-summary_indicates_source_changed :: [ModSummary] -> ModSummary -> Bool
-summary_indicates_source_changed old_summaries new_summary
-   = case [old | old <- old_summaries, 
-                 name_of_summary old == name_of_summary new_summary] of
-
-        (_:_:_) -> panic "summary_indicates_newer_source"
-                   
-        []      -> -- can't find a corresponding old summary, so
-                   -- compare source and iface dates in the new summary.
-                   trace (showSDoc (text "SISC: no old summary, new =" 
-                                    <+> pprSummaryTimes new_summary)) (
-                   case (ms_hs_date new_summary, ms_hi_date new_summary) of
-                      (Just hs_t, Just hi_t) -> hs_t > hi_t
-                      other                  -> True
-                   )
+                          return (cmstate4, False, mods_to_keep_names)
 
-        [old]   -> -- found old summary; compare source timestamps
-                   trace (showSDoc (text "SISC: old =" 
-                                    <+> pprSummaryTimes old
-                                    <+> pprSummaryTimes new_summary)) (
-                   case (ms_hs_date old, ms_hs_date new_summary) of
-                      (Just old_t, Just new_t) -> new_t > old_t
-                      other                    -> True
-                   )
 
 -- Return (names of) all those in modsDone who are part of a cycle
 -- as defined by theGraph.
@@ -356,7 +352,6 @@ data CmThreaded  -- stuff threaded through individual module compilations
 upsweep_mods :: GhciMode
              -> UnlinkedImage         -- old linkables
              -> (ModuleName -> [ModuleName])  -- to construct downward closures
-             -> (ModSummary -> Bool)  -- has source changed?
              -> CmThreaded            -- PCS & HST & HIT
              -> [SCC ModSummary]      -- mods to do (the worklist)
                                       -- ...... RETURNING ......
@@ -365,24 +360,27 @@ upsweep_mods :: GhciMode
                     [ModSummary],     -- mods which succeeded
                     [Linkable])       -- new linkables
 
-upsweep_mods ghci_mode oldUI reachable_from source_changed threaded []
+upsweep_mods ghci_mode oldUI reachable_from threaded 
+     []
    = return (True, threaded, [], [])
 
-upsweep_mods ghci_mode oldUI reachable_from source_changed threaded ((CyclicSCC ms):_)
-   = do hPutStrLn stderr ("ghc: module imports form a cycle for modules:\n\t" ++
+upsweep_mods ghci_mode oldUI reachable_from threaded 
+     ((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 oldUI reachable_from source_changed threaded ((AcyclicSCC mod):mods)
+upsweep_mods ghci_mode oldUI reachable_from threaded 
+     ((AcyclicSCC mod):mods)
    = do (threaded1, maybe_linkable) 
            <- upsweep_mod ghci_mode oldUI threaded mod 
                           (reachable_from (name_of_summary mod)) 
-                          (source_changed mod)
         case maybe_linkable of
            Just linkable 
               -> -- No errors; do the rest
                  do (restOK, threaded2, modOKs, linkables) 
-                       <- upsweep_mods ghci_mode oldUI reachable_from source_changed threaded1 mods
+                       <- upsweep_mods ghci_mode oldUI reachable_from 
+                                       threaded1 mods
                     return (restOK, threaded2, mod:modOKs, linkable:linkables)
            Nothing -- we got a compilation error; give up now
               -> return (False, threaded1, [], [])
@@ -390,17 +388,32 @@ upsweep_mods ghci_mode oldUI reachable_from source_changed threaded ((AcyclicSCC
 
 -- Compile a single module.  Always produce a Linkable for it if 
 -- successful.  If no compilation happened, return the old Linkable.
+maybe_getFileLinkable :: ModuleName -> FilePath -> IO (Maybe Linkable)
+maybe_getFileLinkable mod_name obj_fn
+   = do obj_exist <- doesFileExist obj_fn
+        if not obj_exist 
+         then return Nothing 
+         else 
+         do let stub_fn = case splitFilename3 obj_fn of
+                             (dir, base, ext) -> dir ++ "/" ++ base ++ ".stub_o"
+            stub_exist <- doesFileExist stub_fn
+            obj_time <- getModificationTime obj_fn
+            if stub_exist
+             then return (Just (LM obj_time mod_name [DotO obj_fn, DotO stub_fn]))
+             else return (Just (LM obj_time mod_name [DotO obj_fn]))
+
+
 upsweep_mod :: GhciMode 
             -> UnlinkedImage
             -> CmThreaded
             -> ModSummary
             -> [ModuleName]
-            -> Bool
             -> IO (CmThreaded, Maybe Linkable)
 
-upsweep_mod ghci_mode oldUI threaded1 summary1 
-            reachable_from_here source_might_have_changed
-   = do let mod_name = name_of_summary summary1
+upsweep_mod ghci_mode oldUI threaded1 summary1 reachable_from_here
+   = do hPutStr stderr ("ghc: module " 
+                        ++ moduleNameUserString (name_of_summary summary1) ++ ": ")
+        let mod_name = name_of_summary summary1
         let (CmThreaded pcs1 hst1 hit1) = threaded1
         let old_iface = lookupUFM hit1 (name_of_summary summary1)
 
@@ -415,41 +428,57 @@ upsweep_mod ghci_mode oldUI threaded1 summary1
                                         b <- doesFileExist obj_fn
                                         return (not b)
 
-        let compilation_might_be_needed 
-               = source_might_have_changed || compilation_mandatory
+        let maybe_oldUI_linkable = findModuleLinkable_maybe oldUI mod_name
+        maybe_oldDisk_linkable
+           <- case ml_obj_file (ms_location summary1) of
+                 Nothing -> return Nothing
+                 Just obj_fn -> maybe_getFileLinkable mod_name obj_fn
+
+        -- The most recent of the old UI linkable or whatever we could
+        -- find on disk.  Is returned as the linkable if compile
+        -- doesn't think we need to recompile.        
+        let maybe_old_linkable
+               = case (maybe_oldUI_linkable, maybe_oldDisk_linkable) of
+                    (Nothing, Nothing) -> Nothing
+                    (Nothing, Just di) -> Just di
+                    (Just ui, Nothing) -> Just ui
+                    (Just ui, Just di)
+                       | linkableTime ui >= linkableTime di -> Just ui
+                       | otherwise                          -> Just di
+
+        let compilation_mandatory
+               = case maybe_old_linkable of
+                    Nothing -> True
+                    Just li -> case ms_hs_date summary1 of
+                                  Nothing -> panic "compilation_mandatory:no src date"
+                                  Just src_date -> src_date >= linkableTime li
             source_unchanged
-               = not compilation_might_be_needed
+               = not compilation_mandatory
+
             (hst1_strictDC, hit1_strictDC)
                = retainInTopLevelEnvs reachable_from_here (hst1,hit1)
 
+            old_linkable 
+               = unJust "upsweep_mod:old_linkable" maybe_old_linkable
+
         compresult <- compile ghci_mode summary1 source_unchanged
                          old_iface hst1_strictDC hit1_strictDC pcs1
 
-        --putStrLn ( "UPSWEEP_MOD: smhc = " ++ show source_might_have_changed 
-        --           ++ ",  cman = " ++ show compilation_mandatory)
-
         case compresult of
 
-           -- Compilation "succeeded", but didn't return a new iface or
+           -- Compilation "succeeded", but didn't return a new
            -- linkable, meaning that compilation wasn't needed, and the
            -- new details were manufactured from the old iface.
-           CompOK details Nothing pcs2
-              -> let hst2         = addToUFM hst1 mod_name details
-                     hit2         = hit1
+           CompOK pcs2 new_details new_iface Nothing
+              -> let hst2         = addToUFM hst1 mod_name new_details
+                     hit2         = addToUFM hit1 mod_name new_iface
                      threaded2    = CmThreaded pcs2 hst2 hit2
-                     old_linkable 
-                        | ghci_mode == Interactive 
-                        = findModuleLinkable oldUI mod_name
-                        | otherwise
-                        = LM mod_name
-                             [DotO (unJust (ml_obj_file (ms_location summary1)) 
-                                    "upsweep_mod")]
                  in  return (threaded2, Just old_linkable)
 
            -- Compilation really did happen, and succeeded.  A new
            -- details, iface and linkable are returned.
-           CompOK details (Just (new_iface, new_linkable)) pcs2
-              -> let hst2      = addToUFM hst1 mod_name details
+           CompOK pcs2 new_details new_iface (Just new_linkable)
+              -> let hst2      = addToUFM hst1 mod_name new_details
                      hit2      = addToUFM hit1 mod_name new_iface
                      threaded2 = CmThreaded pcs2 hst2 hit2
                  in  return (threaded2, Just new_linkable)
@@ -493,10 +522,10 @@ downwards_closure_of_module summaries root
              = (name_of_summary summ, ms_srcimps summ ++ ms_imps summ)
          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]
@@ -539,14 +568,30 @@ topological_sort include_source_imports summaries
 -- Chase downwards from the specified root set, returning summaries
 -- for all home modules encountered.  Only follow source-import
 -- links.
-downsweep :: [ModuleName] -> IO [ModSummary]
+downsweep :: [FilePath] -> IO [ModSummary]
 downsweep rootNm
-   = do rootSummaries <- mapM getSummary rootNm
-        loop (filter (isModuleInThisPackage.ms_mod) rootSummaries)
+   = do rootSummaries <- mapM getRootSummary rootNm
+        loop (filter (isHomeModule.ms_mod) rootSummaries)
      where
+       getRootSummary :: FilePath -> IO ModSummary
+       getRootSummary file
+          | haskellish_file file
+          = do exists <- doesFileExist file
+               if exists then summariseFile file else do
+               throwDyn (OtherError ("can't find file `" ++ file ++ "'"))      
+          | otherwise
+          = do exists <- doesFileExist hs_file
+               if exists then summariseFile hs_file else do
+               exists <- doesFileExist lhs_file
+               if exists then summariseFile lhs_file else do
+               getSummary (mkModuleName file)
+           where 
+                hs_file = file ++ ".hs"
+                lhs_file = file ++ ".lhs"
+
         getSummary :: ModuleName -> IO ModSummary
         getSummary nm
-           | trace ("getSummary: "++ showSDoc (ppr nm)) True
+           -- | trace ("getSummary: "++ showSDoc (ppr nm)) True
            = do found <- findModule nm
                case found of
                    -- Be sure not to use the mod and location passed in to 
@@ -556,7 +601,7 @@ downsweep rootNm
                    -- These will then conflict with the passed-in versions.
                   Just (mod, location) -> summarise mod location
                   Nothing -> throwDyn (OtherError 
-                                   ("no signs of life for module `" 
+                                   ("can't find module `" 
                                      ++ showSDoc (ppr nm) ++ "'"))
                                  
         -- loop invariant: homeSummaries doesn't contain package modules
@@ -571,17 +616,51 @@ downsweep rootNm
                 neededSummaries
                        <- mapM getSummary neededImps
                 let newHomeSummaries
-                       = filter (isModuleInThisPackage.ms_mod) neededSummaries
+                       = filter (isHomeModule.ms_mod) neededSummaries
                 if null newHomeSummaries
                  then return homeSummaries
                  else loop (newHomeSummaries ++ homeSummaries)
 
 
+-----------------------------------------------------------------------------
+-- Summarising modules
+
+-- We have two types of summarisation:
+--
+--    * Summarise a file.  This is used for the root module passed to
+--     cmLoadModule.  The file is read, and used to determine the root
+--     module name.  The module name may differ from the filename.
+--
+--    * Summarise a module.  We are given a module name, and must provide
+--     a summary.  The finder is used to locate the file in which the module
+--     resides.
+
+summariseFile :: FilePath -> IO ModSummary
+summariseFile file
+   = do hspp_fn <- preprocess file
+        modsrc <- readFile hspp_fn
+
+        let (srcimps,imps,mod_name) = getImports modsrc
+           (path, basename, ext) = splitFilename3 file
+
+       Just (mod, location)
+          <- mkHomeModuleLocn mod_name (path ++ '/':basename) file
+          
+        maybe_src_timestamp
+           <- case ml_hs_file location of 
+                 Nothing     -> return Nothing
+                 Just src_fn -> maybe_getModificationTime src_fn
+
+        return (ModSummary mod
+                           location{ml_hspp_file=Just hspp_fn}
+                           srcimps imps
+                           maybe_src_timestamp)
+
 -- Summarise a module, and pick up source and interface timestamps.
 summarise :: Module -> ModuleLocation -> IO ModSummary
 summarise mod location
-   | isModuleInThisPackage mod
-   = do let hs_fn = unJust (ml_hs_file location) "summarise"
+   | isHomeModule mod
+   = do let hs_fn = unJust "summarise" (ml_hs_file location)
         hspp_fn <- preprocess hs_fn
         modsrc <- readFile hspp_fn
         let (srcimps,imps,mod_name) = getImports modsrc
@@ -590,49 +669,25 @@ summarise mod location
            <- case ml_hs_file location of 
                  Nothing     -> return Nothing
                  Just src_fn -> maybe_getModificationTime src_fn
-        maybe_iface_timestamp
-           <- case ml_hi_file location of 
-                 Nothing     -> return Nothing
-                 Just if_fn  -> maybe_getModificationTime if_fn
-
-        -- If the module name is Main, allow it to be in a file
-        -- different from Main.hs, and mash the mod and loc 
-        -- to match.  Otherwise just moan.
-        (mashed_mod, mashed_loc)
-           <- case () of
-              () |  mod_name == moduleName mod
-                 -> return (mod, location)
-                 |  mod_name /= moduleName mod && mod_name == mkModuleName "Main"
-                 -> return (mash mod location "Main")
-                 |  otherwise
-                 -> do hPutStrLn stderr (showSDoc (
-                          text "ghc: warning: file name - module name mismatch:" <+> 
-                          ppr (moduleName mod) <+> text "vs" <+> ppr mod_name))
-                       return (mash mod location (moduleNameUserString (moduleName mod)))
-               where
-                 mash old_mod old_loc new_nm
-                    = (mkHomeModule (mkModuleName new_nm), 
-                       old_loc{ml_hi_file = maybe_swizzle_basename new_nm 
-                                                (ml_hi_file old_loc)})
-
-                 maybe_swizzle_basename new Nothing = Nothing
-                 maybe_swizzle_basename new (Just old) 
-                    = case splitFilename3 old of 
-                         (dir, name, ext) -> Just (dir ++ new ++ ext)
-
-        return (ModSummary mashed_mod 
-                           mashed_loc{ml_hspp_file=Just hspp_fn} 
-                           srcimps imps
-                           maybe_src_timestamp maybe_iface_timestamp)
 
-   | otherwise
-   = return (ModSummary mod location [] [] Nothing Nothing)
+       if mod_name == moduleName mod
+               then return ()
+               else throwDyn (OtherError 
+                       (showSDoc (text "file name does not match module name: "
+                          <+> ppr (moduleName mod) <+> text "vs" 
+                          <+> ppr mod_name)))
 
-   where
-      maybe_getModificationTime :: FilePath -> IO (Maybe ClockTime)
-      maybe_getModificationTime fn
-         = (do time <- getModificationTime fn
-               return (Just time)) 
-           `catch`
-           (\err -> return Nothing)
+        return (ModSummary mod location{ml_hspp_file=Just hspp_fn} 
+                               srcimps imps
+                               maybe_src_timestamp)
+
+   | otherwise
+   = return (ModSummary mod location [] [] Nothing)
+
+maybe_getModificationTime :: FilePath -> IO (Maybe ClockTime)
+maybe_getModificationTime fn
+   = (do time <- getModificationTime fn
+         return (Just time)) 
+     `catch`
+     (\err -> return Nothing)
 \end{code}