FinderCache, FindResult(..), ModLocationCache,
Target(..), TargetId(..), pprTarget, pprTargetId,
ModuleGraph, emptyMG,
+ -- ** Callbacks
+ GhcApiCallbacks(..), withLocalCallbacks,
-- * Information about modules
ModDetails(..), emptyModDetails,
-- * Interactive context
InteractiveContext(..), emptyInteractiveContext,
- icPrintUnqual, mkPrintUnqualified, extendInteractiveContext,
+ icPrintUnqual, extendInteractiveContext,
substInteractiveContext,
+ mkPrintUnqualified, pprModulePrefix,
-- * Interfaces
ModIface(..), mkIfaceWarnCache, mkIfaceHashCache, mkIfaceFixCache,
import {-# SOURCE #-} InteractiveEval ( Resume )
#endif
+import HsSyn
import RdrName
import Name
import NameEnv
import NameSet
-import OccName ( OccName, OccEnv, lookupOccEnv, mkOccEnv, emptyOccEnv,
- extendOccEnv )
import Module
import InstEnv ( InstEnv, Instance )
import FamInstEnv ( FamInstEnv, FamInst )
import Type
import Annotations
-import Class ( Class, classSelIds, classATs, classTyCon )
+import Class ( Class, classAllSelIds, classATs, classTyCon )
import TyCon
import DataCon ( DataCon, dataConImplicitIds, dataConWrapId )
import PrelNames ( gHC_PRIM )
import DynFlags ( DynFlags(..), isOneShot, HscTarget (..), dopt,
DynFlag(..) )
import DriverPhases ( HscSource(..), isHsBoot, hscSourceString, Phase )
-import BasicTypes ( IPName, Fixity, defaultFixity, WarningTxt(..) )
+import BasicTypes ( IPName, defaultFixity, WarningTxt(..) )
import OptimizationFuel ( OptFuelState )
import IfaceSyn
-import FiniteMap ( FiniteMap )
import CoreSyn ( CoreRule )
import Maybes ( orElse, expectJust, catMaybes )
import Outputable
import BreakArray
import SrcLoc ( SrcSpan, Located(..) )
-import LazyUniqFM ( lookupUFM, eltsUFM, emptyUFM )
+import UniqFM ( lookupUFM, eltsUFM, emptyUFM )
import UniqSupply ( UniqSupply )
import FastString
import StringBuffer ( StringBuffer )
import Data.IORef
import Data.Array ( Array, array )
import Data.List
+import Data.Map (Map)
import Control.Monad ( mplus, guard, liftM, when )
import Exception
\end{code}
Ghc $ \s -> unGhc act s `gcatch` \e -> unGhc (handle e) s
gblock (Ghc m) = Ghc $ \s -> gblock (m s)
gunblock (Ghc m) = Ghc $ \s -> gunblock (m s)
+ gmask f =
+ Ghc $ \s -> gmask $ \io_restore ->
+ let
+ g_restore (Ghc m) = Ghc $ \s -> io_restore (m s)
+ in
+ unGhc (f g_restore) s
instance WarnLogMonad Ghc where
setWarnings warns = Ghc $ \(Session _ wref) -> writeIORef wref warns
GhcT $ \s -> unGhcT act s `gcatch` \e -> unGhcT (handle e) s
gblock (GhcT m) = GhcT $ \s -> gblock (m s)
gunblock (GhcT m) = GhcT $ \s -> gunblock (m s)
+ gmask f =
+ GhcT $ \s -> gmask $ \io_restore ->
+ let
+ g_restore (GhcT m) = GhcT $ \s -> io_restore (m s)
+ in
+ unGhcT (f g_restore) s
instance MonadIO m => WarnLogMonad (GhcT m) where
setWarnings warns = GhcT $ \(Session _ wref) -> liftIO $ writeIORef wref warns
\end{code}
\begin{code}
--- | HscEnv is like 'Session', except that some of the fields are immutable.
+-- | These functions are called in various places of the GHC API.
+--
+-- API clients can override any of these callbacks to change GHC's default
+-- behaviour.
+data GhcApiCallbacks
+ = GhcApiCallbacks {
+
+ -- | Called by 'load' after the compilating of each module.
+ --
+ -- The default implementation simply prints all warnings and errors to
+ -- @stderr@. Don't forget to call 'clearWarnings' when implementing your
+ -- own call.
+ --
+ -- The first argument is the module that was compiled.
+ --
+ -- The second argument is @Nothing@ if no errors occured, but there may
+ -- have been warnings. If it is @Just err@ at least one error has
+ -- occured. If 'srcErrorMessages' is empty, compilation failed due to
+ -- @-Werror@.
+ reportModuleCompilationResult :: GhcMonad m =>
+ ModSummary -> Maybe SourceError
+ -> m ()
+ }
+
+-- | Temporarily modify the callbacks. After the action is executed all
+-- callbacks are reset (not, however, any other modifications to the session
+-- state.)
+withLocalCallbacks :: GhcMonad m =>
+ (GhcApiCallbacks -> GhcApiCallbacks)
+ -> m a -> m a
+withLocalCallbacks f m = do
+ hsc_env <- getSession
+ let cb0 = hsc_callbacks hsc_env
+ let cb' = f cb0
+ setSession (hsc_env { hsc_callbacks = cb' `seq` cb' })
+ r <- m
+ hsc_env' <- getSession
+ setSession (hsc_env' { hsc_callbacks = cb0 })
+ return r
+
+\end{code}
+
+\begin{code}
+-- | 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.
hsc_dflags :: DynFlags,
-- ^ The dynamic flag settings
+ hsc_callbacks :: GhcApiCallbacks,
+ -- ^ Callbacks for the GHC API.
+
hsc_targets :: [Target],
-- ^ The targets (or roots) of the current session
-- ^ The requested package was not found
| FoundMultiple [PackageId]
-- ^ _Error_: both in multiple packages
- | PackageHidden PackageId
- -- ^ For an explicit source import, the package containing the module is
- -- not exposed.
- | ModuleHidden PackageId
- -- ^ For an explicit source import, the package containing the module is
- -- exposed, but the module itself is hidden.
- | NotFound [FilePath] (Maybe PackageId)
- -- ^ The module was not found, the specified places were searched
+ | NotFound [FilePath] (Maybe PackageId) [PackageId] [PackageId]
+ -- ^ The module was not found, including either
+ -- * the specified places were searched
+ -- * the package that this module should have been in
+ -- * list of packages in which the module was hidden,
+ -- * list of hidden packages containing this module
| NotFoundInPackage PackageId
-- ^ The module was not found in this package
mi_boot :: !IsBootInterface, -- ^ Read from an hi-boot file?
mi_deps :: Dependencies,
- -- ^ The dependencies of the module, consulted for directly
- -- imported modules only
-
- -- This is consulted for directly-imported modules,
- -- but not for anything else (hence lazy)
+ -- ^ The dependencies of the module. This is
+ -- consulted for directly-imported modules, but not
+ -- for anything else (hence lazy)
+
mi_usages :: [Usage],
-- ^ Usages; kept sorted so that it's easy to decide
-- whether to write a new iface file (changing usages
mg_insts :: ![Instance], -- ^ Class instances declared in this module
mg_fam_insts :: ![FamInst], -- ^ Family instances declared in this module
mg_rules :: ![CoreRule], -- ^ Before the core pipeline starts, contains
- -- rules declared in this module. After the core
- -- pipeline starts, it is changed to contain all
- -- known rules for those things imported
+ -- See Note [Overall plumbing for rules] in Rules.lhs
mg_binds :: ![CoreBind], -- ^ Bindings for this module
mg_foreign :: !ForeignStubs, -- ^ Foreign exports declared in this module
mg_warns :: !Warnings, -- ^ Warnings declared in the module
ic_toplev_scope :: [Module], -- ^ The context includes the "top-level" scope of
-- these modules
- ic_exports :: [Module], -- ^ The context includes just the exports of these
+ ic_exports :: [(Module, Maybe (ImportDecl RdrName))], -- ^ The context includes just the exported parts of these
-- modules
ic_rn_gbl_env :: GlobalRdrEnv, -- ^ The contexts' cached 'GlobalRdrEnv', built from
#ifdef GHCI
, ic_resume :: [Resume] -- ^ The stack of breakpoint contexts
#endif
+
+ , ic_cwd :: Maybe FilePath -- virtual CWD of the program
}
#ifdef GHCI
, ic_resume = []
#endif
+ , ic_cwd = Nothing
}
icPrintUnqual :: DynFlags -> InteractiveContext -> PrintUnqualified
%* *
%************************************************************************
+Note [Printing original names]
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Deciding how to print names is pretty tricky. We are given a name
P:M.T, where P is the package name, M is the defining module, and T is
the occurrence name, and we have to decide in which form to display
scope. However, the name might not be in scope at all, and that's
where it gets tricky. Here are the cases:
- 1. T uniquely maps to P:M.T ---> "T"
- 2. there is an X for which X.T uniquely maps to P:M.T ---> "X.T"
- 3. there is no binding for "M.T" ---> "M.T"
- 4. otherwise ---> "P:M.T"
-
-3 and 4 apply when P:M.T is not in scope. In these cases we want to
-refer to the name as "M.T", but "M.T" might mean something else in the
-current scope (e.g. if there's an "import X as M"), so to avoid
-confusion we avoid using "M.T" if there's already a binding for it.
-
-There's one further subtlety: if the module M cannot be imported
-because it is not exposed by any package, then we must refer to it as
-"P:M". This is handled by the qual_mod component of PrintUnqualified.
+ 1. T uniquely maps to P:M.T ---> "T" NameUnqual
+ 2. There is an X for which X.T
+ uniquely maps to P:M.T ---> "X.T" NameQual X
+ 3. There is no binding for "M.T" ---> "M.T" NameNotInScope1
+ 4. Otherwise ---> "P:M.T" NameNotInScope2
+
+(3) and (4) apply when the entity P:M.T is not in the GlobalRdrEnv at
+all. In these cases we still want to refer to the name as "M.T", *but*
+"M.T" might mean something else in the current scope (e.g. if there's
+an "import X as M"), so to avoid confusion we avoid using "M.T" if
+there's already a binding for it. Instead we write P:M.T.
+
+There's one further subtlety: in case (3), what if there are two
+things around, P1:M.T and P2:M.T? Then we don't want to print both of
+them as M.T! However only one of the modules P1:M and P2:M can be
+exposed (say P2), so we use M.T for that, and P1:M.T for the other one.
+This is handled by the qual_mod component of PrintUnqualified, inside
+the (ppr mod) of case (3), in Name.pprModulePrefix
\begin{code}
-- | Creates some functions that work out the best ways to format
implicitTyThings :: TyThing -> [TyThing]
-- For data and newtype declarations:
-implicitTyThings (ATyCon tc) =
- -- fields (names of selectors)
- map AnId (tyConSelIds tc) ++
- -- (possibly) implicit coercion and family coercion
- -- depending on whether it's a newtype or a family instance or both
+implicitTyThings (ATyCon tc)
+ = -- fields (names of selectors)
+ -- (possibly) implicit coercion and family coercion
+ -- depending on whether it's a newtype or a family instance or both
implicitCoTyCon tc ++
- -- for each data constructor in order,
- -- the contructor, worker, and (possibly) wrapper
+ -- for each data constructor in order,
+ -- the contructor, worker, and (possibly) wrapper
concatMap (extras_plus . ADataCon) (tyConDataCons tc)
implicitTyThings (AClass cl)
-- are only the family decls; they have no implicit things
map ATyCon (classATs cl) ++
-- superclass and operation selectors
- map AnId (classSelIds cl)
+ map AnId (classAllSelIds cl)
implicitTyThings (ADataCon dc) =
-- For data cons add the worker and (possibly) wrapper
type OrigNameCache = ModuleEnv (OccEnv Name)
-- | Module-local cache of implicit parameter 'OccName's given 'Name's
-type OrigIParamCache = FiniteMap (IPName OccName) (IPName Name)
+type OrigIParamCache = Map (IPName OccName) (IPName Name)
\end{code}
-- There will be a node for each source module, plus a node for each hi-boot
-- module.
--
--- The graph is not necessarily stored in topologically-sorted order.
+-- The graph is not necessarily stored in topologically-sorted order. Use
+-- 'GHC.topSortModuleGraph' and 'Digraph.flattenSCC' to achieve this.
type ModuleGraph = [ModSummary]
emptyMG :: ModuleGraph
ms_location :: ModLocation, -- ^ Location of the various files belonging to the module
ms_hs_date :: ClockTime, -- ^ Timestamp of source file
ms_obj_date :: Maybe ClockTime, -- ^ Timestamp of object, if we have one
- ms_srcimps :: [Located ModuleName], -- ^ Source imports of the module
- ms_imps :: [Located ModuleName], -- ^ Non-source imports of the module
+ ms_srcimps :: [Located (ImportDecl RdrName)], -- ^ Source imports of the module
+ ms_imps :: [Located (ImportDecl RdrName)], -- ^ Non-source imports of the module
ms_hspp_file :: FilePath, -- ^ Filename of preprocessed source file
ms_hspp_opts :: DynFlags, -- ^ Cached flags from @OPTIONS@, @INCLUDE@
-- and @LANGUAGE@ pragmas in the modules source code
\begin{code}
-- | Vectorisation information for 'ModGuts', 'ModDetails' and 'ExternalPackageState'.
--- All of this information is always tidy, even in ModGuts.
data VectInfo
= VectInfo {
vectInfoVar :: VarEnv (Var , Var ), -- ^ @(f, f_v)@ keyed on @f@