1 {-# OPTIONS -#include "Linker.h" #-}
2 -----------------------------------------------------------------------------
3 -- $Id: InteractiveUI.hs,v 1.189 2005/02/23 12:44:17 simonmar Exp $
5 -- GHC Interactive User Interface
7 -- (c) The GHC Team 2004
9 -----------------------------------------------------------------------------
10 module InteractiveUI (
11 interactiveUI, -- :: CmState -> [FilePath] -> IO ()
15 #include "HsVersions.h"
18 import HscTypes ( GhciMode(..) )
19 import IfaceSyn ( IfaceDecl(..), IfaceClassOp(..), IfaceConDecls(..), IfaceConDecl(..),
20 IfaceInst(..), pprIfaceDeclHead, pprParendIfaceType, pprIfaceForAllPart )
21 import FunDeps ( pprFundeps )
24 import DriverUtil ( remove_spaces )
25 import Linker ( showLinkerState, linkPackages )
27 import Name ( Name, NamedThing(..) )
28 import OccName ( OccName, isSymOcc, occNameUserString )
29 import BasicTypes ( StrictnessMark(..), defaultFixity, SuccessFlag(..),
32 import CmdLineOpts ( DynFlags(..) )
33 import Panic hiding ( showException )
35 import SrcLoc ( SrcLoc, isGoodSrcLoc )
37 #ifndef mingw32_HOST_OS
38 import DriverUtil( handle )
40 #if __GLASGOW_HASKELL__ > 504
46 import Control.Concurrent ( yield ) -- Used in readline loop
47 import System.Console.Readline as Readline
52 import Control.Exception as Exception
54 -- import Control.Concurrent
58 import Data.Int ( Int64 )
59 import Data.Maybe ( isJust )
62 import System.Environment
63 import System.Exit ( exitWith, ExitCode(..) )
64 import System.Directory
66 import System.IO.Error as IO
68 import Control.Monad as Monad
69 import Foreign.StablePtr ( newStablePtr )
71 import GHC.Exts ( unsafeCoerce# )
72 import GHC.IOBase ( IOErrorType(InvalidArgument) )
74 import Data.IORef ( IORef, newIORef, readIORef, writeIORef )
76 import System.Posix.Internals ( setNonBlockingFD )
78 -----------------------------------------------------------------------------
82 " / _ \\ /\\ /\\/ __(_)\n"++
83 " / /_\\// /_/ / / | | GHC Interactive, version " ++ cProjectVersion ++ ", for Haskell 98.\n"++
84 "/ /_\\\\/ __ / /___| | http://www.haskell.org/ghc/\n"++
85 "\\____/\\/ /_/\\____/|_| Type :? for help.\n"
87 GLOBAL_VAR(commands, builtin_commands, [(String, String -> GHCi Bool)])
89 builtin_commands :: [(String, String -> GHCi Bool)]
91 ("add", keepGoingPaths addModule),
92 ("browse", keepGoing browseCmd),
93 ("cd", keepGoing changeDirectory),
94 ("def", keepGoing defineMacro),
95 ("help", keepGoing help),
96 ("?", keepGoing help),
97 ("info", keepGoing info),
98 ("load", keepGoingPaths loadModule_),
99 ("module", keepGoing setContext),
100 ("reload", keepGoing reloadModule),
101 ("set", keepGoing setCmd),
102 ("show", keepGoing showCmd),
103 ("type", keepGoing typeOfExpr),
104 ("kind", keepGoing kindOfType),
105 ("unset", keepGoing unsetOptions),
106 ("undef", keepGoing undefineMacro),
110 keepGoing :: (String -> GHCi ()) -> (String -> GHCi Bool)
111 keepGoing a str = a str >> return False
113 keepGoingPaths :: ([FilePath] -> GHCi ()) -> (String -> GHCi Bool)
114 keepGoingPaths a str = a (toArgs str) >> return False
116 shortHelpText = "use :? for help.\n"
118 -- NOTE: spaces at the end of each line to workaround CPP/string gap bug.
120 " Commands available from the prompt:\n" ++
122 " <stmt> evaluate/run <stmt>\n" ++
123 " :add <filename> ... add module(s) to the current target set\n" ++
124 " :browse [*]<module> display the names defined by <module>\n" ++
125 " :cd <dir> change directory to <dir>\n" ++
126 " :def <cmd> <expr> define a command :<cmd>\n" ++
127 " :help, :? display this list of commands\n" ++
128 " :info [<name> ...] display information about the given names\n" ++
129 " :load <filename> ... load module(s) and their dependents\n" ++
130 " :module [+/-] [*]<mod> ... set the context for expression evaluation\n" ++
131 " :reload reload the current module set\n" ++
133 " :set <option> ... set options\n" ++
134 " :set args <arg> ... set the arguments returned by System.getArgs\n" ++
135 " :set prog <progname> set the value returned by System.getProgName\n" ++
137 " :show modules show the currently loaded modules\n" ++
138 " :show bindings show the current bindings made at the prompt\n" ++
140 " :type <expr> show the type of <expr>\n" ++
141 " :kind <type> show the kind of <type>\n" ++
142 " :undef <cmd> undefine user-defined command :<cmd>\n" ++
143 " :unset <option> ... unset options\n" ++
144 " :quit exit GHCi\n" ++
145 " :!<command> run the shell command <command>\n" ++
147 " Options for ':set' and ':unset':\n" ++
149 " +r revert top-level expressions after each evaluation\n" ++
150 " +s print timing/memory stats after each evaluation\n" ++
151 " +t print type after evaluation\n" ++
152 " -<flags> most GHC command line flags can also be set here\n" ++
153 " (eg. -v2, -fglasgow-exts, etc.)\n"
156 interactiveUI :: DynFlags -> [FilePath] -> Maybe String -> IO ()
157 interactiveUI dflags srcs maybe_expr = do
159 cmstate <- cmInit Interactive dflags;
161 -- HACK! If we happen to get into an infinite loop (eg the user
162 -- types 'let x=x in x' at the prompt), then the thread will block
163 -- on a blackhole, and become unreachable during GC. The GC will
164 -- detect that it is unreachable and send it the NonTermination
165 -- exception. However, since the thread is unreachable, everything
166 -- it refers to might be finalized, including the standard Handles.
167 -- This sounds like a bug, but we don't have a good solution right
174 hSetBuffering stdout NoBuffering
176 -- Initialise buffering for the *interpreted* I/O system
177 initInterpBuffering cmstate
179 -- We don't want the cmd line to buffer any input that might be
180 -- intended for the program, so unbuffer stdin.
181 hSetBuffering stdin NoBuffering
183 -- initial context is just the Prelude
184 cmstate <- cmSetContext cmstate [] ["Prelude"]
190 startGHCi (runGHCi srcs dflags maybe_expr)
191 GHCiState{ progname = "<interactive>",
198 Readline.resetTerminal Nothing
203 runGHCi :: [FilePath] -> DynFlags -> Maybe String -> GHCi ()
204 runGHCi paths dflags maybe_expr = do
205 read_dot_files <- io (readIORef v_Read_DotGHCi)
207 when (read_dot_files) $ do
210 exists <- io (doesFileExist file)
212 dir_ok <- io (checkPerms ".")
213 file_ok <- io (checkPerms file)
214 when (dir_ok && file_ok) $ do
215 either_hdl <- io (IO.try (openFile "./.ghci" ReadMode))
218 Right hdl -> fileLoop hdl False
220 when (read_dot_files) $ do
221 -- Read in $HOME/.ghci
222 either_dir <- io (IO.try (getEnv "HOME"))
226 cwd <- io (getCurrentDirectory)
227 when (dir /= cwd) $ do
228 let file = dir ++ "/.ghci"
229 ok <- io (checkPerms file)
231 either_hdl <- io (IO.try (openFile file ReadMode))
234 Right hdl -> fileLoop hdl False
236 -- Perform a :load for files given on the GHCi command line
237 -- When in -e mode, if the load fails then we want to stop
238 -- immediately rather than going on to evaluate the expression.
239 when (not (null paths)) $ do
240 ok <- ghciHandle (\e -> do showException e; return Failed) $
242 when (isJust maybe_expr && failed ok) $
243 io (exitWith (ExitFailure 1))
245 -- if verbosity is greater than 0, or we are connected to a
246 -- terminal, display the prompt in the interactive loop.
247 is_tty <- io (hIsTerminalDevice stdin)
248 let show_prompt = verbosity dflags > 0 || is_tty
252 -- enter the interactive loop
253 interactiveLoop is_tty show_prompt
255 -- just evaluate the expression we were given
260 io $ do when (verbosity dflags > 0) $ putStrLn "Leaving GHCi."
263 interactiveLoop is_tty show_prompt = do
264 -- Ignore ^C exceptions caught here
265 ghciHandleDyn (\e -> case e of
266 Interrupted -> ghciUnblock (interactiveLoop is_tty show_prompt)
267 _other -> return ()) $ do
269 -- read commands from stdin
273 else fileLoop stdin show_prompt
275 fileLoop stdin show_prompt
279 -- NOTE: We only read .ghci files if they are owned by the current user,
280 -- and aren't world writable. Otherwise, we could be accidentally
281 -- running code planted by a malicious third party.
283 -- Furthermore, We only read ./.ghci if . is owned by the current user
284 -- and isn't writable by anyone else. I think this is sufficient: we
285 -- don't need to check .. and ../.. etc. because "." always refers to
286 -- the same directory while a process is running.
288 checkPerms :: String -> IO Bool
290 #ifdef mingw32_HOST_OS
293 DriverUtil.handle (\_ -> return False) $ do
294 st <- getFileStatus name
296 if fileOwner st /= me then do
297 putStrLn $ "WARNING: " ++ name ++ " is owned by someone else, IGNORING!"
300 let mode = fileMode st
301 if (groupWriteMode == (mode `intersectFileModes` groupWriteMode))
302 || (otherWriteMode == (mode `intersectFileModes` otherWriteMode))
304 putStrLn $ "*** WARNING: " ++ name ++
305 " is writable by someone else, IGNORING!"
310 fileLoop :: Handle -> Bool -> GHCi ()
311 fileLoop hdl prompt = do
312 cmstate <- getCmState
313 (mod,imports) <- io (cmGetContext cmstate)
314 when prompt (io (putStr (mkPrompt mod imports)))
315 l <- io (IO.try (hGetLine hdl))
317 Left e | isEOFError e -> return ()
318 | InvalidArgument <- etype -> return ()
319 | otherwise -> io (ioError e)
320 where etype = ioeGetErrorType e
321 -- treat InvalidArgument in the same way as EOF:
322 -- this can happen if the user closed stdin, or
323 -- perhaps did getContents which closes stdin at
326 case remove_spaces l of
327 "" -> fileLoop hdl prompt
328 l -> do quit <- runCommand l
329 if quit then return () else fileLoop hdl prompt
331 stringLoop :: [String] -> GHCi ()
332 stringLoop [] = return ()
333 stringLoop (s:ss) = do
334 case remove_spaces s of
336 l -> do quit <- runCommand l
337 if quit then return () else stringLoop ss
339 mkPrompt toplevs exports
340 = concat (intersperse " " (map ('*':) toplevs ++ exports)) ++ "> "
343 readlineLoop :: GHCi ()
345 cmstate <- getCmState
346 (mod,imports) <- io (cmGetContext cmstate)
348 l <- io (readline (mkPrompt mod imports)
349 `finally` setNonBlockingFD 0)
350 -- readline sometimes puts stdin into blocking mode,
351 -- so we need to put it back for the IO library
355 case remove_spaces l of
360 if quit then return () else readlineLoop
363 runCommand :: String -> GHCi Bool
364 runCommand c = ghciHandle handler (doCommand c)
366 -- This version is for the GHC command-line option -e. The only difference
367 -- from runCommand is that it catches the ExitException exception and
368 -- exits, rather than printing out the exception.
369 runCommandEval c = ghciHandle handleEval (doCommand c)
371 handleEval (ExitException code) = io (exitWith code)
372 handleEval e = do showException e
373 io (exitWith (ExitFailure 1))
375 -- This is the exception handler for exceptions generated by the
376 -- user's code; it normally just prints out the exception. The
377 -- handler must be recursive, in case showing the exception causes
378 -- more exceptions to be raised.
380 -- Bugfix: if the user closed stdout or stderr, the flushing will fail,
381 -- raising another exception. We therefore don't put the recursive
382 -- handler arond the flushing operation, so if stderr is closed
383 -- GHCi will just die gracefully rather than going into an infinite loop.
384 handler :: Exception -> GHCi Bool
385 handler exception = do
387 io installSignalHandlers
388 ghciHandle handler (showException exception >> return False)
390 showException (DynException dyn) =
391 case fromDynamic dyn of
392 Nothing -> io (putStrLn ("*** Exception: (unknown)"))
393 Just Interrupted -> io (putStrLn "Interrupted.")
394 Just (CmdLineError s) -> io (putStrLn s) -- omit the location for CmdLineError
395 Just ph@PhaseFailed{} -> io (putStrLn (showGhcException ph "")) -- ditto
396 Just other_ghc_ex -> io (print other_ghc_ex)
398 showException other_exception
399 = io (putStrLn ("*** Exception: " ++ show other_exception))
401 doCommand (':' : command) = specialCommand command
403 = do timeIt (do nms <- runStmt stmt; finishEvalExpr nms)
406 runStmt :: String -> GHCi [Name]
408 | null (filter (not.isSpace) stmt) = return []
410 = do st <- getGHCiState
411 cmstate <- getCmState
412 (new_cmstate, result) <-
413 io $ withProgName (progname st) $ withArgs (args st) $
414 cmRunStmt cmstate stmt
415 setGHCiState st{cmstate = new_cmstate}
417 CmRunFailed -> return []
418 CmRunException e -> throw e -- this is caught by runCommand(Eval)
419 CmRunOk names -> return names
421 -- possibly print the type and revert CAFs after evaluating an expression
423 = do b <- isOptionSet ShowType
424 cmstate <- getCmState
425 when b (mapM_ (showTypeOfName cmstate) names)
428 io installSignalHandlers
429 b <- isOptionSet RevertCAFs
430 io (when b revertCAFs)
433 showTypeOfName :: CmState -> Name -> GHCi ()
434 showTypeOfName cmstate n
435 = do maybe_str <- io (cmTypeOfName cmstate n)
438 Just str -> io (putStrLn (showSDoc (ppr n) ++ " :: " ++ str))
440 specialCommand :: String -> GHCi Bool
441 specialCommand ('!':str) = shellEscape (dropWhile isSpace str)
442 specialCommand str = do
443 let (cmd,rest) = break isSpace str
444 cmds <- io (readIORef commands)
445 case [ (s,f) | (s,f) <- cmds, prefixMatch cmd s ] of
446 [] -> io (hPutStr stdout ("unknown command ':" ++ cmd ++ "'\n"
447 ++ shortHelpText) >> return False)
448 [(_,f)] -> f (dropWhile isSpace rest)
449 cs -> io (hPutStrLn stdout ("prefix " ++ cmd ++
450 " matches multiple commands (" ++
451 foldr1 (\a b -> a ++ ',':b) (map fst cs)
452 ++ ")") >> return False)
454 noArgs c = throwDyn (CmdLineError ("command '" ++ c ++ "' takes no arguments"))
457 -----------------------------------------------------------------------------
458 -- To flush buffers for the *interpreted* computation we need
459 -- to refer to *its* stdout/stderr handles
461 GLOBAL_VAR(flush_interp, error "no flush_interp", IO ())
462 GLOBAL_VAR(turn_off_buffering, error "no flush_stdout", IO ())
464 no_buf_cmd = "System.IO.hSetBuffering System.IO.stdout System.IO.NoBuffering" ++
465 " Prelude.>> System.IO.hSetBuffering System.IO.stderr System.IO.NoBuffering"
466 flush_cmd = "System.IO.hFlush System.IO.stdout Prelude.>> System.IO.hFlush IO.stderr"
468 initInterpBuffering :: CmState -> IO ()
469 initInterpBuffering cmstate
470 = do maybe_hval <- cmCompileExpr cmstate no_buf_cmd
473 Just hval -> writeIORef turn_off_buffering (unsafeCoerce# hval :: IO ())
474 other -> panic "interactiveUI:setBuffering"
476 maybe_hval <- cmCompileExpr cmstate flush_cmd
478 Just hval -> writeIORef flush_interp (unsafeCoerce# hval :: IO ())
479 _ -> panic "interactiveUI:flush"
481 turnOffBuffering -- Turn it off right now
486 flushInterpBuffers :: GHCi ()
488 = io $ do Monad.join (readIORef flush_interp)
491 turnOffBuffering :: IO ()
493 = do Monad.join (readIORef turn_off_buffering)
496 -----------------------------------------------------------------------------
499 help :: String -> GHCi ()
500 help _ = io (putStr helpText)
502 info :: String -> GHCi ()
503 info "" = throwDyn (CmdLineError "syntax: ':i <thing-you-want-info-about>'")
504 info s = do { let names = words s
505 ; init_cms <- getCmState
506 ; mapM_ (infoThing init_cms) names }
509 = do { stuff <- io (cmGetInfo cms name)
510 ; io (putStrLn (showSDocForUser (cmGetPrintUnqual cms) $
511 vcat (intersperse (text "") (map showThing stuff)))) }
513 showThing :: GetInfoResult -> SDoc
514 showThing (wanted_str, (thing, fixity, src_loc, insts))
515 = vcat [ showWithLoc src_loc (showDecl want_name thing),
517 vcat (map show_inst insts)]
519 want_name occ = wanted_str == occNameUserString occ
522 | fix == defaultFixity = empty
523 | otherwise = ppr fix <+> text wanted_str
525 show_inst (iface_inst, loc)
526 = showWithLoc loc (ptext SLIT("instance") <+> ppr (ifInstHead iface_inst))
528 showWithLoc :: SrcLoc -> SDoc -> SDoc
530 = hang doc 2 (char '\t' <> show_loc loc)
531 -- The tab tries to make them line up a bit
533 show_loc loc -- The ppr function for SrcLocs is a bit wonky
534 | isGoodSrcLoc loc = comment <+> ptext SLIT("Defined at") <+> ppr loc
535 | otherwise = comment <+> ppr loc
536 comment = ptext SLIT("--")
539 -- Now there is rather a lot of goop just to print declarations in a
540 -- civilised way with "..." for the parts we are less interested in.
542 showDecl :: (OccName -> Bool) -> IfaceDecl -> SDoc
543 showDecl want_name (IfaceForeign {ifName = tc})
544 = ppr tc <+> ptext SLIT("is a foreign type")
546 showDecl want_name (IfaceId {ifName = var, ifType = ty})
547 = ppr var <+> dcolon <+> ppr ty
549 showDecl want_name (IfaceSyn {ifName = tycon, ifTyVars = tyvars, ifSynRhs = mono_ty})
550 = hang (ptext SLIT("type") <+> pprIfaceDeclHead [] tycon tyvars)
551 2 (equals <+> ppr mono_ty)
553 showDecl want_name (IfaceData {ifName = tycon,
554 ifTyVars = tyvars, ifCons = condecls})
555 = hang (pp_nd <+> pprIfaceDeclHead context tycon tyvars)
556 2 (add_bars (ppr_trim show_con cs))
558 show_con (IfVanillaCon { ifConOcc = con_name, ifConInfix = is_infix, ifConArgTys = tys,
559 ifConStricts = strs, ifConFields = flds})
560 | want_name tycon || want_name con_name || any want_name flds
561 = Just (show_guts con_name is_infix tys_w_strs flds)
562 | otherwise = Nothing
564 tys_w_strs = tys `zip` (strs ++ repeat NotMarkedStrict)
565 show_con (IfGadtCon { ifConOcc = con_name, ifConTyVars = tvs, ifConCtxt = theta,
566 ifConArgTys = arg_tys, ifConResTys = res_tys, ifConStricts = strs })
567 | want_name tycon || want_name con_name
568 = Just (ppr_bndr con_name <+> colon <+> pprIfaceForAllPart tvs theta pp_tau)
569 | otherwise = Nothing
571 tys_w_strs = arg_tys `zip` (strs ++ repeat NotMarkedStrict)
572 pp_tau = foldr add pp_res_ty tys_w_strs
573 pp_res_ty = ppr_bndr tycon <+> hsep (map pprParendIfaceType res_tys)
574 add bty pp_ty = ppr_bangty bty <+> arrow <+> pp_ty
576 show_guts con True [ty1, ty2] flds = sep [ppr_bangty ty1, ppr con, ppr_bangty ty2]
577 show_guts con _ tys [] = ppr_bndr con <+> sep (map ppr_bangty tys)
578 show_guts con _ tys flds
579 = ppr_bndr con <+> braces (sep (punctuate comma (ppr_trim show_fld (tys `zip` flds))))
581 show_fld (bty, fld) | want_name tycon || want_name con || want_name fld
582 = Just (ppr_bndr fld <+> dcolon <+> ppr_bangty bty)
583 | otherwise = Nothing
585 (pp_nd, context, cs) = case condecls of
586 IfAbstractTyCon -> (ptext SLIT("data"), [], [])
587 IfDataTyCon (Just cxt) cs -> (ptext SLIT("data"), cxt, cs)
588 IfDataTyCon Nothing cs -> (ptext SLIT("data"), [], cs)
589 IfNewTyCon c -> (ptext SLIT("newtype"), [], [c])
592 add_bars [c] = equals <+> c
593 add_bars (c:cs) = equals <+> sep (c : map (char '|' <+>) cs)
595 ppr_bangty (ty, str) = ppr_str str <> pprParendIfaceType ty
596 ppr_str MarkedStrict = char '!'
597 ppr_str MarkedUnboxed = ptext SLIT("!!")
598 ppr_str NotMarkedStrict = empty
600 showDecl want_name (IfaceClass {ifCtxt = context, ifName = clas, ifTyVars = tyvars,
601 ifFDs = fds, ifSigs = sigs})
602 = hang (ptext SLIT("class") <+> pprIfaceDeclHead context clas tyvars
603 <+> pprFundeps fds <+> ptext SLIT("where"))
604 2 (vcat (ppr_trim show_op sigs))
606 show_op (IfaceClassOp op dm ty)
607 | want_name clas || want_name op = Just (ppr_bndr op <+> dcolon <+> ppr ty)
608 | otherwise = Nothing
610 ppr_trim :: (a -> Maybe SDoc) -> [a] -> [SDoc]
612 = snd (foldr go (False, []) xs)
614 go x (eliding, so_far)
615 | Just doc <- show x = (False, doc : so_far)
616 | otherwise = if eliding then (True, so_far)
617 else (True, ptext SLIT("...") : so_far)
619 ppr_bndr :: OccName -> SDoc
620 -- Wrap operators in ()
621 ppr_bndr occ | isSymOcc occ = parens (ppr occ)
622 | otherwise = ppr occ
625 -----------------------------------------------------------------------------
628 addModule :: [FilePath] -> GHCi ()
630 state <- getGHCiState
631 io (revertCAFs) -- always revert CAFs on load/add.
632 files <- mapM expandPath files
633 let new_targets = files ++ targets state
634 graph <- io (cmDepAnal (cmstate state) new_targets)
635 (cmstate1, ok, mods) <- io (cmLoadModules (cmstate state) graph)
636 setGHCiState state{ cmstate = cmstate1, targets = new_targets }
637 setContextAfterLoad mods
638 dflags <- getDynFlags
639 modulesLoadedMsg ok mods dflags
641 changeDirectory :: String -> GHCi ()
642 changeDirectory dir = do
643 state <- getGHCiState
644 when (targets state /= []) $
645 io $ putStr "Warning: changing directory causes all loaded modules to be unloaded,\nbecause the search path has changed.\n"
646 cmstate1 <- io (cmUnload (cmstate state))
647 setGHCiState state{ cmstate = cmstate1, targets = [] }
648 setContextAfterLoad []
649 dir <- expandPath dir
650 io (setCurrentDirectory dir)
652 defineMacro :: String -> GHCi ()
654 let (macro_name, definition) = break isSpace s
655 cmds <- io (readIORef commands)
657 then throwDyn (CmdLineError "invalid macro name")
659 if (macro_name `elem` map fst cmds)
660 then throwDyn (CmdLineError
661 ("command '" ++ macro_name ++ "' is already defined"))
664 -- give the expression a type signature, so we can be sure we're getting
665 -- something of the right type.
666 let new_expr = '(' : definition ++ ") :: String -> IO String"
668 -- compile the expression
670 maybe_hv <- io (cmCompileExpr cms new_expr)
673 Just hv -> io (writeIORef commands --
674 ((macro_name, keepGoing (runMacro hv)) : cmds))
676 runMacro :: HValue{-String -> IO String-} -> String -> GHCi ()
678 str <- io ((unsafeCoerce# fun :: String -> IO String) s)
679 stringLoop (lines str)
681 undefineMacro :: String -> GHCi ()
682 undefineMacro macro_name = do
683 cmds <- io (readIORef commands)
684 if (macro_name `elem` map fst builtin_commands)
685 then throwDyn (CmdLineError
686 ("command '" ++ macro_name ++ "' cannot be undefined"))
688 if (macro_name `notElem` map fst cmds)
689 then throwDyn (CmdLineError
690 ("command '" ++ macro_name ++ "' not defined"))
692 io (writeIORef commands (filter ((/= macro_name) . fst) cmds))
695 loadModule :: [FilePath] -> GHCi SuccessFlag
696 loadModule fs = timeIt (loadModule' fs)
698 loadModule_ :: [FilePath] -> GHCi ()
699 loadModule_ fs = do loadModule fs; return ()
701 loadModule' :: [FilePath] -> GHCi SuccessFlag
702 loadModule' files = do
703 state <- getGHCiState
706 files <- mapM expandPath files
708 -- do the dependency anal first, so that if it fails we don't throw
709 -- away the current set of modules.
710 graph <- io (cmDepAnal (cmstate state) files)
712 -- Dependency anal ok, now unload everything
713 cmstate1 <- io (cmUnload (cmstate state))
714 setGHCiState state{ cmstate = cmstate1, targets = [] }
716 io (revertCAFs) -- always revert CAFs on load.
717 (cmstate2, ok, mods) <- io (cmLoadModules cmstate1 graph)
718 setGHCiState state{ cmstate = cmstate2, targets = files }
720 setContextAfterLoad mods
721 dflags <- getDynFlags
722 modulesLoadedMsg ok mods dflags
726 reloadModule :: String -> GHCi ()
728 state <- getGHCiState
729 case targets state of
730 [] -> io (putStr "no current target\n")
732 -- do the dependency anal first, so that if it fails we don't throw
733 -- away the current set of modules.
734 graph <- io (cmDepAnal (cmstate state) paths)
736 io (revertCAFs) -- always revert CAFs on reload.
738 <- io (cmLoadModules (cmstate state) graph)
739 setGHCiState state{ cmstate=cmstate1 }
740 setContextAfterLoad mods
741 dflags <- getDynFlags
742 modulesLoadedMsg ok mods dflags
744 reloadModule _ = noArgs ":reload"
746 setContextAfterLoad [] = setContext prel
747 setContextAfterLoad (m:_) = do
748 cmstate <- getCmState
749 b <- io (cmModuleIsInterpreted cmstate m)
750 if b then setContext ('*':m) else setContext m
752 modulesLoadedMsg ok mods dflags =
753 when (verbosity dflags > 0) $ do
755 | null mods = text "none."
757 punctuate comma (map text mods)) <> text "."
760 io (putStrLn (showSDoc (text "Failed, modules loaded: " <> mod_commas)))
762 io (putStrLn (showSDoc (text "Ok, modules loaded: " <> mod_commas)))
765 typeOfExpr :: String -> GHCi ()
767 = do cms <- getCmState
768 maybe_tystr <- io (cmTypeOfExpr cms str)
771 Just tystr -> io (putStrLn tystr)
773 kindOfType :: String -> GHCi ()
775 = do cms <- getCmState
776 maybe_tystr <- io (cmKindOfType cms str)
779 Just tystr -> io (putStrLn tystr)
781 quit :: String -> GHCi Bool
784 shellEscape :: String -> GHCi Bool
785 shellEscape str = io (system str >> return False)
787 -----------------------------------------------------------------------------
788 -- Browsing a module's contents
790 browseCmd :: String -> GHCi ()
793 ['*':m] | looksLikeModuleName m -> browseModule m False
794 [m] | looksLikeModuleName m -> browseModule m True
795 _ -> throwDyn (CmdLineError "syntax: :browse <module>")
797 browseModule m exports_only = do
800 is_interpreted <- io (cmModuleIsInterpreted cms m)
801 when (not is_interpreted && not exports_only) $
802 throwDyn (CmdLineError ("module '" ++ m ++ "' is not interpreted"))
804 -- Temporarily set the context to the module we're interested in,
805 -- just so we can get an appropriate PrintUnqualified
806 (as,bs) <- io (cmGetContext cms)
807 cms1 <- io (if exports_only then cmSetContext cms [] [prel,m]
808 else cmSetContext cms [m] [])
809 cms2 <- io (cmSetContext cms1 as bs)
811 things <- io (cmBrowseModule cms2 m exports_only)
813 let unqual = cmGetPrintUnqual cms1 -- NOTE: cms1 with the new context
815 io (putStrLn (showSDocForUser unqual (
816 vcat (map (showDecl (const True)) things)
819 -----------------------------------------------------------------------------
820 -- Setting the module context
823 | all sensible mods = fn mods
824 | otherwise = throwDyn (CmdLineError "syntax: :module [+/-] [*]M1 ... [*]Mn")
826 (fn, mods) = case str of
827 '+':stuff -> (addToContext, words stuff)
828 '-':stuff -> (removeFromContext, words stuff)
829 stuff -> (newContext, words stuff)
831 sensible ('*':m) = looksLikeModuleName m
832 sensible m = looksLikeModuleName m
836 (as,bs) <- separate cms mods [] []
837 let bs' = if null as && prel `notElem` bs then prel:bs else bs
838 cms' <- io (cmSetContext cms as bs')
841 separate cmstate [] as bs = return (as,bs)
842 separate cmstate (('*':m):ms) as bs = do
843 b <- io (cmModuleIsInterpreted cmstate m)
844 if b then separate cmstate ms (m:as) bs
845 else throwDyn (CmdLineError ("module '" ++ m ++ "' is not interpreted"))
846 separate cmstate (m:ms) as bs = separate cmstate ms as (m:bs)
851 addToContext mods = do
853 (as,bs) <- io (cmGetContext cms)
855 (as',bs') <- separate cms mods [] []
857 let as_to_add = as' \\ (as ++ bs)
858 bs_to_add = bs' \\ (as ++ bs)
860 cms' <- io (cmSetContext cms
861 (as ++ as_to_add) (bs ++ bs_to_add))
865 removeFromContext mods = do
867 (as,bs) <- io (cmGetContext cms)
869 (as_to_remove,bs_to_remove) <- separate cms mods [] []
871 let as' = as \\ (as_to_remove ++ bs_to_remove)
872 bs' = bs \\ (as_to_remove ++ bs_to_remove)
874 cms' <- io (cmSetContext cms as' bs')
877 ----------------------------------------------------------------------------
880 -- set options in the interpreter. Syntax is exactly the same as the
881 -- ghc command line, except that certain options aren't available (-C,
884 -- This is pretty fragile: most options won't work as expected. ToDo:
885 -- figure out which ones & disallow them.
887 setCmd :: String -> GHCi ()
889 = do st <- getGHCiState
890 let opts = options st
891 io $ putStrLn (showSDoc (
892 text "options currently set: " <>
895 else hsep (map (\o -> char '+' <> text (optToStr o)) opts)
899 ("args":args) -> setArgs args
900 ("prog":prog) -> setProg prog
901 wds -> setOptions wds
905 setGHCiState st{ args = args }
909 setGHCiState st{ progname = prog }
911 io (hPutStrLn stderr "syntax: :set prog <progname>")
914 do -- first, deal with the GHCi opts (+s, +t, etc.)
915 let (plus_opts, minus_opts) = partition isPlus wds
916 mapM_ setOpt plus_opts
918 -- now, the GHC flags
919 leftovers <- io $ processStaticFlags minus_opts
921 -- then, dynamic flags
922 dflags <- getDynFlags
923 (dflags',leftovers) <- io $ processDynamicFlags leftovers dflags
926 -- update things if the users wants more packages
928 let new_packages = pkgs_after \\ pkgs_before
929 when (not (null new_packages)) $
930 newPackages new_packages
933 if (not (null leftovers))
934 then throwDyn (CmdLineError ("unrecognised flags: " ++
939 unsetOptions :: String -> GHCi ()
941 = do -- first, deal with the GHCi opts (+s, +t, etc.)
943 (minus_opts, rest1) = partition isMinus opts
944 (plus_opts, rest2) = partition isPlus rest1
946 if (not (null rest2))
947 then io (putStrLn ("unknown option: '" ++ head rest2 ++ "'"))
950 mapM_ unsetOpt plus_opts
952 -- can't do GHC flags for now
953 if (not (null minus_opts))
954 then throwDyn (CmdLineError "can't unset GHC command-line flags")
957 isMinus ('-':s) = True
960 isPlus ('+':s) = True
964 = case strToGHCiOpt str of
965 Nothing -> io (putStrLn ("unknown option: '" ++ str ++ "'"))
966 Just o -> setOption o
969 = case strToGHCiOpt str of
970 Nothing -> io (putStrLn ("unknown option: '" ++ str ++ "'"))
971 Just o -> unsetOption o
973 strToGHCiOpt :: String -> (Maybe GHCiOption)
974 strToGHCiOpt "s" = Just ShowTiming
975 strToGHCiOpt "t" = Just ShowType
976 strToGHCiOpt "r" = Just RevertCAFs
977 strToGHCiOpt _ = Nothing
979 optToStr :: GHCiOption -> String
980 optToStr ShowTiming = "s"
981 optToStr ShowType = "t"
982 optToStr RevertCAFs = "r"
984 newPackages new_pkgs = do -- The new packages are already in v_Packages
985 state <- getGHCiState
986 cmstate1 <- io (cmUnload (cmstate state))
987 setGHCiState state{ cmstate = cmstate1, targets = [] }
988 dflags <- getDynFlags
989 io (linkPackages dflags new_pkgs)
990 setContextAfterLoad []
992 -- ---------------------------------------------------------------------------
997 ["modules" ] -> showModules
998 ["bindings"] -> showBindings
999 ["linker"] -> io showLinkerState
1000 _ -> throwDyn (CmdLineError "syntax: :show [modules|bindings]")
1003 = do { cms <- getCmState
1004 ; let show_one ms = io (putStrLn (cmShowModule cms ms))
1005 ; mapM_ show_one (cmGetModuleGraph cms) }
1010 unqual = cmGetPrintUnqual cms
1011 -- showBinding b = putStrLn (showSDocForUser unqual (ppr (ifaceTyThing b)))
1012 showBinding b = putStrLn (showSDocForUser unqual (ppr (getName b)))
1014 io (mapM_ showBinding (cmGetBindings cms))
1018 -----------------------------------------------------------------------------
1021 data GHCiState = GHCiState
1025 targets :: [FilePath],
1027 options :: [GHCiOption]
1031 = ShowTiming -- show time/allocs after evaluation
1032 | ShowType -- show the type of expressions
1033 | RevertCAFs -- revert CAFs after every evaluation
1036 newtype GHCi a = GHCi { unGHCi :: IORef GHCiState -> IO a }
1038 startGHCi :: GHCi a -> GHCiState -> IO a
1039 startGHCi g state = do ref <- newIORef state; unGHCi g ref
1041 instance Monad GHCi where
1042 (GHCi m) >>= k = GHCi $ \s -> m s >>= \a -> unGHCi (k a) s
1043 return a = GHCi $ \s -> return a
1045 ghciHandleDyn :: Typeable t => (t -> GHCi a) -> GHCi a -> GHCi a
1046 ghciHandleDyn h (GHCi m) = GHCi $ \s ->
1047 Exception.catchDyn (m s) (\e -> unGHCi (h e) s)
1049 getGHCiState = GHCi $ \r -> readIORef r
1050 setGHCiState s = GHCi $ \r -> writeIORef r s
1052 -- for convenience...
1053 getCmState = getGHCiState >>= return . cmstate
1054 setCmState cms = do s <- getGHCiState; setGHCiState s{cmstate=cms}
1056 getDynFlags = getCmState >>= return . cmGetDFlags
1058 setDynFlags dflags = do s <- getCmState; setCmState (cmSetDFlags s dflags)
1060 isOptionSet :: GHCiOption -> GHCi Bool
1062 = do st <- getGHCiState
1063 return (opt `elem` options st)
1065 setOption :: GHCiOption -> GHCi ()
1067 = do st <- getGHCiState
1068 setGHCiState (st{ options = opt : filter (/= opt) (options st) })
1070 unsetOption :: GHCiOption -> GHCi ()
1072 = do st <- getGHCiState
1073 setGHCiState (st{ options = filter (/= opt) (options st) })
1075 io :: IO a -> GHCi a
1076 io m = GHCi { unGHCi = \s -> m >>= return }
1078 -----------------------------------------------------------------------------
1079 -- recursive exception handlers
1081 -- Don't forget to unblock async exceptions in the handler, or if we're
1082 -- in an exception loop (eg. let a = error a in a) the ^C exception
1083 -- may never be delivered. Thanks to Marcin for pointing out the bug.
1085 ghciHandle :: (Exception -> GHCi a) -> GHCi a -> GHCi a
1086 ghciHandle h (GHCi m) = GHCi $ \s ->
1087 Exception.catch (m s)
1088 (\e -> unGHCi (ghciUnblock (h e)) s)
1090 ghciUnblock :: GHCi a -> GHCi a
1091 ghciUnblock (GHCi a) = GHCi $ \s -> Exception.unblock (a s)
1093 -----------------------------------------------------------------------------
1094 -- timing & statistics
1096 timeIt :: GHCi a -> GHCi a
1098 = do b <- isOptionSet ShowTiming
1101 else do allocs1 <- io $ getAllocations
1102 time1 <- io $ getCPUTime
1104 allocs2 <- io $ getAllocations
1105 time2 <- io $ getCPUTime
1106 io $ printTimes (fromIntegral (allocs2 - allocs1))
1110 foreign import ccall unsafe "getAllocations" getAllocations :: IO Int64
1111 -- defined in ghc/rts/Stats.c
1113 printTimes :: Integer -> Integer -> IO ()
1114 printTimes allocs psecs
1115 = do let secs = (fromIntegral psecs / (10^12)) :: Float
1116 secs_str = showFFloat (Just 2) secs
1117 putStrLn (showSDoc (
1118 parens (text (secs_str "") <+> text "secs" <> comma <+>
1119 text (show allocs) <+> text "bytes")))
1121 -----------------------------------------------------------------------------
1128 -- Have to turn off buffering again, because we just
1129 -- reverted stdout, stderr & stdin to their defaults.
1131 foreign import ccall "revertCAFs" rts_revertCAFs :: IO ()
1132 -- Make it "safe", just in case
1134 -- -----------------------------------------------------------------------------
1137 expandPath :: String -> GHCi String
1139 case dropWhile isSpace path of
1141 tilde <- io (getEnv "HOME") -- will fail if HOME not defined
1142 return (tilde ++ '/':d)