summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--compiler/iface/MkIface.lhs22
-rw-r--r--compiler/main/DriverPipeline.hs8
-rw-r--r--compiler/main/GHC.hs66
-rw-r--r--compiler/main/HscMain.lhs690
-rw-r--r--compiler/main/HscTypes.lhs12
5 files changed, 377 insertions, 421 deletions
diff --git a/compiler/iface/MkIface.lhs b/compiler/iface/MkIface.lhs
index 285f17197d..97449b712b 100644
--- a/compiler/iface/MkIface.lhs
+++ b/compiler/iface/MkIface.lhs
@@ -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
diff --git a/compiler/main/DriverPipeline.hs b/compiler/main/DriverPipeline.hs
index 3a883187ef..2846eafaec 100644
--- a/compiler/main/DriverPipeline.hs
+++ b/compiler/main/DriverPipeline.hs
@@ -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
diff --git a/compiler/main/GHC.hs b/compiler/main/GHC.hs
index 29bb4f7288..f3e0199d64 100644
--- a/compiler/main/GHC.hs
+++ b/compiler/main/GHC.hs
@@ -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
diff --git a/compiler/main/HscMain.lhs b/compiler/main/HscMain.lhs
index 9e134d5191..2fefcd4239 100644
--- a/compiler/main/HscMain.lhs
+++ b/compiler/main/HscMain.lhs
@@ -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)
diff --git a/compiler/main/HscTypes.lhs b/compiler/main/HscTypes.lhs
index 76e28be6d4..0d83a925ee 100644
--- a/compiler/main/HscTypes.lhs
+++ b/compiler/main/HscTypes.lhs
@@ -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'.