import PackageConfig
import Outputable
+import Pretty ( Mode(..), showDocWith )
import ErrUtils
import FastString
import SrcLoc
import Util
+import Maybes
import Control.Exception
import Control.Monad
import qualified Data.Map as Map
import Data.Array.Unboxed
-import Data.Traversable ( traverse )
+import Data.Array.Base
+import Data.List
import Data.Typeable ( Typeable )
import Data.Maybe
import Data.IORef
-- | The :print & friends commands
-------------------------------------
pprintClosureCommand :: Bool -> Bool -> String -> GHCi ()
-pprintClosureCommand bindThings force str = do
- cms <- getSession
- let strs = words str
- mbThings <- io$ ( mapM (GHC.lookupName cms) =<<)
- . liftM concat
- . mapM (GHC.parseName cms)
- $ strs
+pprintClosureCommand bindThings force str = do
+ cms <- getSession
newvarsNames <- io$ do
uniques <- liftM uniqsFromSupply (mkSplitUniqSupply 'q')
return$ map (\u-> (mkSysTvName u (mkFastString "a"))) uniques
- let ids_ = [id | Just (AnId id) <- mbThings]
-
- -- Clean up 'Unknown' types artificially injected into tyvars
- ids = map (stripUnknowns newvarsNames) ids_
-
- -- Obtain the terms
- mb_terms <- io$ mapM (obtainTerm cms force) ids
-
- -- Give names to suspensions and bind them in the local env
- mb_terms' <- if bindThings
- then io$ mapM (traverse (bindSuspensions cms)) mb_terms
- else return mb_terms
- ppr_terms <- io$ mapM (traverse (printTerm cms)) mb_terms'
- let docs = [ ppr id <+> char '=' <+> t | (Just t,id) <- zip ppr_terms ids]
- unqual <- io$ GHC.getPrintUnqual cms
- io . putStrLn . showSDocForUser unqual $ Outputable.vcat docs
-
- -- Type reconstruction may have obtained more defined types for some ids
- -- So we refresh their types.
- let new_ids0 = [ setIdType id ty | (id,Just t) <- zip ids mb_terms
- , let Just ty = termType t
- , ty `isMoreSpecificThan` idType id
- ]
- new_ids <- io$ mapM (\x->liftM (setIdType x) . instantiateTyVarsToUnknown cms . idType $ x)
- new_ids0
- let Session ref = cms
- hsc_env <- io$ readIORef ref
- let ictxt = hsc_IC hsc_env
- type_env = ic_type_env ictxt
- filtered_type_env = delListFromNameEnv type_env (map idName new_ids)
- new_type_env = extendTypeEnvWithIds filtered_type_env new_ids
- new_ic = ictxt {ic_type_env = new_type_env }
- io$ writeIORef ref (hsc_env {hsc_IC = new_ic })
-
- where
- isMoreSpecificThan :: Type -> Type -> Bool
- ty `isMoreSpecificThan ` ty1
+ mb_ids <- io$ mapM (cleanUp cms newvarsNames) (words str)
+ mb_new_ids <- mapM (io . go cms) (catMaybes mb_ids)
+ io$ updateIds cms (catMaybes mb_new_ids)
+ where
+ -- Find the Id, clean up 'Unknowns'
+ cleanUp :: Session -> [Name] -> String -> IO (Maybe Id)
+ cleanUp cms newNames str = do
+ tythings <- GHC.parseName cms str >>= mapM (GHC.lookupName cms)
+ return$ listToMaybe (map (stripUnknowns newNames)
+ [ i | Just (AnId i) <- tythings])
+
+ -- Do the obtainTerm--bindSuspensions-refineIdType dance
+ -- Warning! This function got a good deal of side-effects
+ go :: Session -> Id -> IO (Maybe Id)
+ go cms id = do
+ mb_term <- obtainTerm cms force id
+ maybe (return Nothing) `flip` mb_term $ \term -> do
+ term' <- if not bindThings then return term
+ else bindSuspensions cms term
+ showterm <- pprTerm cms term'
+ unqual <- GHC.getPrintUnqual cms
+ let showSDocForUserOneLine unqual doc =
+ showDocWith LeftMode (doc (mkErrStyle unqual))
+ (putStrLn . showSDocForUserOneLine unqual) (ppr id <+> char '=' <+> showterm)
+ -- Before leaving, we compare the type obtained to see if it's more specific
+ -- Note how we need the Unknown-clear type returned by obtainTerm
+ let Just reconstructedType = termType term
+ new_type <- instantiateTyVarsToUnknown cms
+ (mostSpecificType (idType id) reconstructedType)
+ return . Just $ setIdType id new_type
+
+ updateIds :: Session -> [Id] -> IO ()
+ updateIds (Session ref) new_ids = do
+ hsc_env <- readIORef ref
+ let ictxt = hsc_IC hsc_env
+ type_env = ic_type_env ictxt
+ filtered_type_env = delListFromNameEnv type_env (map idName new_ids)
+ new_type_env = extendTypeEnvWithIds filtered_type_env new_ids
+ new_ic = ictxt {ic_type_env = new_type_env }
+ writeIORef ref (hsc_env {hsc_IC = new_ic })
+
+isMoreSpecificThan :: Type -> Type -> Bool
+ty `isMoreSpecificThan` ty1
| Just subst <- tcUnifyTys bindOnlyTy1 [repType' ty] [repType' ty1]
, substFiltered <- filter (not.isTyVarTy) . varEnvElts . getTvSubstEnv $ subst
, not . null $ substFiltered
, all (flip notElemTvSubst subst) ty_vars
--- , pprTrace "subst" (ppr subst) True
= True
| otherwise = False
where bindOnlyTy1 tyv | tyv `elem` ty_vars = AvoidMe
| otherwise = BindMe
ty_vars = varSetElems$ tyVarsOfType ty
- bindSuspensions :: Session -> Term -> IO Term
- bindSuspensions cms@(Session ref) t = do
+mostSpecificType ty1 ty2 | ty1 `isMoreSpecificThan` ty2 = ty1
+ | otherwise = ty2
+
+-- | Give names, and bind in the interactive environment, to all the suspensions
+-- included (inductively) in a term
+bindSuspensions :: Session -> Term -> IO Term
+bindSuspensions cms@(Session ref) t = do
hsc_env <- readIORef ref
inScope <- GHC.getBindings cms
let ictxt = hsc_IC hsc_env
type_env = ic_type_env ictxt
prefix = "_t"
alreadyUsedNames = map (occNameString . nameOccName . getName) inScope
- availNames = [n | n <- map ((prefix++) . show) [1..]
- , n `notElem` alreadyUsedNames ]
+ availNames = map ((prefix++) . show) [1..] \\ alreadyUsedNames
availNames_var <- newIORef availNames
(t', stuff) <- foldTerm (nameSuspensionsAndGetInfos availNames_var) t
let (names, tys, hvals) = unzip3 stuff
-- A custom Term printer to enable the use of Show instances
- printTerm cms@(Session ref) = customPrintTerm customPrint
- where
- customPrint = \p-> customPrintShowable : customPrintTermBase p
- customPrintShowable t@Term{ty=ty, dc=dc, val=val} = do
- let hasType = isEmptyVarSet (tyVarsOfType ty) -- redundant
- isEvaled = isFullyEvaluatedTerm t
- if isEvaled -- && hasType
- then do
- hsc_env <- readIORef ref
- dflags <- GHC.getSessionDynFlags cms
- do
- (new_env, bname) <- bindToFreshName hsc_env ty "showme"
- writeIORef ref (new_env)
- let noop_log _ _ _ _ = return ()
- expr = "show " ++ showSDoc (ppr bname)
- GHC.setSessionDynFlags cms dflags{log_action=noop_log}
- mb_txt <- withExtendedLinkEnv [(bname, val)]
- (GHC.compileExpr cms expr)
- case mb_txt of
- Just txt -> return . Just . text . unsafeCoerce# $ txt
- Nothing -> return Nothing
- `finally` do
- writeIORef ref hsc_env
- GHC.setSessionDynFlags cms dflags
- else return Nothing
-
- bindToFreshName hsc_env ty userName = do
- name <- newGrimName cms userName
- let ictxt = hsc_IC hsc_env
- rn_env = ic_rn_local_env ictxt
- type_env = ic_type_env ictxt
- id = mkGlobalId VanillaGlobal name ty vanillaIdInfo
- new_type_env = extendTypeEnv type_env (AnId id)
- new_rn_env = extendLocalRdrEnv rn_env [name]
- new_ic = ictxt { ic_rn_local_env = new_rn_env,
- ic_type_env = new_type_env }
- return (hsc_env {hsc_IC = new_ic }, name)
+pprTerm cms@(Session ref) = customPrintTerm customPrint
+ where
+ customPrint = \p-> customPrintShowable : customPrintTermBase p
+ customPrintShowable t@Term{ty=ty, dc=dc, val=val} = do
+ let hasType = isEmptyVarSet (tyVarsOfType ty) -- redundant
+ isEvaled = isFullyEvaluatedTerm t
+ if not isEvaled -- || not hasType
+ then return Nothing
+ else do
+ hsc_env <- readIORef ref
+ dflags <- GHC.getSessionDynFlags cms
+ do
+ (new_env, bname) <- bindToFreshName hsc_env ty "showme"
+ writeIORef ref (new_env)
+ let noop_log _ _ _ _ = return ()
+ expr = "show " ++ showSDoc (ppr bname)
+ GHC.setSessionDynFlags cms dflags{log_action=noop_log}
+ mb_txt <- withExtendedLinkEnv [(bname, val)]
+ (GHC.compileExpr cms expr)
+ case mb_txt of
+ Just txt -> return . Just . text . unsafeCoerce# $ txt
+ Nothing -> return Nothing
+ `finally` do
+ writeIORef ref hsc_env
+ GHC.setSessionDynFlags cms dflags
+
+ bindToFreshName hsc_env ty userName = do
+ name <- newGrimName cms userName
+ let ictxt = hsc_IC hsc_env
+ rn_env = ic_rn_local_env ictxt
+ type_env = ic_type_env ictxt
+ id = mkGlobalId VanillaGlobal name ty vanillaIdInfo
+ new_type_env = extendTypeEnv type_env (AnId id)
+ new_rn_env = extendLocalRdrEnv rn_env [name]
+ new_ic = ictxt { ic_rn_local_env = new_rn_env,
+ ic_type_env = new_type_env }
+ return (hsc_env {hsc_IC = new_ic }, name)
+
-- Create new uniques and give them sequentially numbered names
-- newGrimName :: Session -> String -> IO Name
- newGrimName cms userName = do
- us <- mkSplitUniqSupply 'b'
- let unique = uniqFromSupply us
- occname = mkOccName varName userName
- name = mkInternalName unique occname noSrcLoc
- return name
+newGrimName cms userName = do
+ us <- mkSplitUniqSupply 'b'
+ let unique = uniqFromSupply us
+ occname = mkOccName varName userName
+ name = mkInternalName unique occname noSrcLoc
+ return name
----------------------------------------------------------------------------
-- | Replace all the tyvars in a Term with the opaque type GHC.Base.Unknown
-- | The inverse function. Strip the GHC.Base.Unknowns in the type of the id, they correspond to tyvars. The caller must provide an infinite list of fresh names
stripUnknowns :: [Name] -> Id -> Id
-stripUnknowns names id = setIdType id . sigmaType . fst . go names . idType
+stripUnknowns names id = setIdType id . fst . go names . idType
$ id
where
- sigmaType ty = mkForAllTys (varSetElems$ tyVarsOfType (dropForAlls ty)) ty
go tyvarsNames@(v:vv) ty
| Just (ty1,ty2) <- splitFunTy_maybe ty = let
(ty1',vv') = go tyvarsNames ty1
-----------------------------
-- | The :breakpoint command
-----------------------------
-bkptOptions :: String -> GHCi ()
+bkptOptions :: String -> GHCi Bool
+bkptOptions "continue" = -- We want to quit if in an inferior session
+ liftM not isTopLevel
+bkptOptions "stop" = do
+ inside_break <- liftM not isTopLevel
+ when inside_break $ throwDyn StopChildSession
+ return False
+
bkptOptions cmd = do
dflags <- getDynFlags
bt <- getBkptTable
- bkptOptions' (words cmd) bt
+ sess <- getSession
+ bkptOptions' sess (words cmd) bt
+ return False
where
- bkptOptions' ["list"] bt = do
+ bkptOptions' _ ["list"] bt = do
let msgs = [ ppr mod <+> colon <+> ppr coords
| (mod,site) <- btList bt
, let coords = getSiteCoords bt mod site]
else vcat num_msgs
io$ putStrLn msg
- bkptOptions' ["stop"] bt = do
- inside_break <- liftM not isTopLevel
- when inside_break $ throwDyn StopChildSession
+ bkptOptions' s ("add":cmds) bt
+ | [line] <- cmds
+ , [(lineNum,[])] <- reads line
+ = do (toplevel,_) <- io$ GHC.getContext s
+ case toplevel of
+ (m:_) -> handleAdd (\mod->addBkptByLine mod lineNum) m
+ [] -> throwDyn $ CmdLineError $ "No module loaded in debugging mode"
- bkptOptions' ("add":cmds) bt
| [mod_name,line]<- cmds
, [(lineNum,[])] <- reads line
- = handleAdd mod_name $ (\mod->addBkptByLine mod lineNum)
+ = io(GHC.findModule s (GHC.mkModuleName mod_name) Nothing) >>=
+ handleAdd (\mod->addBkptByLine mod lineNum)
| [mod_name,line,col] <- cmds
- = handleAdd mod_name $ (\mod->addBkptByCoord mod (read line, read col))
+ = io(GHC.findModule s (GHC.mkModuleName mod_name) Nothing) >>=
+ handleAdd (\mod->addBkptByCoord mod (read line, read col))
| otherwise = throwDyn $ CmdLineError $
"syntax: :breakpoint add Module line [col]"
where
- handleAdd mod_name f = do
- sess <- getSession
- dflags <- getDynFlags
- mod <- io$ GHC.findModule sess (GHC.mkModuleName mod_name) Nothing
- ghciHandleDyn (handleBkptEx mod) $
- case f mod bt of
- (newTable, site) -> do
- setBkptTable newTable
- io (putStrLn ("Breakpoint set at " ++
- show (getSiteCoords newTable mod site)))
-
- bkptOptions' ("del":cmds) bt
+ handleAdd f mod =
+ either
+ (handleBkptEx s mod)
+ (\(newTable, site) -> do
+ setBkptTable newTable
+ let (x,y) = getSiteCoords newTable mod site
+ io (putStrLn ("Breakpoint set at " ++ showSDoc (ppr mod)
+ ++ ':' : show x ++ ':' : show y)))
+ (f mod bt)
+
+ bkptOptions' s ("del":cmds) bt
| [i'] <- cmds
, [(i,[])] <- reads i'
, bkpts <- btList bt
= handleDel mod $ delBkptByCoord mod (lineNum, colNum)
| otherwise = throwDyn $ CmdLineError $
- "syntax: :breakpoint del (breakpoint # | Module line [col])"
+ "syntax: :breakpoint del (breakpoint # | [Module] line [col])"
where delMsg = "Breakpoint deleted"
- handleDel mod f = ghciHandleDyn (handleBkptEx mod) $ do
- modifyBkptTable f
- newTable <- getBkptTable
- sess <- getSession
- dflags <- getDynFlags
- io$ putStrLn delMsg
-
- bkptOptions' _ _ = throwDyn $ CmdLineError $
- "syntax: :breakpoint (list|stop|add|del)"
-
- handleBkptEx :: Module -> Debugger.BkptException -> a
- handleBkptEx _ NoBkptFound = error "No suitable breakpoint site found" --TODO Automatically add to the next suitable line
- handleBkptEx _ NotNeeded = error "Nothing to do"
- handleBkptEx m NotHandled = error$ "Module " ++ showSDoc (ppr m) ++ " was not loaded under debugging mode. Enable debugging mode and reload it"
+ handleDel mod f = either (handleBkptEx s mod)
+ (\newtable-> setBkptTable newtable >> io (putStrLn delMsg))
+ (f bt)
+
+ bkptOptions' _ _ _ = throwDyn $ CmdLineError $
+ "syntax: :breakpoint (list|continue|stop|add|del)"
+
+-- Error messages
+-- handleBkptEx :: Session -> Module -> Debugger.BkptException -> a
+ handleBkptEx s m NotHandled = io$ do
+ isInterpreted <- findModSummary m >>= isModuleInterpreted s
+ if isInterpreted
+ then error$ "Module " ++ showSDoc (ppr m) ++ " was not loaded under debugging mode.\n"
+ ++ "Enable debugging mode with -fdebugging (and reload your module)"
+ else error$ "Module " ++ showSDoc (ppr m) ++ " was loaded in compiled (.o) mode.\n"
+ ++ "You must load a module in interpreted mode and with -fdebugging on to debug it."
+ where findModSummary m = do
+ mod_graph <- getModuleGraph s
+ return$ head [ modsum | modsum <- mod_graph, ms_mod modsum == m]
+ handleBkptEx _ _ e = error (show e)
-------------------------
-- Breakpoint Tables
-- | A list of lines, each line can have zero or more sites, which are annotated with a column number
, sites :: Map.Map a [[(SiteNumber, Int)]]
}
+ deriving Show
sitesOf :: Ord a => BkptTable a -> a -> Maybe [[(SiteNumber, Int)]]
sitesOf bt fn = Map.lookup fn (sites bt)
bkptsOf bt fn = Map.lookup fn (breakpoints bt)
--- The functions for manipulating BkptTables do throw exceptions
-data BkptException =
- NotHandled
+data BkptError =
+ NotHandled -- Trying to manipulate a element not handled by this BkptTable
| NoBkptFound
| NotNeeded -- Used when a breakpoint was already enabled
deriving Typeable
+instance Show BkptError where
+ show NoBkptFound = "No suitable breakpoint site found"
+ show NotNeeded = "Nothing to do"
+ show NotHandled = "BkptTable: Element not controlled by this table"
+
emptyBkptTable :: Ord a => BkptTable a
addModule :: Ord a => a -> [(SiteNumber,Coord)] -> BkptTable a -> BkptTable a
-- | Lines start at index 1
-addBkptByLine :: Ord a => a -> Int -> BkptTable a -> (BkptTable a, SiteNumber)
-addBkptByCoord :: Ord a => a -> Coord -> BkptTable a -> (BkptTable a, SiteNumber)
-delBkptByLine :: Ord a => a -> Int -> BkptTable a -> BkptTable a
-delBkptBySite :: Ord a => a -> SiteNumber -> BkptTable a -> BkptTable a
-delBkptByCoord :: Ord a => a -> Coord -> BkptTable a -> BkptTable a
+addBkptByLine :: Ord a => a -> Int -> BkptTable a -> Either BkptError (BkptTable a, SiteNumber)
+addBkptByCoord :: Ord a => a -> Coord -> BkptTable a -> Either BkptError (BkptTable a, SiteNumber)
+delBkptByLine :: Ord a => a -> Int -> BkptTable a -> Either BkptError (BkptTable a)
+delBkptBySite :: Ord a => a -> SiteNumber -> BkptTable a -> Either BkptError (BkptTable a)
+delBkptByCoord :: Ord a => a -> Coord -> BkptTable a -> Either BkptError (BkptTable a)
isBkptEnabled :: Ord a => BkptTable a -> BkptLocation a -> Bool
btElems :: Ord a => BkptTable a -> [(a, [SiteNumber])]
| Just lines <- sitesOf bt a
, Just bkptsArr <- bkptsOf bt a
, i < length lines
- = case lines!!i of
- [] -> throwDyn NoBkptFound
- (x:_) -> let (siteNum,col) = x
- wasAlreadyOn = bkptsArr ! siteNum
- newArr = bkptsArr // [(siteNum, True)]
- newTable = Map.insert a newArr (breakpoints bt)
+ = case [line | line <- drop i lines, not (null line)] of
+ ((x:_):_) -> let (siteNum,col) = x
+ wasAlreadyOn = bkptsArr ! siteNum
+ newArr = bkptsArr // [(siteNum, True)]
+ newTable = Map.insert a newArr (breakpoints bt)
in if wasAlreadyOn
- then throwDyn NotNeeded
- else (bt{breakpoints=newTable}, siteNum)
+ then Left NotNeeded
+ else Right (bt{breakpoints=newTable}, siteNum)
+ otherwise -> Left NoBkptFound
| Just sites <- sitesOf bt a
- = throwDyn NoBkptFound
- | otherwise = throwDyn NotHandled
+ = Left NoBkptFound
+ | otherwise = Left NotHandled
addBkptByCoord a (r,c) bt
| Just lines <- sitesOf bt a
, Just bkptsArr <- bkptsOf bt a
, r < length lines
= case [ (sn,col) | (sn,col)<-lines!!r, col>=c] of
- [] -> throwDyn NoBkptFound
+ [] -> Left NoBkptFound
(x:_) -> let (siteNum, col) = x
wasAlreadyOn = bkptsArr ! siteNum
newArr = bkptsArr // [(siteNum, True)]
newTable = Map.insert a newArr (breakpoints bt)
in if wasAlreadyOn
- then throwDyn NotNeeded
- else (bt{breakpoints=newTable}, siteNum)
+ then Left NotNeeded
+ else Right (bt{breakpoints=newTable}, siteNum)
| Just sites <- sitesOf bt a
- = throwDyn NoBkptFound
- | otherwise = throwDyn NotHandled
+ = Left NoBkptFound
+ | otherwise = Left NotHandled
delBkptBySite a i bt
| Just bkptsArr <- bkptsOf bt a
, not (inRange (bounds bkptsArr) i)
- = throwDyn NoBkptFound
+ = Left NoBkptFound
| Just bkptsArr <- bkptsOf bt a
, bkptsArr ! i -- Check that there was a enabled bkpt here
, newArr <- bkptsArr // [(i,False)]
, newTable <- Map.insert a newArr (breakpoints bt)
- = bt {breakpoints=newTable}
+ = Right bt {breakpoints=newTable}
| Just sites <- sitesOf bt a
- = throwDyn NotNeeded
+ = Left NotNeeded
- | otherwise = throwDyn NotHandled
+ | otherwise = Left NotHandled
delBkptByLine a l bt
| Just sites <- sitesOf bt a
= delBkptBySite a site bt
| Just sites <- sitesOf bt a
- = throwDyn NoBkptFound
+ = Left NoBkptFound
- | otherwise = throwDyn NotHandled
+ | otherwise = Left NotHandled
delBkptByCoord a (r,c) bt
| Just sites <- sitesOf bt a
= delBkptBySite a site bt
| Just sites <- sitesOf bt a
- = throwDyn NoBkptFound
+ = Left NoBkptFound
- | otherwise = throwDyn NotHandled
+ | otherwise = Left NotHandled
btElems bt = [ (a, [i | (i,True) <- assocs siteArr])
| (a, siteArr) <- Map.assocs (breakpoints bt) ]
, s == site ]
-- addModule is dumb and inefficient, but it does the job
---addModule fn siteCoords _ | trace ("addModule: " ++ moduleString (unsafeCoerce# fn) ++ " - " ++ show siteCoords) False = undefined
-addModule a [] bt = bt
+addModule a [] bt = bt {sites = Map.insert a [] (sites bt)}
addModule a siteCoords bt
| nrows <- maximum$ [i | (_,(i,j)) <- siteCoords ]
, sitesByRow <- [ [(s,c) | (s,(r,c)) <- siteCoords, r==i]
| i <- [0..nrows] ]
, nsites <- length siteCoords
- , initialBkpts <- listArray (1, nsites) (repeat False)
+ , initialBkpts <- listArray (0, nsites+1) (repeat False)
= bt{ sites = Map.insert a sitesByRow (sites bt)
, breakpoints = Map.insert a initialBkpts (breakpoints bt) }
+-- This MUST be fast
+isBkptEnabled bt site | bt `seq` site `seq` False = undefined
isBkptEnabled bt (a,site)
| Just bkpts <- bkptsOf bt a
- , inRange (bounds bkpts) site
- = bkpts ! site
- | otherwise = throwDyn NotHandled -- This is an error
+ = ASSERT (inRange (bounds bkpts) site)
+ unsafeAt bkpts site
-----------------
-- Other stuff
-----------------
-refreshBkptTable :: [ModSummary] -> GHCi ()
-refreshBkptTable [] = return ()
-refreshBkptTable (ms:mod_sums) = do
- sess <- getSession
- when (Opt_Debugging `elem` flags (GHC.ms_hspp_opts ms)) $ do
- old_table <- getBkptTable
- new_table <- addModuleGHC sess old_table (GHC.ms_mod ms)
- setBkptTable new_table
- refreshBkptTable mod_sums
- where addModuleGHC sess bt mod = do
- Just mod_info <- io$ GHC.getModuleInfo sess mod
- dflags <- getDynFlags
- let sites = GHC.modInfoBkptSites mod_info
- io$ debugTraceMsg dflags 2
+refreshBkptTable :: Session -> BkptTable Module -> [ModSummary] -> IO (BkptTable Module)
+refreshBkptTable sess = foldM updIfDebugging
+ where
+ updIfDebugging bt ms = do
+ isDebugging <- isDebuggingM ms
+ if isDebugging
+ then addModuleGHC sess bt (GHC.ms_mod ms)
+ else return bt
+ addModuleGHC sess bt mod = do
+ Just mod_info <- GHC.getModuleInfo sess mod
+ dflags <- GHC.getSessionDynFlags sess
+ let sites = GHC.modInfoBkptSites mod_info
+ debugTraceMsg dflags 2
(ppr mod <> text ": inserted " <> int (length sites) <>
text " breakpoints")
- return$ addModule mod sites bt
+ return$ addModule mod sites bt
+#if defined(GHCI) && defined(DEBUGGER)
+ isDebuggingM ms = isModuleInterpreted sess ms >>= \isInterpreted ->
+ return (Opt_Debugging `elem` dflags &&
+ target == HscInterpreted && isInterpreted)
+ where dflags = flags (GHC.ms_hspp_opts ms)
+ target = hscTarget (GHC.ms_hspp_opts ms)
+#else
+ isDebuggingM _ = return False
+#endif