+stepOverCmd [] = do
+ mb_span <- getCurrentBreakSpan
+ case mb_span of
+ Nothing -> stepCmd []
+ Just loc -> do
+ Just mod <- getCurrentBreakModule
+ parent <- enclosingSubSpan mod loc
+ allTicksRightmost <- sortBy rightmost `fmap`
+ ticksIn mod parent
+ let lastTick = null allTicksRightmost ||
+ snd(head allTicksRightmost) == loc
+ if not lastTick
+ then doContinue (`lexicalSubSpanOf` parent) GHC.SingleStep
+ else doContinue (const True) GHC.SingleStep
+
+ where
+
+{-
+ So, the only tricky part 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
+ 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
+-}
+
+--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
+ ]
+
+enclosingSubSpan :: Module -> SrcSpan -> GHCi SrcSpan
+enclosingSubSpan mod src = do
+ ticks <- getTickArray mod
+ let line = srcSpanStartLine src
+ ASSERT (inRange (bounds arr) line) do
+ let enclosing_spans = [ t | t@(_,span) <- ticks ! line
+ , srcSpanEnd span >= srcSpanEnd src]
+ return . snd . head . sortBy leftmost_largest $ enclosing_spans
+
+lexicalSubSpanOf :: SrcSpan -> SrcSpan -> Bool
+lexicalSubSpanOf src parent
+ | GHC.srcSpanFile parent /= GHC.srcSpanFile src = False
+ | otherwise = srcSpanStart parent <= srcSpanStart src &&
+ srcSpanEnd parent >= srcSpanEnd src
+