X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;f=compiler%2Fmain%2FHscTypes.lhs;h=c1e6f34b16f2794f64a1dc3ef22affaff09f181d;hb=9393f9eacb06271a1eb820c7ddc14ef8b5872a96;hp=83dda3f81b8ec908c32af0cbde8e1a9f09fd0b30;hpb=66579ff945831c5fc9a17c58c722ff01f2268d76;p=ghc-hetmet.git diff --git a/compiler/main/HscTypes.lhs b/compiler/main/HscTypes.lhs index 83dda3f..c1e6f34 100644 --- a/compiler/main/HscTypes.lhs +++ b/compiler/main/HscTypes.lhs @@ -13,15 +13,18 @@ module HscTypes ( ioMsgMaybe, ioMsg, logWarnings, clearWarnings, hasWarnings, SourceError, GhcApiError, mkSrcErr, srcErrorMessages, mkApiErr, - handleSourceError, + throwOneError, handleSourceError, reflectGhc, reifyGhc, + handleFlagWarnings, -- * Sessions and compilation state - Session(..), withSession, modifySession, + Session(..), withSession, modifySession, withTempSession, HscEnv(..), hscEPS, FinderCache, FindResult(..), ModLocationCache, Target(..), TargetId(..), pprTarget, pprTargetId, ModuleGraph, emptyMG, + -- ** Callbacks + GhcApiCallbacks(..), withLocalCallbacks, -- * Information about modules ModDetails(..), emptyModDetails, @@ -45,6 +48,10 @@ module HscTypes ( PackageInstEnv, PackageRuleBase, + + -- * Annotations + prepareAnnotations, + -- * Interactive context InteractiveContext(..), emptyInteractiveContext, icPrintUnqual, mkPrintUnqualified, extendInteractiveContext, @@ -104,6 +111,7 @@ import ByteCodeAsm ( CompiledByteCode ) import {-# SOURCE #-} InteractiveEval ( Resume ) #endif +import HsSyn import RdrName import Name import NameEnv @@ -121,12 +129,14 @@ import Var import Id import Type +import Annotations import Class ( Class, classSelIds, classATs, classTyCon ) import TyCon import DataCon ( DataCon, dataConImplicitIds, dataConWrapId ) import PrelNames ( gHC_PRIM ) import Packages hiding ( Version(..) ) -import DynFlags ( DynFlags(..), isOneShot, HscTarget (..) ) +import DynFlags ( DynFlags(..), isOneShot, HscTarget (..), dopt, + DynFlag(..) ) import DriverPhases ( HscSource(..), isHsBoot, hscSourceString, Phase ) import BasicTypes ( IPName, Fixity, defaultFixity, WarningTxt(..) ) import OptimizationFuel ( OptFuelState ) @@ -136,29 +146,24 @@ import CoreSyn ( CoreRule ) import Maybes ( orElse, expectJust, catMaybes ) import Outputable import BreakArray -import SrcLoc ( SrcSpan, Located ) +import SrcLoc ( SrcSpan, Located(..) ) import LazyUniqFM ( lookupUFM, eltsUFM, emptyUFM ) import UniqSupply ( UniqSupply ) import FastString import StringBuffer ( StringBuffer ) import Fingerprint import MonadUtils -import Bag ( emptyBag, unionBags, isEmptyBag ) import Data.Dynamic ( Typeable ) import qualified Data.Dynamic as Dyn -#if __GLASGOW_HASKELL__ < 609 -import Data.Dynamic ( toDyn, fromDyn, fromDynamic ) -#else -import Bag ( bagToList ) -#endif -import ErrUtils ( ErrorMessages, WarningMessages, Messages ) +import Bag +import ErrUtils import System.FilePath import System.Time ( ClockTime ) import Data.IORef import Data.Array ( Array, array ) import Data.List -import Control.Monad ( mplus, guard, liftM ) +import Control.Monad ( mplus, guard, liftM, when ) import Exception \end{code} @@ -181,7 +186,8 @@ mkSrcErr :: ErrorMessages -> SourceError srcErrorMessages :: SourceError -> ErrorMessages mkApiErr :: SDoc -> GhcApiError -#if __GLASGOW_HASKELL__ >= 609 +throwOneError :: MonadIO m => ErrMsg -> m ab +throwOneError err = liftIO $ throwIO $ mkSrcErr $ unitBag err -- | A source error is an error that is caused by one or more errors in the -- source code. A 'SourceError' is thrown by many functions in the @@ -242,43 +248,6 @@ instance Exception GhcApiError mkApiErr = GhcApiError -#else ------------------------------------------------------------------------- --- implementation for bootstrapping without extensible exceptions - -data SourceException = SourceException ErrorMessages -sourceExceptionTc :: Dyn.TyCon -sourceExceptionTc = Dyn.mkTyCon "SourceException" -{-# NOINLINE sourceExceptionTc #-} -instance Typeable SourceException where - typeOf _ = Dyn.mkTyConApp sourceExceptionTc [] - --- Source error has to look like a normal exception. Throwing a DynException --- directly would not allow us to use the Exception monad. We also cannot --- make it part of GhcException as that would lead to circular imports. - -type SourceError = Exception -type GhcApiError = Exception - -mkSrcErr msgs = DynException . toDyn $ SourceException msgs - -mkApiErr = IOException . userError . showSDoc - -srcErrorMessages (DynException ms) = - let SourceException msgs = (fromDyn ms (panic "SourceException expected")) - in msgs -srcErrorMessages _ = panic "SourceError expected" - -handleSourceError :: ExceptionMonad m => (Exception -> m a) -> m a -> m a -handleSourceError handler act = - gcatch act - (\e -> case e of - DynException dyn - | Just (SourceException _) <- fromDynamic dyn - -> handler e - _ -> throw e) -#endif - -- | A monad that allows logging of warnings. class Monad m => WarnLogMonad m where setWarnings :: WarningMessages -> m () @@ -327,6 +296,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'. @@ -345,10 +324,9 @@ instance MonadIO Ghc where instance ExceptionMonad Ghc where gcatch act handle = Ghc $ \s -> unGhc act s `gcatch` \e -> unGhc (handle e) s -#if __GLASGOW_HASKELL__ < 609 - gcatchDyn act handler = - Ghc $ \s -> unGhc act s `gcatchDyn` \e -> unGhc (handler e) s -#endif + gblock (Ghc m) = Ghc $ \s -> gblock (m s) + gunblock (Ghc m) = Ghc $ \s -> gunblock (m s) + instance WarnLogMonad Ghc where setWarnings warns = Ghc $ \(Session _ wref) -> writeIORef wref warns -- | Return 'Warnings' accumulated so far. @@ -378,9 +356,8 @@ instance MonadIO m => MonadIO (GhcT m) where instance ExceptionMonad m => ExceptionMonad (GhcT m) where gcatch act handle = GhcT $ \s -> unGhcT act s `gcatch` \e -> unGhcT (handle e) s -#if __GLASGOW_HASKELL__ < 609 - gcatchDyn _act _handler = error "cannot use GhcT in stage1" -#endif + gblock (GhcT m) = GhcT $ \s -> gblock (m s) + gunblock (GhcT m) = GhcT $ \s -> gunblock (m s) instance MonadIO m => WarnLogMonad (GhcT m) where setWarnings warns = GhcT $ \(Session _ wref) -> liftIO $ writeIORef wref warns @@ -413,7 +390,7 @@ ioMsgMaybe ioA = do ((warns,errs), mb_r) <- liftIO ioA logWarnings warns case mb_r of - Nothing -> throw (mkSrcErr errs) + Nothing -> liftIO $ throwIO (mkSrcErr errs) Just r -> ASSERT( isEmptyBag errs ) return r -- | Lift a non-failing IO action into a 'GhcMonad'. @@ -447,10 +424,71 @@ reflectGhc m = unGhc m -- > Dual to 'reflectGhc'. See its documentation. reifyGhc :: (Session -> IO a) -> Ghc a reifyGhc act = Ghc $ act + +handleFlagWarnings :: GhcMonad m => DynFlags -> [Located String] -> m () +handleFlagWarnings dflags warns + = when (dopt Opt_WarnDeprecatedFlags dflags) + (handleFlagWarnings' dflags warns) + +handleFlagWarnings' :: GhcMonad m => DynFlags -> [Located String] -> m () +handleFlagWarnings' _ [] = return () +handleFlagWarnings' dflags warns + = do -- It would be nicer if warns :: [Located Message], but that has circular + -- import problems. + logWarnings $ listToBag (map mkFlagWarning warns) + when (dopt Opt_WarnIsError dflags) $ + liftIO $ throwIO $ mkSrcErr emptyBag + +mkFlagWarning :: Located String -> WarnMsg +mkFlagWarning (L loc warn) + = mkPlainWarnMsg loc (text warn) \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. @@ -465,6 +503,9 @@ data HscEnv 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 @@ -542,9 +583,11 @@ hscEPS hsc_env = readIORef (hsc_EPS hsc_env) -- is for use in an IDE where the file hasn't been saved by -- the user yet). data Target = Target - TargetId -- module or filename - Bool -- object code allowed? - (Maybe (StringBuffer,ClockTime)) -- in-memory text buffer? + { targetId :: TargetId -- ^ module or filename + , targetAllowObjCode :: Bool -- ^ object code allowed? + , targetContents :: Maybe (StringBuffer,ClockTime) + -- ^ in-memory text buffer? + } data TargetId = TargetModule ModuleName @@ -587,30 +630,31 @@ emptyPackageIfaceTable = emptyModuleEnv -- | Information about modules in the package being compiled data HomeModInfo - = HomeModInfo { hm_iface :: !ModIface, -- ^ The basic loaded interface file: every - -- loaded module has one of these, even if - -- it is imported from another package - hm_details :: !ModDetails, -- ^ Extra information that has been created - -- from the 'ModIface' for the module, - -- typically during typechecking - hm_linkable :: !(Maybe Linkable) - -- ^ The actual artifact we would like to link to access - -- things in this module. - -- - -- 'hm_linkable' might be Nothing: - -- - -- 1. If this is an .hs-boot module - -- - -- 2. 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 'HomePackageTable' will be @Just@. - -- - -- When re-linking a module ('HscMain.HscNoRecomp'), we construct - -- the 'HomeModInfo' by building a new 'ModDetails' from the - -- old 'ModIface' (only). - } + = HomeModInfo { + hm_iface :: !ModIface, + -- ^ The basic loaded interface file: every loaded module has one of + -- these, even if it is imported from another package + hm_details :: !ModDetails, + -- ^ Extra information that has been created from the 'ModIface' for + -- the module, typically during typechecking + hm_linkable :: !(Maybe Linkable) + -- ^ The actual artifact we would like to link to access things in + -- this module. + -- + -- 'hm_linkable' might be Nothing: + -- + -- 1. If this is an .hs-boot module + -- + -- 2. 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 'HomePackageTable' will be @Just@. + -- + -- When re-linking a module ('HscMain.HscNoRecomp'), we construct the + -- 'HomeModInfo' by building a new 'ModDetails' from the old + -- 'ModIface' (only). + } -- | Find the 'ModIface' for a 'Module', searching in both the loaded home -- and external package module information @@ -663,6 +707,12 @@ hptRules :: HscEnv -> [(ModuleName, IsBootInterface)] -> [CoreRule] -- ^ Get rules from modules \"below\" this one (in the dependency sense) hptRules = hptSomeThingsBelowUs (md_rules . hm_details) False + +hptAnns :: HscEnv -> Maybe [(ModuleName, IsBootInterface)] -> [Annotation] +-- ^ Get annotations from modules \"below\" this one (in the dependency sense) +hptAnns hsc_env (Just deps) = hptSomeThingsBelowUs (md_anns . hm_details) False hsc_env deps +hptAnns hsc_env Nothing = hptAllThings (md_anns . hm_details) hsc_env + hptAllThings :: (HomeModInfo -> [a]) -> HscEnv -> [a] hptAllThings extract hsc_env = concatMap extract (eltsUFM (hsc_HPT hsc_env)) @@ -697,7 +747,32 @@ hptSomeThingsBelowUs extract include_hi_boot hsc_env deps -- And get its dfuns , thing <- things ] +\end{code} +%************************************************************************ +%* * +\subsection{Dealing with Annotations} +%* * +%************************************************************************ + +\begin{code} +prepareAnnotations :: HscEnv -> Maybe ModGuts -> IO AnnEnv +-- ^ Deal with gathering annotations in from all possible places +-- and combining them into a single 'AnnEnv' +prepareAnnotations hsc_env mb_guts + = do { eps <- hscEPS hsc_env + ; let -- Extract annotations from the module being compiled if supplied one + mb_this_module_anns = fmap (mkAnnEnv . mg_anns) mb_guts + -- Extract dependencies of the module if we are supplied one, + -- otherwise load annotations from all home package table + -- entries regardless of dependency ordering. + home_pkg_anns = (mkAnnEnv . hptAnns hsc_env) $ fmap (dep_mods . mg_deps) mb_guts + other_pkg_anns = eps_ann_env eps + ann_env = foldl1' plusAnnEnv $ catMaybes [mb_this_module_anns, + Just home_pkg_anns, + Just other_pkg_anns] + + ; return ann_env } \end{code} %************************************************************************ @@ -725,14 +800,12 @@ data FindResult -- ^ 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 @@ -769,11 +842,10 @@ data ModIface 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 @@ -800,6 +872,11 @@ data ModIface -- NOT STRICT! we read this field lazily from the interface file + mi_anns :: [IfaceAnnotation], + -- ^ Annotations + + -- NOT STRICT! we read this field lazily from the interface file + -- Type, class and variable declarations -- The hash of an Id changes if its fixity or deprecations change -- (as well as its type of course) @@ -858,6 +935,8 @@ data ModDetails md_insts :: ![Instance], -- ^ 'DFunId's for the instances in this module md_fam_insts :: ![FamInst], md_rules :: ![CoreRule], -- ^ Domain may include 'Id's from other modules + md_anns :: ![Annotation], -- ^ Annotations present in this module: currently + -- they only annotate things also declared in this module md_vect_info :: !VectInfo -- ^ Module vectorisation information } @@ -867,6 +946,7 @@ emptyModDetails = ModDetails { md_types = emptyTypeEnv, md_insts = [], md_rules = [], md_fam_insts = [], + md_anns = [], md_vect_info = noVectInfo } @@ -905,6 +985,7 @@ data ModGuts mg_binds :: ![CoreBind], -- ^ Bindings for this module mg_foreign :: !ForeignStubs, -- ^ Foreign exports declared in this module mg_warns :: !Warnings, -- ^ Warnings declared in the module + mg_anns :: [Annotation], -- ^ Annotations declared in this module mg_hpc_info :: !HpcInfo, -- ^ Coverage tick boxes in the module mg_modBreaks :: !ModBreaks, -- ^ Breakpoints for the module mg_vect_info :: !VectInfo, -- ^ Pool of vectorised declarations in the module @@ -1018,6 +1099,7 @@ emptyModIface mod mi_exp_hash = fingerprint0, mi_fixities = [], mi_warns = NoWarnings, + mi_anns = [], mi_insts = [], mi_fam_insts = [], mi_rules = [], @@ -1064,6 +1146,8 @@ data InteractiveContext #ifdef GHCI , ic_resume :: [Resume] -- ^ The stack of breakpoint contexts #endif + + , ic_cwd :: Maybe FilePath -- virtual CWD of the program } @@ -1077,6 +1161,7 @@ emptyInteractiveContext #ifdef GHCI , ic_resume = [] #endif + , ic_cwd = Nothing } icPrintUnqual :: DynFlags -> InteractiveContext -> PrintUnqualified @@ -1208,14 +1293,13 @@ mkPrintUnqualified dflags env = (qual_name, qual_mod) 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) @@ -1338,7 +1422,7 @@ lookupType dflags hpt pte name lookupTypeHscEnv :: HscEnv -> Name -> IO (Maybe TyThing) lookupTypeHscEnv hsc_env name = do eps <- readIORef (hsc_EPS hsc_env) - return $ lookupType dflags hpt (eps_PTE eps) name + return $! lookupType dflags hpt (eps_PTE eps) name where dflags = hsc_dflags hsc_env hpt = hsc_HPT hsc_env @@ -1648,6 +1732,7 @@ type PackageRuleBase = RuleBase type PackageInstEnv = InstEnv type PackageFamInstEnv = FamInstEnv type PackageVectInfo = VectInfo +type PackageAnnEnv = AnnEnv -- | Information about other packages that we have slurped in by reading -- their interface files @@ -1699,6 +1784,8 @@ data ExternalPackageState -- from all the external-package modules eps_vect_info :: !PackageVectInfo, -- ^ The total 'VectInfo' accumulated -- from all the external-package modules + eps_ann_env :: !PackageAnnEnv, -- ^ The total 'AnnEnv' accumulated + -- from all the external-package modules eps_mod_fam_inst_env :: !(ModuleEnv FamInstEnv), -- ^ The family instances accumulated from external -- packages, keyed off the module that declared them @@ -1766,7 +1853,8 @@ type OrigIParamCache = FiniteMap (IPName OccName) (IPName Name) -- 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 @@ -1786,8 +1874,8 @@ data ModSummary 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 @@ -1953,8 +2041,14 @@ data Linkable = LM { -- (i.e. when the bytecodes were produced, -- or the mod date on the files) linkableModule :: Module, -- ^ The linkable module itself - linkableUnlinked :: [Unlinked] -- ^ Those files and chunks of code we have - -- yet to link + linkableUnlinked :: [Unlinked] + -- ^ Those files and chunks of code we have yet to link. + -- + -- INVARIANT: A valid linkable always has at least one 'Unlinked' item. + -- If this list is empty, the Linkable represents a fake linkable, which + -- is generated in HscNothing mode to avoid recompiling modules. + -- + -- XXX: Do items get removed from this list when they get linked? } isObjectLinkable :: Linkable -> Bool