+HscEnv is like Session, except that some of the fields are immutable.
+An HscEnv is used to compile a single module from plain Haskell source
+code (after preprocessing) to either C, assembly or C--. Things like
+the module graph don't change during a single compilation.
+
+Historical note: "hsc" used to be the name of the compiler binary,
+when there was a separate driver and compiler. To compile a single
+module, the driver would invoke hsc on the source code... so nowadays
+we think of hsc as the layer of the compiler that deals with compiling
+a single module.
+
+\begin{code}
+data HscEnv
+ = HscEnv {
+ hsc_dflags :: DynFlags,
+ -- The dynamic flag settings
+
+ hsc_targets :: [Target],
+ -- The targets (or roots) of the current session
+
+ hsc_mod_graph :: ModuleGraph,
+ -- The module graph of the current session
+
+ hsc_IC :: InteractiveContext,
+ -- The context for evaluating interactive statements
+
+ hsc_HPT :: HomePackageTable,
+ -- The home package table describes already-compiled
+ -- home-packge modules, *excluding* the module we
+ -- are compiling right now.
+ -- (In one-shot mode the current module is the only
+ -- home-package module, so hsc_HPT is empty. All other
+ -- modules count as "external-package" modules.
+ -- However, even in GHCi mode, hi-boot interfaces are
+ -- demand-loadeded into the external-package table.)
+ --
+ -- hsc_HPT is not mutable because we only demand-load
+ -- external packages; the home package is eagerly
+ -- loaded, module by module, by the compilation manager.
+ --
+ -- The HPT may contain modules compiled earlier by --make
+ -- but not actually below the current module in the dependency
+ -- graph. (This changes a previous invariant: changed Jan 05.)
+
+ hsc_EPS :: {-# UNPACK #-} !(IORef ExternalPackageState),
+ hsc_NC :: {-# UNPACK #-} !(IORef NameCache),
+ -- These are side-effected by compiling to reflect
+ -- sucking in interface files. They cache the state of
+ -- external interface files, in effect.
+
+ hsc_FC :: {-# UNPACK #-} !(IORef FinderCache)
+ -- The finder's cache. This caches the location of modules,
+ -- so we don't have to search the filesystem multiple times.
+ }
+
+hscEPS :: HscEnv -> IO ExternalPackageState
+hscEPS hsc_env = readIORef (hsc_EPS hsc_env)
+
+-- | A compilation target.
+--
+-- A target may be supplied with the actual text of the
+-- module. If so, use this instead of the file contents (this
+-- is for use in an IDE where the file hasn't been saved by
+-- the user yet).
+data Target = Target TargetId (Maybe (StringBuffer,ClockTime))
+
+data TargetId
+ = TargetModule Module
+ -- ^ A module name: search for the file
+ | TargetFile FilePath (Maybe Phase)
+ -- ^ A filename: preprocess & parse it to find the module name.
+ -- If specified, the Phase indicates how to compile this file
+ -- (which phase to start from). Nothing indicates the starting phase
+ -- should be determined from the suffix of the filename.
+ deriving Eq
+
+pprTarget :: Target -> SDoc
+pprTarget (Target id _) = pprTargetId id
+
+pprTargetId (TargetModule m) = ppr m
+pprTargetId (TargetFile f _) = text f
+
+type FinderCache = ModuleEnv FinderCacheEntry
+type FinderCacheEntry = (ModLocation, Maybe (PackageConfig,Bool))
+ -- The finder's cache (see module Finder)
+
+type HomePackageTable = ModuleEnv HomeModInfo
+ -- Domain = modules in the home package
+type PackageIfaceTable = ModuleEnv ModIface
+ -- Domain = modules in the imported packages
+
+emptyHomePackageTable = emptyModuleEnv
+emptyPackageIfaceTable = emptyModuleEnv
+
+data HomeModInfo
+ = HomeModInfo { hm_iface :: !ModIface,
+ hm_details :: !ModDetails,
+ hm_linkable :: !(Maybe Linkable) }
+ -- hm_linkable might be Nothing if:
+ -- a) this is an .hs-boot module
+ -- b) temporarily during compilation if we pruned away
+ -- the old linkable because it was out of date.
+ -- after a complete compilation (GHC.load), all hm_linkable
+ -- fields in the HPT will be Just.
+ --
+ -- When re-linking a module (hscNoRecomp), we construct
+ -- the HomModInfo by building a new ModDetails from the
+ -- old ModIface (only).