Print contents of bindings when stopping at a breakpoint
[ghc-hetmet.git] / compiler / ghci / InteractiveUI.hs
index a926bdc..dffae16 100644 (file)
@@ -186,7 +186,7 @@ helpText =
  "   :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"++
+ "   :stepover                   single-step without following function applications\n"++
  "   :trace                      trace after stopping at a breakpoint\n"++
  "   :trace <expr>               trace into <expr> (remembers breakpoints for :history)\n"++
 
@@ -578,7 +578,8 @@ afterRunStmt pred run_result = do
            pred (GHC.resumeSpan $ head resumes) -> do
                printForUser $ ptext SLIT("Stopped at") <+> 
                        ppr (GHC.resumeSpan $ head resumes)
-               printTypeOfNames session names
+--               printTypeOfNames session names
+               printTypeAndContentOfNames session names
                maybe (return ()) runBreakCmd mb_info
                -- run the command set with ":set stop <cmd>"
                st <- getGHCiState
@@ -595,6 +596,18 @@ afterRunStmt pred run_result = do
 
   return (case run_result of GHC.RunOk _ -> True; _ -> False)
 
+      where printTypeAndContentOfNames session names = do
+              let namesSorted = sortBy compareNames names
+              tythings <- catMaybes `liftM` 
+                              io (mapM (GHC.lookupName session) names)
+              docs_ty  <- mapM showTyThing tythings
+              terms    <- mapM (io . GHC.obtainTerm session False)
+                               [ id | (AnId id, Just _) <- zip tythings docs_ty]
+              docs_terms <- mapM (io . showTerm session) terms                                   
+              printForUser $ vcat $ zipWith (\ty cts -> ty <> text " = " <> cts)
+                                            (catMaybes docs_ty)
+                                            docs_terms
+
 runBreakCmd :: GHC.BreakInfo -> GHCi ()
 runBreakCmd info = do
   let mod = GHC.breakInfo_module info
@@ -643,21 +656,6 @@ lookupCommand str = do
                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
@@ -1291,11 +1289,18 @@ showBindings = do
 compareTyThings :: TyThing -> TyThing -> Ordering
 t1 `compareTyThings` t2 = getName t1 `compareNames` getName t2
 
-printTyThing :: TyThing -> GHCi ()
-printTyThing (AnId id) = do
+showTyThing :: TyThing -> GHCi (Maybe SDoc)
+showTyThing (AnId id) = do
   ty' <- cleanType (GHC.idType id)
-  printForUser $ ppr id <> text " :: " <> ppr ty'
-printTyThing _ = return ()
+  return $ Just $ ppr id <> text " :: " <> ppr ty'
+showTyThing _ = return Nothing
+
+printTyThing :: TyThing -> GHCi ()
+printTyThing tyth = do
+  mb_x <- showTyThing tyth
+  case mb_x of
+    Just x  -> printForUser x
+    Nothing -> return ()
 
 -- if -fglasgow-exts is on we show the foralls, otherwise we don't.
 cleanType :: Type -> GHCi Type
@@ -1564,37 +1569,29 @@ 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
+    Just loc -> do
+       Just mod <- getCurrentBreakModule
+       parent   <- enclosingTickSpan mod loc
        allTicksRightmost <- (sortBy rightmost . map snd) `fmap` 
                                ticksIn mod parent
        let lastTick = null allTicksRightmost || 
-                      head allTicksRightmost == curr_loc
+                      head allTicksRightmost == 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
+              then doContinue (`isSubspanOf` parent) GHC.SingleStep
+              else doContinue (const True) GHC.SingleStep
 
 stepOverCmd expression = stepCmd expression
 
 {- 
- The first tricky bit in stepOver is detecting that we have 
+ 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 (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]
@@ -1607,6 +1604,15 @@ ticksIn mod src = do
                 , 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 ()