Major clean-up of HscMain.
authorThomas Schilling <nominolo@googlemail.com>
Tue, 25 Nov 2008 15:32:01 +0000 (15:32 +0000)
committerThomas Schilling <nominolo@googlemail.com>
Tue, 25 Nov 2008 15:32:01 +0000 (15:32 +0000)
This patch entails a major restructuring of HscMain and a small bugfix
to MkIface (which required the restructuring in HscMain).

In MkIface:

  - mkIface* no longer outputs orphan warnings directly and also no
    longer quits GHC when -Werror is set.  Instead, errors are
    reported using the common IO (Messages, Maybe result) scheme.

In HscMain:

  - Get rid of the 'Comp' monad.  This monad was mostly GhcMonad + two
    reader arguments, a ModSummary for the currently compiled module
    and a possible old interface.  The latter actually lead to a small
    space-leak since only its hash was needed (to check whether the
    newly-generated interface file was the same as the original one).

    Functions originally of type 'Comp' now only take the arguments
    that they actually need.  This leads to slighly longer argument
    lists in some places, however, it is now much easier to see what
    is actually going on.

  - Get rid of 'myParseModule'.  Rename 'parseFile' to 'hscParse'.

  - Join 'deSugarModule' and 'hscDesugar' (keeping the latter).

  - Rename 'typecheck{Rename}Module{'}' to 'hscTypecheck{Rename}'.
    One variant keeps the renamed syntax, the other doesn't.

  - Parameterise 'HscStatus', so that 'InteractiveStatus' is just a
    different parameterisation of 'HscStatus'.

  - 'hscCompile{OneShot,Batch,Nothing,Interactive}' are now
    implemented using a (local) typeclass called 'HsCompiler'.  The
    idea is to make the common structure more obvious.  Using this
    typeclass we now have two functions 'genericHscCompile' (original
    'hscCompiler') and 'genericHscRecompile' (original 'genComp')
    describing the default pipeline.  The methods of the typeclass
    describe a sort of "hook" interface (in OO-terms this would be
    called the "template method" pattern).

    One problem with this approach is that we parameterise over the
    /result/ type which, in fact, is not actually different for
    "nothing" and "batch" mode.  To avoid functional dependencies or
    associated types, we use type tags to make them artificially
    different and parameterise the type class over the result type.
    A perhaps better approach might be to use records instead.

  - Drop some redundant 'HscEnv' arguments.  These were likely
    different from what 'getSession' would return because during
    compilation we temporarily set the module's DynFlags as well as a
    few other fields.  We now use the 'withTempSession' combinator to
    temporarily change the 'HscEnv' and automatically restore the
    original session after the enclosed action has returned (even in
    case of exceptions).

  - Rename 'hscCompile' to 'hscGenHardCode' (since that is what it
    does).

Calls in 'GHC' and 'DriverPipeline' accordingly needed small
adaptions.

compiler/iface/MkIface.lhs
compiler/main/DriverPipeline.hs
compiler/main/GHC.hs
compiler/main/HscMain.lhs
compiler/main/HscTypes.lhs

index 285f171..97449b7 100644 (file)
@@ -100,7 +100,6 @@ import Control.Monad
 import Data.List
 import Data.IORef
 import System.FilePath
-import System.Exit     ( exitWith, ExitCode(..) )
 \end{code}
 
 
@@ -116,8 +115,9 @@ mkIface :: HscEnv
        -> Maybe Fingerprint    -- The old fingerprint, if we have it
        -> ModDetails           -- The trimmed, tidied interface
        -> ModGuts              -- Usages, deprecations, etc
-       -> IO (ModIface,        -- The new one
-              Bool)            -- True <=> there was an old Iface, and the 
+       -> IO (Messages,
+               Maybe (ModIface, -- The new one
+                     Bool))    -- True <=> there was an old Iface, and the
                                 --          new one is identical, so no need
                                 --          to write it
 
@@ -134,7 +134,7 @@ mkIface hsc_env maybe_old_fingerprint mod_details
         = mkIface_ hsc_env maybe_old_fingerprint
                    this_mod is_boot used_names deps rdr_env 
                    fix_env warns hpc_info dir_imp_mods mod_details
-       
+
 -- | make an interface from the results of typechecking only.  Useful
 -- for non-optimising compilation, or where we aren't generating any
 -- object code at all ('HscNothing').
@@ -142,8 +142,7 @@ mkIfaceTc :: HscEnv
           -> Maybe Fingerprint -- The old fingerprint, if we have it
           -> ModDetails                -- gotten from mkBootModDetails, probably
           -> TcGblEnv          -- Usages, deprecations, etc
-         -> IO (ModIface,
-                Bool)
+         -> IO (Messages, Maybe (ModIface, Bool))
 mkIfaceTc hsc_env maybe_old_fingerprint mod_details
   tc_result@TcGblEnv{ tcg_mod = this_mod,
                       tcg_src = hsc_src,
@@ -214,7 +213,7 @@ mkIface_ :: HscEnv -> Maybe Fingerprint -> Module -> IsBootInterface
          -> NameEnv FixItem -> Warnings -> HpcInfo
          -> ImportedMods
          -> ModDetails
-         -> IO (ModIface, Bool)
+        -> IO (Messages, Maybe (ModIface, Bool))
 mkIface_ hsc_env maybe_old_fingerprint 
          this_mod is_boot used_names deps rdr_env fix_env src_warns hpc_info
          dir_imp_mods
@@ -305,10 +304,9 @@ mkIface_ hsc_env maybe_old_fingerprint
                                     | r <- iface_rules
                                     , isNothing (ifRuleOrph r) ]
 
-       ; when (not (isEmptyBag orph_warnings))
-              (do { printErrorsAndWarnings dflags errs_and_warns -- XXX
-                  ; when (errorsFound dflags errs_and_warns) 
-                         (exitWith (ExitFailure 1)) })
+       ; if errorsFound dflags errs_and_warns
+            then return ( errs_and_warns, Nothing )
+            else do {
 
 -- XXX ; when (dopt Opt_D_dump_hi_diffs dflags) (printDump pp_diffs)
    
@@ -322,7 +320,7 @@ mkIface_ hsc_env maybe_old_fingerprint
                 -- with the old GlobalRdrEnv (mi_globals).
         ; let final_iface = new_iface{ mi_globals = Just rdr_env }
 
-       ; return (final_iface, no_change_at_all) }
+       ; return (errs_and_warns, Just (final_iface, no_change_at_all)) }}
   where
      r1 `le_rule`     r2 = ifRuleName      r1    <=    ifRuleName      r2
      i1 `le_inst`     i2 = ifDFun          i1 `le_occ` ifDFun          i2  
index 3a88318..2846eaf 100644 (file)
@@ -153,7 +153,7 @@ compile hsc_env0 summary mod_index nmods mb_old_iface maybe_old_linkable
            = ASSERT (isJust maybe_old_linkable)
              return maybe_old_linkable
 
-       handleBatch (HscRecomp hasStub)
+       handleBatch (HscRecomp hasStub _)
            | isHsBoot src_flavour
                = do when (isObjectTarget hsc_lang) $ -- interpreted reaches here too
                        liftIO $ SysTools.touch dflags' "Touching object file"
@@ -179,10 +179,10 @@ compile hsc_env0 summary mod_index nmods mb_old_iface maybe_old_linkable
                                   (hs_unlinked ++ stub_unlinked)
                     return (Just linkable)
 
-       handleInterpreted InteractiveNoRecomp
+       handleInterpreted HscNoRecomp
            = ASSERT (isJust maybe_old_linkable)
              return maybe_old_linkable
-       handleInterpreted (InteractiveRecomp hasStub comp_bc modBreaks)
+       handleInterpreted (HscRecomp hasStub (comp_bc, modBreaks))
            = do stub_unlinked <- getStubLinkable hasStub
                 let hs_unlinked = [BCOs comp_bc modBreaks]
                     unlinked_time = ms_hs_date summary
@@ -830,7 +830,7 @@ runPhase (Hsc src_flavour) stop hsc_env basename suff input_fn get_output_fn _ma
                     -- than the source file (else we wouldn't be in HscNoRecomp)
                     -- but we touch it anyway, to keep 'make' happy (we think).
                     return (StopLn, dflags', Just location4, o_file)
-          (HscRecomp hasStub)
+          (HscRecomp hasStub _)
               -> do when hasStub $
                          do stub_o <- compileStub hsc_env' mod location4
                             liftIO $ consIORef v_Ld_inputs stub_o
index 29bb4f7..f3e0199 100644 (file)
@@ -1040,9 +1040,9 @@ getModSummary mod = do
 -- Throws a 'SourceError' on parse error.
 parseModule :: GhcMonad m => ModSummary -> m ParsedModule
 parseModule ms = do
-   hsc_env0 <- getSession
-   let hsc_env = hsc_env0 { hsc_dflags = ms_hspp_opts ms }
-   rdr_module <- parseFile hsc_env ms
+   rdr_module <- withTempSession
+                     (\e -> e { hsc_dflags = ms_hspp_opts ms }) $
+                   hscParse ms
    return (ParsedModule ms rdr_module)
 
 -- | Typecheck and rename a parsed module.
@@ -1050,12 +1050,11 @@ parseModule ms = do
 -- Throws a 'SourceError' if either fails.
 typecheckModule :: GhcMonad m => ParsedModule -> m TypecheckedModule
 typecheckModule pmod = do
-   let ms = modSummary pmod
-   hsc_env0 <- getSession
-   let hsc_env = hsc_env0 { hsc_dflags = ms_hspp_opts ms }
+ let ms = modSummary pmod
+ withTempSession (\e -> e { hsc_dflags = ms_hspp_opts ms }) $ do
    (tc_gbl_env, rn_info)
-       <- typecheckRenameModule hsc_env ms (parsedSource pmod)
-   details <- liftIO $ makeSimpleDetails hsc_env tc_gbl_env
+       <- hscTypecheckRename ms (parsedSource pmod)
+   details <- makeSimpleDetails tc_gbl_env
    return $
      TypecheckedModule {
        tm_internals_          = (tc_gbl_env, details),
@@ -1076,11 +1075,10 @@ typecheckModule pmod = do
 -- | Desugar a typechecked module.
 desugarModule :: GhcMonad m => TypecheckedModule -> m DesugaredModule
 desugarModule tcm = do
-   let ms = modSummary tcm
-   hsc_env0 <- getSession
-   let hsc_env = hsc_env0 { hsc_dflags = ms_hspp_opts ms }
+ let ms = modSummary tcm
+ withTempSession (\e -> e { hsc_dflags = ms_hspp_opts ms }) $ do
    let (tcg, _) = tm_internals tcm
-   guts <- deSugarModule hsc_env ms tcg
+   guts <- hscDesugar ms tcg
    return $
      DesugaredModule {
        dm_typechecked_module = tcm,
@@ -1094,16 +1092,17 @@ loadModule :: (TypecheckedMod mod, GhcMonad m) => mod -> m mod
 loadModule tcm = do
    let ms = modSummary tcm
    let mod = ms_mod_name ms
-   hsc_env0 <- getSession
-   let hsc_env = hsc_env0 { hsc_dflags = ms_hspp_opts ms }
    let (tcg, details) = tm_internals tcm
-   (iface,_) <- liftIO $ makeSimpleIface hsc_env Nothing tcg details
-   let mod_info = HomeModInfo {
-                    hm_iface = iface,
-                    hm_details = details,
-                    hm_linkable = Nothing }
-   let hpt_new = addToUFM (hsc_HPT hsc_env) mod mod_info
-   modifySession $ \_ -> hsc_env0{ hsc_HPT = hpt_new }
+   hpt_new <-
+       withTempSession (\e -> e { hsc_dflags = ms_hspp_opts ms }) $ do
+         (iface, _) <- makeSimpleIface Nothing tcg details
+         let mod_info = HomeModInfo {
+                          hm_iface = iface,
+                          hm_details = details,
+                          hm_linkable = Nothing }
+         hsc_env <- getSession
+         return $ addToUFM (hsc_HPT hsc_env) mod mod_info
+   modifySession $ \e -> e{ hsc_HPT = hpt_new }
    return tcm
 
 -- | This is the way to get access to the Core bindings corresponding
@@ -1132,11 +1131,9 @@ compileToCore fn = do
 -- whether to run the simplifier.
 -- The resulting .o, .hi, and executable files, if any, are stored in the
 -- current directory, and named according to the module name.
--- Returns True iff compilation succeeded.
 -- This has only so far been tested with a single self-contained module.
 compileCoreToObj :: GhcMonad m => Bool -> CoreModule -> m ()
 compileCoreToObj simplify cm@(CoreModule{ cm_module = mName }) = do
-  hscEnv      <- getSession
   dflags      <- getSessionDynFlags
   currentTime <- liftIO $ getClockTime
   cwd         <- liftIO $ getCurrentDirectory
@@ -1161,15 +1158,13 @@ compileCoreToObj simplify cm@(CoreModule{ cm_module = mName }) = do
          ms_hspp_buf = Nothing
       }
 
-  ioMsgMaybe $ flip evalComp (CompState{ compHscEnv=hscEnv,
-                                         compModSummary=modSummary,
-                                         compOldIface=Nothing}) $
-     let maybe_simplify mod_guts | simplify = hscSimplify mod_guts
-                                 | otherwise = return mod_guts
-     in maybe_simplify (mkModGuts cm)
-          >>= hscNormalIface
-          >>= hscWriteIface
-          >>= hscOneShot
+  let maybe_simplify mod_guts | simplify = hscSimplify mod_guts
+                              | otherwise = return mod_guts
+  guts <- maybe_simplify (mkModGuts cm)
+  (iface, changed, _details, cgguts)
+      <- hscNormalIface guts Nothing
+  hscWriteIface iface changed modSummary
+  hscGenHardCode cgguts modSummary
   return ()
 
 -- Makes a "vanilla" ModGuts.
@@ -1211,6 +1206,7 @@ compileCore simplify fn = do
        -- Now we have the module name;
        -- parse, typecheck and desugar the module
        mod_guts <- coreModule `fmap`
+                      -- TODO: space leaky: call hsc* directly?
                       (desugarModule =<< typecheckModule =<< parseModule modSummary)
        liftM gutsToCoreModule $
          if simplify
@@ -1218,11 +1214,7 @@ compileCore simplify fn = do
              -- If simplify is true: simplify (hscSimplify), then tidy
              -- (tidyProgram).
              hsc_env <- getSession
-             simpl_guts <- ioMsg $ evalComp (hscSimplify mod_guts)
-                                    (CompState{
-                                       compHscEnv = hsc_env,
-                                       compModSummary = modSummary,
-                                       compOldIface = Nothing})
+             simpl_guts <- hscSimplify mod_guts
              tidy_guts <- liftIO $ tidyProgram hsc_env simpl_guts
              return $ Left tidy_guts
           else
index 9e134d5..2fefcd4 100644 (file)
@@ -9,9 +9,7 @@ module HscMain
     ( newHscEnv, hscCmmFile
     , hscParseIdentifier
     , hscSimplify
-    , evalComp
-    , hscNormalIface, hscWriteIface, hscOneShot
-    , CompState (..)
+    , hscNormalIface, hscWriteIface, hscGenHardCode
 #ifdef GHCI
     , hscStmt, hscTcExpr, hscKcType
     , compileExpr
@@ -20,14 +18,14 @@ module HscMain
     , hscCompileBatch       -- :: Compiler (HscStatus, ModIface, ModDetails)
     , hscCompileNothing     -- :: Compiler (HscStatus, ModIface, ModDetails)
     , hscCompileInteractive -- :: Compiler (InteractiveStatus, ModIface, ModDetails)
-    , HscStatus (..)
-    , InteractiveStatus (..)
+    , HscStatus' (..)
+    , InteractiveStatus, NothingStatus, OneShotStatus, BatchStatus
 
     -- The new interface
-    , parseFile
-    , typecheckModule'
-    , typecheckRenameModule
-    , deSugarModule
+    , hscParse
+    , hscTypecheck
+    , hscTypecheckRename
+    , hscDesugar
     , makeSimpleIface
     , makeSimpleDetails
     ) where
@@ -90,6 +88,7 @@ import CmmTx
 import CmmContFlowOpt
 import CodeOutput      ( codeOutput )
 import NameEnv          ( emptyNameEnv )
+import Fingerprint      ( Fingerprint )
 
 import DynFlags
 import ErrUtils
@@ -102,7 +101,7 @@ import MkExternalCore       ( emitExternalCore )
 import FastString
 import LazyUniqFM              ( emptyUFM )
 import UniqSupply       ( initUs_ )
-import Bag             ( unitBag, emptyBag, unionBags )
+import Bag             ( unitBag )
 import Exception
 import MonadUtils
 
@@ -141,7 +140,7 @@ newHscEnv dflags
                            hsc_type_env_var = Nothing,
                            hsc_global_rdr_env = emptyGlobalRdrEnv,
                            hsc_global_type_env = emptyNameEnv } ) }
-                       
+
 
 knownKeyNames :: [Name]        -- Put here to avoid loops involving DsMeta,
                        -- where templateHaskellNames are defined
@@ -155,24 +154,49 @@ knownKeyNames = map getName wiredInThings
 
 \begin{code}
 -- | parse a file, returning the abstract syntax
-parseFile :: GhcMonad m => HscEnv -> ModSummary -> m (Located (HsModule RdrName))
-parseFile hsc_env mod_summary = do
-    ((warns,errs), maybe_parsed) <- liftIO $ myParseModule dflags hspp_file hspp_buf
-    logWarnings warns
-    case maybe_parsed of
-      Nothing -> liftIO $ throwIO (mkSrcErr errs)
-      Just rdr_module
-              -> return rdr_module
-  where
-           dflags    = hsc_dflags hsc_env
-           hspp_file = ms_hspp_file mod_summary
-           hspp_buf  = ms_hspp_buf  mod_summary
+hscParse :: GhcMonad m =>
+            ModSummary
+         -> m (Located (HsModule RdrName))
+hscParse mod_summary = do
+   hsc_env <- getSession
+   let dflags        = hsc_dflags hsc_env
+       src_filename  = ms_hspp_file mod_summary
+       maybe_src_buf = ms_hspp_buf  mod_summary
+   --------------------------  Parser  ----------------
+   liftIO $ showPass dflags "Parser"
+   {-# SCC "Parser" #-} do
+
+       -- sometimes we already have the buffer in memory, perhaps
+       -- because we needed to parse the imports out of it, or get the
+       -- module name.
+   buf <- case maybe_src_buf of
+            Just b  -> return b
+            Nothing -> liftIO $ hGetStringBuffer src_filename
+
+   let loc  = mkSrcLoc (mkFastString src_filename) 1 0
+
+   case unP parseModule (mkPState buf loc dflags) of
+     PFailed span err ->
+         throwOneError (mkPlainErrMsg span err)
+
+     POk pst rdr_module -> do
+         let ms@(warns,errs) = getMessages pst
+         logWarnings warns
+         if errorsFound dflags ms then
+           liftIO $ throwIO $ mkSrcErr errs
+          else liftIO $ do
+           dumpIfSet_dyn dflags Opt_D_dump_parsed "Parser" (ppr rdr_module) ;
+           dumpIfSet_dyn dflags Opt_D_source_stats "Source Statistics"
+                               (ppSourceStats False rdr_module) ;
+           return rdr_module
+          -- ToDo: free the string buffer later.
 
 -- | Rename and typecheck a module
-typecheckModule' :: GhcMonad m =>
-                   HscEnv -> ModSummary -> Located (HsModule RdrName)
-                -> m TcGblEnv
-typecheckModule' hsc_env mod_summary rdr_module = do
+hscTypecheck :: GhcMonad m =>
+                ModSummary -> Located (HsModule RdrName)
+             -> m TcGblEnv
+hscTypecheck mod_summary rdr_module = do
+      hsc_env <- getSession
       r <- {-# SCC "Typecheck-Rename" #-}
            ioMsgMaybe $ tcRnModule hsc_env (ms_hsc_src mod_summary) False rdr_module
       return r
@@ -185,11 +209,12 @@ type RenamedStuff =
                 Maybe (HsDoc Name), HaddockModInfo Name))
 
 -- | Rename and typecheck a module, additionally returning the renamed syntax
-typecheckRenameModule
-    :: GhcMonad m =>
-       HscEnv -> ModSummary -> Located (HsModule RdrName)
+hscTypecheckRename ::
+       GhcMonad m =>
+       ModSummary -> Located (HsModule RdrName)
     -> m (TcGblEnv, RenamedStuff)
-typecheckRenameModule hsc_env mod_summary rdr_module = do
+hscTypecheckRename mod_summary rdr_module = do
+    hsc_env <- getSession
     tc_result
           <- {-# SCC "Typecheck-Rename" #-}
              ioMsgMaybe $ tcRnModule hsc_env (ms_hsc_src mod_summary) True rdr_module
@@ -204,8 +229,9 @@ typecheckRenameModule hsc_env mod_summary rdr_module = do
     return (tc_result, rn_info)
 
 -- | Convert a typechecked module to Core
-deSugarModule :: GhcMonad m => HscEnv -> ModSummary -> TcGblEnv -> m ModGuts
-deSugarModule hsc_env mod_summary tc_result = do
+hscDesugar :: GhcMonad m => ModSummary -> TcGblEnv -> m ModGuts
+hscDesugar mod_summary tc_result =
+  withSession $ \hsc_env ->
     ioMsgMaybe $ deSugar hsc_env (ms_location mod_summary) tc_result
 
 -- | Make a 'ModIface' from the results of typechecking.  Used when
@@ -213,17 +239,18 @@ deSugarModule hsc_env mod_summary tc_result = do
 -- unfoldings or other cross-module optimisation info.
 -- ToDo: the old interface is only needed to get the version numbers,
 -- we should use fingerprint versions instead.
-makeSimpleIface :: HscEnv -> Maybe ModIface -> TcGblEnv -> ModDetails
-                -> IO (ModIface,Bool)
-makeSimpleIface hsc_env maybe_old_iface tc_result details = do
-  mkIfaceTc hsc_env (fmap mi_iface_hash maybe_old_iface) details tc_result
+makeSimpleIface :: GhcMonad m =>
+                   Maybe ModIface -> TcGblEnv -> ModDetails
+                -> m (ModIface,Bool)
+makeSimpleIface maybe_old_iface tc_result details =
+  withSession $ \hsc_env ->
+  ioMsgMaybe $ mkIfaceTc hsc_env (fmap mi_iface_hash maybe_old_iface) details tc_result
 
 -- | Make a 'ModDetails' from the results of typechecking.  Used when
 -- typechecking only, as opposed to full compilation.
-makeSimpleDetails :: HscEnv -> TcGblEnv -> IO ModDetails
-makeSimpleDetails hsc_env tc_result = mkBootModDetailsTc hsc_env tc_result
-
--- deSugarModule :: HscEnv -> TcGblEnv -> IO Core
+makeSimpleDetails :: GhcMonad m => TcGblEnv -> m ModDetails
+makeSimpleDetails tc_result =
+    withSession $ \hsc_env -> liftIO $ mkBootModDetailsTc hsc_env tc_result
 \end{code}
 
 %************************************************************************
@@ -266,64 +293,30 @@ error. This is the only thing that isn't caught by the type-system.
 \begin{code}
 
 -- Status of a compilation to hard-code or nothing.
-data HscStatus
+data HscStatus' a
     = HscNoRecomp
-    | HscRecomp  Bool -- Has stub files.
-                      -- This is a hack. We can't compile C files here
-                      -- since it's done in DriverPipeline. For now we
-                      -- just return True if we want the caller to compile
-                      -- them for us.
-
--- Status of a compilation to byte-code.
-data InteractiveStatus
-    = InteractiveNoRecomp
-    | InteractiveRecomp Bool     -- Same as HscStatus
-                        CompiledByteCode
-                        ModBreaks
-
-
--- I want Control.Monad.State! --Lemmih 03/07/2006
-newtype Comp a = Comp {runComp :: CompState -> IORef Messages -> IO (a, CompState)}
-
-instance Monad Comp where
-    g >>= fn = Comp $ \s r -> runComp g s r >>= \(a,s') -> runComp (fn a) s' r
-    return a = Comp $ \s _ -> return (a,s)
-    fail = error
-
-evalComp :: Comp a -> CompState -> IO (Messages, a)
-evalComp comp st = do r <- newIORef emptyMessages
-                      (val,_st') <- runComp comp st r
-                      msgs <- readIORef r
-                      return (msgs, val)
-
-logMsgs :: Messages -> Comp ()
-logMsgs (warns', errs') = Comp $ \s r -> do
-                           (warns, errs) <- readIORef r
-                           writeIORef r $! ( warns' `unionBags` warns
-                                           , errs' `unionBags` errs )
-                           return ((), s)
-
-data CompState
-    = CompState
-    { compHscEnv     :: HscEnv
-    , compModSummary :: ModSummary
-    , compOldIface   :: Maybe ModIface
-    }
-
-get :: Comp CompState
-get = Comp $ \s _ -> return (s,s)
-
-modify :: (CompState -> CompState) -> Comp ()
-modify f = Comp $ \s _ -> return ((), f s)
-
-gets :: (CompState -> a) -> Comp a
-gets getter = do st <- get
-                 return (getter st)
-
-instance MonadIO Comp where
-  liftIO ioA = Comp $ \s _ -> do a <- ioA; return (a,s)
-
-type NoRecomp result = ModIface -> Comp result
+    | HscRecomp
+       Bool -- Has stub files.  This is a hack. We can't compile C files here
+            -- since it's done in DriverPipeline. For now we just return True
+            -- if we want the caller to compile them for us.
+       a
+
+-- This is a bit ugly.  Since we use a typeclass below and would like to avoid
+-- functional dependencies, we have to parameterise the typeclass over the
+-- result type.  Therefore we need to artificially distinguish some types.  We
+-- do this by adding type tags which will simply be ignored by the caller.
+data HscOneShotTag = HscOneShotTag
+data HscNothingTag = HscNothingTag
+
+type OneShotStatus     = HscStatus' HscOneShotTag
+type BatchStatus       = HscStatus' ()
+type InteractiveStatus = HscStatus' (CompiledByteCode, ModBreaks)
+type NothingStatus     = HscStatus' HscNothingTag
+
+type OneShotResult = OneShotStatus
+type BatchResult   = (BatchStatus, ModIface, ModDetails)
+type NothingResult = (NothingStatus, ModIface, ModDetails)
+type InteractiveResult = (InteractiveStatus, ModIface, ModDetails)
 
 -- FIXME: The old interface and module index are only using in 'batch' and
 --        'interactive' mode. They should be removed from 'oneshot' mode.
@@ -335,14 +328,77 @@ type Compiler result =  GhcMonad m =>
                      -> Maybe (Int,Int)     -- Just (i,n) <=> module i of n (for msgs)
                      -> m result
 
+class HsCompiler a where
+  -- | The main interface.
+  hscCompile :: GhcMonad m =>
+                HscEnv -> ModSummary -> Bool
+             -> Maybe ModIface -> Maybe (Int, Int)
+             -> m a
+
+  -- | Called when no recompilation is necessary.
+  hscNoRecomp :: GhcMonad m =>
+                 ModIface -> m a
+
+  -- | Called to recompile the module.
+  hscRecompile :: GhcMonad m =>
+                  ModSummary -> Maybe Fingerprint -> m a
+
+  -- | Code generation for Boot modules.
+  hscGenBootOutput :: GhcMonad m =>
+                      TcGblEnv -> ModSummary -> Maybe Fingerprint -> m a
+
+  -- | Code generation for normal modules.
+  hscGenOutput :: GhcMonad m =>
+                  ModGuts  -> ModSummary -> Maybe Fingerprint -> m a
+
+
+genericHscCompile :: (HsCompiler a, GhcMonad m) =>
+                     (Maybe (Int,Int) -> Bool -> ModSummary -> m ())
+                  -> HscEnv -> ModSummary -> Bool
+                  -> Maybe ModIface -> Maybe (Int, Int)
+                  -> m a
+genericHscCompile hscMessage
+                  hsc_env mod_summary source_unchanged
+                  mb_old_iface0 mb_mod_index =
+   withTempSession (\_ -> hsc_env) $ do
+     (recomp_reqd, mb_checked_iface)
+         <- {-# SCC "checkOldIface" #-}
+            liftIO $ checkOldIface hsc_env mod_summary
+                                   source_unchanged mb_old_iface0
+     -- save the interface that comes back from checkOldIface.
+     -- In one-shot mode we don't have the old iface until this
+     -- point, when checkOldIface reads it from the disk.
+     let mb_old_hash = fmap mi_iface_hash mb_checked_iface
+     case mb_checked_iface of
+       Just iface | not recomp_reqd
+           -> do hscMessage mb_mod_index False mod_summary
+                 hscNoRecomp iface
+       _otherwise
+           -> do hscMessage mb_mod_index True mod_summary
+                 hscRecompile mod_summary mb_old_hash
+
+genericHscRecompile :: (HsCompiler a, GhcMonad m) =>
+                       ModSummary -> Maybe Fingerprint
+                    -> m a
+genericHscRecompile mod_summary mb_old_hash
+  | ExtCoreFile <- ms_hsc_src mod_summary =
+      panic "GHC does not currently support reading External Core files"
+  | otherwise = do
+      tc_result <- hscFileFrontEnd mod_summary
+      case ms_hsc_src mod_summary of
+        HsBootFile ->
+            hscGenBootOutput tc_result mod_summary mb_old_hash
+        _other     -> do
+            guts <- hscDesugar mod_summary tc_result
+            hscGenOutput guts mod_summary mb_old_hash
+
 --------------------------------------------------------------
 -- Compilers
 --------------------------------------------------------------
 
--- Compile Haskell, boot and extCore in OneShot mode.
-hscCompileOneShot :: Compiler HscStatus
-hscCompileOneShot hsc_env mod_summary src_changed mb_old_iface mb_i_of_n
-  = do
+instance HsCompiler OneShotResult where
+
+  hscCompile hsc_env mod_summary src_changed mb_old_iface mb_i_of_n = do
      -- One-shot mode needs a knot-tying mutable variable for interface files.
      -- See TcRnTypes.TcGblEnv.tcg_type_env_var.
     type_env_var <- liftIO $ newIORef emptyNameEnv
@@ -350,141 +406,143 @@ hscCompileOneShot hsc_env mod_summary src_changed mb_old_iface mb_i_of_n
        mod = ms_mod mod_summary
        hsc_env' = hsc_env{ hsc_type_env_var = Just (mod, type_env_var) }
     ---
-    hscCompilerOneShot' hsc_env' mod_summary src_changed mb_old_iface mb_i_of_n
+    genericHscCompile oneShotMsg hsc_env' mod_summary src_changed
+                      mb_old_iface mb_i_of_n
+
+  hscNoRecomp _old_iface = do
+    withSession (liftIO . dumpIfaceStats)
+    return HscNoRecomp
+
+  hscRecompile = genericHscRecompile
+
+  hscGenBootOutput tc_result mod_summary mb_old_iface = do
+     (iface, changed, _) <- hscSimpleIface tc_result mb_old_iface
+     hscWriteIface iface changed mod_summary
+     return (HscRecomp False HscOneShotTag)
+
+  hscGenOutput guts0 mod_summary mb_old_iface = do
+     guts <- hscSimplify guts0
+     (iface, changed, _details, cgguts)
+         <- hscNormalIface guts mb_old_iface
+     hscWriteIface iface changed mod_summary
+     hasStub <- hscGenHardCode cgguts mod_summary
+     return (HscRecomp hasStub HscOneShotTag)
 
-hscCompilerOneShot' :: Compiler HscStatus
-hscCompilerOneShot'
-   = hscCompiler norecompOneShot oneShotMsg (genComp backend boot_backend)
-   where
-     backend inp  = hscSimplify inp >>= hscNormalIface >>= hscWriteIface >>= hscOneShot
-     boot_backend inp = hscSimpleIface inp >>= hscWriteIface >> return (Just (HscRecomp False))
+-- Compile Haskell, boot and extCore in OneShot mode.
+hscCompileOneShot :: Compiler OneShotStatus
+hscCompileOneShot = hscCompile
+
+--------------------------------------------------------------
+
+instance HsCompiler BatchResult where
+
+  hscCompile = genericHscCompile batchMsg
+
+  hscNoRecomp iface = do
+     details <- genModDetails iface
+     return (HscNoRecomp, iface, details)
+
+  hscRecompile = genericHscRecompile
+
+  hscGenBootOutput tc_result mod_summary mb_old_iface = do
+     (iface, changed, details)
+         <- hscSimpleIface tc_result mb_old_iface
+     hscWriteIface iface changed mod_summary
+     return (HscRecomp False (), iface, details)
+
+  hscGenOutput guts0 mod_summary mb_old_iface = do
+     guts <- hscSimplify guts0
+     (iface, changed, details, cgguts)
+         <- hscNormalIface guts mb_old_iface
+     hscWriteIface iface changed mod_summary
+     hasStub <- hscGenHardCode cgguts mod_summary
+     return (HscRecomp hasStub (), iface, details)
 
 -- Compile Haskell, boot and extCore in batch mode.
-hscCompileBatch :: Compiler (HscStatus, ModIface, ModDetails)
-hscCompileBatch
-   = hscCompiler norecompBatch batchMsg (genComp backend boot_backend)
-   where
-     backend inp  = hscSimplify inp >>= hscNormalIface >>= hscWriteIface >>= hscBatch
-     boot_backend inp = hscSimpleIface inp >>= hscWriteIface >>= hscNothing
+hscCompileBatch :: Compiler (BatchStatus, ModIface, ModDetails)
+hscCompileBatch = hscCompile
+
+--------------------------------------------------------------
+
+instance HsCompiler InteractiveResult where
+
+  hscCompile = genericHscCompile batchMsg
+
+  hscNoRecomp iface = do
+     details <- genModDetails iface
+     return (HscNoRecomp, iface, details)
+
+  hscRecompile = genericHscRecompile
+
+  hscGenBootOutput _ _ _ = panic "hscCompileInteractive: HsBootFile"
+
+  hscGenOutput guts0 mod_summary mb_old_iface = do
+     guts <- hscSimplify guts0
+     (iface, _changed, details, cgguts)
+         <- hscNormalIface guts mb_old_iface
+     hscInteractive (iface, details, cgguts) mod_summary
 
 -- Compile Haskell, extCore to bytecode.
 hscCompileInteractive :: Compiler (InteractiveStatus, ModIface, ModDetails)
-hscCompileInteractive
-   = hscCompiler norecompInteractive batchMsg (genComp backend boot_backend)
-   where
-     backend inp = hscSimplify inp >>= hscNormalIface >>= hscIgnoreIface >>= hscInteractive
-     boot_backend _ = panic "hscCompileInteractive: HsBootFile"
+hscCompileInteractive = hscCompile
+
+--------------------------------------------------------------
+
+instance HsCompiler NothingResult where
+
+  hscCompile = genericHscCompile batchMsg
+
+  hscNoRecomp iface = do
+     details <- genModDetails iface
+     return (HscNoRecomp, iface, details)
+
+  hscRecompile mod_summary mb_old_hash
+    | ExtCoreFile <- ms_hsc_src mod_summary =
+        panic "hscCompileNothing: cannot do external core"
+    | otherwise = do
+        tc_result <- hscFileFrontEnd mod_summary
+        hscGenBootOutput tc_result mod_summary mb_old_hash
+
+  hscGenBootOutput tc_result _mod_summary mb_old_iface = do
+     (iface, _changed, details) <- hscSimpleIface tc_result mb_old_iface
+     return (HscRecomp False HscNothingTag, iface, details)
+
+  hscGenOutput _ _ _ =
+      panic "hscCompileNothing: hscGenOutput should not be called"
 
 -- Type-check Haskell and .hs-boot only (no external core)
-hscCompileNothing :: Compiler (HscStatus, ModIface, ModDetails)
-hscCompileNothing
-   = hscCompiler norecompBatch batchMsg comp
-   where
-     backend tc = hscSimpleIface tc >>= hscIgnoreIface >>= hscNothing
-
-     comp = do   -- genComp doesn't fit here, because we want to omit
-                 -- desugaring and for the backend to take a TcGblEnv
-        mod_summary <- gets compModSummary
-        case ms_hsc_src mod_summary of
-           ExtCoreFile -> panic "hscCompileNothing: cannot do external core"
-           _other -> do
-                mb_tc <- hscFileFrontEnd
-                case mb_tc of
-                  Nothing -> return Nothing
-                  Just tc_result -> backend tc_result
-        
-hscCompiler
-        :: NoRecomp result                       -- No recomp necessary
-        -> (Maybe (Int,Int) -> Bool -> Comp ())  -- Message callback
-        -> Comp (Maybe result)
-        -> Compiler result
-hscCompiler norecomp messenger recomp hsc_env mod_summary 
-            source_unchanged mbOldIface mbModIndex
-   = ioMsgMaybe $
-      flip evalComp (CompState hsc_env mod_summary mbOldIface) $
-      do (recomp_reqd, mbCheckedIface)
-             <- {-# SCC "checkOldIface" #-}
-                liftIO $ checkOldIface hsc_env mod_summary
-                              source_unchanged mbOldIface
-        -- save the interface that comes back from checkOldIface.
-        -- In one-shot mode we don't have the old iface until this
-        -- point, when checkOldIface reads it from the disk.
-        modify (\s -> s{ compOldIface = mbCheckedIface })
-         case mbCheckedIface of 
-           Just iface | not recomp_reqd
-               -> do messenger mbModIndex False
-                     result <- norecomp iface
-                     return (Just result)
-           _otherwise
-               -> do messenger mbModIndex True
-                     recomp
-
--- the usual way to build the Comp (Maybe result) to pass to hscCompiler
-genComp :: (ModGuts  -> Comp (Maybe a))
-        -> (TcGblEnv -> Comp (Maybe a))
-        -> Comp (Maybe a)
-genComp backend boot_backend = do
-    mod_summary <- gets compModSummary
-    case ms_hsc_src mod_summary of
-       ExtCoreFile -> do
-          panic "GHC does not currently support reading External Core files"
-       _not_core -> do
-          mb_tc <- hscFileFrontEnd
-          case mb_tc of
-            Nothing -> return Nothing
-            Just tc_result -> 
-              case ms_hsc_src mod_summary of
-                HsBootFile -> boot_backend tc_result
-                _other     -> do
-                  mb_guts <- hscDesugar tc_result
-                  case mb_guts of
-                    Nothing -> return Nothing
-                    Just guts -> backend guts
+hscCompileNothing :: Compiler (NothingStatus, ModIface, ModDetails)
+hscCompileNothing = hscCompile
 
 --------------------------------------------------------------
 -- NoRecomp handlers
 --------------------------------------------------------------
 
-norecompOneShot :: NoRecomp HscStatus
-norecompOneShot _old_iface
-    = do hsc_env <- gets compHscEnv
-         liftIO $ do
-         dumpIfaceStats hsc_env
-         return HscNoRecomp
-
-norecompBatch :: NoRecomp (HscStatus, ModIface, ModDetails)
-norecompBatch = norecompWorker HscNoRecomp False
-
-norecompInteractive :: NoRecomp (InteractiveStatus, ModIface, ModDetails)
-norecompInteractive = norecompWorker InteractiveNoRecomp True
-
-norecompWorker :: a -> Bool -> NoRecomp (a, ModIface, ModDetails)
-norecompWorker a _isInterp old_iface
-    = do hsc_env <- gets compHscEnv
-         liftIO $ do
-         new_details <- {-# SCC "tcRnIface" #-}
-                        initIfaceCheck hsc_env $
-                        typecheckIface old_iface
-         dumpIfaceStats hsc_env
-         return (a, old_iface, new_details)
+genModDetails :: GhcMonad m => ModIface -> m ModDetails
+genModDetails old_iface =
+    withSession $ \hsc_env -> liftIO $ do
+      new_details <- {-# SCC "tcRnIface" #-}
+                     initIfaceCheck hsc_env $
+                     typecheckIface old_iface
+      dumpIfaceStats hsc_env
+      return new_details
 
 --------------------------------------------------------------
 -- Progress displayers.
 --------------------------------------------------------------
 
-oneShotMsg :: Maybe (Int,Int) -> Bool -> Comp ()
-oneShotMsg _mb_mod_index recomp
-    = do hsc_env <- gets compHscEnv
+oneShotMsg :: GhcMonad m => Maybe (Int,Int) -> Bool -> ModSummary -> m ()
+oneShotMsg _mb_mod_index recomp _mod_summary
+    = do hsc_env <- getSession
          liftIO $ do
          if recomp
             then return ()
             else compilationProgressMsg (hsc_dflags hsc_env) $
                      "compilation IS NOT required"
 
-batchMsg :: Maybe (Int,Int) -> Bool -> Comp ()
-batchMsg mb_mod_index recomp
-    = do hsc_env <- gets compHscEnv
-         mod_summary <- gets compModSummary
+batchMsg :: GhcMonad m => Maybe (Int,Int) -> Bool -> ModSummary -> m ()
+batchMsg mb_mod_index recomp mod_summary
+    = do hsc_env <- getSession
          let showMsg msg = compilationProgressMsg (hsc_dflags hsc_env) $
                            (showModuleIndex mb_mod_index ++
                             msg ++ showModMsg (hscTarget (hsc_dflags hsc_env)) recomp mod_summary)
@@ -498,118 +556,66 @@ batchMsg mb_mod_index recomp
 --------------------------------------------------------------
 -- FrontEnds
 --------------------------------------------------------------
-hscFileFrontEnd :: Comp (Maybe TcGblEnv)
-hscFileFrontEnd =
-    do hsc_env <- gets compHscEnv
-       mod_summary <- gets compModSummary
-
-             -------------------
-             -- PARSE
-             -------------------
-       let dflags = hsc_dflags hsc_env
-           hspp_file = ms_hspp_file mod_summary
-           hspp_buf  = ms_hspp_buf  mod_summary
-       (ms@(warns,_), maybe_parsed)
-           <- liftIO $ myParseModule dflags hspp_file hspp_buf
-       case maybe_parsed of
-         Nothing
-             -> do logMsgs ms
-                   return Nothing
-         Just rdr_module
-             -------------------
-             -- RENAME and TYPECHECK
-             -------------------
-             -> do logMsgs (warns, emptyBag)
-                   (tc_msgs, maybe_tc_result)
-                       <- {-# SCC "Typecheck-Rename" #-}
-                          liftIO $ tcRnModule hsc_env (ms_hsc_src mod_summary)
-                                              False rdr_module
-                   logMsgs tc_msgs
-                   return maybe_tc_result
-
---------------------------------------------------------------
--- Desugaring
---------------------------------------------------------------
-
-hscDesugar :: TcGblEnv -> Comp (Maybe ModGuts)
-hscDesugar tc_result
-  = do mod_summary <- gets compModSummary
-       hsc_env <- gets compHscEnv
-
-          -------------------
-          -- DESUGAR
-          -------------------
-       (msgs, ds_result)
-           <- {-# SCC "DeSugar" #-}
-              liftIO $ deSugar hsc_env (ms_location mod_summary) tc_result
-       logMsgs msgs
-       return ds_result
+hscFileFrontEnd :: GhcMonad m => ModSummary -> m TcGblEnv
+hscFileFrontEnd mod_summary =
+    do rdr_module <- hscParse mod_summary
+       hscTypecheck mod_summary rdr_module
 
 --------------------------------------------------------------
 -- Simplifiers
 --------------------------------------------------------------
 
-hscSimplify :: ModGuts -> Comp ModGuts
+hscSimplify :: GhcMonad m => ModGuts -> m ModGuts
 hscSimplify ds_result
-  = do hsc_env <- gets compHscEnv
-       liftIO $ do
-           -------------------
-           -- SIMPLIFY
-           -------------------
+  = do hsc_env <- getSession
        simpl_result <- {-# SCC "Core2Core" #-}
-                       core2core hsc_env ds_result
+                       liftIO $ core2core hsc_env ds_result
        return simpl_result
 
 --------------------------------------------------------------
 -- Interface generators
 --------------------------------------------------------------
 
--- HACK: we return ModGuts even though we know it's not gonna be used.
---       We do this because the type signature needs to be identical
---       in structure to the type of 'hscNormalIface'.
-hscSimpleIface :: TcGblEnv -> Comp (ModIface, Bool, ModDetails, TcGblEnv)
-hscSimpleIface tc_result
-  = do hsc_env <- gets compHscEnv
-       maybe_old_iface <- gets compOldIface
-       liftIO $ do
-       details <- mkBootModDetailsTc hsc_env tc_result
+hscSimpleIface :: GhcMonad m =>
+                  TcGblEnv
+               -> Maybe Fingerprint
+               -> m (ModIface, Bool, ModDetails)
+hscSimpleIface tc_result mb_old_iface
+  = do hsc_env <- getSession
+       details <- liftIO $ mkBootModDetailsTc hsc_env tc_result
        (new_iface, no_change)
            <- {-# SCC "MkFinalIface" #-}
-              mkIfaceTc hsc_env (fmap mi_iface_hash maybe_old_iface) details tc_result
+              ioMsgMaybe $ mkIfaceTc hsc_env mb_old_iface details tc_result
        -- And the answer is ...
-       dumpIfaceStats hsc_env
-       return (new_iface, no_change, details, tc_result)
-
-hscNormalIface :: ModGuts -> Comp (ModIface, Bool, ModDetails, CgGuts)
-hscNormalIface simpl_result
-  = do hsc_env <- gets compHscEnv
-       _mod_summary <- gets compModSummary
-       maybe_old_iface <- gets compOldIface
-       liftIO $ do
-           -------------------
-           -- TIDY
-           -------------------
+       liftIO $ dumpIfaceStats hsc_env
+       return (new_iface, no_change, details)
+
+hscNormalIface :: GhcMonad m =>
+                  ModGuts
+               -> Maybe Fingerprint
+               -> m (ModIface, Bool, ModDetails, CgGuts)
+hscNormalIface simpl_result mb_old_iface
+  = do hsc_env <- getSession
+
        (cg_guts, details) <- {-# SCC "CoreTidy" #-}
-                             tidyProgram hsc_env simpl_result
+                             liftIO $ tidyProgram hsc_env simpl_result
 
-           -------------------
            -- BUILD THE NEW ModIface and ModDetails
            --  and emit external core if necessary
            -- This has to happen *after* code gen so that the back-end
            -- info has been set.  Not yet clear if it matters waiting
            -- until after code output
        (new_iface, no_change)
-               <- {-# SCC "MkFinalIface" #-}
-                  mkIface hsc_env (fmap mi_iface_hash maybe_old_iface)
-                         details simpl_result
+          <- {-# SCC "MkFinalIface" #-}
+             ioMsgMaybe $ mkIface hsc_env mb_old_iface
+                                   details simpl_result
        -- Emit external core
        -- This should definitely be here and not after CorePrep,
        -- because CorePrep produces unqualified constructor wrapper declarations,
        -- so its output isn't valid External Core (without some preprocessing).
-       emitExternalCore (hsc_dflags hsc_env) cg_guts 
-       dumpIfaceStats hsc_env
+       liftIO $ emitExternalCore (hsc_dflags hsc_env) cg_guts
+       liftIO $ dumpIfaceStats hsc_env
 
-           -------------------
            -- Return the prepared code.
        return (new_iface, no_change, details, cg_guts)
 
@@ -617,43 +623,23 @@ hscNormalIface simpl_result
 -- BackEnd combinators
 --------------------------------------------------------------
 
-hscWriteIface :: (ModIface, Bool, ModDetails, a) -> Comp (ModIface, ModDetails, a)
-hscWriteIface (iface, no_change, details, a)
-    = do mod_summary <- gets compModSummary
-         hsc_env <- gets compHscEnv
+hscWriteIface :: GhcMonad m =>
+                 ModIface -> Bool
+              -> ModSummary
+              -> m ()
+hscWriteIface iface no_change mod_summary
+    = do hsc_env <- getSession
          let dflags = hsc_dflags hsc_env
          liftIO $ do
          unless no_change
            $ writeIfaceFile dflags (ms_location mod_summary) iface
-         return (iface, details, a)
-
-hscIgnoreIface :: (ModIface, Bool, ModDetails, a) -> Comp (ModIface, ModDetails, a)
-hscIgnoreIface (iface, _no_change, details, a)
-    = return (iface, details, a)
-
--- Don't output any code.
-hscNothing :: (ModIface, ModDetails, a) -> Comp (Maybe (HscStatus, ModIface, ModDetails))
-hscNothing (iface, details, _)
-    = return (Just (HscRecomp False, iface, details))
-
--- Generate code and return both the new ModIface and the ModDetails.
-hscBatch :: (ModIface, ModDetails, CgGuts) -> Comp (Maybe (HscStatus, ModIface, ModDetails))
-hscBatch (iface, details, cgguts)
-    = do hasStub <- hscCompile cgguts
-         return (Just (HscRecomp hasStub, iface, details))
-
--- Here we don't need the ModIface and ModDetails anymore.
-hscOneShot :: (ModIface, ModDetails, CgGuts) -> Comp (Maybe HscStatus)
-hscOneShot (_, _, cgguts)
-    = do hasStub <- hscCompile cgguts
-         return (Just (HscRecomp hasStub))
-
--- Compile to hard-code.
-hscCompile :: CgGuts -> Comp Bool
-hscCompile cgguts
-    = do hsc_env <- gets compHscEnv
-         mod_summary <- gets compModSummary
-         liftIO $ do
+
+-- | Compile to hard-code.
+hscGenHardCode :: GhcMonad m =>
+                  CgGuts -> ModSummary
+               -> m Bool -- ^ @True@ <=> stub.c exists
+hscGenHardCode cgguts mod_summary
+    = withSession $ \hsc_env -> liftIO $ do
          let CgGuts{ -- This is the last use of the ModGuts in a compilation.
                      -- From now on, we just use the bits we need.
                      cg_module   = this_mod,
@@ -693,12 +679,13 @@ hscCompile cgguts
                 dependencies rawcmms
          return stub_c_exists
 
-hscInteractive :: (ModIface, ModDetails, CgGuts)
-               -> Comp (Maybe (InteractiveStatus, ModIface, ModDetails))
+hscInteractive :: GhcMonad m =>
+                  (ModIface, ModDetails, CgGuts)
+               -> ModSummary
+               -> m (InteractiveStatus, ModIface, ModDetails)
 #ifdef GHCI
-hscInteractive (iface, details, cgguts)
-    = do hsc_env <- gets compHscEnv
-         mod_summary <- gets compModSummary
+hscInteractive (iface, details, cgguts) mod_summary
+    = do hsc_env <- getSession
          liftIO $ do
          let CgGuts{ -- This is the last use of the ModGuts in a compilation.
                      -- From now on, we just use the bits we need.
@@ -723,9 +710,9 @@ hscInteractive (iface, details, cgguts)
          ------------------ Create f-x-dynamic C-side stuff ---
          (_istub_h_exists, istub_c_exists) 
              <- outputForeignStubs dflags this_mod location foreign_stubs
-         return (Just (InteractiveRecomp istub_c_exists comp_bc mod_breaks, iface, details))
+         return (HscRecomp istub_c_exists (comp_bc, mod_breaks), iface, details)
 #else
-hscInteractive _ = panic "GHC not compiled with interpreter"
+hscInteractive _ _ = panic "GHC not compiled with interpreter"
 #endif
 
 ------------------------------
@@ -780,37 +767,6 @@ testCmmConversion hsc_env cmm =
        return cvt
        -- return cmm -- don't use the conversion
 
-myParseModule :: DynFlags -> FilePath -> Maybe StringBuffer
-              -> IO (Messages, Maybe (Located (HsModule RdrName)))
-myParseModule dflags src_filename maybe_src_buf =
-   --------------------------  Parser  ----------------
-   showPass dflags "Parser" >>
-   {-# SCC "Parser" #-} do
-
-       -- sometimes we already have the buffer in memory, perhaps
-       -- because we needed to parse the imports out of it, or get the 
-       -- module name.
-     buf <- case maybe_src_buf of
-             Just b  -> return b
-             Nothing -> hGetStringBuffer src_filename
-
-     let loc  = mkSrcLoc (mkFastString src_filename) 1 0
-
-     case unP parseModule (mkPState buf loc dflags) of
-       PFailed span err ->
-           return ((emptyBag, unitBag (mkPlainErrMsg span err)), Nothing);
-
-       POk pst rdr_module -> do
-          let ms = getMessages pst
-          if errorsFound dflags ms then
-            return (ms, Nothing)
-           else do
-            dumpIfSet_dyn dflags Opt_D_dump_parsed "Parser" (ppr rdr_module) ;
-            dumpIfSet_dyn dflags Opt_D_source_stats "Source Statistics"
-                                 (ppSourceStats False rdr_module) ;
-            return (ms, Just rdr_module)
-            -- ToDo: free the string buffer later.
-
 myCoreToStg :: DynFlags -> Module -> [CoreBind]
             -> IO ( [(StgBinding,[(Id,[Id])])]  -- output program
                  , CollectedCCs) -- cost centre info (declared and used)
index 76e28be..0d83a92 100644 (file)
@@ -18,7 +18,7 @@ module HscTypes (
         handleFlagWarnings,
 
        -- * Sessions and compilation state
-       Session(..), withSession, modifySession,
+       Session(..), withSession, modifySession, withTempSession,
         HscEnv(..), hscEPS,
        FinderCache, FindResult(..), ModLocationCache,
        Target(..), TargetId(..), pprTarget, pprTargetId,
@@ -293,6 +293,16 @@ modifySession :: GhcMonad m => (HscEnv -> HscEnv) -> m ()
 modifySession f = do h <- getSession
                      setSession $! f h
 
+withSavedSession :: GhcMonad m => m a -> m a
+withSavedSession m = do
+  saved_session <- getSession
+  m `gfinally` setSession saved_session
+
+-- | Call an action with a temporarily modified Session.
+withTempSession :: GhcMonad m => (HscEnv -> HscEnv) -> m a -> m a
+withTempSession f m =
+  withSavedSession $ modifySession f >> m
+
 -- | A minimal implementation of a 'GhcMonad'.  If you need a custom monad,
 -- e.g., to maintain additional state consider wrapping this monad or using
 -- 'GhcT'.