1 {-# OPTIONS -#include "Linker.h" #-}
2 -----------------------------------------------------------------------------
4 -- GHC Interactive User Interface
6 -- (c) The GHC Team 2005
8 -----------------------------------------------------------------------------
14 #include "HsVersions.h"
18 import GHC ( Session, verbosity, dopt, DynFlag(..),
19 mkModule, pprModule, Type, Module, SuccessFlag(..),
20 TyThing(..), Name, LoadHowMuch(..),
21 GhcException(..), showGhcException )
24 -- following all needed for :info... ToDo: remove
25 import IfaceSyn ( IfaceDecl(..), IfaceClassOp(..), IfaceConDecls(..),
26 IfaceConDecl(..), IfaceType,
27 pprIfaceDeclHead, pprParendIfaceType,
28 pprIfaceForAllPart, pprIfaceType )
29 import FunDeps ( pprFundeps )
30 import SrcLoc ( SrcLoc, isGoodSrcLoc )
31 import OccName ( OccName, parenSymOcc, occNameUserString )
32 import BasicTypes ( StrictnessMark(..), defaultFixity )
34 -- Other random utilities
35 import Panic ( panic, installSignalHandlers )
37 import StaticFlags ( opt_IgnoreDotGhci )
38 import Linker ( showLinkerState )
39 import Util ( removeSpaces, handle, global, toArgs,
40 looksLikeModuleName, prefixMatch )
42 #ifndef mingw32_HOST_OS
43 import Util ( handle )
45 #if __GLASGOW_HASKELL__ > 504
51 import Control.Concurrent ( yield ) -- Used in readline loop
52 import System.Console.Readline as Readline
57 import Control.Exception as Exception
59 -- import Control.Concurrent
63 import Data.Int ( Int64 )
66 import System.Environment
67 import System.Exit ( exitWith, ExitCode(..) )
68 import System.Directory
70 import System.IO.Error as IO
72 import Control.Monad as Monad
73 import Foreign.StablePtr ( newStablePtr )
75 import GHC.Exts ( unsafeCoerce# )
76 import GHC.IOBase ( IOErrorType(InvalidArgument) )
78 import Data.IORef ( IORef, newIORef, readIORef, writeIORef )
80 import System.Posix.Internals ( setNonBlockingFD )
82 -----------------------------------------------------------------------------
86 " / _ \\ /\\ /\\/ __(_)\n"++
87 " / /_\\// /_/ / / | | GHC Interactive, version " ++ cProjectVersion ++ ", for Haskell 98.\n"++
88 "/ /_\\\\/ __ / /___| | http://www.haskell.org/ghc/\n"++
89 "\\____/\\/ /_/\\____/|_| Type :? for help.\n"
91 GLOBAL_VAR(commands, builtin_commands, [(String, String -> GHCi Bool)])
93 builtin_commands :: [(String, String -> GHCi Bool)]
95 ("add", keepGoingPaths addModule),
96 ("browse", keepGoing browseCmd),
97 ("cd", keepGoing changeDirectory),
98 ("def", keepGoing defineMacro),
99 ("help", keepGoing help),
100 ("?", keepGoing help),
101 ("info", keepGoing info),
102 ("load", keepGoingPaths loadModule),
103 ("module", keepGoing setContext),
104 ("reload", keepGoing reloadModule),
105 ("set", keepGoing setCmd),
106 ("show", keepGoing showCmd),
107 ("type", keepGoing typeOfExpr),
108 ("kind", keepGoing kindOfType),
109 ("unset", keepGoing unsetOptions),
110 ("undef", keepGoing undefineMacro),
114 keepGoing :: (String -> GHCi ()) -> (String -> GHCi Bool)
115 keepGoing a str = a str >> return False
117 keepGoingPaths :: ([FilePath] -> GHCi ()) -> (String -> GHCi Bool)
118 keepGoingPaths a str = a (toArgs str) >> return False
120 shortHelpText = "use :? for help.\n"
122 -- NOTE: spaces at the end of each line to workaround CPP/string gap bug.
124 " Commands available from the prompt:\n" ++
126 " <stmt> evaluate/run <stmt>\n" ++
127 " :add <filename> ... add module(s) to the current target set\n" ++
128 " :browse [*]<module> display the names defined by <module>\n" ++
129 " :cd <dir> change directory to <dir>\n" ++
130 " :def <cmd> <expr> define a command :<cmd>\n" ++
131 " :help, :? display this list of commands\n" ++
132 " :info [<name> ...] display information about the given names\n" ++
133 " :load <filename> ... load module(s) and their dependents\n" ++
134 " :module [+/-] [*]<mod> ... set the context for expression evaluation\n" ++
135 " :reload reload the current module set\n" ++
137 " :set <option> ... set options\n" ++
138 " :set args <arg> ... set the arguments returned by System.getArgs\n" ++
139 " :set prog <progname> set the value returned by System.getProgName\n" ++
141 " :show modules show the currently loaded modules\n" ++
142 " :show bindings show the current bindings made at the prompt\n" ++
144 " :type <expr> show the type of <expr>\n" ++
145 " :kind <type> show the kind of <type>\n" ++
146 " :undef <cmd> undefine user-defined command :<cmd>\n" ++
147 " :unset <option> ... unset options\n" ++
148 " :quit exit GHCi\n" ++
149 " :!<command> run the shell command <command>\n" ++
151 " Options for ':set' and ':unset':\n" ++
153 " +r revert top-level expressions after each evaluation\n" ++
154 " +s print timing/memory stats after each evaluation\n" ++
155 " +t print type after evaluation\n" ++
156 " -<flags> most GHC command line flags can also be set here\n" ++
157 " (eg. -v2, -fglasgow-exts, etc.)\n"
160 interactiveUI :: Session -> [FilePath] -> Maybe String -> IO ()
161 interactiveUI session srcs maybe_expr = do
163 -- HACK! If we happen to get into an infinite loop (eg the user
164 -- types 'let x=x in x' at the prompt), then the thread will block
165 -- on a blackhole, and become unreachable during GC. The GC will
166 -- detect that it is unreachable and send it the NonTermination
167 -- exception. However, since the thread is unreachable, everything
168 -- it refers to might be finalized, including the standard Handles.
169 -- This sounds like a bug, but we don't have a good solution right
176 hSetBuffering stdout NoBuffering
178 -- Initialise buffering for the *interpreted* I/O system
179 initInterpBuffering session
181 -- We don't want the cmd line to buffer any input that might be
182 -- intended for the program, so unbuffer stdin.
183 hSetBuffering stdin NoBuffering
185 -- initial context is just the Prelude
186 GHC.setContext session [] [prelude_mod]
192 startGHCi (runGHCi srcs maybe_expr)
193 GHCiState{ progname = "<interactive>",
199 Readline.resetTerminal Nothing
204 runGHCi :: [FilePath] -> Maybe String -> GHCi ()
205 runGHCi paths maybe_expr = do
206 let read_dot_files = not opt_IgnoreDotGhci
208 when (read_dot_files) $ do
211 exists <- io (doesFileExist file)
213 dir_ok <- io (checkPerms ".")
214 file_ok <- io (checkPerms file)
215 when (dir_ok && file_ok) $ do
216 either_hdl <- io (IO.try (openFile "./.ghci" ReadMode))
219 Right hdl -> fileLoop hdl False
221 when (read_dot_files) $ do
222 -- Read in $HOME/.ghci
223 either_dir <- io (IO.try (getEnv "HOME"))
227 cwd <- io (getCurrentDirectory)
228 when (dir /= cwd) $ do
229 let file = dir ++ "/.ghci"
230 ok <- io (checkPerms file)
232 either_hdl <- io (IO.try (openFile file ReadMode))
235 Right hdl -> fileLoop hdl False
237 -- Perform a :load for files given on the GHCi command line
238 when (not (null paths)) $
239 ghciHandle showException $
242 -- if verbosity is greater than 0, or we are connected to a
243 -- terminal, display the prompt in the interactive loop.
244 is_tty <- io (hIsTerminalDevice stdin)
245 dflags <- getDynFlags
246 let show_prompt = verbosity dflags > 0 || is_tty
250 -- enter the interactive loop
251 interactiveLoop is_tty show_prompt
253 -- just evaluate the expression we were given
258 io $ do when (verbosity dflags > 0) $ putStrLn "Leaving GHCi."
261 interactiveLoop is_tty show_prompt = do
262 -- Ignore ^C exceptions caught here
263 ghciHandleDyn (\e -> case e of
264 Interrupted -> ghciUnblock (interactiveLoop is_tty show_prompt)
265 _other -> return ()) $ do
267 -- read commands from stdin
271 else fileLoop stdin show_prompt
273 fileLoop stdin show_prompt
277 -- NOTE: We only read .ghci files if they are owned by the current user,
278 -- and aren't world writable. Otherwise, we could be accidentally
279 -- running code planted by a malicious third party.
281 -- Furthermore, We only read ./.ghci if . is owned by the current user
282 -- and isn't writable by anyone else. I think this is sufficient: we
283 -- don't need to check .. and ../.. etc. because "." always refers to
284 -- the same directory while a process is running.
286 checkPerms :: String -> IO Bool
288 #ifdef mingw32_HOST_OS
291 Util.handle (\_ -> return False) $ do
292 st <- getFileStatus name
294 if fileOwner st /= me then do
295 putStrLn $ "WARNING: " ++ name ++ " is owned by someone else, IGNORING!"
298 let mode = fileMode st
299 if (groupWriteMode == (mode `intersectFileModes` groupWriteMode))
300 || (otherWriteMode == (mode `intersectFileModes` otherWriteMode))
302 putStrLn $ "*** WARNING: " ++ name ++
303 " is writable by someone else, IGNORING!"
308 fileLoop :: Handle -> Bool -> GHCi ()
309 fileLoop hdl prompt = do
310 session <- getSession
311 (mod,imports) <- io (GHC.getContext session)
312 when prompt (io (putStr (mkPrompt mod imports)))
313 l <- io (IO.try (hGetLine hdl))
315 Left e | isEOFError e -> return ()
316 | InvalidArgument <- etype -> return ()
317 | otherwise -> io (ioError e)
318 where etype = ioeGetErrorType e
319 -- treat InvalidArgument in the same way as EOF:
320 -- this can happen if the user closed stdin, or
321 -- perhaps did getContents which closes stdin at
324 case removeSpaces l of
325 "" -> fileLoop hdl prompt
326 l -> do quit <- runCommand l
327 if quit then return () else fileLoop hdl prompt
329 stringLoop :: [String] -> GHCi ()
330 stringLoop [] = return ()
331 stringLoop (s:ss) = do
332 case removeSpaces s of
334 l -> do quit <- runCommand l
335 if quit then return () else stringLoop ss
337 mkPrompt toplevs exports
338 = showSDoc (hsep (map (\m -> char '*' <> pprModule m) toplevs)
339 <+> hsep (map pprModule exports)
343 readlineLoop :: GHCi ()
345 session <- getSession
346 (mod,imports) <- io (GHC.getContext session)
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 removeSpaces 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 session <- getSession
412 result <- io $ withProgName (progname st) $ withArgs (args st) $
413 GHC.runStmt session stmt
415 GHC.RunFailed -> return []
416 GHC.RunException e -> throw e -- this is caught by runCommand(Eval)
417 GHC.RunOk names -> return names
419 -- possibly print the type and revert CAFs after evaluating an expression
421 = do b <- isOptionSet ShowType
422 session <- getSession
423 when b (mapM_ (showTypeOfName session) names)
426 io installSignalHandlers
427 b <- isOptionSet RevertCAFs
428 io (when b revertCAFs)
431 showTypeOfName :: Session -> Name -> GHCi ()
432 showTypeOfName session n
433 = do maybe_tything <- io (GHC.lookupName session n)
434 case maybe_tything of
436 Just thing -> showTyThing thing
438 showForUser :: SDoc -> GHCi String
440 session <- getSession
441 unqual <- io (GHC.getPrintUnqual session)
442 return $! showSDocForUser unqual doc
444 specialCommand :: String -> GHCi Bool
445 specialCommand ('!':str) = shellEscape (dropWhile isSpace str)
446 specialCommand str = do
447 let (cmd,rest) = break isSpace str
448 cmds <- io (readIORef commands)
449 case [ (s,f) | (s,f) <- cmds, prefixMatch cmd s ] of
450 [] -> io (hPutStr stdout ("unknown command ':" ++ cmd ++ "'\n"
451 ++ shortHelpText) >> return False)
452 [(_,f)] -> f (dropWhile isSpace rest)
453 cs -> io (hPutStrLn stdout ("prefix " ++ cmd ++
454 " matches multiple commands (" ++
455 foldr1 (\a b -> a ++ ',':b) (map fst cs)
456 ++ ")") >> return False)
458 noArgs c = throwDyn (CmdLineError ("command '" ++ c ++ "' takes no arguments"))
461 -----------------------------------------------------------------------------
462 -- To flush buffers for the *interpreted* computation we need
463 -- to refer to *its* stdout/stderr handles
465 GLOBAL_VAR(flush_interp, error "no flush_interp", IO ())
466 GLOBAL_VAR(turn_off_buffering, error "no flush_stdout", IO ())
468 no_buf_cmd = "System.IO.hSetBuffering System.IO.stdout System.IO.NoBuffering" ++
469 " Prelude.>> System.IO.hSetBuffering System.IO.stderr System.IO.NoBuffering"
470 flush_cmd = "System.IO.hFlush System.IO.stdout Prelude.>> System.IO.hFlush IO.stderr"
472 initInterpBuffering :: Session -> IO ()
473 initInterpBuffering session
474 = do maybe_hval <- GHC.compileExpr session no_buf_cmd
477 Just hval -> writeIORef turn_off_buffering (unsafeCoerce# hval :: IO ())
478 other -> panic "interactiveUI:setBuffering"
480 maybe_hval <- GHC.compileExpr session flush_cmd
482 Just hval -> writeIORef flush_interp (unsafeCoerce# hval :: IO ())
483 _ -> panic "interactiveUI:flush"
485 turnOffBuffering -- Turn it off right now
490 flushInterpBuffers :: GHCi ()
492 = io $ do Monad.join (readIORef flush_interp)
495 turnOffBuffering :: IO ()
497 = do Monad.join (readIORef turn_off_buffering)
500 -----------------------------------------------------------------------------
503 help :: String -> GHCi ()
504 help _ = io (putStr helpText)
506 info :: String -> GHCi ()
507 info "" = throwDyn (CmdLineError "syntax: ':i <thing-you-want-info-about>'")
508 info s = do { let names = words s
509 ; session <- getSession
510 ; dflags <- getDynFlags
511 ; let exts = dopt Opt_GlasgowExts dflags
512 ; mapM_ (infoThing exts session) names }
514 infoThing exts session name
515 = do { stuff <- io (GHC.getInfo session name)
516 ; unqual <- io (GHC.getPrintUnqual session)
517 ; io (putStrLn (showSDocForUser unqual $
518 vcat (intersperse (text "") (map (showThing exts) stuff)))) }
520 showThing :: Bool -> GHC.GetInfoResult -> SDoc
521 showThing exts (wanted_str, thing, fixity, src_loc, insts)
522 = vcat [ showWithLoc src_loc (showDecl exts want_name thing),
524 vcat (map show_inst insts)]
526 want_name occ = wanted_str == occNameUserString occ
529 | fix == defaultFixity = empty
530 | otherwise = ppr fix <+> text wanted_str
532 show_inst (inst_ty, loc)
533 = showWithLoc loc (ptext SLIT("instance") <+> ppr inst_ty)
535 showWithLoc :: SrcLoc -> SDoc -> SDoc
537 = hang doc 2 (char '\t' <> show_loc loc)
538 -- The tab tries to make them line up a bit
540 show_loc loc -- The ppr function for SrcLocs is a bit wonky
541 | isGoodSrcLoc loc = comment <+> ptext SLIT("Defined at") <+> ppr loc
542 | otherwise = comment <+> ppr loc
543 comment = ptext SLIT("--")
546 -- Now there is rather a lot of goop just to print declarations in a
547 -- civilised way with "..." for the parts we are less interested in.
549 showDecl :: Bool -> (OccName -> Bool) -> IfaceDecl -> SDoc
550 showDecl exts want_name (IfaceForeign {ifName = tc})
551 = ppr tc <+> ptext SLIT("is a foreign type")
553 showDecl exts want_name (IfaceId {ifName = var, ifType = ty})
554 = ppr var <+> dcolon <+> showIfaceType exts ty
556 showDecl exts want_name (IfaceSyn {ifName = tycon, ifTyVars = tyvars, ifSynRhs = mono_ty})
557 = hang (ptext SLIT("type") <+> pprIfaceDeclHead [] tycon tyvars)
558 2 (equals <+> ppr mono_ty)
560 showDecl exts want_name (IfaceData {ifName = tycon,
561 ifTyVars = tyvars, ifCons = condecls})
562 = hang (pp_nd <+> pprIfaceDeclHead context tycon tyvars)
563 2 (add_bars (ppr_trim show_con cs))
565 show_con (IfVanillaCon { ifConOcc = con_name, ifConInfix = is_infix, ifConArgTys = tys,
566 ifConStricts = strs, ifConFields = flds})
567 | want_name tycon || want_name con_name || any want_name flds
568 = Just (show_guts con_name is_infix tys_w_strs flds)
569 | otherwise = Nothing
571 tys_w_strs = tys `zip` (strs ++ repeat NotMarkedStrict)
572 show_con (IfGadtCon { ifConOcc = con_name, ifConTyVars = tvs, ifConCtxt = theta,
573 ifConArgTys = arg_tys, ifConResTys = res_tys, ifConStricts = strs })
574 | want_name tycon || want_name con_name
575 = Just (ppr_bndr con_name <+> colon <+> pprIfaceForAllPart tvs theta pp_tau)
576 | otherwise = Nothing
578 tys_w_strs = arg_tys `zip` (strs ++ repeat NotMarkedStrict)
579 pp_tau = foldr add pp_res_ty tys_w_strs
580 pp_res_ty = ppr_bndr tycon <+> hsep (map pprParendIfaceType res_tys)
581 add bty pp_ty = ppr_bangty bty <+> arrow <+> pp_ty
583 show_guts con True [ty1, ty2] flds = sep [ppr_bangty ty1, ppr con, ppr_bangty ty2]
584 show_guts con _ tys [] = ppr_bndr con <+> sep (map ppr_bangty tys)
585 show_guts con _ tys flds
586 = ppr_bndr con <+> braces (sep (punctuate comma (ppr_trim show_fld (tys `zip` flds))))
588 show_fld (bty, fld) | want_name tycon || want_name con || want_name fld
589 = Just (ppr_bndr fld <+> dcolon <+> ppr_bangty bty)
590 | otherwise = Nothing
592 (pp_nd, context, cs) = case condecls of
593 IfAbstractTyCon -> (ptext SLIT("data"), [], [])
594 IfDataTyCon (Just cxt) cs -> (ptext SLIT("data"), cxt, cs)
595 IfDataTyCon Nothing cs -> (ptext SLIT("data"), [], cs)
596 IfNewTyCon c -> (ptext SLIT("newtype"), [], [c])
599 add_bars [c] = equals <+> c
600 add_bars (c:cs) = equals <+> sep (c : map (char '|' <+>) cs)
602 ppr_bangty (ty, str) = ppr_str str <> pprParendIfaceType ty
603 ppr_str MarkedStrict = char '!'
604 ppr_str MarkedUnboxed = ptext SLIT("!!")
605 ppr_str NotMarkedStrict = empty
607 showDecl exts want_name (IfaceClass {ifCtxt = context, ifName = clas, ifTyVars = tyvars,
608 ifFDs = fds, ifSigs = sigs})
609 = hang (ptext SLIT("class") <+> pprIfaceDeclHead context clas tyvars
610 <+> pprFundeps fds <+> opt_where)
611 2 (vcat (ppr_trim show_op sigs))
613 opt_where | null sigs = empty
614 | otherwise = ptext SLIT("where")
615 show_op (IfaceClassOp op dm ty)
616 | want_name clas || want_name op
617 = Just (ppr_bndr op <+> dcolon <+> showIfaceType exts ty)
621 showIfaceType :: Bool -> IfaceType -> SDoc
622 showIfaceType True ty = pprIfaceType ty -- -fglasgow-exts: print with the foralls
623 showIfaceType False ty = ppr ty -- otherwise, print without the foralls
625 ppr_trim :: (a -> Maybe SDoc) -> [a] -> [SDoc]
627 = snd (foldr go (False, []) xs)
629 go x (eliding, so_far)
630 | Just doc <- show x = (False, doc : so_far)
631 | otherwise = if eliding then (True, so_far)
632 else (True, ptext SLIT("...") : so_far)
634 ppr_bndr :: OccName -> SDoc
635 -- Wrap operators in ()
636 ppr_bndr occ = parenSymOcc occ (ppr occ)
639 -----------------------------------------------------------------------------
642 addModule :: [FilePath] -> GHCi ()
644 io (revertCAFs) -- always revert CAFs on load/add.
645 files <- mapM expandPath files
646 targets <- mapM (io . GHC.guessTarget) files
647 session <- getSession
648 io (mapM_ (GHC.addTarget session) targets)
649 ok <- io (GHC.load session LoadAllTargets)
652 changeDirectory :: String -> GHCi ()
653 changeDirectory dir = do
654 session <- getSession
655 graph <- io (GHC.getModuleGraph session)
656 when (not (null graph)) $
657 io $ putStr "Warning: changing directory causes all loaded modules to be unloaded,\nbecause the search path has changed.\n"
658 io (GHC.setTargets session [])
659 io (GHC.load session LoadAllTargets)
660 setContextAfterLoad []
661 io (GHC.workingDirectoryChanged session)
662 dir <- expandPath dir
663 io (setCurrentDirectory dir)
665 defineMacro :: String -> GHCi ()
667 let (macro_name, definition) = break isSpace s
668 cmds <- io (readIORef commands)
670 then throwDyn (CmdLineError "invalid macro name")
672 if (macro_name `elem` map fst cmds)
673 then throwDyn (CmdLineError
674 ("command '" ++ macro_name ++ "' is already defined"))
677 -- give the expression a type signature, so we can be sure we're getting
678 -- something of the right type.
679 let new_expr = '(' : definition ++ ") :: String -> IO String"
681 -- compile the expression
683 maybe_hv <- io (GHC.compileExpr cms new_expr)
686 Just hv -> io (writeIORef commands --
687 ((macro_name, keepGoing (runMacro hv)) : cmds))
689 runMacro :: GHC.HValue{-String -> IO String-} -> String -> GHCi ()
691 str <- io ((unsafeCoerce# fun :: String -> IO String) s)
692 stringLoop (lines str)
694 undefineMacro :: String -> GHCi ()
695 undefineMacro macro_name = do
696 cmds <- io (readIORef commands)
697 if (macro_name `elem` map fst builtin_commands)
698 then throwDyn (CmdLineError
699 ("command '" ++ macro_name ++ "' cannot be undefined"))
701 if (macro_name `notElem` map fst cmds)
702 then throwDyn (CmdLineError
703 ("command '" ++ macro_name ++ "' not defined"))
705 io (writeIORef commands (filter ((/= macro_name) . fst) cmds))
708 loadModule :: [FilePath] -> GHCi ()
709 loadModule fs = timeIt (loadModule' fs)
711 loadModule' :: [FilePath] -> GHCi ()
712 loadModule' files = do
713 session <- getSession
716 io (GHC.setTargets session [])
717 io (GHC.load session LoadAllTargets)
720 files <- mapM expandPath files
721 targets <- io (mapM GHC.guessTarget files)
723 -- NOTE: we used to do the dependency anal first, so that if it
724 -- fails we didn't throw away the current set of modules. This would
725 -- require some re-working of the GHC interface, so we'll leave it
726 -- as a ToDo for now.
728 io (GHC.setTargets session targets)
729 ok <- io (GHC.load session LoadAllTargets)
733 reloadModule :: String -> GHCi ()
735 io (revertCAFs) -- always revert CAFs on reload.
736 session <- getSession
737 ok <- io (GHC.load session LoadAllTargets)
740 io (revertCAFs) -- always revert CAFs on reload.
741 session <- getSession
742 ok <- io (GHC.load session (LoadUpTo (mkModule m)))
745 afterLoad ok session = do
746 io (revertCAFs) -- always revert CAFs on load.
747 graph <- io (GHC.getModuleGraph session)
748 let mods = map GHC.ms_mod graph
749 mods' <- filterM (io . GHC.isLoaded session) mods
750 setContextAfterLoad mods'
751 modulesLoadedMsg ok mods'
753 setContextAfterLoad [] = do
754 session <- getSession
755 io (GHC.setContext session [] [prelude_mod])
756 setContextAfterLoad (m:_) = do
757 session <- getSession
758 b <- io (GHC.moduleIsInterpreted session m)
759 if b then io (GHC.setContext session [m] [])
760 else io (GHC.setContext session [] [m])
762 modulesLoadedMsg :: SuccessFlag -> [Module] -> GHCi ()
763 modulesLoadedMsg ok mods = do
764 dflags <- getDynFlags
765 when (verbosity dflags > 0) $ do
767 | null mods = text "none."
769 punctuate comma (map pprModule mods)) <> text "."
772 io (putStrLn (showSDoc (text "Failed, modules loaded: " <> mod_commas)))
774 io (putStrLn (showSDoc (text "Ok, modules loaded: " <> mod_commas)))
777 typeOfExpr :: String -> GHCi ()
779 = do cms <- getSession
780 maybe_ty <- io (GHC.exprType cms str)
783 Just ty -> do ty' <- cleanType ty
784 tystr <- showForUser (ppr ty')
785 io (putStrLn (str ++ " :: " ++ tystr))
787 kindOfType :: String -> GHCi ()
789 = do cms <- getSession
790 maybe_ty <- io (GHC.typeKind cms str)
793 Just ty -> do tystr <- showForUser (ppr ty)
794 io (putStrLn (str ++ " :: " ++ tystr))
796 quit :: String -> GHCi Bool
799 shellEscape :: String -> GHCi Bool
800 shellEscape str = io (system str >> return False)
802 -----------------------------------------------------------------------------
803 -- Browsing a module's contents
805 browseCmd :: String -> GHCi ()
808 ['*':m] | looksLikeModuleName m -> browseModule m False
809 [m] | looksLikeModuleName m -> browseModule m True
810 _ -> throwDyn (CmdLineError "syntax: :browse <module>")
812 browseModule m exports_only = do
815 let modl = mkModule m
816 is_interpreted <- io (GHC.moduleIsInterpreted s modl)
817 when (not is_interpreted && not exports_only) $
818 throwDyn (CmdLineError ("module '" ++ m ++ "' is not interpreted"))
820 -- Temporarily set the context to the module we're interested in,
821 -- just so we can get an appropriate PrintUnqualified
822 (as,bs) <- io (GHC.getContext s)
823 io (if exports_only then GHC.setContext s [] [prelude_mod,modl]
824 else GHC.setContext s [modl] [])
825 io (GHC.setContext s as bs)
827 things <- io (GHC.browseModule s modl exports_only)
828 unqual <- io (GHC.getPrintUnqual s)
830 dflags <- getDynFlags
831 let exts = dopt Opt_GlasgowExts dflags
832 io (putStrLn (showSDocForUser unqual (
833 vcat (map (showDecl exts (const True)) things)
836 -----------------------------------------------------------------------------
837 -- Setting the module context
840 | all sensible mods = fn mods
841 | otherwise = throwDyn (CmdLineError "syntax: :module [+/-] [*]M1 ... [*]Mn")
843 (fn, mods) = case str of
844 '+':stuff -> (addToContext, words stuff)
845 '-':stuff -> (removeFromContext, words stuff)
846 stuff -> (newContext, words stuff)
848 sensible ('*':m) = looksLikeModuleName m
849 sensible m = looksLikeModuleName m
852 session <- getSession
853 (as,bs) <- separate session mods [] []
854 let bs' = if null as && prelude_mod `notElem` bs then prelude_mod:bs else bs
855 io (GHC.setContext session as bs')
857 separate :: Session -> [String] -> [Module] -> [Module]
858 -> GHCi ([Module],[Module])
859 separate session [] as bs = return (as,bs)
860 separate session (('*':m):ms) as bs = do
861 let modl = mkModule m
862 b <- io (GHC.moduleIsInterpreted session modl)
863 if b then separate session ms (modl:as) bs
864 else throwDyn (CmdLineError ("module '" ++ m ++ "' is not interpreted"))
865 separate session (m:ms) as bs = separate session ms as (mkModule m:bs)
867 prelude_mod = mkModule "Prelude"
870 addToContext mods = do
872 (as,bs) <- io (GHC.getContext cms)
874 (as',bs') <- separate cms mods [] []
876 let as_to_add = as' \\ (as ++ bs)
877 bs_to_add = bs' \\ (as ++ bs)
879 io (GHC.setContext cms (as ++ as_to_add) (bs ++ bs_to_add))
882 removeFromContext mods = do
884 (as,bs) <- io (GHC.getContext cms)
886 (as_to_remove,bs_to_remove) <- separate cms mods [] []
888 let as' = as \\ (as_to_remove ++ bs_to_remove)
889 bs' = bs \\ (as_to_remove ++ bs_to_remove)
891 io (GHC.setContext cms as' bs')
893 ----------------------------------------------------------------------------
896 -- set options in the interpreter. Syntax is exactly the same as the
897 -- ghc command line, except that certain options aren't available (-C,
900 -- This is pretty fragile: most options won't work as expected. ToDo:
901 -- figure out which ones & disallow them.
903 setCmd :: String -> GHCi ()
905 = do st <- getGHCiState
906 let opts = options st
907 io $ putStrLn (showSDoc (
908 text "options currently set: " <>
911 else hsep (map (\o -> char '+' <> text (optToStr o)) opts)
915 ("args":args) -> setArgs args
916 ("prog":prog) -> setProg prog
917 wds -> setOptions wds
921 setGHCiState st{ args = args }
925 setGHCiState st{ progname = prog }
927 io (hPutStrLn stderr "syntax: :set prog <progname>")
930 do -- first, deal with the GHCi opts (+s, +t, etc.)
931 let (plus_opts, minus_opts) = partition isPlus wds
932 mapM_ setOpt plus_opts
934 -- then, dynamic flags
935 dflags <- getDynFlags
936 (dflags',leftovers) <- io $ GHC.parseDynamicFlags dflags minus_opts
939 -- update things if the users wants more packages
941 let new_packages = pkgs_after \\ pkgs_before
942 when (not (null new_packages)) $
943 newPackages new_packages
946 if (not (null leftovers))
947 then throwDyn (CmdLineError ("unrecognised flags: " ++
952 unsetOptions :: String -> GHCi ()
954 = do -- first, deal with the GHCi opts (+s, +t, etc.)
956 (minus_opts, rest1) = partition isMinus opts
957 (plus_opts, rest2) = partition isPlus rest1
959 if (not (null rest2))
960 then io (putStrLn ("unknown option: '" ++ head rest2 ++ "'"))
963 mapM_ unsetOpt plus_opts
965 -- can't do GHC flags for now
966 if (not (null minus_opts))
967 then throwDyn (CmdLineError "can't unset GHC command-line flags")
970 isMinus ('-':s) = True
973 isPlus ('+':s) = True
977 = case strToGHCiOpt str of
978 Nothing -> io (putStrLn ("unknown option: '" ++ str ++ "'"))
979 Just o -> setOption o
982 = case strToGHCiOpt str of
983 Nothing -> io (putStrLn ("unknown option: '" ++ str ++ "'"))
984 Just o -> unsetOption o
986 strToGHCiOpt :: String -> (Maybe GHCiOption)
987 strToGHCiOpt "s" = Just ShowTiming
988 strToGHCiOpt "t" = Just ShowType
989 strToGHCiOpt "r" = Just RevertCAFs
990 strToGHCiOpt _ = Nothing
992 optToStr :: GHCiOption -> String
993 optToStr ShowTiming = "s"
994 optToStr ShowType = "t"
995 optToStr RevertCAFs = "r"
998 newPackages new_pkgs = do -- The new packages are already in v_Packages
999 session <- getSession
1000 io (GHC.setTargets session [])
1001 io (GHC.load session Nothing)
1002 dflags <- getDynFlags
1003 io (linkPackages dflags new_pkgs)
1004 setContextAfterLoad []
1007 -- ---------------------------------------------------------------------------
1012 ["modules" ] -> showModules
1013 ["bindings"] -> showBindings
1014 ["linker"] -> io showLinkerState
1015 _ -> throwDyn (CmdLineError "syntax: :show [modules|bindings]")
1018 session <- getSession
1019 let show_one ms = do m <- io (GHC.showModule session ms)
1021 graph <- io (GHC.getModuleGraph session)
1022 mapM_ show_one graph
1026 unqual <- io (GHC.getPrintUnqual s)
1027 bindings <- io (GHC.getBindings s)
1028 mapM_ showTyThing bindings
1031 showTyThing (AnId id) = do
1032 ty' <- cleanType (GHC.idType id)
1033 str <- showForUser (ppr id <> text " :: " <> ppr ty')
1035 showTyThing _ = return ()
1037 -- if -fglasgow-exts is on we show the foralls, otherwise we don't.
1038 cleanType :: Type -> GHCi Type
1040 dflags <- getDynFlags
1041 if dopt Opt_GlasgowExts dflags
1043 else return $! GHC.dropForAlls ty
1045 -----------------------------------------------------------------------------
1048 data GHCiState = GHCiState
1052 session :: GHC.Session,
1053 options :: [GHCiOption]
1057 = ShowTiming -- show time/allocs after evaluation
1058 | ShowType -- show the type of expressions
1059 | RevertCAFs -- revert CAFs after every evaluation
1062 newtype GHCi a = GHCi { unGHCi :: IORef GHCiState -> IO a }
1064 startGHCi :: GHCi a -> GHCiState -> IO a
1065 startGHCi g state = do ref <- newIORef state; unGHCi g ref
1067 instance Monad GHCi where
1068 (GHCi m) >>= k = GHCi $ \s -> m s >>= \a -> unGHCi (k a) s
1069 return a = GHCi $ \s -> return a
1071 ghciHandleDyn :: Typeable t => (t -> GHCi a) -> GHCi a -> GHCi a
1072 ghciHandleDyn h (GHCi m) = GHCi $ \s ->
1073 Exception.catchDyn (m s) (\e -> unGHCi (h e) s)
1075 getGHCiState = GHCi $ \r -> readIORef r
1076 setGHCiState s = GHCi $ \r -> writeIORef r s
1078 -- for convenience...
1079 getSession = getGHCiState >>= return . session
1083 io (GHC.getSessionDynFlags s)
1084 setDynFlags dflags = do
1086 io (GHC.setSessionDynFlags s dflags)
1088 isOptionSet :: GHCiOption -> GHCi Bool
1090 = do st <- getGHCiState
1091 return (opt `elem` options st)
1093 setOption :: GHCiOption -> GHCi ()
1095 = do st <- getGHCiState
1096 setGHCiState (st{ options = opt : filter (/= opt) (options st) })
1098 unsetOption :: GHCiOption -> GHCi ()
1100 = do st <- getGHCiState
1101 setGHCiState (st{ options = filter (/= opt) (options st) })
1103 io :: IO a -> GHCi a
1104 io m = GHCi { unGHCi = \s -> m >>= return }
1106 -----------------------------------------------------------------------------
1107 -- recursive exception handlers
1109 -- Don't forget to unblock async exceptions in the handler, or if we're
1110 -- in an exception loop (eg. let a = error a in a) the ^C exception
1111 -- may never be delivered. Thanks to Marcin for pointing out the bug.
1113 ghciHandle :: (Exception -> GHCi a) -> GHCi a -> GHCi a
1114 ghciHandle h (GHCi m) = GHCi $ \s ->
1115 Exception.catch (m s)
1116 (\e -> unGHCi (ghciUnblock (h e)) s)
1118 ghciUnblock :: GHCi a -> GHCi a
1119 ghciUnblock (GHCi a) = GHCi $ \s -> Exception.unblock (a s)
1121 -----------------------------------------------------------------------------
1122 -- timing & statistics
1124 timeIt :: GHCi a -> GHCi a
1126 = do b <- isOptionSet ShowTiming
1129 else do allocs1 <- io $ getAllocations
1130 time1 <- io $ getCPUTime
1132 allocs2 <- io $ getAllocations
1133 time2 <- io $ getCPUTime
1134 io $ printTimes (fromIntegral (allocs2 - allocs1))
1138 foreign import ccall unsafe "getAllocations" getAllocations :: IO Int64
1139 -- defined in ghc/rts/Stats.c
1141 printTimes :: Integer -> Integer -> IO ()
1142 printTimes allocs psecs
1143 = do let secs = (fromIntegral psecs / (10^12)) :: Float
1144 secs_str = showFFloat (Just 2) secs
1145 putStrLn (showSDoc (
1146 parens (text (secs_str "") <+> text "secs" <> comma <+>
1147 text (show allocs) <+> text "bytes")))
1149 -----------------------------------------------------------------------------
1156 -- Have to turn off buffering again, because we just
1157 -- reverted stdout, stderr & stdin to their defaults.
1159 foreign import ccall "revertCAFs" rts_revertCAFs :: IO ()
1160 -- Make it "safe", just in case
1162 -- -----------------------------------------------------------------------------
1165 expandPath :: String -> GHCi String
1167 case dropWhile isSpace path of
1169 tilde <- io (getEnv "HOME") -- will fail if HOME not defined
1170 return (tilde ++ '/':d)