1 {-# OPTIONS -#include "Linker.h" -#include "SchedAPI.h" #-}
2 -----------------------------------------------------------------------------
3 -- $Id: InteractiveUI.hs,v 1.137 2002/10/17 14:49:52 simonmar Exp $
5 -- GHC Interactive User Interface
7 -- (c) The GHC Team 2000
9 -----------------------------------------------------------------------------
10 module InteractiveUI (
11 interactiveUI, -- :: CmState -> [FilePath] -> [LibrarySpec] -> IO ()
15 #include "../includes/config.h"
16 #include "HsVersions.h"
19 import HscTypes ( TyThing(..), HomeModInfo(hm_linkable), HomePackageTable,
21 import HsSyn ( TyClDecl(..), ConDecl(..), Sig(..) )
22 import MkIface ( ifaceTyThing )
25 import DriverUtil ( remove_spaces, handle )
26 import Linker ( initLinker, showLinkerState, linkLibraries )
27 import Finder ( flushFinderCache )
29 import Id ( isRecordSelector, recordSelectorFieldLabel,
30 isDataConWrapId, isDataConId, idName )
31 import Class ( className )
32 import TyCon ( tyConName, tyConClass_maybe, isPrimTyCon, DataConDetails(..) )
33 import FieldLabel ( fieldLabelTyCon )
34 import SrcLoc ( isGoodSrcLoc )
35 import Module ( showModMsg, lookupModuleEnv )
36 import Name ( Name, isHomePackageName, nameSrcLoc, nameOccName,
38 import OccName ( isSymOcc )
39 import BasicTypes ( defaultFixity, SuccessFlag(..) )
42 import CmdLineOpts ( DynFlag(..), DynFlags(..), getDynFlags, saveDynFlags,
43 restoreDynFlags, dopt_unset )
44 import Panic ( GhcException(..), showGhcException )
47 #ifndef mingw32_TARGET_OS
51 #if HAVE_READLINE_HEADERS && HAVE_READLINE_LIBS
52 import Control.Concurrent ( yield ) -- Used in readline loop
53 import System.Console.Readline as Readline
58 import Control.Exception as Exception
60 import Control.Concurrent
66 import System.Environment
67 import System.Directory
68 import System.IO as IO
70 import Control.Monad as Monad
72 import GHC.Exts ( unsafeCoerce# )
74 import Foreign ( nullPtr )
75 import Foreign.C.String ( CString, peekCString, withCString )
76 import Data.IORef ( IORef, newIORef, readIORef, writeIORef )
78 import GHC.Posix ( setNonBlockingFD )
80 -----------------------------------------------------------------------------
84 \ / _ \\ /\\ /\\/ __(_)\n\
85 \ / /_\\// /_/ / / | | GHC Interactive, version " ++ cProjectVersion ++ ", for Haskell 98.\n\
86 \/ /_\\\\/ __ / /___| | http://www.haskell.org/ghc/\n\
87 \\\____/\\/ /_/\\____/|_| Type :? for help.\n"
89 GLOBAL_VAR(commands, builtin_commands, [(String, String -> GHCi Bool)])
91 builtin_commands :: [(String, String -> GHCi Bool)]
93 ("add", keepGoing addModule),
94 ("browse", keepGoing browseCmd),
95 ("cd", keepGoing changeDirectory),
96 ("def", keepGoing defineMacro),
97 ("help", keepGoing help),
98 ("?", keepGoing help),
99 ("info", keepGoing info),
100 ("load", keepGoing loadModule),
101 ("module", keepGoing setContext),
102 ("reload", keepGoing reloadModule),
103 ("set", keepGoing setCmd),
104 ("show", keepGoing showCmd),
105 ("type", keepGoing typeOfExpr),
106 ("unset", keepGoing unsetOptions),
107 ("undef", keepGoing undefineMacro),
111 keepGoing :: (String -> GHCi ()) -> (String -> GHCi Bool)
112 keepGoing a str = a str >> return False
114 shortHelpText = "use :? for help.\n"
116 -- NOTE: spaces at the end of each line to workaround CPP/string gap bug.
118 \ Commands available from the prompt:\n\
120 \ <stmt> evaluate/run <stmt>\n\
121 \ :add <filename> ... add module(s) to the current target set\n\
122 \ :browse [*]<module> display the names defined by <module>\n\
123 \ :cd <dir> change directory to <dir>\n\
124 \ :def <cmd> <expr> define a command :<cmd>\n\
125 \ :help, :? display this list of commands\n\
126 \ :info [<name> ...] display information about the given names\n\
127 \ :load <filename> ... load module(s) and their dependents\n\
128 \ :module [+/-] [*]<mod> ... set the context for expression evaluation\n\
129 \ :reload reload the current module set\n\
131 \ :set <option> ... set options\n\
132 \ :set args <arg> ... set the arguments returned by System.getArgs\n\
133 \ :set prog <progname> set the value returned by System.getProgName\n\
135 \ :show modules show the currently loaded modules\n\
136 \ :show bindings show the current bindings made at the prompt\n\
138 \ :type <expr> show the type of <expr>\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 :: CmState -> [FilePath] -> [FilePath] -> IO ()
154 interactiveUI cmstate paths cmdline_objs = do
156 hSetBuffering stdout NoBuffering
158 dflags <- getDynFlags
160 -- packages are loaded "on-demand" now
162 linkLibraries dflags cmdline_objs
164 -- Initialise buffering for the *interpreted* I/O system
165 cmstate <- initInterpBuffering cmstate dflags
167 -- We don't want the cmd line to buffer any input that might be
168 -- intended for the program, so unbuffer stdin.
169 hSetBuffering stdin NoBuffering
171 -- initial context is just the Prelude
172 cmstate <- cmSetContext cmstate dflags [] ["Prelude"]
174 #if HAVE_READLINE_HEADERS && HAVE_READLINE_LIBS
178 startGHCi (runGHCi paths dflags)
179 GHCiState{ progname = "<interactive>",
185 #if HAVE_READLINE_HEADERS && HAVE_READLINE_LIBS
186 Readline.resetTerminal Nothing
191 runGHCi :: [FilePath] -> DynFlags -> GHCi ()
192 runGHCi paths dflags = do
193 read_dot_files <- io (readIORef v_Read_DotGHCi)
195 when (read_dot_files) $ do
198 exists <- io (doesFileExist file)
200 dir_ok <- io (checkPerms ".")
201 file_ok <- io (checkPerms file)
202 when (dir_ok && file_ok) $ do
203 either_hdl <- io (IO.try (openFile "./.ghci" ReadMode))
206 Right hdl -> fileLoop hdl False
208 when (read_dot_files) $ do
209 -- Read in $HOME/.ghci
210 either_dir <- io (IO.try (getEnv "HOME"))
214 cwd <- io (getCurrentDirectory)
215 when (dir /= cwd) $ do
216 let file = dir ++ "/.ghci"
217 ok <- io (checkPerms file)
219 either_hdl <- io (IO.try (openFile file ReadMode))
222 Right hdl -> fileLoop hdl False
224 -- perform a :load for files given on the GHCi command line
225 when (not (null paths)) $
226 ghciHandle showException $
227 loadModule (unwords paths)
229 -- enter the interactive loop
230 #if defined(mingw32_TARGET_OS)
231 -- always show prompt, since hIsTerminalDevice returns True for Consoles
232 -- only, which we may or may not be running under (cf. Emacs sub-shells.)
235 is_tty <- io (hIsTerminalDevice stdin)
236 interactiveLoop is_tty
240 io $ do when (verbosity dflags > 0) $ putStrLn "Leaving GHCi."
243 interactiveLoop is_tty = do
244 -- ignore ^C exceptions caught here
245 ghciHandleDyn (\e -> case e of
246 Interrupted -> ghciUnblock (interactiveLoop is_tty)
247 _other -> return ()) $ do
249 -- read commands from stdin
250 #if HAVE_READLINE_HEADERS && HAVE_READLINE_LIBS
253 else fileLoop stdin False -- turn off prompt for non-TTY input
255 fileLoop stdin is_tty
259 -- NOTE: We only read .ghci files if they are owned by the current user,
260 -- and aren't world writable. Otherwise, we could be accidentally
261 -- running code planted by a malicious third party.
263 -- Furthermore, We only read ./.ghci if . is owned by the current user
264 -- and isn't writable by anyone else. I think this is sufficient: we
265 -- don't need to check .. and ../.. etc. because "." always refers to
266 -- the same directory while a process is running.
268 checkPerms :: String -> IO Bool
270 #ifdef mingw32_TARGET_OS
273 DriverUtil.handle (\_ -> return False) $ do
274 st <- getFileStatus name
276 if fileOwner st /= me then do
277 putStrLn $ "WARNING: " ++ name ++ " is owned by someone else, IGNORING!"
280 let mode = fileMode st
281 if (groupWriteMode == (mode `intersectFileModes` groupWriteMode))
282 || (otherWriteMode == (mode `intersectFileModes` otherWriteMode))
284 putStrLn $ "*** WARNING: " ++ name ++
285 " is writable by someone else, IGNORING!"
290 fileLoop :: Handle -> Bool -> GHCi ()
291 fileLoop hdl prompt = do
292 cmstate <- getCmState
293 (mod,imports) <- io (cmGetContext cmstate)
294 when prompt (io (putStr (mkPrompt mod imports)))
295 l <- io (IO.try (hGetLine hdl))
297 Left e | isEOFError e -> return ()
298 | otherwise -> throw e
300 case remove_spaces l of
301 "" -> fileLoop hdl prompt
302 l -> do quit <- runCommand l
303 if quit then return () else fileLoop hdl prompt
305 stringLoop :: [String] -> GHCi ()
306 stringLoop [] = return ()
307 stringLoop (s:ss) = do
308 case remove_spaces s of
310 l -> do quit <- runCommand l
311 if quit then return () else stringLoop ss
313 mkPrompt toplevs exports
314 = concat (intersperse " " (map ('*':) toplevs ++ exports)) ++ "> "
316 #if HAVE_READLINE_HEADERS && HAVE_READLINE_LIBS
317 readlineLoop :: GHCi ()
319 cmstate <- getCmState
320 (mod,imports) <- io (cmGetContext cmstate)
322 l <- io (readline (mkPrompt mod imports)
323 `finally` setNonBlockingFD 0)
324 -- readline sometimes puts stdin into blocking mode,
325 -- so we need to put it back for the IO library
329 case remove_spaces l of
334 if quit then return () else readlineLoop
337 -- Top level exception handler, just prints out the exception
339 runCommand :: String -> GHCi Bool
341 ghciHandle ( \exception -> do
343 showException exception
348 showException (DynException dyn) =
349 case fromDynamic dyn of
350 Nothing -> io (putStrLn ("*** Exception: (unknown)"))
351 Just Interrupted -> io (putStrLn "Interrupted.")
352 Just (CmdLineError s) -> io (putStrLn s) -- omit the location for CmdLineError
353 Just ph@PhaseFailed{} -> io (putStrLn (showGhcException ph "")) -- ditto
354 Just other_ghc_ex -> io (print other_ghc_ex)
356 showException other_exception
357 = io (putStrLn ("*** Exception: " ++ show other_exception))
359 doCommand (':' : command) = specialCommand command
361 = do timeIt (do nms <- runStmt stmt; finishEvalExpr nms)
364 runStmt :: String -> GHCi [Name]
366 | null (filter (not.isSpace) stmt) = return []
368 = do st <- getGHCiState
369 dflags <- io getDynFlags
370 let dflags' = dopt_unset dflags Opt_WarnUnusedBinds
371 (new_cmstate, result) <-
372 io $ withProgName (progname st) $ withArgs (args st) $
373 cmRunStmt (cmstate st) dflags' stmt
374 setGHCiState st{cmstate = new_cmstate}
376 CmRunFailed -> return []
377 CmRunException e -> showException e >> return []
378 CmRunOk names -> return names
380 -- possibly print the type and revert CAFs after evaluating an expression
382 = do b <- isOptionSet ShowType
383 cmstate <- getCmState
384 when b (mapM_ (showTypeOfName cmstate) names)
387 b <- isOptionSet RevertCAFs
388 io (when b revertCAFs)
391 showTypeOfName :: CmState -> Name -> GHCi ()
392 showTypeOfName cmstate n
393 = do maybe_str <- io (cmTypeOfName cmstate n)
396 Just str -> io (putStrLn (showSDoc (ppr n) ++ " :: " ++ str))
398 specialCommand :: String -> GHCi Bool
399 specialCommand ('!':str) = shellEscape (dropWhile isSpace str)
400 specialCommand str = do
401 let (cmd,rest) = break isSpace str
402 cmds <- io (readIORef commands)
403 case [ (s,f) | (s,f) <- cmds, prefixMatch cmd s ] of
404 [] -> io (hPutStr stdout ("unknown command `:" ++ cmd ++ "'\n"
405 ++ shortHelpText) >> return False)
406 [(_,f)] -> f (dropWhile isSpace rest)
407 cs -> io (hPutStrLn stdout ("prefix " ++ cmd ++
408 " matches multiple commands (" ++
409 foldr1 (\a b -> a ++ ',':b) (map fst cs)
410 ++ ")") >> return False)
412 noArgs c = throwDyn (CmdLineError ("command `" ++ c ++ "' takes no arguments"))
415 -----------------------------------------------------------------------------
416 -- To flush buffers for the *interpreted* computation we need
417 -- to refer to *its* stdout/stderr handles
419 GLOBAL_VAR(flush_interp, error "no flush_interp", IO ())
420 GLOBAL_VAR(turn_off_buffering, error "no flush_stdout", IO ())
422 no_buf_cmd = "IO.hSetBuffering IO.stdout IO.NoBuffering" ++
423 " Prelude.>> IO.hSetBuffering IO.stderr IO.NoBuffering"
424 flush_cmd = "IO.hFlush IO.stdout Prelude.>> IO.hFlush IO.stderr"
426 initInterpBuffering :: CmState -> DynFlags -> IO CmState
427 initInterpBuffering cmstate dflags
428 = do (cmstate, maybe_hval) <- cmCompileExpr cmstate dflags no_buf_cmd
431 Just hval -> writeIORef turn_off_buffering (unsafeCoerce# hval :: IO ())
432 other -> panic "interactiveUI:setBuffering"
434 (cmstate, maybe_hval) <- cmCompileExpr cmstate dflags flush_cmd
436 Just hval -> writeIORef flush_interp (unsafeCoerce# hval :: IO ())
437 _ -> panic "interactiveUI:flush"
439 turnOffBuffering -- Turn it off right now
444 flushInterpBuffers :: GHCi ()
446 = io $ do Monad.join (readIORef flush_interp)
449 turnOffBuffering :: IO ()
451 = do Monad.join (readIORef turn_off_buffering)
454 -----------------------------------------------------------------------------
457 help :: String -> GHCi ()
458 help _ = io (putStr helpText)
460 info :: String -> GHCi ()
461 info "" = throwDyn (CmdLineError "syntax: `:i <thing-you-want-info-about>'")
464 init_cms <- getCmState
465 dflags <- io getDynFlags
467 infoThings cms [] = return cms
468 infoThings cms (name:names) = do
469 (cms, stuff) <- io (cmInfoThing cms dflags name)
470 io (putStrLn (showSDocForUser unqual (
471 vcat (intersperse (text "") (map showThing stuff))))
475 unqual = cmGetPrintUnqual init_cms
477 showThing (ty_thing, fixity)
478 = vcat [ text "-- " <> showTyThing ty_thing,
479 showFixity fixity (getName ty_thing),
480 ppr (ifaceTyThing ty_thing) ]
483 | fix == defaultFixity = empty
484 | otherwise = ppr fix <+>
485 (if isSymOcc (nameOccName name)
487 else char '`' <> ppr name <> char '`')
489 showTyThing (AClass cl)
490 = hcat [ppr cl, text " is a class", showSrcLoc (className cl)]
491 showTyThing (ATyCon ty)
493 = hcat [ppr ty, text " is a primitive type constructor"]
495 = hcat [ppr ty, text " is a type constructor", showSrcLoc (tyConName ty)]
496 showTyThing (AnId id)
497 = hcat [ppr id, text " is a ", idDescr id, showSrcLoc (idName id)]
500 | isRecordSelector id =
501 case tyConClass_maybe (fieldLabelTyCon (
502 recordSelectorFieldLabel id)) of
503 Nothing -> text "record selector"
504 Just c -> text "method in class " <> ppr c
505 | isDataConWrapId id = text "data constructor"
506 | otherwise = text "variable"
508 -- also print out the source location for home things
510 | isHomePackageName name && isGoodSrcLoc loc
511 = hsep [ text ", defined at", ppr loc ]
514 where loc = nameSrcLoc name
516 cms <- infoThings init_cms names
520 addModule :: String -> GHCi ()
522 let files = words str
523 state <- getGHCiState
524 dflags <- io (getDynFlags)
525 io (revertCAFs) -- always revert CAFs on load/add.
526 let new_targets = files ++ targets state
527 graph <- io (cmDepAnal (cmstate state) dflags new_targets)
528 (cmstate1, ok, mods) <- io (cmLoadModules (cmstate state) dflags graph)
529 setGHCiState state{ cmstate = cmstate1, targets = new_targets }
530 setContextAfterLoad mods
531 modulesLoadedMsg ok mods dflags
533 changeDirectory :: String -> GHCi ()
534 changeDirectory ('~':d) = do
535 tilde <- io (getEnv "HOME") -- will fail if HOME not defined
536 io (setCurrentDirectory (tilde ++ '/':d))
537 changeDirectory d = io (setCurrentDirectory d)
539 defineMacro :: String -> GHCi ()
541 let (macro_name, definition) = break isSpace s
542 cmds <- io (readIORef commands)
544 then throwDyn (CmdLineError "invalid macro name")
546 if (macro_name `elem` map fst cmds)
547 then throwDyn (CmdLineError
548 ("command `" ++ macro_name ++ "' is already defined"))
551 -- give the expression a type signature, so we can be sure we're getting
552 -- something of the right type.
553 let new_expr = '(' : definition ++ ") :: String -> IO String"
555 -- compile the expression
557 dflags <- io getDynFlags
558 (new_cmstate, maybe_hv) <- io (cmCompileExpr cms dflags new_expr)
559 setCmState new_cmstate
562 Just hv -> io (writeIORef commands --
563 ((macro_name, keepGoing (runMacro hv)) : cmds))
565 runMacro :: HValue{-String -> IO String-} -> String -> GHCi ()
567 str <- io ((unsafeCoerce# fun :: String -> IO String) s)
568 stringLoop (lines str)
570 undefineMacro :: String -> GHCi ()
571 undefineMacro macro_name = do
572 cmds <- io (readIORef commands)
573 if (macro_name `elem` map fst builtin_commands)
574 then throwDyn (CmdLineError
575 ("command `" ++ macro_name ++ "' cannot be undefined"))
577 if (macro_name `notElem` map fst cmds)
578 then throwDyn (CmdLineError
579 ("command `" ++ macro_name ++ "' not defined"))
581 io (writeIORef commands (filter ((/= macro_name) . fst) cmds))
584 loadModule :: String -> GHCi ()
585 loadModule str = timeIt (loadModule' str)
588 let files = words str
589 state <- getGHCiState
590 dflags <- io getDynFlags
592 -- do the dependency anal first, so that if it fails we don't throw
593 -- away the current set of modules.
594 graph <- io (cmDepAnal (cmstate state) dflags files)
596 -- Dependency anal ok, now unload everything
597 cmstate1 <- io (cmUnload (cmstate state) dflags)
598 setGHCiState state{ cmstate = cmstate1, targets = [] }
600 io (revertCAFs) -- always revert CAFs on load.
601 (cmstate2, ok, mods) <- io (cmLoadModules cmstate1 dflags graph)
602 setGHCiState state{ cmstate = cmstate2, targets = files }
604 setContextAfterLoad mods
605 modulesLoadedMsg ok mods dflags
608 reloadModule :: String -> GHCi ()
610 state <- getGHCiState
611 dflags <- io getDynFlags
612 case targets state of
613 [] -> io (putStr "no current target\n")
615 -- do the dependency anal first, so that if it fails we don't throw
616 -- away the current set of modules.
617 graph <- io (cmDepAnal (cmstate state) dflags paths)
619 io (revertCAFs) -- always revert CAFs on reload.
621 <- io (cmLoadModules (cmstate state) dflags graph)
622 setGHCiState state{ cmstate=cmstate1 }
623 setContextAfterLoad mods
624 modulesLoadedMsg ok mods dflags
626 reloadModule _ = noArgs ":reload"
628 setContextAfterLoad [] = setContext prel
629 setContextAfterLoad (m:_) = do
630 cmstate <- getCmState
631 b <- io (cmModuleIsInterpreted cmstate m)
632 if b then setContext ('*':m) else setContext m
634 modulesLoadedMsg ok mods dflags =
635 when (verbosity dflags > 0) $ do
637 | null mods = text "none."
639 punctuate comma (map text mods)) <> text "."
642 io (putStrLn (showSDoc (text "Failed, modules loaded: " <> mod_commas)))
644 io (putStrLn (showSDoc (text "Ok, modules loaded: " <> mod_commas)))
647 typeOfExpr :: String -> GHCi ()
649 = do cms <- getCmState
650 dflags <- io getDynFlags
651 (new_cmstate, maybe_tystr) <- io (cmTypeOfExpr cms dflags str)
652 setCmState new_cmstate
655 Just tystr -> io (putStrLn tystr)
657 quit :: String -> GHCi Bool
660 shellEscape :: String -> GHCi Bool
661 shellEscape str = io (system str >> return False)
663 -----------------------------------------------------------------------------
664 -- Browing a module's contents
666 browseCmd :: String -> GHCi ()
669 ['*':m] | looksLikeModuleName m -> browseModule m False
670 [m] | looksLikeModuleName m -> browseModule m True
671 _ -> throwDyn (CmdLineError "syntax: :browse <module>")
673 browseModule m exports_only = do
675 dflags <- io getDynFlags
677 is_interpreted <- io (cmModuleIsInterpreted cms m)
678 when (not is_interpreted && not exports_only) $
679 throwDyn (CmdLineError ("module `" ++ m ++ "' is not interpreted"))
681 -- temporarily set the context to the module we're interested in,
682 -- just so we can get an appropriate PrintUnqualified
683 (as,bs) <- io (cmGetContext cms)
684 cms1 <- io (if exports_only then cmSetContext cms dflags [] [prel,m]
685 else cmSetContext cms dflags [m] [])
686 cms2 <- io (cmSetContext cms1 dflags as bs)
688 (cms3, things) <- io (cmBrowseModule cms2 dflags m exports_only)
692 let unqual = cmGetPrintUnqual cms1 -- NOTE: cms1 with the new context
694 things' = filter wantToSee things
696 wantToSee (AnId id) = not (isDataConId id || isDataConWrapId id)
699 thing_names = map getName things
701 thingDecl thing@(AnId id) = ifaceTyThing thing
703 thingDecl thing@(AClass c) =
704 let rn_decl = ifaceTyThing thing in
706 ClassDecl { tcdSigs = cons } ->
707 rn_decl{ tcdSigs = filter methodIsVisible cons }
710 methodIsVisible (ClassOpSig n _ _ _) = n `elem` thing_names
712 thingDecl thing@(ATyCon t) =
713 let rn_decl = ifaceTyThing thing in
715 TyData { tcdCons = DataCons cons } ->
716 rn_decl{ tcdCons = DataCons (filter conIsVisible cons) }
719 conIsVisible (ConDecl n _ _ _ _) = n `elem` thing_names
721 io (putStrLn (showSDocForUser unqual (
722 vcat (map (ppr . thingDecl) things')))
727 -----------------------------------------------------------------------------
728 -- Setting the module context
731 | all sensible mods = fn mods
732 | otherwise = throwDyn (CmdLineError "syntax: :module [+/-] [*]M1 ... [*]Mn")
734 (fn, mods) = case str of
735 '+':stuff -> (addToContext, words stuff)
736 '-':stuff -> (removeFromContext, words stuff)
737 stuff -> (newContext, words stuff)
739 sensible ('*':m) = looksLikeModuleName m
740 sensible m = looksLikeModuleName m
744 dflags <- io getDynFlags
745 (as,bs) <- separate cms mods [] []
746 let bs' = if null as && prel `notElem` bs then prel:bs else bs
747 cms' <- io (cmSetContext cms dflags as bs')
750 separate cmstate [] as bs = return (as,bs)
751 separate cmstate (('*':m):ms) as bs = do
752 b <- io (cmModuleIsInterpreted cmstate m)
753 if b then separate cmstate ms (m:as) bs
754 else throwDyn (CmdLineError ("module `" ++ m ++ "' is not interpreted"))
755 separate cmstate (m:ms) as bs = separate cmstate ms as (m:bs)
760 addToContext mods = do
762 dflags <- io getDynFlags
763 (as,bs) <- io (cmGetContext cms)
765 (as',bs') <- separate cms mods [] []
767 let as_to_add = as' \\ (as ++ bs)
768 bs_to_add = bs' \\ (as ++ bs)
770 cms' <- io (cmSetContext cms dflags
771 (as ++ as_to_add) (bs ++ bs_to_add))
775 removeFromContext mods = do
777 dflags <- io getDynFlags
778 (as,bs) <- io (cmGetContext cms)
780 (as_to_remove,bs_to_remove) <- separate cms mods [] []
782 let as' = as \\ (as_to_remove ++ bs_to_remove)
783 bs' = bs \\ (as_to_remove ++ bs_to_remove)
785 cms' <- io (cmSetContext cms dflags as' bs')
788 ----------------------------------------------------------------------------
791 -- set options in the interpreter. Syntax is exactly the same as the
792 -- ghc command line, except that certain options aren't available (-C,
795 -- This is pretty fragile: most options won't work as expected. ToDo:
796 -- figure out which ones & disallow them.
798 setCmd :: String -> GHCi ()
800 = do st <- getGHCiState
801 let opts = options st
802 io $ putStrLn (showSDoc (
803 text "options currently set: " <>
806 else hsep (map (\o -> char '+' <> text (optToStr o)) opts)
810 ("args":args) -> setArgs args
811 ("prog":prog) -> setProg prog
812 wds -> setOptions wds
816 setGHCiState st{ args = args }
820 setGHCiState st{ progname = prog }
822 io (hPutStrLn stderr "syntax: :set prog <progname>")
825 do -- first, deal with the GHCi opts (+s, +t, etc.)
826 let (plus_opts, minus_opts) = partition isPlus wds
827 mapM_ setOpt plus_opts
829 -- now, the GHC flags
830 pkgs_before <- io (readIORef v_Packages)
831 leftovers <- io (processArgs static_flags minus_opts [])
832 pkgs_after <- io (readIORef v_Packages)
834 -- update things if the users wants more packages
835 let new_packages = pkgs_after \\ pkgs_before
836 when (not (null new_packages)) $
837 newPackages new_packages
839 -- don't forget about the extra command-line flags from the
840 -- extra_ghc_opts fields in the new packages
841 new_package_details <- io (getPackageDetails new_packages)
842 let pkg_extra_opts = concatMap extra_ghc_opts new_package_details
843 pkg_extra_dyn <- io (processArgs static_flags pkg_extra_opts [])
845 -- then, dynamic flags
848 leftovers <- processArgs dynamic_flags (leftovers ++ pkg_extra_dyn) []
851 if (not (null leftovers))
852 then throwDyn (CmdLineError ("unrecognised flags: " ++
857 unsetOptions :: String -> GHCi ()
859 = do -- first, deal with the GHCi opts (+s, +t, etc.)
861 (minus_opts, rest1) = partition isMinus opts
862 (plus_opts, rest2) = partition isPlus rest1
864 if (not (null rest2))
865 then io (putStrLn ("unknown option: `" ++ head rest2 ++ "'"))
868 mapM_ unsetOpt plus_opts
870 -- can't do GHC flags for now
871 if (not (null minus_opts))
872 then throwDyn (CmdLineError "can't unset GHC command-line flags")
875 isMinus ('-':s) = True
878 isPlus ('+':s) = True
882 = case strToGHCiOpt str of
883 Nothing -> io (putStrLn ("unknown option: `" ++ str ++ "'"))
884 Just o -> setOption o
887 = case strToGHCiOpt str of
888 Nothing -> io (putStrLn ("unknown option: `" ++ str ++ "'"))
889 Just o -> unsetOption o
891 strToGHCiOpt :: String -> (Maybe GHCiOption)
892 strToGHCiOpt "s" = Just ShowTiming
893 strToGHCiOpt "t" = Just ShowType
894 strToGHCiOpt "r" = Just RevertCAFs
895 strToGHCiOpt _ = Nothing
897 optToStr :: GHCiOption -> String
898 optToStr ShowTiming = "s"
899 optToStr ShowType = "t"
900 optToStr RevertCAFs = "r"
902 newPackages new_pkgs = do -- The new packages are already in v_Packages
903 state <- getGHCiState
904 dflags <- io getDynFlags
905 cmstate1 <- io (cmUnload (cmstate state) dflags)
906 setGHCiState state{ cmstate = cmstate1, targets = [] }
907 setContextAfterLoad []
909 -----------------------------------------------------------------------------
914 ["modules" ] -> showModules
915 ["bindings"] -> showBindings
916 ["linker"] -> io showLinkerState
917 _ -> throwDyn (CmdLineError "syntax: :show [modules|bindings]")
921 let (mg, hpt) = cmGetModInfo cms
922 mapM_ (showModule hpt) mg
925 showModule :: HomePackageTable -> ModSummary -> GHCi ()
926 showModule hpt mod_summary
927 = case lookupModuleEnv hpt mod of
928 Nothing -> panic "missing linkable"
929 Just mod_info -> io (putStrLn (showModMsg obj_linkable mod locn))
931 obj_linkable = isObjectLinkable (hm_linkable mod_info)
933 mod = ms_mod mod_summary
934 locn = ms_location mod_summary
939 unqual = cmGetPrintUnqual cms
940 showBinding b = putStrLn (showSDocForUser unqual (ppr (ifaceTyThing b)))
942 io (mapM_ showBinding (cmGetBindings cms))
946 -----------------------------------------------------------------------------
949 data GHCiState = GHCiState
953 targets :: [FilePath],
955 options :: [GHCiOption]
959 = ShowTiming -- show time/allocs after evaluation
960 | ShowType -- show the type of expressions
961 | RevertCAFs -- revert CAFs after every evaluation
964 newtype GHCi a = GHCi { unGHCi :: IORef GHCiState -> IO a }
966 startGHCi :: GHCi a -> GHCiState -> IO a
967 startGHCi g state = do ref <- newIORef state; unGHCi g ref
969 instance Monad GHCi where
970 (GHCi m) >>= k = GHCi $ \s -> m s >>= \a -> unGHCi (k a) s
971 return a = GHCi $ \s -> return a
973 ghciHandleDyn :: Typeable t => (t -> GHCi a) -> GHCi a -> GHCi a
974 ghciHandleDyn h (GHCi m) = GHCi $ \s ->
975 Exception.catchDyn (m s) (\e -> unGHCi (h e) s)
977 getGHCiState = GHCi $ \r -> readIORef r
978 setGHCiState s = GHCi $ \r -> writeIORef r s
980 -- for convenience...
981 getCmState = getGHCiState >>= return . cmstate
982 setCmState cms = do s <- getGHCiState; setGHCiState s{cmstate=cms}
984 isOptionSet :: GHCiOption -> GHCi Bool
986 = do st <- getGHCiState
987 return (opt `elem` options st)
989 setOption :: GHCiOption -> GHCi ()
991 = do st <- getGHCiState
992 setGHCiState (st{ options = opt : filter (/= opt) (options st) })
994 unsetOption :: GHCiOption -> GHCi ()
996 = do st <- getGHCiState
997 setGHCiState (st{ options = filter (/= opt) (options st) })
1000 io m = GHCi { unGHCi = \s -> m >>= return }
1002 -----------------------------------------------------------------------------
1003 -- recursive exception handlers
1005 -- Don't forget to unblock async exceptions in the handler, or if we're
1006 -- in an exception loop (eg. let a = error a in a) the ^C exception
1007 -- may never be delivered. Thanks to Marcin for pointing out the bug.
1009 ghciHandle :: (Exception -> GHCi a) -> GHCi a -> GHCi a
1010 ghciHandle h (GHCi m) = GHCi $ \s ->
1011 Exception.catch (m s)
1012 (\e -> unGHCi (ghciHandle h (ghciUnblock (h e))) s)
1014 ghciUnblock :: GHCi a -> GHCi a
1015 ghciUnblock (GHCi a) = GHCi $ \s -> Exception.unblock (a s)
1017 -----------------------------------------------------------------------------
1018 -- timing & statistics
1020 timeIt :: GHCi a -> GHCi a
1022 = do b <- isOptionSet ShowTiming
1025 else do allocs1 <- io $ getAllocations
1026 time1 <- io $ getCPUTime
1028 allocs2 <- io $ getAllocations
1029 time2 <- io $ getCPUTime
1030 io $ printTimes (allocs2 - allocs1) (time2 - time1)
1033 foreign import ccall "getAllocations" getAllocations :: IO Int
1035 printTimes :: Int -> Integer -> IO ()
1036 printTimes allocs psecs
1037 = do let secs = (fromIntegral psecs / (10^12)) :: Float
1038 secs_str = showFFloat (Just 2) secs
1039 putStrLn (showSDoc (
1040 parens (text (secs_str "") <+> text "secs" <> comma <+>
1041 int allocs <+> text "bytes")))
1043 -----------------------------------------------------------------------------
1050 -- Have to turn off buffering again, because we just
1051 -- reverted stdout, stderr & stdin to their defaults.
1053 foreign import ccall "revertCAFs" rts_revertCAFs :: IO ()
1054 -- Make it "safe", just in case