newSession,
-- * Flags and settings
- DynFlags(..), DynFlag(..), GhcMode(..), HscTarget(..), dopt,
+ DynFlags(..), DynFlag(..), Severity(..), GhcMode(..), HscTarget(..), dopt,
parseDynamicFlags,
initPackages,
getSessionDynFlags,
setSessionDynFlags,
- setMsgHandler,
-- * Targets
Target(..), TargetId(..), Phase,
-- * Loading\/compiling the program
depanal,
load, LoadHowMuch(..), SuccessFlag(..), -- also does depanal
- loadMsgs,
workingDirectoryChanged,
checkModule, CheckedModule(..),
TypecheckedSource, ParsedSource, RenamedSource,
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,
+ isExportedId, isLocalId, isGlobalId,
isRecordSelector,
- isPrimOpId, isFCallId,
+ isPrimOpId, isFCallId, isClassOpId_maybe,
isDataConWorkId, idDataCon,
isBottomingId, isDictonaryId,
+ recordSelectorFieldLabel,
-- ** Type constructors
TyCon,
- isClassTyCon, isSynTyCon, isNewTyCon,
+ tyConTyVars, tyConDataCons, tyConArity,
+ isClassTyCon, isSynTyCon, isNewTyCon, isPrimTyCon,
+ getSynTyConDefn,
+
+ -- ** Type variables
+ TyVar,
+ alphaTyVars,
-- ** 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, pprInstanceHdr,
-- ** 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 TcRnDriver ( getModuleContents, tcRnLookupRdrName,
- getModuleExports )
+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 SrcLoc ( srcLocSpan, interactiveSrcLoc )
#endif
-import Packages ( initPackages, isHomeModule )
+import Packages ( initPackages )
import NameSet ( NameSet, nameSetToList, elemNameSet )
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,
+ isExportedId, isLocalId, isGlobalId,
+ 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 Var ( TyVar )
+import TysPrim ( alphaTyVars )
+import TyCon ( TyCon, isClassTyCon, isSynTyCon, isNewTyCon,
+ isPrimTyCon, tyConArity,
+ 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, pprInstanceHdr )
+import SrcLoc
import DriverPipeline
import DriverPhases ( Phase(..), isHaskellSrcFilename, startPhase )
import GetImports ( getImports )
import FiniteMap
import Panic
import Digraph
-import Bag ( unitBag, emptyBag )
-import ErrUtils ( showPass, Messages, putMsg, debugTraceMsg,
- mkPlainErrMsg, pprBagOfErrors )
+import Bag ( unitBag )
+import ErrUtils ( Severity(..), showPass, Messages, fatalErrorMsg, debugTraceMsg,
+ mkPlainErrMsg, printBagOfErrors, printErrorsAndWarnings )
import qualified ErrUtils
import Util
import StringBuffer ( StringBuffer, hGetStringBuffer )
import Outputable
import SysTools ( cleanTempFilesExcept )
-import BasicTypes ( SuccessFlag(..), succeeded, failed )
+import BasicTypes
import TcType ( tcSplitSigmaTy, isDictTy )
import FastString ( mkFastString )
-- Unless you want to handle exceptions yourself, you should wrap this around
-- the top level of your program. The default handlers output the error
-- message(s) to stderr and exit cleanly.
-defaultErrorHandler :: IO a -> IO a
-defaultErrorHandler inner =
+defaultErrorHandler :: DynFlags -> IO a -> IO a
+defaultErrorHandler dflags inner =
-- top-level exception handler: any unrecognised exception is a compiler bug.
handle (\exception -> do
hFlush stdout
case exception of
-- an IO exception probably isn't our fault, so don't panic
- IOException _ -> putMsg (show exception)
+ IOException _ ->
+ fatalErrorMsg dflags (text (show exception))
AsyncException StackOverflow ->
- putMsg "stack overflow: use +RTS -K<size> to increase it"
- _other -> putMsg (show (Panic (show exception)))
+ fatalErrorMsg dflags (text "stack overflow: use +RTS -K<size> to increase it")
+ _other ->
+ fatalErrorMsg dflags (text (show (Panic (show exception))))
exitWith (ExitFailure 1)
) $
-- program errors: messages with locations attached. Sometimes it is
-- convenient to just throw these as exceptions.
- handleDyn (\dyn -> do printErrs (pprBagOfErrors (unitBag dyn))
+ handleDyn (\dyn -> do printBagOfErrors dflags (unitBag dyn)
exitWith (ExitFailure 1)) $
-- error messages propagated as exceptions
case dyn of
PhaseFailed _ code -> exitWith code
Interrupted -> exitWith (ExitFailure 1)
- _ -> do putMsg (show (dyn :: GhcException))
+ _ -> do fatalErrorMsg dflags (text (show (dyn :: GhcException)))
exitWith (ExitFailure 1)
) $
inner
setSessionDynFlags :: Session -> DynFlags -> IO ()
setSessionDynFlags s dflags = modifySession s (\h -> h{ hsc_dflags = dflags })
--- | Messages during compilation (eg. warnings and progress messages)
--- are reported using this callback. By default, these messages are
--- printed to stderr.
-setMsgHandler :: (String -> IO ()) -> IO ()
-setMsgHandler = ErrUtils.setMsgHandler
-
-- -----------------------------------------------------------------------------
-- Targets
-- Perform a dependency analysis starting from the current targets
-- and update the session with the new module graph.
-depanal :: Session -> [Module] -> IO (Either Messages ModuleGraph)
-depanal (Session ref) excluded_mods = do
+depanal :: Session -> [Module] -> Bool -> IO (Maybe ModuleGraph)
+depanal (Session ref) excluded_mods allow_dup_roots = do
hsc_env <- readIORef ref
let
dflags = hsc_dflags hsc_env
showPass dflags "Chasing dependencies"
when (gmode == BatchCompile) $
- debugTraceMsg dflags 1 (showSDoc (hcat [
+ debugTraceMsg dflags 1 (hcat [
text "Chasing modules from: ",
- hcat (punctuate comma (map pprTarget targets))]))
+ hcat (punctuate comma (map pprTarget targets))])
- downsweep hsc_env old_graph excluded_mods
+ r <- downsweep hsc_env old_graph excluded_mods allow_dup_roots
+ case r of
+ Just mod_graph -> writeIORef ref hsc_env{ hsc_mod_graph = mod_graph }
+ _ -> return ()
+ return r
{-
-- | The result of load.
-- attempt to load up to this target. If no Module is supplied,
-- then try to load all targets.
load :: Session -> LoadHowMuch -> IO SuccessFlag
-load session how_much =
- loadMsgs session how_much ErrUtils.printErrorsAndWarnings
-
--- | Version of 'load' that takes a callback function to be invoked
--- on compiler errors and warnings as they occur during compilation.
-loadMsgs :: Session -> LoadHowMuch -> (Messages-> IO ()) -> IO SuccessFlag
-loadMsgs s@(Session ref) how_much msg_act
+load s@(Session ref) how_much
= do
-- Dependency analysis first. Note that this fixes the module graph:
-- 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.
- 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
+ mb_graph <- depanal s [] False
+ case mb_graph of
+ Just mod_graph -> load2 s how_much mod_graph
+ Nothing -> return Failed
-loadMsgs2 s@(Session ref) how_much msg_act mod_graph = do
+load2 s@(Session ref) how_much mod_graph = do
hsc_env <- readIORef ref
- writeIORef ref hsc_env{ hsc_mod_graph = mod_graph }
let hpt1 = hsc_HPT hsc_env
let dflags = hsc_dflags 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
evaluate pruned_hpt
- debugTraceMsg dflags 2 (showSDoc (text "Stable obj:" <+> ppr stable_obj $$
- text "Stable BCO:" <+> ppr stable_bco))
+ debugTraceMsg dflags 2 (text "Stable obj:" <+> ppr stable_obj $$
+ text "Stable BCO:" <+> ppr stable_bco)
-- Unload any modules which are going to be re-linked this time around.
let stable_linkables = [ linkable
(upsweep_ok, hsc_env1, modsUpswept)
<- upsweep (hsc_env { hsc_HPT = emptyHomePackageTable })
- pruned_hpt stable_mods cleanup msg_act mg
+ pruned_hpt stable_mods cleanup mg
-- Make modsDone be the summaries for each home module now
-- available; this should equal the domain of hpt3.
then
-- Easy; just relink it all.
- do debugTraceMsg dflags 2 "Upsweep completely successful."
+ do debugTraceMsg dflags 2 (text "Upsweep completely successful.")
-- Clean up after ourselves
cleanTempFilesExcept dflags (ppFilesFromSummaries modsDone)
do_linking = a_root_is_Main || no_hs_main
when (ghci_mode == BatchCompile && isJust ofile && not do_linking) $
- debugTraceMsg dflags 1 ("Warning: output was redirected with -o, " ++
- "but no output will be generated\n" ++
- "because there is no " ++ main_mod ++ " module.")
+ debugTraceMsg dflags 1 (text ("Warning: output was redirected with -o, " ++
+ "but no output will be generated\n" ++
+ "because there is no " ++ main_mod ++ " module."))
-- link everything together
linkresult <- link ghci_mode dflags do_linking (hsc_HPT hsc_env1)
-- Tricky. We need to back out the effects of compiling any
-- half-done cycles, both so as to clean up the top level envs
-- and to avoid telling the interactive linker to link them.
- do debugTraceMsg dflags 2 "Upsweep partially successful."
+ do debugTraceMsg dflags 2 (text "Upsweep partially successful.")
let modsDone_names
= map ms_mod modsDone
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
-- successful, it returns the abstract syntax for the module.
-checkModule :: Session -> Module -> (Messages -> IO ())
- -> IO (Maybe CheckedModule)
-checkModule session@(Session ref) mod msg_act = do
+checkModule :: Session -> Module -> IO (Maybe CheckedModule)
+checkModule session@(Session ref) mod = do
-- load up the dependencies first
- r <- loadMsgs session (LoadDependenciesOf mod) msg_act
+ r <- load session (LoadDependenciesOf mod)
if (failed r) then return Nothing else do
-- now parse & typecheck the module
-- ml_hspp_file field, say
let dflags0 = hsc_dflags hsc_env
hspp_buf = expectJust "GHC.checkModule" (ms_hspp_buf ms)
- opts = getOptionsFromStringBuffer hspp_buf
+ filename = fromJust (ml_hs_file (ms_location ms))
+ opts = getOptionsFromStringBuffer hspp_buf filename
(dflags1,leftovers) <- parseDynamicFlags dflags0 (map snd opts)
if (not (null leftovers))
- then do let filename = fromJust (ml_hs_file (ms_location ms))
- msg_act (optionsErrorMsgs leftovers opts filename)
+ then do printErrorsAndWarnings dflags1 (optionsErrorMsgs leftovers opts filename)
return Nothing
else do
- r <- hscFileCheck hsc_env{hsc_dflags=dflags1} msg_act ms
+ r <- hscFileCheck hsc_env{hsc_dflags=dflags1} ms
case r of
HscFail ->
return Nothing
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)
-> HomePackageTable -- HPT from last time round (pruned)
-> ([Module],[Module]) -- stable modules (see checkStability)
-> IO () -- How to clean up unwanted tmp files
- -> (Messages -> IO ()) -- Compiler error message callback
-> [SCC ModSummary] -- Mods to do (the worklist)
-> IO (SuccessFlag,
HscEnv, -- With an updated HPT
[ModSummary]) -- Mods which succeeded
-upsweep hsc_env old_hpt stable_mods cleanup msg_act mods
- = upsweep' hsc_env old_hpt stable_mods cleanup msg_act mods 1 (length mods)
+upsweep hsc_env old_hpt stable_mods cleanup mods
+ = upsweep' hsc_env old_hpt stable_mods cleanup mods 1 (length mods)
-upsweep' hsc_env old_hpt stable_mods cleanup msg_act
+upsweep' hsc_env old_hpt stable_mods cleanup
[] _ _
= return (Succeeded, hsc_env, [])
-upsweep' hsc_env old_hpt stable_mods cleanup msg_act
+upsweep' hsc_env old_hpt stable_mods cleanup
(CyclicSCC ms:_) _ _
- = do putMsg (showSDoc (cyclicModuleErr ms))
+ = do fatalErrorMsg (hsc_dflags hsc_env) (cyclicModuleErr ms)
return (Failed, hsc_env, [])
-upsweep' hsc_env old_hpt stable_mods cleanup msg_act
+upsweep' hsc_env old_hpt stable_mods cleanup
(AcyclicSCC mod:mods) mod_index nmods
= do -- putStrLn ("UPSWEEP_MOD: hpt = " ++
-- show (map (moduleUserString.moduleName.mi_module.hm_iface)
-- (moduleEnvElts (hsc_HPT hsc_env)))
- mb_mod_info <- upsweep_mod hsc_env old_hpt stable_mods msg_act mod
+ mb_mod_info <- upsweep_mod hsc_env old_hpt stable_mods mod
mod_index nmods
cleanup -- Remove unwanted tmp files between compilations
; (restOK, hsc_env2, modOKs)
<- upsweep' hsc_env1 old_hpt1 stable_mods cleanup
- msg_act mods (mod_index+1) nmods
+ mods (mod_index+1) nmods
; return (restOK, hsc_env2, mod:modOKs)
}
upsweep_mod :: HscEnv
-> HomePackageTable
-> ([Module],[Module])
- -> (Messages -> IO ())
-> ModSummary
-> Int -- index of module
-> Int -- total number of modules
-> IO (Maybe HomeModInfo) -- Nothing => Failed
-upsweep_mod hsc_env old_hpt (stable_obj, stable_bco) msg_act summary mod_index nmods
+upsweep_mod hsc_env old_hpt (stable_obj, stable_bco) summary mod_index nmods
= do
let
this_mod = ms_mod summary
compile_it :: Maybe Linkable -> IO (Maybe HomeModInfo)
compile_it = upsweep_compile hsc_env old_hpt this_mod
- msg_act summary mod_index nmods
+ summary mod_index nmods
case ghcMode (hsc_dflags hsc_env) of
BatchCompile ->
old_hmi = lookupModuleEnv old_hpt this_mod
-- Run hsc to compile a module
-upsweep_compile hsc_env old_hpt this_mod msg_act summary
+upsweep_compile hsc_env old_hpt this_mod summary
mod_index nmods
mb_old_linkable = do
let
where
iface = hm_iface hm_info
- compresult <- compile hsc_env msg_act summary mb_old_linkable mb_old_iface
+ compresult <- compile hsc_env summary mb_old_linkable mb_old_iface
mod_index nmods
case compresult of
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)
downsweep :: HscEnv
-> [ModSummary] -- Old summaries
- -> [Module] -- Ignore dependencies on these; treat them as
- -- if they were package modules
- -> IO (Either Messages [ModSummary])
-downsweep hsc_env old_summaries excl_mods
+ -> [Module] -- Ignore dependencies on these; treat
+ -- them as if they were package modules
+ -> Bool -- True <=> allow multiple targets to have
+ -- the same module name; this is
+ -- very useful for ghc -M
+ -> IO (Maybe [ModSummary])
+ -- The elts of [ModSummary] all have distinct
+ -- (Modules, IsBoot) identifiers, unless the Bool is true
+ -- in which case there can be repeats
+downsweep hsc_env old_summaries excl_mods allow_dup_roots
= -- catch error messages and return them
- handleDyn (\err_msg -> return (Left (emptyBag, unitBag err_msg))) $ do
+ handleDyn (\err_msg -> printBagOfErrors (hsc_dflags hsc_env) (unitBag err_msg) >> return Nothing) $ do
rootSummaries <- mapM getRootSummary roots
- checkDuplicates rootSummaries
- summs <- loop (concatMap msDeps rootSummaries) (mkNodeMap rootSummaries)
- return (Right summs)
+ let root_map = mkRootMap rootSummaries
+ checkDuplicates root_map
+ summs <- loop (concatMap msDeps rootSummaries) root_map
+ return (Just 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
-- name, so we have to check that there aren't multiple root files
-- defining the same module (otherwise the duplicates will be silently
-- ignored, leading to confusing behaviour).
- checkDuplicates :: [ModSummary] -> IO ()
- checkDuplicates summaries = mapM_ check summaries
- where check summ =
- case dups of
- [] -> return ()
- [_one] -> return ()
- many -> multiRootsErr modl many
- where modl = ms_mod summ
- dups =
- [ expectJust "checkDup" (ml_hs_file (ms_location summ'))
- | summ' <- summaries, ms_mod summ' == modl ]
+ checkDuplicates :: NodeMap [ModSummary] -> IO ()
+ checkDuplicates root_map
+ | allow_dup_roots = return ()
+ | null dup_roots = return ()
+ | otherwise = multiRootsErr (head dup_roots)
+ where
+ dup_roots :: [[ModSummary]] -- Each at least of length 2
+ dup_roots = filterOut isSingleton (nodeMapElts root_map)
loop :: [(Located Module,IsBootInterface)]
-- Work list: process these modules
- -> NodeMap ModSummary
- -- Visited set
+ -> NodeMap [ModSummary]
+ -- Visited set; the range is a list because
+ -- the roots can have the same module names
+ -- if allow_dup_roots is True
-> IO [ModSummary]
-- The result includes the worklist, except
-- for those mentioned in the visited set
- loop [] done = return (nodeMapElts done)
+ loop [] done = return (concat (nodeMapElts done))
loop ((wanted_mod, is_boot) : ss) done
- | key `elemFM` done = loop ss done
+ | Just summs <- lookupFM done key
+ = if isSingleton summs then
+ loop ss done
+ else
+ do { multiRootsErr summs; return [] }
| otherwise = do { mb_s <- summariseModule hsc_env old_summary_map
is_boot wanted_mod Nothing excl_mods
; case mb_s of
Nothing -> loop ss done
Just s -> loop (msDeps s ++ ss)
- (addToFM done key s) }
+ (addToFM done key [s]) }
where
key = (unLoc wanted_mod, if is_boot then HsBootFile else HsSrcFile)
+mkRootMap :: [ModSummary] -> NodeMap [ModSummary]
+mkRootMap summaries = addListToFM_C (++) emptyFM
+ [ (msKey s, [s]) | s <- summaries ]
+
msDeps :: ModSummary -> [(Located Module, IsBootInterface)]
-- (msDeps s) returns the dependencies of the ModSummary s.
-- A wrinkle is that for a {-# SOURCE #-} import we return
src_timestamp <- case maybe_buf of
Just (_,t) -> return t
Nothing -> getModificationTime file
+ -- The file exists; we checked in getRootSummary above.
+ -- If it gets removed subsequently, then this
+ -- getModificationTime may fail, but that's the right
+ -- behaviour.
if ms_hs_date old_summary == src_timestamp
then do -- update the object-file timestamp
src_timestamp <- case maybe_buf of
Just (_,t) -> return t
Nothing -> getModificationTime file
+ -- getMofificationTime may fail
obj_timestamp <- modificationTimeIfExists (ml_obj_file location)
let location = ms_location old_summary
src_fn = expectJust "summariseModule" (ml_hs_file location)
- -- return the cached summary if the source didn't change
- src_timestamp <- case maybe_buf of
- Just (_,t) -> return t
- Nothing -> getModificationTime src_fn
+ -- check the modification time on the source file, and
+ -- return the cached summary if it hasn't changed. If the
+ -- file has disappeared, we need to call the Finder again.
+ case maybe_buf of
+ Just (_,t) -> check_timestamp old_summary location src_fn t
+ Nothing -> do
+ m <- IO.try (getModificationTime src_fn)
+ case m of
+ Right t -> check_timestamp old_summary location src_fn t
+ Left e | isDoesNotExistError e -> find_it
+ | otherwise -> ioError e
+
+ | otherwise = find_it
+ where
+ dflags = hsc_dflags hsc_env
- if ms_hs_date old_summary == src_timestamp
- then do -- update the object-file timestamp
- obj_timestamp <- getObjTimestamp location is_boot
- return (Just old_summary{ ms_obj_date = obj_timestamp })
- else
- -- source changed: re-summarise
- new_summary location src_fn maybe_buf src_timestamp
+ hsc_src = if is_boot then HsBootFile else HsSrcFile
- | otherwise
- = do found <- findModule hsc_env wanted_mod True {-explicit-}
+ check_timestamp old_summary location src_fn src_timestamp
+ | ms_hs_date old_summary == src_timestamp = do
+ -- update the object-file timestamp
+ obj_timestamp <- getObjTimestamp location is_boot
+ return (Just old_summary{ ms_obj_date = obj_timestamp })
+ | otherwise =
+ -- source changed: find and re-summarise. We call the finder
+ -- again, because the user may have moved the source file.
+ new_summary location src_fn src_timestamp
+
+ find_it = do
+ -- Don't use the Finder's cache this time. If the module was
+ -- previously a package module, it may have now appeared on the
+ -- search path, so we want to consider it to be a home module. If
+ -- the module was previously a home module, it may have moved.
+ uncacheModule hsc_env wanted_mod
+ found <- findModule hsc_env wanted_mod True {-explicit-}
case found of
Found location pkg
| not (isHomePackage pkg) -> return Nothing
-- Home package
err -> noModError dflags loc wanted_mod err
-- Not found
- where
- dflags = hsc_dflags hsc_env
-
- hsc_src = if is_boot then HsBootFile else HsSrcFile
just_found location = do
-- Adjust location to point to the hs-boot source file,
maybe_t <- modificationTimeIfExists src_fn
case maybe_t of
Nothing -> noHsFileErr loc src_fn
- Just t -> new_summary location' src_fn Nothing t
+ Just t -> new_summary location' src_fn t
- new_summary location src_fn maybe_bug src_timestamp
+ new_summary location src_fn src_timestamp
= do
-- Preprocess the source file and get its imports
-- The dflags' contains the OPTIONS pragmas
= do
-- case we bypass the preprocessing stage?
let
- local_opts = getOptionsFromStringBuffer buf
+ local_opts = getOptionsFromStringBuffer buf src_fn
--
(dflags', errs) <- parseDynamicFlags dflags (map snd local_opts)
= 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 (
+multiRootsErr :: [ModSummary] -> IO ()
+multiRootsErr summs@(summ1:_)
+ = throwDyn $ mkPlainErrMsg noSrcSpan $
text "module" <+> quotes (ppr mod) <+>
text "is defined in multiple files:" <+>
- sep (map text files))))
+ sep (map text files)
+ where
+ mod = ms_mod summ1
+ files = map (expectJust "checkDup" . ml_hs_file . ms_location) summs
cyclicModuleErr :: [ModSummary] -> SDoc
cyclicModuleErr ms
if mdl `elem` map ms_mod mg
then getHomeModuleInfo hsc_env mdl
else do
- if isHomeModule (hsc_dflags hsc_env) mdl
+ {- if isHomeModule (hsc_dflags hsc_env) mdl
then return Nothing
- else getPackageModuleInfo hsc_env mdl
+ 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.
+ -- exist... hence the isHomeModule test here. (ToDo: reinstate)
getPackageModuleInfo :: HscEnv -> Module -> IO (Maybe ModuleInfo)
getPackageModuleInfo hsc_env mdl = do
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)
let all_env = foldr plusGlobalRdrEnv export_env toplev_envs
writeIORef ref hsc_env{ hsc_IC = old_ic { ic_toplev_scope = toplevs,
ic_exports = exports,
- ic_rn_gbl_env = all_env } }
+ ic_rn_gbl_env = all_env }}
+
-- Make a GlobalRdrEnv based on the exports of the modules only.
mkExportEnv :: HscEnv -> [Module] -> IO GlobalRdrEnv
_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