1 {-# OPTIONS -#include "Linker.h" #-}
2 -----------------------------------------------------------------------------
3 -- $Id: InteractiveUI.hs,v 1.166 2004/05/27 09:29:29 simonmar Exp $
5 -- GHC Interactive User Interface
7 -- (c) The GHC Team 2004
9 -----------------------------------------------------------------------------
10 module InteractiveUI (
11 interactiveUI, -- :: CmState -> [FilePath] -> IO ()
15 #include "../includes/config.h"
16 #include "HsVersions.h"
19 import HscTypes ( TyThing(..), HomeModInfo(hm_linkable), HomePackageTable,
20 isObjectLinkable, GhciMode(..) )
21 import IfaceSyn ( IfaceDecl( ifName ) )
24 import DriverUtil ( remove_spaces )
25 import Linker ( showLinkerState, linkPackages )
27 import Module ( showModMsg, lookupModuleEnv )
28 import Name ( Name, isHomePackageName, nameSrcLoc, nameOccName,
30 import OccName ( isSymOcc )
31 import BasicTypes ( defaultFixity, SuccessFlag(..) )
34 import CmdLineOpts ( DynFlag(..), DynFlags(..), getDynFlags, saveDynFlags,
35 restoreDynFlags, dopt_unset )
36 import Panic hiding ( showException )
39 #ifndef mingw32_HOST_OS
40 import DriverUtil( handle )
42 #if __GLASGOW_HASKELL__ > 504
47 #if HAVE_READLINE_HEADERS && HAVE_READLINE_LIBS
48 import Control.Concurrent ( yield ) -- Used in readline loop
49 import System.Console.Readline as Readline
54 import Control.Exception as Exception
56 import Control.Concurrent
60 import Data.Int ( Int64 )
63 import System.Environment
64 import System.Directory
65 import System.IO as IO
67 import Control.Monad as Monad
69 import GHC.Exts ( unsafeCoerce# )
71 import Data.IORef ( IORef, newIORef, readIORef, writeIORef )
73 import System.Posix.Internals ( setNonBlockingFD )
75 -----------------------------------------------------------------------------
79 \ / _ \\ /\\ /\\/ __(_)\n\
80 \ / /_\\// /_/ / / | | GHC Interactive, version " ++ cProjectVersion ++ ", for Haskell 98.\n\
81 \/ /_\\\\/ __ / /___| | http://www.haskell.org/ghc/\n\
82 \\\____/\\/ /_/\\____/|_| Type :? for help.\n"
84 GLOBAL_VAR(commands, builtin_commands, [(String, String -> GHCi Bool)])
86 builtin_commands :: [(String, String -> GHCi Bool)]
88 ("add", keepGoingPaths addModule),
89 ("browse", keepGoing browseCmd),
90 ("cd", keepGoing changeDirectory),
91 ("def", keepGoing defineMacro),
92 ("help", keepGoing help),
93 ("?", keepGoing help),
94 ("info", keepGoing info),
95 ("load", keepGoingPaths loadModule),
96 ("module", keepGoing setContext),
97 ("reload", keepGoing reloadModule),
98 ("set", keepGoing setCmd),
99 ("show", keepGoing showCmd),
100 ("type", keepGoing typeOfExpr),
101 ("kind", keepGoing kindOfType),
102 ("unset", keepGoing unsetOptions),
103 ("undef", keepGoing undefineMacro),
107 keepGoing :: (String -> GHCi ()) -> (String -> GHCi Bool)
108 keepGoing a str = a str >> return False
110 keepGoingPaths :: ([FilePath] -> GHCi ()) -> (String -> GHCi Bool)
111 keepGoingPaths a str = a (toArgs str) >> return False
113 shortHelpText = "use :? for help.\n"
115 -- NOTE: spaces at the end of each line to workaround CPP/string gap bug.
117 \ Commands available from the prompt:\n\
119 \ <stmt> evaluate/run <stmt>\n\
120 \ :add <filename> ... add module(s) to the current target set\n\
121 \ :browse [*]<module> display the names defined by <module>\n\
122 \ :cd <dir> change directory to <dir>\n\
123 \ :def <cmd> <expr> define a command :<cmd>\n\
124 \ :help, :? display this list of commands\n\
125 \ :info [<name> ...] display information about the given names\n\
126 \ :load <filename> ... load module(s) and their dependents\n\
127 \ :module [+/-] [*]<mod> ... set the context for expression evaluation\n\
128 \ :reload reload the current module set\n\
130 \ :set <option> ... set options\n\
131 \ :set args <arg> ... set the arguments returned by System.getArgs\n\
132 \ :set prog <progname> set the value returned by System.getProgName\n\
134 \ :show modules show the currently loaded modules\n\
135 \ :show bindings show the current bindings made at the prompt\n\
137 \ :type <expr> show the type of <expr>\n\
138 \ :kind <type> show the kind of <type>\n\
139 \ :undef <cmd> undefine user-defined command :<cmd>\n\
140 \ :unset <option> ... unset options\n\
142 \ :!<command> run the shell command <command>\n\
144 \ Options for `:set' and `:unset':\n\
146 \ +r revert top-level expressions after each evaluation\n\
147 \ +s print timing/memory stats after each evaluation\n\
148 \ +t print type after evaluation\n\
149 \ -<flags> most GHC command line flags can also be set here\n\
150 \ (eg. -v2, -fglasgow-exts, etc.)\n\
153 interactiveUI :: [FilePath] -> Maybe String -> IO ()
154 interactiveUI srcs maybe_expr = do
155 dflags <- getDynFlags
157 cmstate <- cmInit Interactive dflags;
160 hSetBuffering stdout NoBuffering
162 -- Initialise buffering for the *interpreted* I/O system
163 initInterpBuffering cmstate
165 -- We don't want the cmd line to buffer any input that might be
166 -- intended for the program, so unbuffer stdin.
167 hSetBuffering stdin NoBuffering
169 -- initial context is just the Prelude
170 cmstate <- cmSetContext cmstate [] ["Prelude"]
172 #if HAVE_READLINE_HEADERS && HAVE_READLINE_LIBS
176 startGHCi (runGHCi srcs dflags maybe_expr)
177 GHCiState{ progname = "<interactive>",
183 #if HAVE_READLINE_HEADERS && HAVE_READLINE_LIBS
184 Readline.resetTerminal Nothing
189 runGHCi :: [FilePath] -> DynFlags -> Maybe String -> GHCi ()
190 runGHCi paths dflags maybe_expr = do
191 read_dot_files <- io (readIORef v_Read_DotGHCi)
193 when (read_dot_files) $ do
196 exists <- io (doesFileExist file)
198 dir_ok <- io (checkPerms ".")
199 file_ok <- io (checkPerms file)
200 when (dir_ok && file_ok) $ do
201 either_hdl <- io (IO.try (openFile "./.ghci" ReadMode))
204 Right hdl -> fileLoop hdl False
206 when (read_dot_files) $ do
207 -- Read in $HOME/.ghci
208 either_dir <- io (IO.try (getEnv "HOME"))
212 cwd <- io (getCurrentDirectory)
213 when (dir /= cwd) $ do
214 let file = dir ++ "/.ghci"
215 ok <- io (checkPerms file)
217 either_hdl <- io (IO.try (openFile file ReadMode))
220 Right hdl -> fileLoop hdl False
222 -- Perform a :load for files given on the GHCi command line
223 when (not (null paths)) $
224 ghciHandle showException $
227 -- if verbosity is greater than 0, or we are connected to a
228 -- terminal, display the prompt in the interactive loop.
229 is_tty <- io (hIsTerminalDevice stdin)
230 let show_prompt = verbosity dflags > 0 || is_tty
234 -- enter the interactive loop
235 interactiveLoop is_tty show_prompt
237 -- just evaluate the expression we were given
242 io $ do when (verbosity dflags > 0) $ putStrLn "Leaving GHCi."
245 interactiveLoop is_tty show_prompt = do
246 -- Ignore ^C exceptions caught here
247 ghciHandleDyn (\e -> case e of
248 Interrupted -> ghciUnblock (interactiveLoop is_tty show_prompt)
249 _other -> return ()) $ do
251 -- read commands from stdin
252 #if HAVE_READLINE_HEADERS && HAVE_READLINE_LIBS
255 else fileLoop stdin show_prompt
257 fileLoop stdin show_prompt
261 -- NOTE: We only read .ghci files if they are owned by the current user,
262 -- and aren't world writable. Otherwise, we could be accidentally
263 -- running code planted by a malicious third party.
265 -- Furthermore, We only read ./.ghci if . is owned by the current user
266 -- and isn't writable by anyone else. I think this is sufficient: we
267 -- don't need to check .. and ../.. etc. because "." always refers to
268 -- the same directory while a process is running.
270 checkPerms :: String -> IO Bool
272 #ifdef mingw32_HOST_OS
275 DriverUtil.handle (\_ -> return False) $ do
276 st <- getFileStatus name
278 if fileOwner st /= me then do
279 putStrLn $ "WARNING: " ++ name ++ " is owned by someone else, IGNORING!"
282 let mode = fileMode st
283 if (groupWriteMode == (mode `intersectFileModes` groupWriteMode))
284 || (otherWriteMode == (mode `intersectFileModes` otherWriteMode))
286 putStrLn $ "*** WARNING: " ++ name ++
287 " is writable by someone else, IGNORING!"
292 fileLoop :: Handle -> Bool -> GHCi ()
293 fileLoop hdl prompt = do
294 cmstate <- getCmState
295 (mod,imports) <- io (cmGetContext cmstate)
296 when prompt (io (putStr (mkPrompt mod imports)))
297 l <- io (IO.try (hGetLine hdl))
299 Left e | isEOFError e -> return ()
300 | otherwise -> io (ioError e)
302 case remove_spaces l of
303 "" -> fileLoop hdl prompt
304 l -> do quit <- runCommand l
305 if quit then return () else fileLoop hdl prompt
307 stringLoop :: [String] -> GHCi ()
308 stringLoop [] = return ()
309 stringLoop (s:ss) = do
310 case remove_spaces s of
312 l -> do quit <- runCommand l
313 if quit then return () else stringLoop ss
315 mkPrompt toplevs exports
316 = concat (intersperse " " (map ('*':) toplevs ++ exports)) ++ "> "
318 #if HAVE_READLINE_HEADERS && HAVE_READLINE_LIBS
319 readlineLoop :: GHCi ()
321 cmstate <- getCmState
322 (mod,imports) <- io (cmGetContext cmstate)
324 l <- io (readline (mkPrompt mod imports)
325 `finally` setNonBlockingFD 0)
326 -- readline sometimes puts stdin into blocking mode,
327 -- so we need to put it back for the IO library
331 case remove_spaces l of
336 if quit then return () else readlineLoop
339 runCommand :: String -> GHCi Bool
340 runCommand c = ghciHandle handler (doCommand c)
342 -- This is the exception handler for exceptions generated by the
343 -- user's code; it normally just prints out the exception. The
344 -- handler must be recursive, in case showing the exception causes
345 -- more exceptions to be raised.
347 -- Bugfix: if the user closed stdout or stderr, the flushing will fail,
348 -- raising another exception. We therefore don't put the recursive
349 -- handler arond the flushing operation, so if stderr is closed
350 -- GHCi will just die gracefully rather than going into an infinite loop.
351 handler :: Exception -> GHCi Bool
352 handler exception = do
354 io installSignalHandlers
355 ghciHandle handler (showException exception >> return False)
357 showException (DynException dyn) =
358 case fromDynamic dyn of
359 Nothing -> io (putStrLn ("*** Exception: (unknown)"))
360 Just Interrupted -> io (putStrLn "Interrupted.")
361 Just (CmdLineError s) -> io (putStrLn s) -- omit the location for CmdLineError
362 Just ph@PhaseFailed{} -> io (putStrLn (showGhcException ph "")) -- ditto
363 Just other_ghc_ex -> io (print other_ghc_ex)
365 showException other_exception
366 = io (putStrLn ("*** Exception: " ++ show other_exception))
368 doCommand (':' : command) = specialCommand command
370 = do timeIt (do nms <- runStmt stmt; finishEvalExpr nms)
373 runStmt :: String -> GHCi [Name]
375 | null (filter (not.isSpace) stmt) = return []
377 = do st <- getGHCiState
378 dflags <- io getDynFlags
379 let cm_state' = cmSetDFlags (cmstate st)
380 (dopt_unset dflags Opt_WarnUnusedBinds)
381 (new_cmstate, result) <-
382 io $ withProgName (progname st) $ withArgs (args st) $
383 cmRunStmt cm_state' stmt
384 setGHCiState st{cmstate = new_cmstate}
386 CmRunFailed -> return []
387 CmRunException e -> showException e >> return []
388 CmRunOk names -> return names
390 -- possibly print the type and revert CAFs after evaluating an expression
392 = do b <- isOptionSet ShowType
393 cmstate <- getCmState
394 when b (mapM_ (showTypeOfName cmstate) names)
397 io installSignalHandlers
398 b <- isOptionSet RevertCAFs
399 io (when b revertCAFs)
402 showTypeOfName :: CmState -> Name -> GHCi ()
403 showTypeOfName cmstate n
404 = do maybe_str <- io (cmTypeOfName cmstate n)
407 Just str -> io (putStrLn (showSDoc (ppr n) ++ " :: " ++ str))
409 specialCommand :: String -> GHCi Bool
410 specialCommand ('!':str) = shellEscape (dropWhile isSpace str)
411 specialCommand str = do
412 let (cmd,rest) = break isSpace str
413 cmds <- io (readIORef commands)
414 case [ (s,f) | (s,f) <- cmds, prefixMatch cmd s ] of
415 [] -> io (hPutStr stdout ("unknown command `:" ++ cmd ++ "'\n"
416 ++ shortHelpText) >> return False)
417 [(_,f)] -> f (dropWhile isSpace rest)
418 cs -> io (hPutStrLn stdout ("prefix " ++ cmd ++
419 " matches multiple commands (" ++
420 foldr1 (\a b -> a ++ ',':b) (map fst cs)
421 ++ ")") >> return False)
423 noArgs c = throwDyn (CmdLineError ("command `" ++ c ++ "' takes no arguments"))
426 -----------------------------------------------------------------------------
427 -- To flush buffers for the *interpreted* computation we need
428 -- to refer to *its* stdout/stderr handles
430 GLOBAL_VAR(flush_interp, error "no flush_interp", IO ())
431 GLOBAL_VAR(turn_off_buffering, error "no flush_stdout", IO ())
433 no_buf_cmd = "IO.hSetBuffering IO.stdout IO.NoBuffering" ++
434 " Prelude.>> IO.hSetBuffering IO.stderr IO.NoBuffering"
435 flush_cmd = "IO.hFlush IO.stdout Prelude.>> IO.hFlush IO.stderr"
437 initInterpBuffering :: CmState -> IO ()
438 initInterpBuffering cmstate
439 = do maybe_hval <- cmCompileExpr cmstate no_buf_cmd
442 Just hval -> writeIORef turn_off_buffering (unsafeCoerce# hval :: IO ())
443 other -> panic "interactiveUI:setBuffering"
445 maybe_hval <- cmCompileExpr cmstate flush_cmd
447 Just hval -> writeIORef flush_interp (unsafeCoerce# hval :: IO ())
448 _ -> panic "interactiveUI:flush"
450 turnOffBuffering -- Turn it off right now
455 flushInterpBuffers :: GHCi ()
457 = io $ do Monad.join (readIORef flush_interp)
460 turnOffBuffering :: IO ()
462 = do Monad.join (readIORef turn_off_buffering)
465 -----------------------------------------------------------------------------
468 help :: String -> GHCi ()
469 help _ = io (putStr helpText)
471 info :: String -> GHCi ()
472 info "" = throwDyn (CmdLineError "syntax: `:i <thing-you-want-info-about>'")
475 init_cms <- getCmState
477 infoThings cms [] = return cms
478 infoThings cms (name:names) = do
479 stuff <- io (cmInfoThing cms name)
480 io (putStrLn (showSDocForUser unqual (
481 vcat (intersperse (text "") (map showThing stuff))))
485 unqual = cmGetPrintUnqual init_cms
487 showThing (decl, fixity)
488 = vcat [ text "-- " <> showTyThing decl,
489 showFixity fixity (ifName decl),
493 | fix == defaultFixity = empty
494 | otherwise = ppr fix <+>
497 else char '`' <> ppr name <> char '`')
499 showTyThing decl = ppr decl
502 showTyThing (AClass cl)
503 = hcat [ppr cl, text " is a class", showSrcLoc (className cl)]
504 showTyThing (ADataCon dc)
505 = hcat [ppr dc, text " is a data constructor", showSrcLoc (dataConName dc)]
506 showTyThing (ATyCon ty)
508 = hcat [ppr ty, text " is a primitive type constructor"]
510 = hcat [ppr ty, text " is a type constructor", showSrcLoc (tyConName ty)]
511 showTyThing (AnId id)
512 = hcat [ppr id, text " is a ", idDescr id, showSrcLoc (idName id)]
515 = case globalIdDetails id of
516 RecordSelId lbl -> text "record selector for type" <+> ppr (fieldLabelTyCon lbl)
517 ClassOpId cls -> text "method in class" <+> ppr cls
518 otherwise -> text "variable"
520 -- also print out the source location for home things
522 | isHomePackageName name && isGoodSrcLoc loc
523 = hsep [ text ", defined at", ppr loc ]
526 where loc = nameSrcLoc name
529 infoThings init_cms names
532 addModule :: [FilePath] -> GHCi ()
534 state <- getGHCiState
535 io (revertCAFs) -- always revert CAFs on load/add.
536 files <- mapM expandPath files
537 let new_targets = files ++ targets state
538 graph <- io (cmDepAnal (cmstate state) new_targets)
539 (cmstate1, ok, mods) <- io (cmLoadModules (cmstate state) graph)
540 setGHCiState state{ cmstate = cmstate1, targets = new_targets }
541 setContextAfterLoad mods
542 dflags <- io getDynFlags
543 modulesLoadedMsg ok mods dflags
545 changeDirectory :: String -> GHCi ()
546 changeDirectory dir = do
547 state <- getGHCiState
548 when (targets state /= []) $
549 io $ putStr "Warning: changing directory causes all loaded modules to be unloaded, \n\
550 \because the search path has changed.\n"
551 cmstate1 <- io (cmUnload (cmstate state))
552 setGHCiState state{ cmstate = cmstate1, targets = [] }
553 setContextAfterLoad []
554 dir <- expandPath dir
555 io (setCurrentDirectory dir)
557 defineMacro :: String -> GHCi ()
559 let (macro_name, definition) = break isSpace s
560 cmds <- io (readIORef commands)
562 then throwDyn (CmdLineError "invalid macro name")
564 if (macro_name `elem` map fst cmds)
565 then throwDyn (CmdLineError
566 ("command `" ++ macro_name ++ "' is already defined"))
569 -- give the expression a type signature, so we can be sure we're getting
570 -- something of the right type.
571 let new_expr = '(' : definition ++ ") :: String -> IO String"
573 -- compile the expression
575 maybe_hv <- io (cmCompileExpr cms new_expr)
578 Just hv -> io (writeIORef commands --
579 ((macro_name, keepGoing (runMacro hv)) : cmds))
581 runMacro :: HValue{-String -> IO String-} -> String -> GHCi ()
583 str <- io ((unsafeCoerce# fun :: String -> IO String) s)
584 stringLoop (lines str)
586 undefineMacro :: String -> GHCi ()
587 undefineMacro macro_name = do
588 cmds <- io (readIORef commands)
589 if (macro_name `elem` map fst builtin_commands)
590 then throwDyn (CmdLineError
591 ("command `" ++ macro_name ++ "' cannot be undefined"))
593 if (macro_name `notElem` map fst cmds)
594 then throwDyn (CmdLineError
595 ("command `" ++ macro_name ++ "' not defined"))
597 io (writeIORef commands (filter ((/= macro_name) . fst) cmds))
600 loadModule :: [FilePath] -> GHCi ()
601 loadModule fs = timeIt (loadModule' fs)
603 loadModule' :: [FilePath] -> GHCi ()
604 loadModule' files = do
605 state <- getGHCiState
608 files <- mapM expandPath files
610 -- do the dependency anal first, so that if it fails we don't throw
611 -- away the current set of modules.
612 graph <- io (cmDepAnal (cmstate state) files)
614 -- Dependency anal ok, now unload everything
615 cmstate1 <- io (cmUnload (cmstate state))
616 setGHCiState state{ cmstate = cmstate1, targets = [] }
618 io (revertCAFs) -- always revert CAFs on load.
619 (cmstate2, ok, mods) <- io (cmLoadModules cmstate1 graph)
620 setGHCiState state{ cmstate = cmstate2, targets = files }
622 setContextAfterLoad mods
623 dflags <- io (getDynFlags)
624 modulesLoadedMsg ok mods dflags
627 reloadModule :: String -> GHCi ()
629 state <- getGHCiState
630 case targets state of
631 [] -> io (putStr "no current target\n")
633 -- do the dependency anal first, so that if it fails we don't throw
634 -- away the current set of modules.
635 graph <- io (cmDepAnal (cmstate state) paths)
637 io (revertCAFs) -- always revert CAFs on reload.
639 <- io (cmLoadModules (cmstate state) graph)
640 setGHCiState state{ cmstate=cmstate1 }
641 setContextAfterLoad mods
642 dflags <- io getDynFlags
643 modulesLoadedMsg ok mods dflags
645 reloadModule _ = noArgs ":reload"
647 setContextAfterLoad [] = setContext prel
648 setContextAfterLoad (m:_) = do
649 cmstate <- getCmState
650 b <- io (cmModuleIsInterpreted cmstate m)
651 if b then setContext ('*':m) else setContext m
653 modulesLoadedMsg ok mods dflags =
654 when (verbosity dflags > 0) $ do
656 | null mods = text "none."
658 punctuate comma (map text mods)) <> text "."
661 io (putStrLn (showSDoc (text "Failed, modules loaded: " <> mod_commas)))
663 io (putStrLn (showSDoc (text "Ok, modules loaded: " <> mod_commas)))
666 typeOfExpr :: String -> GHCi ()
668 = do cms <- getCmState
669 maybe_tystr <- io (cmTypeOfExpr cms str)
672 Just tystr -> io (putStrLn tystr)
674 kindOfType :: String -> GHCi ()
676 = do cms <- getCmState
677 maybe_tystr <- io (cmKindOfType cms str)
680 Just tystr -> io (putStrLn tystr)
682 quit :: String -> GHCi Bool
685 shellEscape :: String -> GHCi Bool
686 shellEscape str = io (system str >> return False)
688 -----------------------------------------------------------------------------
689 -- Browsing a module's contents
691 browseCmd :: String -> GHCi ()
694 ['*':m] | looksLikeModuleName m -> browseModule m False
695 [m] | looksLikeModuleName m -> browseModule m True
696 _ -> throwDyn (CmdLineError "syntax: :browse <module>")
698 browseModule m exports_only = do
701 is_interpreted <- io (cmModuleIsInterpreted cms m)
702 when (not is_interpreted && not exports_only) $
703 throwDyn (CmdLineError ("module `" ++ m ++ "' is not interpreted"))
705 -- Temporarily set the context to the module we're interested in,
706 -- just so we can get an appropriate PrintUnqualified
707 (as,bs) <- io (cmGetContext cms)
708 cms1 <- io (if exports_only then cmSetContext cms [] [prel,m]
709 else cmSetContext cms [m] [])
710 cms2 <- io (cmSetContext cms1 as bs)
712 things <- io (cmBrowseModule cms2 m exports_only)
714 let unqual = cmGetPrintUnqual cms1 -- NOTE: cms1 with the new context
716 io (putStrLn (showSDocForUser unqual (
717 vcat (map ppr things)
720 -----------------------------------------------------------------------------
721 -- Setting the module context
724 | all sensible mods = fn mods
725 | otherwise = throwDyn (CmdLineError "syntax: :module [+/-] [*]M1 ... [*]Mn")
727 (fn, mods) = case str of
728 '+':stuff -> (addToContext, words stuff)
729 '-':stuff -> (removeFromContext, words stuff)
730 stuff -> (newContext, words stuff)
732 sensible ('*':m) = looksLikeModuleName m
733 sensible m = looksLikeModuleName m
737 (as,bs) <- separate cms mods [] []
738 let bs' = if null as && prel `notElem` bs then prel:bs else bs
739 cms' <- io (cmSetContext cms as bs')
742 separate cmstate [] as bs = return (as,bs)
743 separate cmstate (('*':m):ms) as bs = do
744 b <- io (cmModuleIsInterpreted cmstate m)
745 if b then separate cmstate ms (m:as) bs
746 else throwDyn (CmdLineError ("module `" ++ m ++ "' is not interpreted"))
747 separate cmstate (m:ms) as bs = separate cmstate ms as (m:bs)
752 addToContext mods = do
754 (as,bs) <- io (cmGetContext cms)
756 (as',bs') <- separate cms mods [] []
758 let as_to_add = as' \\ (as ++ bs)
759 bs_to_add = bs' \\ (as ++ bs)
761 cms' <- io (cmSetContext cms
762 (as ++ as_to_add) (bs ++ bs_to_add))
766 removeFromContext mods = do
768 (as,bs) <- io (cmGetContext cms)
770 (as_to_remove,bs_to_remove) <- separate cms mods [] []
772 let as' = as \\ (as_to_remove ++ bs_to_remove)
773 bs' = bs \\ (as_to_remove ++ bs_to_remove)
775 cms' <- io (cmSetContext cms as' bs')
778 ----------------------------------------------------------------------------
781 -- set options in the interpreter. Syntax is exactly the same as the
782 -- ghc command line, except that certain options aren't available (-C,
785 -- This is pretty fragile: most options won't work as expected. ToDo:
786 -- figure out which ones & disallow them.
788 setCmd :: String -> GHCi ()
790 = do st <- getGHCiState
791 let opts = options st
792 io $ putStrLn (showSDoc (
793 text "options currently set: " <>
796 else hsep (map (\o -> char '+' <> text (optToStr o)) opts)
800 ("args":args) -> setArgs args
801 ("prog":prog) -> setProg prog
802 wds -> setOptions wds
806 setGHCiState st{ args = args }
810 setGHCiState st{ progname = prog }
812 io (hPutStrLn stderr "syntax: :set prog <progname>")
815 do -- first, deal with the GHCi opts (+s, +t, etc.)
816 let (plus_opts, minus_opts) = partition isPlus wds
817 mapM_ setOpt plus_opts
819 -- now, the GHC flags
820 pkgs_before <- io (readIORef v_ExplicitPackages)
821 leftovers <- io (processArgs static_flags minus_opts [])
822 pkgs_after <- io (readIORef v_ExplicitPackages)
824 -- update things if the users wants more packages
825 let new_packages = pkgs_after \\ pkgs_before
826 when (not (null new_packages)) $
827 newPackages new_packages
829 -- don't forget about the extra command-line flags from the
830 -- extra_ghc_opts fields in the new packages
831 new_package_details <- io (getPackageDetails new_packages)
832 let pkg_extra_opts = concatMap extra_ghc_opts new_package_details
833 pkg_extra_dyn <- io (processArgs static_flags pkg_extra_opts [])
835 -- then, dynamic flags
838 leftovers <- processArgs dynamic_flags (leftovers ++ pkg_extra_dyn) []
841 if (not (null leftovers))
842 then throwDyn (CmdLineError ("unrecognised flags: " ++
847 unsetOptions :: String -> GHCi ()
849 = do -- first, deal with the GHCi opts (+s, +t, etc.)
851 (minus_opts, rest1) = partition isMinus opts
852 (plus_opts, rest2) = partition isPlus rest1
854 if (not (null rest2))
855 then io (putStrLn ("unknown option: `" ++ head rest2 ++ "'"))
858 mapM_ unsetOpt plus_opts
860 -- can't do GHC flags for now
861 if (not (null minus_opts))
862 then throwDyn (CmdLineError "can't unset GHC command-line flags")
865 isMinus ('-':s) = True
868 isPlus ('+':s) = True
872 = case strToGHCiOpt str of
873 Nothing -> io (putStrLn ("unknown option: `" ++ str ++ "'"))
874 Just o -> setOption o
877 = case strToGHCiOpt str of
878 Nothing -> io (putStrLn ("unknown option: `" ++ str ++ "'"))
879 Just o -> unsetOption o
881 strToGHCiOpt :: String -> (Maybe GHCiOption)
882 strToGHCiOpt "s" = Just ShowTiming
883 strToGHCiOpt "t" = Just ShowType
884 strToGHCiOpt "r" = Just RevertCAFs
885 strToGHCiOpt _ = Nothing
887 optToStr :: GHCiOption -> String
888 optToStr ShowTiming = "s"
889 optToStr ShowType = "t"
890 optToStr RevertCAFs = "r"
892 newPackages new_pkgs = do -- The new packages are already in v_Packages
893 state <- getGHCiState
894 cmstate1 <- io (cmUnload (cmstate state))
895 setGHCiState state{ cmstate = cmstate1, targets = [] }
896 dflags <- io getDynFlags
897 io (linkPackages dflags new_pkgs)
898 setContextAfterLoad []
900 -- ---------------------------------------------------------------------------
905 ["modules" ] -> showModules
906 ["bindings"] -> showBindings
907 ["linker"] -> io showLinkerState
908 _ -> throwDyn (CmdLineError "syntax: :show [modules|bindings]")
912 let (mg, hpt) = cmGetModInfo cms
913 mapM_ (showModule hpt) mg
916 showModule :: HomePackageTable -> ModSummary -> GHCi ()
917 showModule hpt mod_summary
918 = case lookupModuleEnv hpt mod of
919 Nothing -> panic "missing linkable"
920 Just mod_info -> io (putStrLn (showModMsg obj_linkable mod locn))
922 obj_linkable = isObjectLinkable (hm_linkable mod_info)
924 mod = ms_mod mod_summary
925 locn = ms_location mod_summary
930 unqual = cmGetPrintUnqual cms
931 -- showBinding b = putStrLn (showSDocForUser unqual (ppr (ifaceTyThing b)))
932 showBinding b = putStrLn (showSDocForUser unqual (ppr (getName b)))
934 io (mapM_ showBinding (cmGetBindings cms))
938 -----------------------------------------------------------------------------
941 data GHCiState = GHCiState
945 targets :: [FilePath],
947 options :: [GHCiOption]
951 = ShowTiming -- show time/allocs after evaluation
952 | ShowType -- show the type of expressions
953 | RevertCAFs -- revert CAFs after every evaluation
956 newtype GHCi a = GHCi { unGHCi :: IORef GHCiState -> IO a }
958 startGHCi :: GHCi a -> GHCiState -> IO a
959 startGHCi g state = do ref <- newIORef state; unGHCi g ref
961 instance Monad GHCi where
962 (GHCi m) >>= k = GHCi $ \s -> m s >>= \a -> unGHCi (k a) s
963 return a = GHCi $ \s -> return a
965 ghciHandleDyn :: Typeable t => (t -> GHCi a) -> GHCi a -> GHCi a
966 ghciHandleDyn h (GHCi m) = GHCi $ \s ->
967 Exception.catchDyn (m s) (\e -> unGHCi (h e) s)
969 getGHCiState = GHCi $ \r -> readIORef r
970 setGHCiState s = GHCi $ \r -> writeIORef r s
972 -- for convenience...
973 getCmState = getGHCiState >>= return . cmstate
974 setCmState cms = do s <- getGHCiState; setGHCiState s{cmstate=cms}
976 isOptionSet :: GHCiOption -> GHCi Bool
978 = do st <- getGHCiState
979 return (opt `elem` options st)
981 setOption :: GHCiOption -> GHCi ()
983 = do st <- getGHCiState
984 setGHCiState (st{ options = opt : filter (/= opt) (options st) })
986 unsetOption :: GHCiOption -> GHCi ()
988 = do st <- getGHCiState
989 setGHCiState (st{ options = filter (/= opt) (options st) })
992 io m = GHCi { unGHCi = \s -> m >>= return }
994 -----------------------------------------------------------------------------
995 -- recursive exception handlers
997 -- Don't forget to unblock async exceptions in the handler, or if we're
998 -- in an exception loop (eg. let a = error a in a) the ^C exception
999 -- may never be delivered. Thanks to Marcin for pointing out the bug.
1001 ghciHandle :: (Exception -> GHCi a) -> GHCi a -> GHCi a
1002 ghciHandle h (GHCi m) = GHCi $ \s ->
1003 Exception.catch (m s)
1004 (\e -> unGHCi (ghciUnblock (h e)) s)
1006 ghciUnblock :: GHCi a -> GHCi a
1007 ghciUnblock (GHCi a) = GHCi $ \s -> Exception.unblock (a s)
1009 -----------------------------------------------------------------------------
1010 -- timing & statistics
1012 timeIt :: GHCi a -> GHCi a
1014 = do b <- isOptionSet ShowTiming
1017 else do allocs1 <- io $ getAllocations
1018 time1 <- io $ getCPUTime
1020 allocs2 <- io $ getAllocations
1021 time2 <- io $ getCPUTime
1022 io $ printTimes (fromIntegral (allocs2 - allocs1))
1026 foreign import ccall unsafe "getAllocations" getAllocations :: IO Int64
1027 -- defined in ghc/rts/Stats.c
1029 printTimes :: Integer -> Integer -> IO ()
1030 printTimes allocs psecs
1031 = do let secs = (fromIntegral psecs / (10^12)) :: Float
1032 secs_str = showFFloat (Just 2) secs
1033 putStrLn (showSDoc (
1034 parens (text (secs_str "") <+> text "secs" <> comma <+>
1035 text (show allocs) <+> text "bytes")))
1037 -----------------------------------------------------------------------------
1044 -- Have to turn off buffering again, because we just
1045 -- reverted stdout, stderr & stdin to their defaults.
1047 foreign import ccall "revertCAFs" rts_revertCAFs :: IO ()
1048 -- Make it "safe", just in case
1050 -- -----------------------------------------------------------------------------
1053 expandPath :: String -> GHCi String
1055 case dropWhile isSpace path of
1057 tilde <- io (getEnv "HOME") -- will fail if HOME not defined
1058 return (tilde ++ '/':d)