Added the new :breakpoint continue option
[ghc-hetmet.git] / compiler / ghci / Debugger.hs
1 -----------------------------------------------------------------------------
2 --
3 -- GHCi Interactive debugging commands 
4 --
5 -- Pepe Iborra (supported by Google SoC) 2006
6 --
7 -----------------------------------------------------------------------------
8
9 module Debugger where
10
11 import Linker
12 import Breakpoints
13 import RtClosureInspect
14
15 import PrelNames
16 import HscTypes
17 import IdInfo
18 --import Id
19 import Var hiding ( varName )
20 import VarSet
21 import VarEnv
22 import Name 
23 import NameEnv
24 import RdrName
25 import Module
26 import Finder
27 import UniqSupply
28 import Type
29 import TyCon
30 import DataCon
31 import TcGadt
32 import GHC
33 import GhciMonad
34 import PackageConfig
35
36 import Outputable
37 import ErrUtils
38 import FastString
39 import SrcLoc
40 import Util
41 import Maybes
42
43 import Control.Exception
44 import Control.Monad
45 import qualified Data.Map as Map
46 import Data.Array.Unboxed
47 import Data.Typeable             ( Typeable )
48 import Data.Maybe
49 import Data.IORef
50
51 import System.IO
52 import GHC.Exts
53
54 #include "HsVersions.h"
55
56 -------------------------------------
57 -- | The :print & friends commands
58 -------------------------------------
59 pprintClosureCommand :: Bool -> Bool -> String -> GHCi ()
60 pprintClosureCommand bindThings force str = do
61   cms <- getSession 
62   let strs = words str
63   mbThings <- io$ ( mapM (GHC.lookupName cms) =<<) 
64                   . liftM concat 
65                   . mapM (GHC.parseName cms) 
66                    $ strs
67   newvarsNames <- io$ do 
68            uniques <- liftM uniqsFromSupply (mkSplitUniqSupply 'q')
69            return$ map (\u-> (mkSysTvName u (mkFastString "a"))) uniques
70   let ids_ = [id | Just (AnId id) <- mbThings]
71
72   -- Clean up 'Unknown' types artificially injected into tyvars 
73       ids = map (stripUnknowns newvarsNames) ids_
74  
75  -- Obtain the terms 
76   mb_terms  <- io$ mapM (obtainTerm cms force) ids
77
78   -- Give names to suspensions and bind them in the local env
79   mb_terms' <- if bindThings
80                then io$ mapM (fmapMMaybe (bindSuspensions cms)) mb_terms
81                else return mb_terms
82   ppr_terms <- io$ mapM (fmapMMaybe (printTerm cms)) mb_terms' 
83   let docs = [ ppr id <+> char '=' <+> t | (Just t,id) <- zip ppr_terms ids]
84   unqual  <- io$ GHC.getPrintUnqual cms
85   io . putStrLn . showSDocForUser unqual $ Outputable.vcat docs
86
87   -- Type reconstruction may have obtained more defined types for some ids
88   -- So we refresh their types.
89   let new_ids0 = [ setIdType id ty | (id,Just t) <- zip ids mb_terms
90                                    , let Just ty = termType t
91                                    , ty `isMoreSpecificThan` idType id 
92                                    ]
93   new_ids <- io$ mapM (\x->liftM (setIdType x) . instantiateTyVarsToUnknown cms . idType $ x) 
94                       new_ids0   
95   let Session ref = cms
96   hsc_env <- io$ readIORef ref
97   let ictxt = hsc_IC hsc_env
98       type_env = ic_type_env ictxt
99       filtered_type_env = delListFromNameEnv type_env (map idName new_ids)
100       new_type_env =  extendTypeEnvWithIds filtered_type_env new_ids
101       new_ic = ictxt {ic_type_env = new_type_env }
102   io$ writeIORef ref (hsc_env {hsc_IC = new_ic })
103                                           
104   where
105     isMoreSpecificThan :: Type -> Type -> Bool
106     ty `isMoreSpecificThan   ` ty1 
107       | Just subst    <- tcUnifyTys bindOnlyTy1 [repType' ty] [repType' ty1] 
108       , substFiltered <- filter (not.isTyVarTy) . varEnvElts . getTvSubstEnv $ subst
109       , not . null $ substFiltered
110       , all (flip notElemTvSubst subst) ty_vars
111       = True
112       | otherwise = False
113       where bindOnlyTy1 tyv | tyv `elem` ty_vars = AvoidMe
114                             | otherwise = BindMe
115             ty_vars = varSetElems$ tyVarsOfType ty
116
117     bindSuspensions :: Session -> Term -> IO Term
118     bindSuspensions cms@(Session ref) t = do 
119       hsc_env <- readIORef ref
120       inScope <- GHC.getBindings cms
121       let ictxt        = hsc_IC hsc_env
122           rn_env       = ic_rn_local_env ictxt
123           type_env     = ic_type_env ictxt
124           prefix       = "_t"
125           alreadyUsedNames = map (occNameString . nameOccName . getName) inScope
126           availNames   = [n | n <- map ((prefix++) . show) [1..]
127                             , n `notElem` alreadyUsedNames ]
128       availNames_var  <- newIORef availNames
129       (t', stuff)     <- foldTerm (nameSuspensionsAndGetInfos availNames_var) t
130       let (names, tys, hvals) = unzip3 stuff
131       concrete_tys    <- mapM (instantiateTyVarsToUnknown cms) tys
132       let ids = [ mkGlobalId VanillaGlobal name ty vanillaIdInfo
133                   | (name,ty) <- zip names concrete_tys]
134           new_type_env = extendTypeEnvWithIds type_env ids 
135           new_rn_env   = extendLocalRdrEnv rn_env names
136           new_ic       = ictxt { ic_rn_local_env = new_rn_env, 
137                                  ic_type_env     = new_type_env }
138       extendLinkEnv (zip names hvals)
139       writeIORef ref (hsc_env {hsc_IC = new_ic })
140       return t'
141      where    
142
143 --    Processing suspensions. Give names and recopilate info
144         nameSuspensionsAndGetInfos :: IORef [String] -> TermFold (IO (Term, [(Name,Type,HValue)]))
145         nameSuspensionsAndGetInfos freeNames = TermFold 
146                       {
147                         fSuspension = doSuspension freeNames
148                       , fTerm = \ty dc v tt -> do 
149                                     tt' <- sequence tt 
150                                     let (terms,names) = unzip tt' 
151                                     return (Term ty dc v terms, concat names)
152                       , fPrim    = \ty n ->return (Prim ty n,[])
153                       }
154         doSuspension freeNames ct mb_ty hval Nothing = do
155           name <- atomicModifyIORef freeNames (\x->(tail x, head x))
156           n <- newGrimName cms name
157           let ty' = fromMaybe (error "unexpected") mb_ty
158           return (Suspension ct mb_ty hval (Just n), [(n,ty',hval)])
159
160
161 --  A custom Term printer to enable the use of Show instances
162     printTerm cms@(Session ref) = customPrintTerm customPrint
163       where
164         customPrint = \p-> customPrintShowable : customPrintTermBase p 
165         customPrintShowable t@Term{ty=ty, dc=dc, val=val} = do
166           let hasType = isEmptyVarSet (tyVarsOfType ty)  -- redundant
167               isEvaled = isFullyEvaluatedTerm t
168           if isEvaled -- && hasType
169            then do 
170               hsc_env <- readIORef ref
171               dflags  <- GHC.getSessionDynFlags cms
172               do
173                    (new_env, bname) <- bindToFreshName hsc_env ty "showme"
174                    writeIORef ref (new_env)
175                    let noop_log _ _ _ _ = return () 
176                        expr = "show " ++ showSDoc (ppr bname)
177                    GHC.setSessionDynFlags cms dflags{log_action=noop_log}
178                    mb_txt <- withExtendedLinkEnv [(bname, val)] 
179                                (GHC.compileExpr cms expr)
180                    case mb_txt of 
181                      Just txt -> return . Just . text . unsafeCoerce# $ txt
182                      Nothing  -> return Nothing
183                `finally` do 
184                    writeIORef ref hsc_env
185                    GHC.setSessionDynFlags cms dflags
186            else return Nothing
187
188         bindToFreshName hsc_env ty userName = do
189           name <- newGrimName cms userName 
190           let ictxt    = hsc_IC hsc_env
191               rn_env   = ic_rn_local_env ictxt
192               type_env = ic_type_env ictxt
193               id       = mkGlobalId VanillaGlobal name ty vanillaIdInfo
194               new_type_env = extendTypeEnv type_env (AnId id)
195               new_rn_env   = extendLocalRdrEnv rn_env [name]
196               new_ic       = ictxt { ic_rn_local_env = new_rn_env, 
197                                      ic_type_env     = new_type_env }
198           return (hsc_env {hsc_IC = new_ic }, name)
199 --    Create new uniques and give them sequentially numbered names
200 --    newGrimName :: Session -> String -> IO Name
201     newGrimName cms userName  = do
202       us <- mkSplitUniqSupply 'b'
203       let unique  = uniqFromSupply us
204           occname = mkOccName varName userName
205           name    = mkInternalName unique occname noSrcLoc
206       return name
207
208 ----------------------------------------------------------------------------
209 -- | Replace all the tyvars in a Term with the opaque type GHC.Base.Unknown
210 ----------------------------------------------------------------------------
211 instantiateTyVarsToUnknown :: Session -> Type -> IO Type
212 instantiateTyVarsToUnknown cms ty
213 -- We have a GADT, so just fix its tyvars
214     | Just (tycon, args) <- splitTyConApp_maybe ty
215     , tycon /= funTyCon
216     , isGADT tycon
217     = mapM fixTyVars args >>= return . mkTyConApp tycon
218 -- We have a regular TyCon, so map recursively to its args
219     | Just (tycon, args) <- splitTyConApp_maybe ty
220     , tycon /= funTyCon
221     = do unknownTyVar <- unknownTV
222          args' <- mapM (instantiateTyVarsToUnknown cms) args
223          return$ mkTyConApp tycon args'
224 -- we have a tyvar of kind *
225     | Just tyvar <- getTyVar_maybe ty
226     , ([],_) <- splitKindFunTys (tyVarKind tyvar) 
227     = unknownTV
228 -- we have a higher kind tyvar, so insert an unknown of the appropriate kind
229     | Just tyvar <- getTyVar_maybe ty
230     , (args,_) <- splitKindFunTys (tyVarKind tyvar)
231     = liftM mkTyConTy $ unknownTC !! length args
232 -- Base case
233     | otherwise    = return ty 
234
235  where unknownTV = do 
236          Just (ATyCon unknown_tc) <- lookupName cms unknownTyConName
237          return$ mkTyConTy unknown_tc
238        unknownTC = [undefined, unknownTC1, unknownTC2, unknownTC3]
239        unknownTC1 = do 
240          Just (ATyCon unknown_tc) <- lookupName cms unknown1TyConName
241          return unknown_tc
242        unknownTC2 = do 
243          Just (ATyCon unknown_tc) <- lookupName cms unknown2TyConName
244          return unknown_tc
245        unknownTC3 = do 
246          Just (ATyCon unknown_tc) <- lookupName cms unknown3TyConName
247          return unknown_tc
248 --       isGADT ty | pprTrace' "isGADT" (ppr ty <> colon <> ppr(isGadtSyntaxTyCon ty)) False = undefined
249        isGADT tc | Just dcs <- tyConDataCons_maybe tc = any (not . null . dataConEqSpec) dcs
250                  | otherwise = False
251        fixTyVars ty 
252            | Just (tycon, args) <- splitTyConApp_maybe ty
253            = mapM fixTyVars args >>= return . mkTyConApp tycon
254 -- Fix the tyvar so that the interactive environment doesn't choke on it TODO 
255            | Just tv <- getTyVar_maybe ty = return ty --TODO
256            | otherwise = return ty
257
258 -- | 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
259 stripUnknowns :: [Name] -> Id -> Id
260 stripUnknowns names id = setIdType id . sigmaType . fst . go names . idType 
261                            $ id
262  where 
263    sigmaType ty = mkForAllTys (varSetElems$ tyVarsOfType (dropForAlls ty)) ty
264    go tyvarsNames@(v:vv) ty 
265     | Just (ty1,ty2) <- splitFunTy_maybe ty = let
266                (ty1',vv') = go tyvarsNames ty1
267                (ty2',vv'')= go vv' ty2
268                in (mkFunTy ty1' ty2', vv'')
269     | Just (ty1,ty2) <- splitAppTy_maybe ty = let
270                (ty1',vv') = go tyvarsNames ty1
271                (ty2',vv'')= go vv' ty2
272                in (mkAppTy ty1' ty2', vv'')
273     | Just (tycon, args) <- splitTyConApp_maybe ty 
274     , Just (tycon', vv') <- (fixTycon tycon tyvarsNames)
275     , (args',vv'') <- foldr (\arg (aa,vv) -> let (arg',vv') = go vv' arg 
276                                              in (arg':aa,vv'))
277                             ([],vv') args
278     = (mkAppTys tycon' args',vv'')
279     | Just (tycon, args) <- splitTyConApp_maybe ty
280     , (args',vv') <- foldr (\arg (aa,vv) -> let (arg',vv') = go vv' arg 
281                                             in (arg':aa,vv'))
282                            ([],tyvarsNames) args
283     = (mkTyConApp tycon args',vv')
284     | otherwise = (ty, tyvarsNames)
285     where  fixTycon tycon (v:vv) = do
286                k <- lookup (tyConName tycon) kinds
287                return (mkTyVarTy$ mkTyVar v k, vv)
288            kinds = [ (unknownTyConName, liftedTypeKind)
289                    , (unknown1TyConName, kind1)
290                    , (unknown2TyConName, kind2)
291                    , (unknown3TyConName, kind3)]
292            kind1 = mkArrowKind liftedTypeKind liftedTypeKind
293            kind2 = mkArrowKind kind1 liftedTypeKind
294            kind3 = mkArrowKind kind2 liftedTypeKind
295 stripUnknowns _ id = id
296
297 -----------------------------
298 -- | The :breakpoint command
299 -----------------------------
300 bkptOptions :: String -> GHCi Bool
301 bkptOptions "continue" = -- We want to quit if in an inferior session
302                          liftM not isTopLevel 
303 bkptOptions "stop" = do
304   inside_break <- liftM not isTopLevel
305   when inside_break $ throwDyn StopChildSession 
306   return False
307
308 bkptOptions cmd = do 
309   dflags <- getDynFlags
310   bt     <- getBkptTable
311   bkptOptions' (words cmd) bt
312   return False
313    where
314     bkptOptions' ["list"] bt = do 
315       let msgs = [ ppr mod <+> colon <+> ppr coords 
316                    | (mod,site) <- btList bt
317                    , let coords = getSiteCoords bt mod site]
318           num_msgs = [parens (int n) <+> msg | (n,msg) <- zip [1..] msgs]
319       msg <- showForUser$ if null num_msgs 
320                             then text "There are no enabled breakpoints"
321                             else vcat num_msgs
322       io$ putStrLn msg
323
324     bkptOptions' ("add":cmds) bt 
325       | [mod_name,line]<- cmds
326       , [(lineNum,[])] <- reads line
327       =  handleAdd mod_name $ (\mod->addBkptByLine mod lineNum)
328
329       | [mod_name,line,col] <- cmds
330       = handleAdd mod_name $ (\mod->addBkptByCoord mod (read line, read col))
331
332       | otherwise = throwDyn $ CmdLineError $ 
333                        "syntax: :breakpoint add Module line [col]"
334        where 
335          handleAdd mod_name f = do
336            sess        <- getSession
337            dflags      <- getDynFlags
338            mod         <- io$ GHC.findModule sess (GHC.mkModuleName mod_name) Nothing
339            ghciHandleDyn (handleBkptEx mod) $
340             case f mod bt of
341              (newTable, site)  -> do
342                setBkptTable newTable 
343                io (putStrLn ("Breakpoint set at " ++ 
344                               show (getSiteCoords newTable mod site)))
345
346     bkptOptions' ("del":cmds) bt 
347       | [i']     <- cmds 
348       , [(i,[])] <- reads i'
349       , bkpts    <- btList bt
350       = if i > length bkpts
351            then throwDyn $ CmdLineError 
352               "Not a valid breakpoint #. Use :breakpoint list to see the current breakpoints."
353            else 
354              let (mod, site) = bkpts !! (i-1)
355              in handleDel mod $ delBkptBySite mod site
356
357       | [fn,line]      <- cmds 
358       , [(lineNum,[])] <- reads line
359       , mod            <- GHC.mkModule mainPackageId (GHC.mkModuleName fn)
360       = handleDel mod $  delBkptByLine mod lineNum
361
362       | [fn,line,col]  <- cmds 
363       , [(lineNum,[])] <- reads line
364       , [(colNum,[])]  <- reads col
365       , mod            <- GHC.mkModule mainPackageId (GHC.mkModuleName fn)
366       = handleDel mod $ delBkptByCoord mod (lineNum, colNum)
367         
368       | otherwise = throwDyn $ CmdLineError $ 
369              "syntax: :breakpoint del (breakpoint # | Module line [col])"
370
371        where delMsg = "Breakpoint deleted"
372              handleDel mod f = ghciHandleDyn (handleBkptEx mod) $ do
373                modifyBkptTable f
374                newTable <- getBkptTable
375                sess <- getSession
376                dflags <- getDynFlags
377                io$ putStrLn delMsg
378
379     bkptOptions' _ _ = throwDyn $ CmdLineError $ 
380                          "syntax: :breakpoint (list|continue|stop|add|del)"
381
382 -- Error messages
383     handleBkptEx :: Module -> Debugger.BkptException -> a
384     handleBkptEx _ NoBkptFound = error "No suitable breakpoint site found"  
385          -- ^ TODO Instead of complaining, set a bkpt in the next suitable line
386     handleBkptEx _ NotNeeded   = error "Nothing to do"
387     handleBkptEx m NotHandled  = error$ "Module " ++ showSDoc (ppr m) ++  " was not loaded under debugging mode. Enable debugging mode with -fdebugging (and reload your module)"
388
389 -------------------------
390 -- Breakpoint Tables
391 -------------------------
392
393 data BkptTable a  = BkptTable { 
394                            -- | An array of breaks, indexed by site number
395      breakpoints :: Map.Map a (UArray Int Bool)  
396                            -- | A list of lines, each line can have zero or more sites, which are annotated with a column number
397    , sites       :: Map.Map a [[(SiteNumber, Int)]] 
398    }
399
400 sitesOf :: Ord a => BkptTable a -> a -> Maybe [[(SiteNumber, Int)]] 
401 sitesOf bt fn = Map.lookup fn (sites bt)
402 bkptsOf bt fn = Map.lookup fn (breakpoints bt)
403
404
405 -- The functions for manipulating BkptTables do throw exceptions
406 data BkptException =
407                     NotHandled
408                   | NoBkptFound
409                   | NotNeeded   -- Used when a breakpoint was already enabled
410   deriving Typeable
411
412 emptyBkptTable :: Ord a => BkptTable a
413 addModule      :: Ord a => a -> [(SiteNumber,Coord)] -> BkptTable a -> BkptTable a
414 -- | Lines start at index 1
415 addBkptByLine  :: Ord a => a -> Int        -> BkptTable a -> (BkptTable a, SiteNumber)
416 addBkptByCoord :: Ord a => a -> Coord      -> BkptTable a -> (BkptTable a, SiteNumber)
417 delBkptByLine  :: Ord a => a -> Int        -> BkptTable a -> BkptTable a
418 delBkptBySite  :: Ord a => a -> SiteNumber -> BkptTable a -> BkptTable a
419 delBkptByCoord :: Ord a => a -> Coord      -> BkptTable a -> BkptTable a
420
421 isBkptEnabled  :: Ord a => BkptTable a -> BkptLocation a -> Bool
422 btElems        :: Ord a => BkptTable a -> [(a, [SiteNumber])]
423 btList         :: Ord a => BkptTable a -> [BkptLocation a]
424 sitesList      :: Ord a => BkptTable a -> [(a, [Coord])]
425 getSiteCoords  :: Ord a => BkptTable a -> a -> SiteNumber -> Coord
426
427 emptyBkptTable = BkptTable Map.empty Map.empty
428
429 addBkptByLine a i bt
430    | Just lines    <- sitesOf bt a
431    , Just bkptsArr <- bkptsOf bt a
432    , i < length lines
433    = case lines!!i of 
434        []    -> throwDyn NoBkptFound
435        (x:_) -> let (siteNum,col) = x
436                     wasAlreadyOn  = bkptsArr ! siteNum
437                     newArr        = bkptsArr // [(siteNum, True)]
438                     newTable      = Map.insert a newArr (breakpoints bt)
439         in if wasAlreadyOn 
440            then throwDyn NotNeeded
441            else (bt{breakpoints=newTable}, siteNum)
442
443    | Just sites    <- sitesOf bt a
444    = throwDyn NoBkptFound
445    | otherwise     = throwDyn NotHandled  
446
447 addBkptByCoord a (r,c) bt 
448    | Just lines    <- sitesOf bt a
449    , Just bkptsArr <- bkptsOf bt a
450    , r < length lines
451        = case [ (sn,col) | (sn,col)<-lines!!r, col>=c] of 
452        []    -> throwDyn NoBkptFound
453        (x:_) -> let (siteNum, col) = x
454                     wasAlreadyOn  = bkptsArr ! siteNum
455                     newArr        = bkptsArr // [(siteNum, True)]
456                     newTable      = Map.insert a newArr (breakpoints bt)
457         in if wasAlreadyOn 
458            then throwDyn NotNeeded
459            else (bt{breakpoints=newTable}, siteNum)
460
461    | Just sites    <- sitesOf bt a
462    = throwDyn NoBkptFound
463    | otherwise     = throwDyn NotHandled  
464
465 delBkptBySite a i bt 
466    | Just bkptsArr <- bkptsOf bt a
467    , not (inRange (bounds bkptsArr) i)
468    = throwDyn NoBkptFound
469
470    | Just bkptsArr <- bkptsOf bt a
471    , bkptsArr ! i     -- Check that there was a enabled bkpt here 
472    , newArr        <- bkptsArr // [(i,False)] 
473    , newTable      <- Map.insert a newArr (breakpoints bt)
474    = bt {breakpoints=newTable}
475
476    | Just sites    <- sitesOf bt a
477    = throwDyn NotNeeded
478
479    | otherwise = throwDyn NotHandled
480
481 delBkptByLine a l bt 
482    | Just sites    <- sitesOf bt a
483    , (site:_)      <- [s | (s,c') <- sites !! l]
484    = delBkptBySite a site bt
485
486    | Just sites    <- sitesOf bt a
487    = throwDyn NoBkptFound
488
489    | otherwise = throwDyn NotHandled
490
491 delBkptByCoord a (r,c) bt 
492    | Just sites    <- sitesOf bt a
493    , (site:_)      <- [s | (s,c') <- sites !! r, c>=c', isBkptEnabled bt (a,s)]
494    = delBkptBySite a site bt
495
496    | Just sites    <- sitesOf bt a
497    = throwDyn NoBkptFound
498
499    | otherwise = throwDyn NotHandled
500
501 btElems bt = [ (a, [i | (i,True) <- assocs siteArr])
502              | (a, siteArr) <- Map.assocs (breakpoints bt) ]
503
504 btList bt =  [(a,site) | (a, sites) <- btElems bt, site <- sites] 
505
506 sitesList bt = [ (a, sitesCoords sitesCols) | (a, sitesCols) <- Map.assocs (sites bt) ]
507     where sitesCoords sitesCols = 
508               [ (row,col) 
509                 | (row, cols) <- zip [0..] sitesCols, (_,col) <- cols ] 
510
511 getSiteCoords bt a site 
512    | Just rows <- sitesOf bt a
513    = head [ (r,c) | (r,row) <- zip [0..] rows
514                   , (s,c)   <- row
515                   , s == site ]
516
517 -- addModule is dumb and inefficient, but it does the job
518 addModule a [] bt = bt {sites = Map.insert a [] (sites bt)}
519 addModule a siteCoords bt 
520    | nrows        <- maximum$ [i | (_,(i,j)) <- siteCoords ]
521    , sitesByRow   <- [ [(s,c) | (s,(r,c)) <- siteCoords, r==i] 
522                        | i <- [0..nrows] ]
523    , nsites       <- length siteCoords
524    , initialBkpts <- listArray (1, nsites) (repeat False) 
525    = bt{ sites       = Map.insert a sitesByRow (sites bt) 
526        , breakpoints = Map.insert a initialBkpts (breakpoints bt) }
527
528 isBkptEnabled bt (a,site) 
529    | Just bkpts <- bkptsOf bt a 
530    , inRange (bounds bkpts) site
531    = bkpts ! site 
532    | otherwise = panic "unexpected condition: I don't know that breakpoint site"
533
534 -----------------
535 -- Other stuff
536 -----------------
537 refreshBkptTable :: [ModSummary] -> GHCi ()
538 refreshBkptTable [] = return ()
539 refreshBkptTable (ms:mod_sums) = do
540     sess   <- getSession
541     when isDebugging $ do
542       old_table <- getBkptTable
543       new_table <- addModuleGHC sess old_table (GHC.ms_mod ms)
544       setBkptTable new_table
545     refreshBkptTable mod_sums
546   where addModuleGHC sess bt mod = do
547           Just mod_info <- io$ GHC.getModuleInfo sess mod
548           dflags <- getDynFlags
549           let sites = GHC.modInfoBkptSites mod_info
550           io$ debugTraceMsg dflags 2 
551                 (ppr mod <> text ": inserted " <> int (length sites) <>
552                  text " breakpoints")
553           return$ addModule mod sites bt
554 #if defined(GHCI) && defined(DEBUGGER)
555         isDebugging = Opt_Debugging `elem` flags (GHC.ms_hspp_opts ms)
556 #else
557         isDebugging = False
558 #endif