Remove a tracing statement, change a comment, and make more obvious an unexpected...
[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 ()
301 bkptOptions cmd = do 
302   dflags <- getDynFlags
303   bt     <- getBkptTable
304   bkptOptions' (words cmd) bt
305    where
306     bkptOptions' ["list"] bt = do 
307       let msgs = [ ppr mod <+> colon <+> ppr coords 
308                    | (mod,site) <- btList bt
309                    , let coords = getSiteCoords bt mod site]
310           num_msgs = [parens (int n) <+> msg | (n,msg) <- zip [1..] msgs]
311       msg <- showForUser$ if null num_msgs 
312                             then text "There are no enabled breakpoints"
313                             else vcat num_msgs
314       io$ putStrLn msg
315
316     bkptOptions' ["stop"] bt = do
317         inside_break <- liftM not isTopLevel
318         when inside_break $ throwDyn StopChildSession
319
320     bkptOptions' ("add":cmds) bt 
321       | [mod_name,line]<- cmds
322       , [(lineNum,[])] <- reads line
323       =  handleAdd mod_name $ (\mod->addBkptByLine mod lineNum)
324
325       | [mod_name,line,col] <- cmds
326       = handleAdd mod_name $ (\mod->addBkptByCoord mod (read line, read col))
327
328       | otherwise = throwDyn $ CmdLineError $ 
329                        "syntax: :breakpoint add Module line [col]"
330        where 
331          handleAdd mod_name f = do
332            sess        <- getSession
333            dflags      <- getDynFlags
334            mod         <- io$ GHC.findModule sess (GHC.mkModuleName mod_name) Nothing
335            ghciHandleDyn (handleBkptEx mod) $
336             case f mod bt of
337              (newTable, site)  -> do
338                setBkptTable newTable 
339                io (putStrLn ("Breakpoint set at " ++ 
340                               show (getSiteCoords newTable mod site)))
341
342     bkptOptions' ("del":cmds) bt 
343       | [i']     <- cmds 
344       , [(i,[])] <- reads i'
345       , bkpts    <- btList bt
346       = if i > length bkpts
347            then throwDyn $ CmdLineError 
348               "Not a valid breakpoint #. Use :breakpoint list to see the current breakpoints."
349            else 
350              let (mod, site) = bkpts !! (i-1)
351              in handleDel mod $ delBkptBySite mod site
352
353       | [fn,line]      <- cmds 
354       , [(lineNum,[])] <- reads line
355       , mod            <- GHC.mkModule mainPackageId (GHC.mkModuleName fn)
356       = handleDel mod $  delBkptByLine mod lineNum
357
358       | [fn,line,col]  <- cmds 
359       , [(lineNum,[])] <- reads line
360       , [(colNum,[])]  <- reads col
361       , mod            <- GHC.mkModule mainPackageId (GHC.mkModuleName fn)
362       = handleDel mod $ delBkptByCoord mod (lineNum, colNum)
363         
364       | otherwise = throwDyn $ CmdLineError $ 
365              "syntax: :breakpoint del (breakpoint # | Module line [col])"
366
367        where delMsg = "Breakpoint deleted"
368              handleDel mod f = ghciHandleDyn (handleBkptEx mod) $ do
369                modifyBkptTable f
370                newTable <- getBkptTable
371                sess <- getSession
372                dflags <- getDynFlags
373                io$ putStrLn delMsg
374
375     bkptOptions' _ _ = throwDyn $ CmdLineError $ 
376                          "syntax: :breakpoint (list|stop|add|del)"
377
378 -- Error messages
379     handleBkptEx :: Module -> Debugger.BkptException -> a
380     handleBkptEx _ NoBkptFound = error "No suitable breakpoint site found"  
381          -- ^ TODO Instead of complaining, set a bkpt in the next suitable line
382     handleBkptEx _ NotNeeded   = error "Nothing to do"
383     handleBkptEx m NotHandled  = error$ "Module " ++ showSDoc (ppr m) ++  " was not loaded under debugging mode. Enable debugging mode with -fdebugging (and reload your module)"
384
385 -------------------------
386 -- Breakpoint Tables
387 -------------------------
388
389 data BkptTable a  = BkptTable { 
390                            -- | An array of breaks, indexed by site number
391      breakpoints :: Map.Map a (UArray Int Bool)  
392                            -- | A list of lines, each line can have zero or more sites, which are annotated with a column number
393    , sites       :: Map.Map a [[(SiteNumber, Int)]] 
394    }
395
396 sitesOf :: Ord a => BkptTable a -> a -> Maybe [[(SiteNumber, Int)]] 
397 sitesOf bt fn = Map.lookup fn (sites bt)
398 bkptsOf bt fn = Map.lookup fn (breakpoints bt)
399
400
401 -- The functions for manipulating BkptTables do throw exceptions
402 data BkptException =
403                     NotHandled
404                   | NoBkptFound
405                   | NotNeeded   -- Used when a breakpoint was already enabled
406   deriving Typeable
407
408 emptyBkptTable :: Ord a => BkptTable a
409 addModule      :: Ord a => a -> [(SiteNumber,Coord)] -> BkptTable a -> BkptTable a
410 -- | Lines start at index 1
411 addBkptByLine  :: Ord a => a -> Int        -> BkptTable a -> (BkptTable a, SiteNumber)
412 addBkptByCoord :: Ord a => a -> Coord      -> BkptTable a -> (BkptTable a, SiteNumber)
413 delBkptByLine  :: Ord a => a -> Int        -> BkptTable a -> BkptTable a
414 delBkptBySite  :: Ord a => a -> SiteNumber -> BkptTable a -> BkptTable a
415 delBkptByCoord :: Ord a => a -> Coord      -> BkptTable a -> BkptTable a
416
417 isBkptEnabled  :: Ord a => BkptTable a -> BkptLocation a -> Bool
418 btElems        :: Ord a => BkptTable a -> [(a, [SiteNumber])]
419 btList         :: Ord a => BkptTable a -> [BkptLocation a]
420 sitesList      :: Ord a => BkptTable a -> [(a, [Coord])]
421 getSiteCoords  :: Ord a => BkptTable a -> a -> SiteNumber -> Coord
422
423 emptyBkptTable = BkptTable Map.empty Map.empty
424
425 addBkptByLine a i bt
426    | Just lines    <- sitesOf bt a
427    , Just bkptsArr <- bkptsOf bt a
428    , i < length lines
429    = case lines!!i of 
430        []    -> throwDyn NoBkptFound
431        (x:_) -> let (siteNum,col) = x
432                     wasAlreadyOn  = bkptsArr ! siteNum
433                     newArr        = bkptsArr // [(siteNum, True)]
434                     newTable      = Map.insert a newArr (breakpoints bt)
435         in if wasAlreadyOn 
436            then throwDyn NotNeeded
437            else (bt{breakpoints=newTable}, siteNum)
438
439    | Just sites    <- sitesOf bt a
440    = throwDyn NoBkptFound
441    | otherwise     = throwDyn NotHandled  
442
443 addBkptByCoord a (r,c) bt 
444    | Just lines    <- sitesOf bt a
445    , Just bkptsArr <- bkptsOf bt a
446    , r < length lines
447        = case [ (sn,col) | (sn,col)<-lines!!r, col>=c] of 
448        []    -> throwDyn NoBkptFound
449        (x:_) -> let (siteNum, col) = x
450                     wasAlreadyOn  = bkptsArr ! siteNum
451                     newArr        = bkptsArr // [(siteNum, True)]
452                     newTable      = Map.insert a newArr (breakpoints bt)
453         in if wasAlreadyOn 
454            then throwDyn NotNeeded
455            else (bt{breakpoints=newTable}, siteNum)
456
457    | Just sites    <- sitesOf bt a
458    = throwDyn NoBkptFound
459    | otherwise     = throwDyn NotHandled  
460
461 delBkptBySite a i bt 
462    | Just bkptsArr <- bkptsOf bt a
463    , not (inRange (bounds bkptsArr) i)
464    = throwDyn NoBkptFound
465
466    | Just bkptsArr <- bkptsOf bt a
467    , bkptsArr ! i     -- Check that there was a enabled bkpt here 
468    , newArr        <- bkptsArr // [(i,False)] 
469    , newTable      <- Map.insert a newArr (breakpoints bt)
470    = bt {breakpoints=newTable}
471
472    | Just sites    <- sitesOf bt a
473    = throwDyn NotNeeded
474
475    | otherwise = throwDyn NotHandled
476
477 delBkptByLine a l bt 
478    | Just sites    <- sitesOf bt a
479    , (site:_)      <- [s | (s,c') <- sites !! l]
480    = delBkptBySite a site bt
481
482    | Just sites    <- sitesOf bt a
483    = throwDyn NoBkptFound
484
485    | otherwise = throwDyn NotHandled
486
487 delBkptByCoord a (r,c) bt 
488    | Just sites    <- sitesOf bt a
489    , (site:_)      <- [s | (s,c') <- sites !! r, c>=c', isBkptEnabled bt (a,s)]
490    = delBkptBySite a site bt
491
492    | Just sites    <- sitesOf bt a
493    = throwDyn NoBkptFound
494
495    | otherwise = throwDyn NotHandled
496
497 btElems bt = [ (a, [i | (i,True) <- assocs siteArr])
498              | (a, siteArr) <- Map.assocs (breakpoints bt) ]
499
500 btList bt =  [(a,site) | (a, sites) <- btElems bt, site <- sites] 
501
502 sitesList bt = [ (a, sitesCoords sitesCols) | (a, sitesCols) <- Map.assocs (sites bt) ]
503     where sitesCoords sitesCols = 
504               [ (row,col) 
505                 | (row, cols) <- zip [0..] sitesCols, (_,col) <- cols ] 
506
507 getSiteCoords bt a site 
508    | Just rows <- sitesOf bt a
509    = head [ (r,c) | (r,row) <- zip [0..] rows
510                   , (s,c)   <- row
511                   , s == site ]
512
513 -- addModule is dumb and inefficient, but it does the job
514 addModule a [] bt = bt {sites = Map.insert a [] (sites bt)}
515 addModule a siteCoords bt 
516    | nrows        <- maximum$ [i | (_,(i,j)) <- siteCoords ]
517    , sitesByRow   <- [ [(s,c) | (s,(r,c)) <- siteCoords, r==i] 
518                        | i <- [0..nrows] ]
519    , nsites       <- length siteCoords
520    , initialBkpts <- listArray (1, nsites) (repeat False) 
521    = bt{ sites       = Map.insert a sitesByRow (sites bt) 
522        , breakpoints = Map.insert a initialBkpts (breakpoints bt) }
523
524 isBkptEnabled bt (a,site) 
525    | Just bkpts <- bkptsOf bt a 
526    , inRange (bounds bkpts) site
527    = bkpts ! site 
528    | otherwise = panic "unexpected condition: I don't know that breakpoint site"
529
530 -----------------
531 -- Other stuff
532 -----------------
533 refreshBkptTable :: [ModSummary] -> GHCi ()
534 refreshBkptTable [] = return ()
535 refreshBkptTable (ms:mod_sums) = do
536     sess   <- getSession
537     when isDebugging $ do
538       old_table <- getBkptTable
539       new_table <- addModuleGHC sess old_table (GHC.ms_mod ms)
540       setBkptTable new_table
541     refreshBkptTable mod_sums
542   where addModuleGHC sess bt mod = do
543           Just mod_info <- io$ GHC.getModuleInfo sess mod
544           dflags <- getDynFlags
545           let sites = GHC.modInfoBkptSites mod_info
546           io$ debugTraceMsg dflags 2 
547                 (ppr mod <> text ": inserted " <> int (length sites) <>
548                  text " breakpoints")
549           return$ addModule mod sites bt
550 #if defined(GHCI) && defined(DEBUGGER)
551         isDebugging = Opt_Debugging `elem` flags (GHC.ms_hspp_opts ms)
552 #else
553         isDebugging = False
554 #endif