modInfoLookupName,
lookupGlobalName,
+ -- * Printing
+ PrintUnqualified, alwaysQualify,
+
-- * Interactive evaluation
getBindings, getPrintUnqual,
#ifdef GHCI
setContext, getContext,
getNamesInScope,
moduleIsInterpreted,
- getInfo, GetInfoResult,
+ getInfo,
exprType,
typeKind,
parseName,
RunResult(..),
runStmt,
- browseModule,
showModule,
compileExpr, HValue,
lookupName,
Module, mkModule, pprModule,
-- ** Names
- Name, nameModule,
+ Name,
+ nameModule, nameParent_maybe, pprParenSymName, nameSrcLoc,
+ NamedThing(..),
-- ** Identifiers
Id, idType,
isImplicitId, isDeadBinder,
isSpecPragmaId, isExportedId, isLocalId, isGlobalId,
isRecordSelector,
- isPrimOpId, isFCallId,
+ isPrimOpId, isFCallId, isClassOpId_maybe,
isDataConWorkId, idDataCon,
isBottomingId, isDictonaryId,
+ recordSelectorFieldLabel,
-- ** Type constructors
TyCon,
+ tyConTyVars, tyConDataCons,
isClassTyCon, isSynTyCon, isNewTyCon,
+ getSynTyConDefn,
-- ** Data constructors
DataCon,
+ dataConSig, dataConType, dataConTyCon, dataConFieldLabels,
+ dataConIsInfix, isVanillaDataCon,
+ dataConStrictMarks,
+ StrictnessMark(..), isMarkedStrict,
-- ** Classes
Class,
- classSCTheta, classTvsFds,
+ classMethods, classSCTheta, classTvsFds,
+ pprFundeps,
-- ** Instances
- Instance,
+ Instance,
+ instanceDFunId, pprInstance,
-- ** Types and Kinds
- Type, dropForAlls,
+ Type, dropForAlls, splitForAllTys, funResultTy, pprParendType,
Kind,
+ PredType,
+ ThetaType, pprThetaArrow,
-- ** Entities
TyThing(..),
-- ** Syntax
module HsSyn, -- ToDo: remove extraneous bits
+ -- ** Fixities
+ FixityDirection(..),
+ defaultFixity, maxPrecedence,
+ negateFixity,
+ compareFixity,
+
+ -- ** Source locations
+ SrcLoc, pprDefnLoc,
+
-- * Exceptions
GhcException(..), showGhcException,
{-
ToDo:
- * inline bits of HscMain here to simplify layering: hscGetInfo,
- hscTcExpr, hscStmt.
+ * inline bits of HscMain here to simplify layering: hscTcExpr, hscStmt.
* we need to expose DynFlags, so should parseDynamicFlags really be
part of this interface?
* what StaticFlags should we expose, if any?
#ifdef GHCI
import qualified Linker
import Linker ( HValue, extendLinkEnv )
-import NameEnv ( lookupNameEnv )
-import TcRnDriver ( getModuleContents, tcRnLookupRdrName,
- getModuleExports )
-import RdrName ( plusGlobalRdrEnv, Provenance(..), ImportSpec(..),
+import TcRnDriver ( tcRnLookupRdrName, tcRnGetInfo,
+ tcRnLookupName, getModuleExports )
+import RdrName ( plusGlobalRdrEnv, Provenance(..),
+ ImportSpec(..), ImpDeclSpec(..), ImpItemSpec(..),
emptyGlobalRdrEnv, mkGlobalRdrEnv )
-import HscMain ( hscGetInfo, GetInfoResult, hscParseIdentifier,
- hscStmt, hscTcExpr, hscKcType )
+import HscMain ( hscParseIdentifier, hscStmt, hscTcExpr, hscKcType )
import Type ( tidyType )
import VarEnv ( emptyTidyEnv )
import GHC.Exts ( unsafeCoerce# )
-import IfaceSyn ( IfaceDecl )
-import Name ( getName, nameModule_maybe )
-import SrcLoc ( mkSrcLoc, srcLocSpan, interactiveSrcLoc )
-import Bag ( unitBag, emptyBag )
#endif
-import Packages ( initPackages )
+import Packages ( initPackages, isHomeModule )
import NameSet ( NameSet, nameSetToList, elemNameSet )
-import RdrName ( GlobalRdrEnv, GlobalRdrElt(..), RdrName, gre_name,
+import RdrName ( GlobalRdrEnv, GlobalRdrElt(..), RdrName,
globalRdrEnvElts )
import HsSyn
-import Type ( Kind, Type, dropForAlls )
+import Type ( Kind, Type, dropForAlls, PredType, ThetaType,
+ pprThetaArrow, pprParendType, splitForAllTys,
+ funResultTy )
import Id ( Id, idType, isImplicitId, isDeadBinder,
isSpecPragmaId, isExportedId, isLocalId, isGlobalId,
- isRecordSelector,
- isPrimOpId, isFCallId,
+ isRecordSelector, recordSelectorFieldLabel,
+ isPrimOpId, isFCallId, isClassOpId_maybe,
isDataConWorkId, idDataCon,
isBottomingId )
-import TyCon ( TyCon, isClassTyCon, isSynTyCon, isNewTyCon )
-import Class ( Class, classSCTheta, classTvsFds )
-import DataCon ( DataCon )
-import Name ( Name, nameModule )
+import TyCon ( TyCon, isClassTyCon, isSynTyCon, isNewTyCon,
+ tyConTyVars, tyConDataCons, getSynTyConDefn )
+import Class ( Class, classSCTheta, classTvsFds, classMethods )
+import FunDeps ( pprFundeps )
+import DataCon ( DataCon, dataConWrapId, dataConSig, dataConTyCon,
+ dataConFieldLabels, dataConStrictMarks,
+ dataConIsInfix, isVanillaDataCon )
+import Name ( Name, nameModule, NamedThing(..), nameParent_maybe,
+ nameSrcLoc )
+import OccName ( parenSymOcc )
import NameEnv ( nameEnvElts )
-import InstEnv ( Instance )
-import SrcLoc ( Located(..), mkGeneralSrcSpan, SrcSpan, unLoc )
+import InstEnv ( Instance, instanceDFunId, pprInstance )
+import SrcLoc
import DriverPipeline
import DriverPhases ( Phase(..), isHaskellSrcFilename, startPhase )
import GetImports ( getImports )
import FiniteMap
import Panic
import Digraph
-import ErrUtils ( showPass, Messages, putMsg, debugTraceMsg, mkLocMessage )
+import Bag ( unitBag, emptyBag )
+import ErrUtils ( showPass, Messages, putMsg, debugTraceMsg,
+ mkPlainErrMsg, pprBagOfErrors )
import qualified ErrUtils
import Util
import StringBuffer ( StringBuffer, hGetStringBuffer )
import Outputable
import SysTools ( cleanTempFilesExcept )
-import BasicTypes ( SuccessFlag(..), succeeded, failed )
-import Maybes ( orElse, expectJust, mapCatMaybes )
+import BasicTypes
import TcType ( tcSplitSigmaTy, isDictTy )
import FastString ( mkFastString )
import Directory ( getModificationTime, doesFileExist )
-import Maybe ( isJust, isNothing, fromJust, fromMaybe, catMaybes )
-import Maybes ( expectJust )
+import Maybe ( isJust, isNothing, fromJust )
+import Maybes ( orElse, expectJust, mapCatMaybes )
import List ( partition, nub )
import qualified List
-import Monad ( unless, when, foldM )
+import Monad ( unless, when )
import System ( exitWith, ExitCode(..) )
import Time ( ClockTime )
import EXCEPTION as Exception hiding (handle)
exitWith (ExitFailure 1)
) $
- -- all error messages are propagated as exceptions
+ -- program errors: messages with locations attached. Sometimes it is
+ -- convenient to just throw these as exceptions.
+ handleDyn (\dyn -> do printErrs (pprBagOfErrors (unitBag dyn))
+ exitWith (ExitFailure 1)) $
+
+ -- error messages propagated as exceptions
handleDyn (\dyn -> do
hFlush stdout
case dyn of
-- Perform a dependency analysis starting from the current targets
-- and update the session with the new module graph.
-depanal :: Session -> [Module] -> IO ()
+depanal :: Session -> [Module] -> IO (Either Messages ModuleGraph)
depanal (Session ref) excluded_mods = do
hsc_env <- readIORef ref
let
text "Chasing modules from: ",
hcat (punctuate comma (map pprTarget targets))]))
- graph <- downsweep hsc_env old_graph excluded_mods
- writeIORef ref hsc_env{ hsc_mod_graph=graph }
+ r <- downsweep hsc_env old_graph excluded_mods
+ case r of
+ Right mod_graph -> writeIORef ref hsc_env{ hsc_mod_graph = mod_graph }
+ _ -> return ()
+ return r
{-
-- | The result of load.
-- even if we don't get a fully successful upsweep, the full module
-- graph is still retained in the Session. We can tell which modules
-- were successfully loaded by inspecting the Session's HPT.
- depanal s []
+ mb_graph <- depanal s []
+ case mb_graph of
+ Left msgs -> do msg_act msgs; return Failed
+ Right mod_graph -> loadMsgs2 s how_much msg_act mod_graph
+loadMsgs2 s@(Session ref) how_much msg_act mod_graph = do
hsc_env <- readIORef ref
let hpt1 = hsc_HPT hsc_env
let dflags = hsc_dflags hsc_env
- let mod_graph = hsc_mod_graph hsc_env
-
- let ghci_mode = ghcMode (hsc_dflags hsc_env) -- this never changes
- let verb = verbosity dflags
+ let ghci_mode = ghcMode dflags -- this never changes
-- The "bad" boot modules are the ones for which we have
-- B.hs-boot in the module graph, but no B.hs
-- The downsweep should have ensured this does not happen
-- (see msDeps)
let all_home_mods = [ms_mod s | s <- mod_graph, not (isBootSummary s)]
+#ifdef DEBUG
bad_boot_mods = [s | s <- mod_graph, isBootSummary s,
not (ms_mod s `elem` all_home_mods)]
+#endif
ASSERT( null bad_boot_mods ) return ()
-- mg2_with_srcimps drops the hi-boot nodes, returning a
type RenamedSource = HsGroup Name
type TypecheckedSource = LHsBinds Id
+-- NOTE:
+-- - things that aren't in the output of the renamer:
+-- - the export list
+-- - the imports
+-- - things that aren't in the output of the typechecker right now:
+-- - the export list
+-- - the imports
+-- - type signatures
+-- - type/data/newtype declarations
+-- - class declarations
+-- - instances
+-- - extra things in the typechecker's output:
+-- - default methods are turned into top-level decls.
+-- - dictionary bindings
+
+
-- | This is the way to get access to parsed and typechecked source code
-- for a module. 'checkModule' loads all the dependencies of the specified
-- module in the Session, and then attempts to typecheck the module. If
renamedSource = renamed,
typecheckedSource = Just tc_binds,
checkedModuleInfo = Just minf }))
+ _other ->
+ panic "checkModule"
-- ---------------------------------------------------------------------------
-- Unloading
| otherwise = False
where
same_as_prev t = case lookupModuleEnv hpt (ms_mod ms) of
- Nothing -> True
Just hmi | Just l <- hm_linkable hmi
-> isObjectLinkable l && t == linkableTime l
+ _other -> True
-- why '>=' rather than '>' above? If the filesystem stores
-- times to the nearset second, we may occasionally find that
-- the object & source have the same modification time,
bco_ok ms
= case lookupModuleEnv hpt (ms_mod ms) of
- Nothing -> False
Just hmi | Just l <- hm_linkable hmi ->
not (isObjectLinkable l) &&
linkableTime l >= ms_hs_date ms
+ _other -> False
ms_allimps :: ModSummary -> [Module]
ms_allimps ms = map unLoc (ms_srcimps ms ++ ms_imps ms)
msKey :: ModSummary -> NodeKey
msKey (ModSummary { ms_mod = mod, ms_hsc_src = boot }) = (mod,boot)
-emptyNodeMap :: NodeMap a
-emptyNodeMap = emptyFM
-
mkNodeMap :: [ModSummary] -> NodeMap ModSummary
mkNodeMap summaries = listToFM [ (msKey s, s) | s <- summaries]
nodeMapElts :: NodeMap a -> [a]
nodeMapElts = eltsFM
--- -----------------------------------------------------------------
--- The unlinked image
---
--- The compilation manager keeps a list of compiled, but as-yet unlinked
--- binaries (byte code or object code). Even when it links bytecode
--- it keeps the unlinked version so it can re-link it later without
--- recompiling.
-
-type UnlinkedImage = [Linkable] -- the unlinked images (should be a set, really)
-
-findModuleLinkable_maybe :: [Linkable] -> Module -> Maybe Linkable
-findModuleLinkable_maybe lis mod
- = case [LM time nm us | LM time nm us <- lis, nm == mod] of
- [] -> Nothing
- [li] -> Just li
- many -> pprPanic "findModuleLinkable" (ppr mod)
-
-delModuleLinkable :: [Linkable] -> Module -> [Linkable]
-delModuleLinkable ls mod = [ l | l@(LM _ nm _) <- ls, nm /= mod ]
-
-----------------------------------------------------------------------------
-- Downsweep (dependency analysis)
-> [ModSummary] -- Old summaries
-> [Module] -- Ignore dependencies on these; treat them as
-- if they were package modules
- -> IO [ModSummary]
+ -> IO (Either Messages [ModSummary])
downsweep hsc_env old_summaries excl_mods
- = do rootSummaries <- mapM getRootSummary roots
- checkDuplicates rootSummaries
- loop (concatMap msDeps rootSummaries)
- (mkNodeMap rootSummaries)
+ = -- catch error messages and return them
+ handleDyn (\err_msg -> return (Left (emptyBag, unitBag err_msg))) $ do
+ rootSummaries <- mapM getRootSummary roots
+ checkDuplicates rootSummaries
+ summs <- loop (concatMap msDeps rootSummaries) (mkNodeMap rootSummaries)
+ return (Right summs)
where
roots = hsc_targets hsc_env
= do exists <- doesFileExist file
if exists
then summariseFile hsc_env old_summaries file mb_phase maybe_buf
- else do
- throwDyn (CmdLineError ("can't find file: " ++ file))
+ else throwDyn $ mkPlainErrMsg noSrcSpan $
+ text "can't find file:" <+> text file
getRootSummary (Target (TargetModule modl) maybe_buf)
= do maybe_summary <- summariseModule hsc_env old_summary_map False
(L rootLoc modl) maybe_buf excl_mods
(srcimps, the_imps, L mod_loc mod_name) <- getImports dflags' buf hspp_fn
when (mod_name /= wanted_mod) $
- throwDyn (ProgramError
- (showSDoc (mkLocMessage mod_loc $
+ throwDyn $ mkPlainErrMsg mod_loc $
text "file name does not match module name"
- <+> quotes (ppr mod_name))))
+ <+> quotes (ppr mod_name)
-- Find the object timestamp, and return the summary
obj_timestamp <- getObjTimestamp location is_boot
noModError :: DynFlags -> SrcSpan -> Module -> FindResult -> IO ab
-- ToDo: we don't have a proper line number for this error
noModError dflags loc wanted_mod err
- = throwDyn $ ProgramError $ showSDoc $
- mkLocMessage loc $ cantFindError dflags wanted_mod err
+ = throwDyn $ mkPlainErrMsg loc $ cantFindError dflags wanted_mod err
noHsFileErr loc path
- = throwDyn $ CmdLineError $ showSDoc $
- mkLocMessage loc $ text "Can't find" <+> text path
+ = throwDyn $ mkPlainErrMsg loc $ text "Can't find" <+> text path
packageModErr mod
- = throwDyn (CmdLineError (showSDoc (text "module" <+>
- quotes (ppr mod) <+>
- text "is a package module")))
+ = throwDyn $ mkPlainErrMsg noSrcSpan $
+ text "module" <+> quotes (ppr mod) <+> text "is a package module"
multiRootsErr mod files
- = throwDyn (ProgramError (showSDoc (
+ = throwDyn $ mkPlainErrMsg noSrcSpan $
text "module" <+> quotes (ppr mod) <+>
text "is defined in multiple files:" <+>
- sep (map text files))))
+ sep (map text files)
cyclicModuleErr :: [ModSummary] -> SDoc
cyclicModuleErr ms
-- | Request information about a loaded 'Module'
getModuleInfo :: Session -> Module -> IO (Maybe ModuleInfo)
getModuleInfo s mdl = withSession s $ \hsc_env -> do
- case lookupModuleEnv (hsc_HPT hsc_env) mdl of
- Nothing -> do
+ let mg = hsc_mod_graph hsc_env
+ if mdl `elem` map ms_mod mg
+ then getHomeModuleInfo hsc_env mdl
+ else do
+ if isHomeModule (hsc_dflags hsc_env) mdl
+ then return Nothing
+ else getPackageModuleInfo hsc_env mdl
+ -- getPackageModuleInfo will attempt to find the interface, so
+ -- we don't want to call it for a home module, just in case there
+ -- was a problem loading the module and the interface doesn't
+ -- exist... hence the isHomeModule test here.
+
+getPackageModuleInfo :: HscEnv -> Module -> IO (Maybe ModuleInfo)
+getPackageModuleInfo hsc_env mdl = do
#ifdef GHCI
- mb_names <- getModuleExports hsc_env mdl
- case mb_names of
- Nothing -> return Nothing
- Just names -> do
- eps <- readIORef (hsc_EPS hsc_env)
- let
- pte = eps_PTE eps
- n_list = nameSetToList names
- tys = [ ty | name <- n_list,
- Just ty <- [lookupTypeEnv pte name] ]
- --
- return (Just (ModuleInfo {
- minf_type_env = mkTypeEnv tys,
- minf_exports = names,
- minf_rdr_env = Just $! nameSetToGlobalRdrEnv names mdl,
- minf_instances = error "getModuleInfo: instances for package module unimplemented"
- }))
+ (_msgs, mb_names) <- getModuleExports hsc_env mdl
+ case mb_names of
+ Nothing -> return Nothing
+ Just names -> do
+ eps <- readIORef (hsc_EPS hsc_env)
+ let
+ pte = eps_PTE eps
+ n_list = nameSetToList names
+ tys = [ ty | name <- n_list,
+ Just ty <- [lookupTypeEnv pte name] ]
+ --
+ return (Just (ModuleInfo {
+ minf_type_env = mkTypeEnv tys,
+ minf_exports = names,
+ minf_rdr_env = Just $! nameSetToGlobalRdrEnv names mdl,
+ minf_instances = error "getModuleInfo: instances for package module unimplemented"
+ }))
#else
- -- bogusly different for non-GHCI (ToDo)
- return Nothing
+ -- bogusly different for non-GHCI (ToDo)
+ return Nothing
#endif
- Just hmi ->
- let details = hm_details hmi in
- return (Just (ModuleInfo {
+
+getHomeModuleInfo hsc_env mdl =
+ case lookupModuleEnv (hsc_HPT hsc_env) mdl of
+ Nothing -> return Nothing
+ Just hmi -> do
+ let details = hm_details hmi
+ return (Just (ModuleInfo {
minf_type_env = md_types details,
minf_exports = md_exports details,
minf_rdr_env = mi_globals $! hm_iface hmi,
minf_instances = md_insts details
}))
- -- ToDo: we should be able to call getModuleInfo on a package module,
- -- even one that isn't loaded yet.
-
-- | The list of top-level entities defined in a module
modInfoTyThings :: ModuleInfo -> [TyThing]
modInfoTyThings minf = typeEnvElts (minf_type_env minf)
eps <- readIORef (hsc_EPS hsc_env)
return $! lookupType (hsc_HPT hsc_env) (eps_PTE eps) name
-#if 0
+-- -----------------------------------------------------------------------------
+-- Misc exported utils
-data ObjectCode
- = ByteCode
- | BinaryCode FilePath
+dataConType :: DataCon -> Type
+dataConType dc = idType (dataConWrapId dc)
--- ToDo: typechecks abstract syntax or renamed abstract syntax. Issues:
--- - typechecked syntax includes extra dictionary translation and
--- AbsBinds which need to be translated back into something closer to
--- the original source.
+-- | print a 'NamedThing', adding parentheses if the name is an operator.
+pprParenSymName :: NamedThing a => a -> SDoc
+pprParenSymName a = parenSymOcc (getOccName a) (ppr (getName a))
--- ToDo:
--- - Data and Typeable instances for HsSyn.
+-- ----------------------------------------------------------------------------
--- ToDo:
--- - things that aren't in the output of the renamer:
--- - the export list
--- - the imports
+#if 0
-- ToDo:
--- - things that aren't in the output of the typechecker right now:
--- - the export list
--- - the imports
--- - type signatures
--- - type/data/newtype declarations
--- - class declarations
--- - instances
--- - extra things in the typechecker's output:
--- - default methods are turned into top-level decls.
--- - dictionary bindings
+-- - Data and Typeable instances for HsSyn.
-- ToDo: check for small transformations that happen to the syntax in
-- the typechecker (eg. -e ==> negate e, perhaps for fromIntegral)
-- Make a GlobalRdrEnv based on the exports of the modules only.
mkExportEnv :: HscEnv -> [Module] -> IO GlobalRdrEnv
mkExportEnv hsc_env mods = do
- mb_name_sets <- mapM (getModuleExports hsc_env) mods
+ stuff <- mapM (getModuleExports hsc_env) mods
let
+ (_msgs, mb_name_sets) = unzip stuff
gres = [ nameSetToGlobalRdrEnv name_set mod
| (Just name_set, mod) <- zip mb_name_sets mods ]
--
vanillaProv :: Module -> Provenance
-- We're building a GlobalRdrEnv as if the user imported
-- all the specified modules into the global interactive module
-vanillaProv mod = Imported [ImportSpec { is_mod = mod, is_as = mod,
- is_qual = False, is_explicit = False,
- is_loc = srcLocSpan interactiveSrcLoc }]
+vanillaProv mod = Imported [ImpSpec { is_decl = decl, is_item = ImpAll}]
+ where
+ decl = ImpDeclSpec { is_mod = mod, is_as = mod,
+ is_qual = False,
+ is_dloc = srcLocSpan interactiveSrcLoc }
checkModuleExists :: HscEnv -> HomePackageTable -> Module -> IO ()
checkModuleExists hsc_env hpt mod =
_not_a_home_module -> return False
-- | Looks up an identifier in the current interactive context (for :info)
-{-# DEPRECATED getInfo "we should be using parseName/lookupName instead" #-}
-getInfo :: Session -> String -> IO [GetInfoResult]
-getInfo s id = withSession s $ \hsc_env -> hscGetInfo hsc_env id
+getInfo :: Session -> Name -> IO (Maybe (TyThing,Fixity,[Instance]))
+getInfo s name = withSession s $ \hsc_env -> tcRnGetInfo hsc_env name
-- | Returns all names in scope in the current interactive context
getNamesInScope :: Session -> IO [Name]
-- | Returns the 'TyThing' for a 'Name'. The 'Name' may refer to any
-- entity known to GHC, including 'Name's defined using 'runStmt'.
lookupName :: Session -> Name -> IO (Maybe TyThing)
-lookupName s name = withSession s $ \hsc_env -> do
- case lookupTypeEnv (ic_type_env (hsc_IC hsc_env)) name of
- Just tt -> return (Just tt)
- Nothing -> do
- eps <- readIORef (hsc_EPS hsc_env)
- return $! lookupType (hsc_HPT hsc_env) (eps_PTE eps) name
+lookupName s name = withSession s $ \hsc_env -> tcRnLookupName hsc_env name
-- -----------------------------------------------------------------------------
-- Getting the type of an expression
Just ty -> return (Just tidy_ty)
where
tidy_ty = tidyType emptyTidyEnv ty
- dflags = hsc_dflags hsc_env
-- -----------------------------------------------------------------------------
-- Getting the kind of a type
-- more informative than the C type!
-}
--- ---------------------------------------------------------------------------
--- cmBrowseModule: get all the TyThings defined in a module
-
-{-# DEPRECATED browseModule "we should be using getModuleInfo instead" #-}
-browseModule :: Session -> Module -> Bool -> IO [IfaceDecl]
-browseModule s modl exports_only = withSession s $ \hsc_env -> do
- mb_decls <- getModuleContents hsc_env modl exports_only
- case mb_decls of
- Nothing -> return [] -- An error of some kind
- Just ds -> return ds
-
-
-----------------------------------------------------------------------------
-- show a module and it's source/object filenames