-foreign import ccall "rts_setStepFlag" setStepFlag :: IO ()
-
-stepCmd :: String -> GHCi Bool
-stepCmd [] = doContinue setStepFlag
-stepCmd expression = do
- io $ setStepFlag
- runCommand expression
-
-continueCmd :: String -> GHCi Bool
-continueCmd [] = doContinue $ return ()
-continueCmd other = do
- io $ putStrLn "The continue command accepts no arguments."
- return False
-
-doContinue :: IO () -> GHCi Bool
-doContinue actionBeforeCont = do
- resumeAction <- popResume
- case resumeAction of
- Nothing -> do
- io $ putStrLn "There is no computation running."
- return False
- Just (_,_,handle) -> do
- io $ actionBeforeCont
- session <- getSession
- runResult <- io $ GHC.resume session handle
- names <- switchOnRunResult runResult
- finishEvalExpr names
- return False
+sprintCmd = pprintCommand False False
+printCmd = pprintCommand True False
+forceCmd = pprintCommand False True
+
+pprintCommand bind force str = do
+ session <- getSession
+ io $ pprintClosureCommand session bind force str
+
+stepCmd :: String -> GHCi ()
+stepCmd [] = doContinue (const True) GHC.SingleStep
+stepCmd expression = do runStmt expression GHC.SingleStep; return ()
+
+stepOverCmd [] = do
+ mb_span <- getCurrentBreakSpan
+ session <- getSession
+ case mb_span of
+ Nothing -> stepCmd []
+ 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 == curr_loc
+ if not lastTick
+ 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
+
+stepOverCmd expression = stepCmd expression
+
+{-
+ 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]
+ticksIn mod src = do
+ ticks <- getTickArray mod
+ let lines = [srcSpanStartLine src .. srcSpanEndLine src]
+ return [ t | line <- lines
+ , t@(_,span) <- ticks ! line
+ , srcSpanStart src <= srcSpanStart span
+ , srcSpanEnd src >= srcSpanEnd span
+ ]
+
+traceCmd :: String -> GHCi ()
+traceCmd [] = doContinue (const True) GHC.RunAndLogSteps
+traceCmd expression = do runStmt expression GHC.RunAndLogSteps; return ()
+
+continueCmd :: String -> GHCi ()
+continueCmd = noArgs $ doContinue (const True) GHC.RunToCompletion
+
+-- doContinue :: SingleStep -> GHCi ()
+doContinue pred step = do
+ session <- getSession
+ runResult <- io $ GHC.resume session step
+ afterRunStmt pred runResult
+ return ()
+
+abandonCmd :: String -> GHCi ()
+abandonCmd = noArgs $ do
+ s <- getSession
+ b <- io $ GHC.abandon s -- the prompt will change to indicate the new context
+ when (not b) $ io $ putStrLn "There is no computation running."
+ return ()