" :sprint [<name> ...] simplifed version of :print\n" ++
" :step single-step after stopping at a breakpoint\n"++
" :step <expr> single-step into <expr>\n"++
+ " :stepover (locally) single-step over function applications"++
" :trace trace after stopping at a breakpoint\n"++
" :trace <expr> trace into <expr> (remembers breakpoints for :history)\n"++
c:_ -> return (Just c)
+getCurrentBreakTick :: GHCi (Maybe BreakIndex)
+getCurrentBreakTick = do
+ session <- getSession
+ resumes <- io $ GHC.getResumeContext session
+ case resumes of
+ [] -> return Nothing
+ (r:rs) -> do
+ let ix = GHC.resumeHistoryIx r
+ if ix == 0
+ then return (GHC.breakInfo_number `fmap` GHC.resumeBreakInfo r)
+ else do
+ let hist = GHC.resumeHistory r !! (ix-1)
+ let tick = GHC.getHistoryTick hist
+ return (Just tick)
+
getCurrentBreakSpan :: GHCi (Maybe SrcSpan)
getCurrentBreakSpan = do
session <- getSession
(r:rs) -> do
let ix = GHC.resumeHistoryIx r
if ix == 0
- then return (GHC.breakInfo_module `fmap` GHC.resumeBreakInfo r)
+ then return (GHC.breakInfo_module `liftM` GHC.resumeBreakInfo r)
else do
let hist = GHC.resumeHistory r !! (ix-1)
return $ Just $ GHC.getHistoryModule hist
reloadModule :: String -> GHCi ()
reloadModule m = do
- io (revertCAFs) -- always revert CAFs on reload.
- discardActiveBreakPoints
session <- getSession
doLoad session $ if null m then LoadAllTargets
else LoadUpTo (GHC.mkModuleName m)
stepOverCmd [] = do
mb_span <- getCurrentBreakSpan
+ session <- getSession
case mb_span of
Nothing -> stepCmd []
- Just loc -> do
- Just mod <- getCurrentBreakModule
- parent <- enclosingTickSpan mod loc
+ Just curr_loc -> do
+ Just tick <- getCurrentBreakTick
+ Just mod <- getCurrentBreakModule
+ parent <- io$ GHC.findEnclosingDeclSpanByTick session mod tick
allTicksRightmost <- (sortBy rightmost . map snd) `fmap`
ticksIn mod parent
let lastTick = null allTicksRightmost ||
- head allTicksRightmost == loc
+ head allTicksRightmost == curr_loc
if not lastTick
- then doContinue (`isSubspanOf` parent) GHC.SingleStep
- else doContinue (const True) GHC.SingleStep
+ then let f t = t `isSubspanOf` parent &&
+ (curr_loc `leftmost_largest` t == LT)
+ in doContinue f GHC.SingleStep
+ else printForUser (text "Warning: no more breakpoints in this function body, switching to :step") >>
+ doContinue (const True) GHC.SingleStep
- where
+stepOverCmd expression = stepCmd expression
{-
- So, the only tricky part in stepOver is detecting that we have
+ The first tricky bit in stepOver is detecting that we have
arrived to the last tick in an expression, in which case we must
step normally to the next tick.
What we do is:
1. Retrieve the enclosing expression block (with a tick)
2. Retrieve all the ticks there and sort them out by 'rightness'
3. See if the current tick turned out the first one in the list
+
+ The second tricky bit is how to step over recursive calls.
+
-}
--ticksIn :: Module -> SrcSpan -> GHCi [Tick]
, srcSpanEnd src >= srcSpanEnd span
]
-enclosingTickSpan :: Module -> SrcSpan -> GHCi SrcSpan
-enclosingTickSpan mod src = do
- ticks <- getTickArray mod
- let line = srcSpanStartLine src
- ASSERT (inRange (bounds ticks) line) do
- let enclosing_spans = [ span | (_,span) <- ticks ! line
- , srcSpanEnd span >= srcSpanEnd src]
- return . head . sortBy leftmost_largest $ enclosing_spans
-
traceCmd :: String -> GHCi ()
traceCmd [] = doContinue (const True) GHC.RunAndLogSteps
traceCmd expression = do runStmt expression GHC.RunAndLogSteps; return ()
printForUser (vcat(zipWith3
(\x y z -> x <+> y <+> z)
(map text nums)
- (map (ftext . occNameFS . nameOccName) names)
+ (map (bold . ppr) names)
(map (parens . ppr) spans)))
io $ putStrLn $ if null rest then "<end of history>" else "..."
+bold c | do_bold = text start_bold <> c <> text end_bold
+ | otherwise = c
+
backCmd :: String -> GHCi ()
backCmd = noArgs $ do
s <- getSession
do_bold = False
#endif
-start_bold = BS.pack "\ESC[1m"
-end_bold = BS.pack "\ESC[0m"
+start_bold = "\ESC[1m"
+end_bold = "\ESC[0m"
listCmd :: String -> GHCi ()
listCmd "" = do
= let (a,r) = BS.splitAt col1 line
(b,c) = BS.splitAt (col2-col1) r
in
- BS.concat [a,start_bold,b,end_bold,c]
+ BS.concat [a,BS.pack start_bold,b,BS.pack end_bold,c]
| no == line1
= let (a,b) = BS.splitAt col1 line in
- BS.concat [a, start_bold, b]
+ BS.concat [a, BS.pack start_bold, b]
| no == line2
= let (a,b) = BS.splitAt col2 line in
- BS.concat [a, end_bold, b]
+ BS.concat [a, BS.pack end_bold, b]
| otherwise = line
highlight_carets no line