3 #include "HsVersions.h"
6 import {-#SOURCE#-} Debugger
9 import Panic hiding (showException)
13 import Control.Exception as Exception
16 import Data.Int ( Int64 )
22 import Control.Monad as Monad
25 -----------------------------------------------------------------------------
28 data GHCiState = GHCiState
34 session :: GHC.Session,
35 options :: [GHCiOption],
36 prelude :: GHC.Module,
37 bkptTable :: IORef (BkptTable GHC.Module),
42 = ShowTiming -- show time/allocs after evaluation
43 | ShowType -- show the type of expressions
44 | RevertCAFs -- revert CAFs after every evaluation
47 newtype GHCi a = GHCi { unGHCi :: IORef GHCiState -> IO a }
49 startGHCi :: GHCi a -> GHCiState -> IO a
50 startGHCi g state = do ref <- newIORef state; unGHCi g ref
52 instance Monad GHCi where
53 (GHCi m) >>= k = GHCi $ \s -> m s >>= \a -> unGHCi (k a) s
54 return a = GHCi $ \s -> return a
56 ghciHandleDyn :: Typeable t => (t -> GHCi a) -> GHCi a -> GHCi a
57 ghciHandleDyn h (GHCi m) = GHCi $ \s ->
58 Exception.catchDyn (m s) (\e -> unGHCi (h e) s)
60 getGHCiState = GHCi $ \r -> readIORef r
61 setGHCiState s = GHCi $ \r -> writeIORef r s
64 getSession = getGHCiState >>= return . session
65 getPrelude = getGHCiState >>= return . prelude
67 GLOBAL_VAR(saved_sess, no_saved_sess, GHC.Session)
68 no_saved_sess = error "no saved_ses"
69 saveSession = getSession >>= io . writeIORef saved_sess
70 splatSavedSession = io (writeIORef saved_sess no_saved_sess)
71 restoreSession = readIORef saved_sess
75 io (GHC.getSessionDynFlags s)
76 setDynFlags dflags = do
78 io (GHC.setSessionDynFlags s dflags)
80 isOptionSet :: GHCiOption -> GHCi Bool
82 = do st <- getGHCiState
83 return (opt `elem` options st)
85 setOption :: GHCiOption -> GHCi ()
87 = do st <- getGHCiState
88 setGHCiState (st{ options = opt : filter (/= opt) (options st) })
90 unsetOption :: GHCiOption -> GHCi ()
92 = do st <- getGHCiState
93 setGHCiState (st{ options = filter (/= opt) (options st) })
96 io m = GHCi { unGHCi = \s -> m >>= return }
98 isTopLevel :: GHCi Bool
99 isTopLevel = getGHCiState >>= return . topLevel
101 getBkptTable :: GHCi (BkptTable GHC.Module)
102 getBkptTable = do table_ref <- getGHCiState >>= return . bkptTable
103 io$ readIORef table_ref
105 setBkptTable :: BkptTable GHC.Module -> GHCi ()
106 setBkptTable new_table = do
107 table_ref <- getGHCiState >>= return . bkptTable
108 io$ writeIORef table_ref new_table
110 modifyBkptTable :: (BkptTable GHC.Module -> BkptTable GHC.Module) -> GHCi ()
111 modifyBkptTable f = do
113 new_bt <- io . evaluate$ f bt
116 showForUser :: SDoc -> GHCi String
118 session <- getSession
119 unqual <- io (GHC.getPrintUnqual session)
120 return $! showSDocForUser unqual doc
122 -- --------------------------------------------------------------------------
123 -- Inferior Sessions Exceptions (used by the debugger)
125 data InfSessionException =
126 StopChildSession -- A child session requests to be stopped
127 | StopParentSession -- A child session requests to be stopped
128 -- AND that the parent session quits after that
129 | ChildSessionStopped String -- A child session has stopped
133 -- --------------------------------------------------------------------------
134 -- timing & statistics
136 timeIt :: GHCi a -> GHCi a
138 = do b <- isOptionSet ShowTiming
141 else do allocs1 <- io $ getAllocations
142 time1 <- io $ getCPUTime
144 allocs2 <- io $ getAllocations
145 time2 <- io $ getCPUTime
146 io $ printTimes (fromIntegral (allocs2 - allocs1))
150 foreign import ccall unsafe "getAllocations" getAllocations :: IO Int64
151 -- defined in ghc/rts/Stats.c
153 printTimes :: Integer -> Integer -> IO ()
154 printTimes allocs psecs
155 = do let secs = (fromIntegral psecs / (10^12)) :: Float
156 secs_str = showFFloat (Just 2) secs
158 parens (text (secs_str "") <+> text "secs" <> comma <+>
159 text (show allocs) <+> text "bytes")))
161 -----------------------------------------------------------------------------
168 -- Have to turn off buffering again, because we just
169 -- reverted stdout, stderr & stdin to their defaults.
171 foreign import ccall "revertCAFs" rts_revertCAFs :: IO ()
172 -- Make it "safe", just in case
174 -----------------------------------------------------------------------------
175 -- To flush buffers for the *interpreted* computation we need
176 -- to refer to *its* stdout/stderr handles
178 GLOBAL_VAR(flush_interp, error "no flush_interp", IO ())
179 GLOBAL_VAR(turn_off_buffering, error "no flush_stdout", IO ())
181 command_sequence :: [String] -> String
182 command_sequence = unwords . intersperse "Prelude.>>"
184 no_buffer :: String -> String
185 no_buffer h = unwords ["System.IO.hSetBuffering",
187 "System.IO.NoBuffering"]
190 no_buf_cmd = command_sequence $ map no_buffer ["stdout", "stderr", "stdin"]
192 flush_buffer :: String -> String
193 flush_buffer h = unwords ["System.IO.hFlush", "System.IO." ++ h]
196 flush_cmd = command_sequence [flush_buffer "stdout", flush_buffer "stderr"]
198 initInterpBuffering :: GHC.Session -> IO ()
199 initInterpBuffering session
200 = do maybe_hval <- GHC.compileExpr session no_buf_cmd
203 Just hval -> writeIORef turn_off_buffering (unsafeCoerce# hval :: IO ())
204 other -> panic "interactiveUI:setBuffering"
206 maybe_hval <- GHC.compileExpr session flush_cmd
208 Just hval -> writeIORef flush_interp (unsafeCoerce# hval :: IO ())
209 _ -> panic "interactiveUI:flush"
214 flushInterpBuffers :: GHCi ()
216 = io $ do Monad.join (readIORef flush_interp)
219 turnOffBuffering :: IO ()
221 = do Monad.join (readIORef turn_off_buffering)