1 {-# OPTIONS -#include "Linker.h" #-}
2 -----------------------------------------------------------------------------
3 -- $Id: InteractiveUI.hs,v 1.154 2003/05/21 12:38:37 simonmar Exp $
5 -- GHC Interactive User Interface
7 -- (c) The GHC Team 2000
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 HsSyn ( TyClDecl(..), ConDecl(..), Sig(..) )
22 import MkIface ( ifaceTyThing )
25 import DriverUtil ( remove_spaces, handle )
26 import Linker ( showLinkerState, linkPackages )
28 import IdInfo ( GlobalIdDetails(..) )
29 import Id ( isImplicitId, idName, globalIdDetails )
30 import Class ( className )
31 import TyCon ( tyConName, tyConClass_maybe, isPrimTyCon, DataConDetails(..) )
32 import DataCon ( dataConName )
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 hiding ( showException )
47 #ifndef mingw32_HOST_OS
49 #if __GLASGOW_HASKELL__ > 504
54 #if HAVE_READLINE_HEADERS && HAVE_READLINE_LIBS
55 import Control.Concurrent ( yield ) -- Used in readline loop
56 import System.Console.Readline as Readline
61 import Control.Exception as Exception
63 import Control.Concurrent
69 import System.Environment
70 import System.Directory
71 import System.IO as IO
73 import Control.Monad as Monad
75 import GHC.Exts ( unsafeCoerce# )
77 import Data.IORef ( IORef, newIORef, readIORef, writeIORef )
79 import System.Posix.Internals ( setNonBlockingFD )
81 -----------------------------------------------------------------------------
85 \ / _ \\ /\\ /\\/ __(_)\n\
86 \ / /_\\// /_/ / / | | GHC Interactive, version " ++ cProjectVersion ++ ", for Haskell 98.\n\
87 \/ /_\\\\/ __ / /___| | http://www.haskell.org/ghc/\n\
88 \\\____/\\/ /_/\\____/|_| Type :? for help.\n"
90 GLOBAL_VAR(commands, builtin_commands, [(String, String -> GHCi Bool)])
92 builtin_commands :: [(String, String -> GHCi Bool)]
94 ("add", keepGoingPaths addModule),
95 ("browse", keepGoing browseCmd),
96 ("cd", keepGoing changeDirectory),
97 ("def", keepGoing defineMacro),
98 ("help", keepGoing help),
99 ("?", keepGoing help),
100 ("info", keepGoing info),
101 ("load", keepGoingPaths loadModule),
102 ("module", keepGoing setContext),
103 ("reload", keepGoing reloadModule),
104 ("set", keepGoing setCmd),
105 ("show", keepGoing showCmd),
106 ("type", keepGoing typeOfExpr),
107 ("unset", keepGoing unsetOptions),
108 ("undef", keepGoing undefineMacro),
112 keepGoing :: (String -> GHCi ()) -> (String -> GHCi Bool)
113 keepGoing a str = a str >> return False
115 keepGoingPaths :: ([FilePath] -> GHCi ()) -> (String -> GHCi Bool)
116 keepGoingPaths a str = a (toArgs str) >> return False
118 shortHelpText = "use :? for help.\n"
120 -- NOTE: spaces at the end of each line to workaround CPP/string gap bug.
122 \ Commands available from the prompt:\n\
124 \ <stmt> evaluate/run <stmt>\n\
125 \ :add <filename> ... add module(s) to the current target set\n\
126 \ :browse [*]<module> display the names defined by <module>\n\
127 \ :cd <dir> change directory to <dir>\n\
128 \ :def <cmd> <expr> define a command :<cmd>\n\
129 \ :help, :? display this list of commands\n\
130 \ :info [<name> ...] display information about the given names\n\
131 \ :load <filename> ... load module(s) and their dependents\n\
132 \ :module [+/-] [*]<mod> ... set the context for expression evaluation\n\
133 \ :reload reload the current module set\n\
135 \ :set <option> ... set options\n\
136 \ :set args <arg> ... set the arguments returned by System.getArgs\n\
137 \ :set prog <progname> set the value returned by System.getProgName\n\
139 \ :show modules show the currently loaded modules\n\
140 \ :show bindings show the current bindings made at the prompt\n\
142 \ :type <expr> show the type of <expr>\n\
143 \ :undef <cmd> undefine user-defined command :<cmd>\n\
144 \ :unset <option> ... unset options\n\
146 \ :!<command> run the shell command <command>\n\
148 \ Options for `:set' and `:unset':\n\
150 \ +r revert top-level expressions after each evaluation\n\
151 \ +s print timing/memory stats after each evaluation\n\
152 \ +t print type after evaluation\n\
153 \ -<flags> most GHC command line flags can also be set here\n\
154 \ (eg. -v2, -fglasgow-exts, etc.)\n\
157 interactiveUI :: [FilePath] -> IO ()
158 interactiveUI srcs = do
159 dflags <- getDynFlags
161 cmstate <- cmInit Interactive;
164 hSetBuffering stdout NoBuffering
166 -- Initialise buffering for the *interpreted* I/O system
167 cmstate <- initInterpBuffering cmstate dflags
169 -- We don't want the cmd line to buffer any input that might be
170 -- intended for the program, so unbuffer stdin.
171 hSetBuffering stdin NoBuffering
173 -- initial context is just the Prelude
174 cmstate <- cmSetContext cmstate dflags [] ["Prelude"]
176 #if HAVE_READLINE_HEADERS && HAVE_READLINE_LIBS
180 startGHCi (runGHCi srcs dflags)
181 GHCiState{ progname = "<interactive>",
187 #if HAVE_READLINE_HEADERS && HAVE_READLINE_LIBS
188 Readline.resetTerminal Nothing
193 runGHCi :: [FilePath] -> DynFlags -> GHCi ()
194 runGHCi paths dflags = do
195 read_dot_files <- io (readIORef v_Read_DotGHCi)
197 when (read_dot_files) $ do
200 exists <- io (doesFileExist file)
202 dir_ok <- io (checkPerms ".")
203 file_ok <- io (checkPerms file)
204 when (dir_ok && file_ok) $ do
205 either_hdl <- io (IO.try (openFile "./.ghci" ReadMode))
208 Right hdl -> fileLoop hdl False
210 when (read_dot_files) $ do
211 -- Read in $HOME/.ghci
212 either_dir <- io (IO.try (getEnv "HOME"))
216 cwd <- io (getCurrentDirectory)
217 when (dir /= cwd) $ do
218 let file = dir ++ "/.ghci"
219 ok <- io (checkPerms file)
221 either_hdl <- io (IO.try (openFile file ReadMode))
224 Right hdl -> fileLoop hdl False
226 -- Perform a :load for files given on the GHCi command line
227 when (not (null paths)) $
228 ghciHandle showException $
231 -- enter the interactive loop
232 #if defined(mingw32_HOST_OS)
233 -- Always show prompt, since hIsTerminalDevice returns True for Consoles
234 -- only, which we may or may not be running under (cf. Emacs sub-shells.)
237 is_tty <- io (hIsTerminalDevice stdin)
238 interactiveLoop is_tty
242 io $ do when (verbosity dflags > 0) $ putStrLn "Leaving GHCi."
245 interactiveLoop is_tty = do
246 -- Ignore ^C exceptions caught here
247 ghciHandleDyn (\e -> case e of
248 Interrupted -> ghciUnblock (interactiveLoop is_tty)
249 _other -> return ()) $ do
251 -- read commands from stdin
252 #if HAVE_READLINE_HEADERS && HAVE_READLINE_LIBS
255 else fileLoop stdin False -- turn off prompt for non-TTY input
257 fileLoop stdin is_tty
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 dflags' = dopt_unset dflags Opt_WarnUnusedBinds
380 (new_cmstate, result) <-
381 io $ withProgName (progname st) $ withArgs (args st) $
382 cmRunStmt (cmstate st) dflags' stmt
383 setGHCiState st{cmstate = new_cmstate}
385 CmRunFailed -> return []
386 CmRunException e -> showException e >> return []
387 CmRunOk names -> return names
389 -- possibly print the type and revert CAFs after evaluating an expression
391 = do b <- isOptionSet ShowType
392 cmstate <- getCmState
393 when b (mapM_ (showTypeOfName cmstate) names)
396 io installSignalHandlers
397 b <- isOptionSet RevertCAFs
398 io (when b revertCAFs)
401 showTypeOfName :: CmState -> Name -> GHCi ()
402 showTypeOfName cmstate n
403 = do maybe_str <- io (cmTypeOfName cmstate n)
406 Just str -> io (putStrLn (showSDoc (ppr n) ++ " :: " ++ str))
408 specialCommand :: String -> GHCi Bool
409 specialCommand ('!':str) = shellEscape (dropWhile isSpace str)
410 specialCommand str = do
411 let (cmd,rest) = break isSpace str
412 cmds <- io (readIORef commands)
413 case [ (s,f) | (s,f) <- cmds, prefixMatch cmd s ] of
414 [] -> io (hPutStr stdout ("unknown command `:" ++ cmd ++ "'\n"
415 ++ shortHelpText) >> return False)
416 [(_,f)] -> f (dropWhile isSpace rest)
417 cs -> io (hPutStrLn stdout ("prefix " ++ cmd ++
418 " matches multiple commands (" ++
419 foldr1 (\a b -> a ++ ',':b) (map fst cs)
420 ++ ")") >> return False)
422 noArgs c = throwDyn (CmdLineError ("command `" ++ c ++ "' takes no arguments"))
425 -----------------------------------------------------------------------------
426 -- To flush buffers for the *interpreted* computation we need
427 -- to refer to *its* stdout/stderr handles
429 GLOBAL_VAR(flush_interp, error "no flush_interp", IO ())
430 GLOBAL_VAR(turn_off_buffering, error "no flush_stdout", IO ())
432 no_buf_cmd = "IO.hSetBuffering IO.stdout IO.NoBuffering" ++
433 " Prelude.>> IO.hSetBuffering IO.stderr IO.NoBuffering"
434 flush_cmd = "IO.hFlush IO.stdout Prelude.>> IO.hFlush IO.stderr"
436 initInterpBuffering :: CmState -> DynFlags -> IO CmState
437 initInterpBuffering cmstate dflags
438 = do (cmstate, maybe_hval) <- cmCompileExpr cmstate dflags no_buf_cmd
441 Just hval -> writeIORef turn_off_buffering (unsafeCoerce# hval :: IO ())
442 other -> panic "interactiveUI:setBuffering"
444 (cmstate, maybe_hval) <- cmCompileExpr cmstate dflags flush_cmd
446 Just hval -> writeIORef flush_interp (unsafeCoerce# hval :: IO ())
447 _ -> panic "interactiveUI:flush"
449 turnOffBuffering -- Turn it off right now
454 flushInterpBuffers :: GHCi ()
456 = io $ do Monad.join (readIORef flush_interp)
459 turnOffBuffering :: IO ()
461 = do Monad.join (readIORef turn_off_buffering)
464 -----------------------------------------------------------------------------
467 help :: String -> GHCi ()
468 help _ = io (putStr helpText)
470 info :: String -> GHCi ()
471 info "" = throwDyn (CmdLineError "syntax: `:i <thing-you-want-info-about>'")
474 init_cms <- getCmState
475 dflags <- io getDynFlags
477 infoThings cms [] = return cms
478 infoThings cms (name:names) = do
479 (cms, stuff) <- io (cmInfoThing cms dflags name)
480 io (putStrLn (showSDocForUser unqual (
481 vcat (intersperse (text "") (map showThing stuff))))
485 unqual = cmGetPrintUnqual init_cms
487 showThing (ty_thing, fixity)
488 = vcat [ text "-- " <> showTyThing ty_thing,
489 showFixity fixity (getName ty_thing),
490 ppr (ifaceTyThing ty_thing) ]
493 | fix == defaultFixity = empty
494 | otherwise = ppr fix <+>
495 (if isSymOcc (nameOccName name)
497 else char '`' <> ppr name <> char '`')
499 showTyThing (AClass cl)
500 = hcat [ppr cl, text " is a class", showSrcLoc (className cl)]
501 showTyThing (ADataCon dc)
502 = hcat [ppr dc, text " is a data constructor", showSrcLoc (dataConName dc)]
503 showTyThing (ATyCon ty)
505 = hcat [ppr ty, text " is a primitive type constructor"]
507 = hcat [ppr ty, text " is a type constructor", showSrcLoc (tyConName ty)]
508 showTyThing (AnId id)
509 = hcat [ppr id, text " is a ", idDescr id, showSrcLoc (idName id)]
512 = case globalIdDetails id of
513 RecordSelId lbl -> text "record selector for type" <+> ppr (fieldLabelTyCon lbl)
514 ClassOpId cls -> text "method in class" <+> ppr cls
515 otherwise -> text "variable"
517 -- also print out the source location for home things
519 | isHomePackageName name && isGoodSrcLoc loc
520 = hsep [ text ", defined at", ppr loc ]
523 where loc = nameSrcLoc name
525 cms <- infoThings init_cms names
529 addModule :: [FilePath] -> GHCi ()
531 state <- getGHCiState
532 dflags <- io (getDynFlags)
533 io (revertCAFs) -- always revert CAFs on load/add.
534 files <- mapM expandPath files
535 let new_targets = files ++ targets state
536 graph <- io (cmDepAnal (cmstate state) dflags new_targets)
537 (cmstate1, ok, mods) <- io (cmLoadModules (cmstate state) dflags graph)
538 setGHCiState state{ cmstate = cmstate1, targets = new_targets }
539 setContextAfterLoad mods
540 modulesLoadedMsg ok mods dflags
542 changeDirectory :: String -> GHCi ()
543 changeDirectory dir = do
544 dir <- expandPath dir
545 io (setCurrentDirectory dir)
547 defineMacro :: String -> GHCi ()
549 let (macro_name, definition) = break isSpace s
550 cmds <- io (readIORef commands)
552 then throwDyn (CmdLineError "invalid macro name")
554 if (macro_name `elem` map fst cmds)
555 then throwDyn (CmdLineError
556 ("command `" ++ macro_name ++ "' is already defined"))
559 -- give the expression a type signature, so we can be sure we're getting
560 -- something of the right type.
561 let new_expr = '(' : definition ++ ") :: String -> IO String"
563 -- compile the expression
565 dflags <- io getDynFlags
566 (new_cmstate, maybe_hv) <- io (cmCompileExpr cms dflags new_expr)
567 setCmState new_cmstate
570 Just hv -> io (writeIORef commands --
571 ((macro_name, keepGoing (runMacro hv)) : cmds))
573 runMacro :: HValue{-String -> IO String-} -> String -> GHCi ()
575 str <- io ((unsafeCoerce# fun :: String -> IO String) s)
576 stringLoop (lines str)
578 undefineMacro :: String -> GHCi ()
579 undefineMacro macro_name = do
580 cmds <- io (readIORef commands)
581 if (macro_name `elem` map fst builtin_commands)
582 then throwDyn (CmdLineError
583 ("command `" ++ macro_name ++ "' cannot be undefined"))
585 if (macro_name `notElem` map fst cmds)
586 then throwDyn (CmdLineError
587 ("command `" ++ macro_name ++ "' not defined"))
589 io (writeIORef commands (filter ((/= macro_name) . fst) cmds))
592 loadModule :: [FilePath] -> GHCi ()
593 loadModule fs = timeIt (loadModule' fs)
595 loadModule' :: [FilePath] -> GHCi ()
596 loadModule' files = do
597 state <- getGHCiState
598 dflags <- io getDynFlags
601 files <- mapM expandPath files
603 -- do the dependency anal first, so that if it fails we don't throw
604 -- away the current set of modules.
605 graph <- io (cmDepAnal (cmstate state) dflags files)
607 -- Dependency anal ok, now unload everything
608 cmstate1 <- io (cmUnload (cmstate state) dflags)
609 setGHCiState state{ cmstate = cmstate1, targets = [] }
611 io (revertCAFs) -- always revert CAFs on load.
612 (cmstate2, ok, mods) <- io (cmLoadModules cmstate1 dflags graph)
613 setGHCiState state{ cmstate = cmstate2, targets = files }
615 setContextAfterLoad mods
616 modulesLoadedMsg ok mods dflags
619 reloadModule :: String -> GHCi ()
621 state <- getGHCiState
622 dflags <- io getDynFlags
623 case targets state of
624 [] -> io (putStr "no current target\n")
626 -- do the dependency anal first, so that if it fails we don't throw
627 -- away the current set of modules.
628 graph <- io (cmDepAnal (cmstate state) dflags paths)
630 io (revertCAFs) -- always revert CAFs on reload.
632 <- io (cmLoadModules (cmstate state) dflags graph)
633 setGHCiState state{ cmstate=cmstate1 }
634 setContextAfterLoad mods
635 modulesLoadedMsg ok mods dflags
637 reloadModule _ = noArgs ":reload"
639 setContextAfterLoad [] = setContext prel
640 setContextAfterLoad (m:_) = do
641 cmstate <- getCmState
642 b <- io (cmModuleIsInterpreted cmstate m)
643 if b then setContext ('*':m) else setContext m
645 modulesLoadedMsg ok mods dflags =
646 when (verbosity dflags > 0) $ do
648 | null mods = text "none."
650 punctuate comma (map text mods)) <> text "."
653 io (putStrLn (showSDoc (text "Failed, modules loaded: " <> mod_commas)))
655 io (putStrLn (showSDoc (text "Ok, modules loaded: " <> mod_commas)))
658 typeOfExpr :: String -> GHCi ()
660 = do cms <- getCmState
661 dflags <- io getDynFlags
662 (new_cmstate, maybe_tystr) <- io (cmTypeOfExpr cms dflags str)
663 setCmState new_cmstate
666 Just tystr -> io (putStrLn tystr)
668 quit :: String -> GHCi Bool
671 shellEscape :: String -> GHCi Bool
672 shellEscape str = io (system str >> return False)
674 -----------------------------------------------------------------------------
675 -- Browing a module's contents
677 browseCmd :: String -> GHCi ()
680 ['*':m] | looksLikeModuleName m -> browseModule m False
681 [m] | looksLikeModuleName m -> browseModule m True
682 _ -> throwDyn (CmdLineError "syntax: :browse <module>")
684 browseModule m exports_only = do
686 dflags <- io getDynFlags
688 is_interpreted <- io (cmModuleIsInterpreted cms m)
689 when (not is_interpreted && not exports_only) $
690 throwDyn (CmdLineError ("module `" ++ m ++ "' is not interpreted"))
692 -- temporarily set the context to the module we're interested in,
693 -- just so we can get an appropriate PrintUnqualified
694 (as,bs) <- io (cmGetContext cms)
695 cms1 <- io (if exports_only then cmSetContext cms dflags [] [prel,m]
696 else cmSetContext cms dflags [m] [])
697 cms2 <- io (cmSetContext cms1 dflags as bs)
699 (cms3, things) <- io (cmBrowseModule cms2 dflags m exports_only)
703 let unqual = cmGetPrintUnqual cms1 -- NOTE: cms1 with the new context
705 things' = filter wantToSee things
707 wantToSee (AnId id) = not (isImplicitId id)
708 wantToSee (ADataCon _) = False -- They'll come via their TyCon
711 thing_names = map getName things
713 thingDecl thing@(AnId id) = ifaceTyThing thing
715 thingDecl thing@(AClass c) =
716 let rn_decl = ifaceTyThing thing in
718 ClassDecl { tcdSigs = cons } ->
719 rn_decl{ tcdSigs = filter methodIsVisible cons }
722 methodIsVisible (ClassOpSig n _ _ _) = n `elem` thing_names
724 thingDecl thing@(ATyCon t) =
725 let rn_decl = ifaceTyThing thing in
727 TyData { tcdCons = DataCons cons } ->
728 rn_decl{ tcdCons = DataCons (filter conIsVisible cons) }
731 conIsVisible (ConDecl n _ _ _ _) = n `elem` thing_names
733 io (putStrLn (showSDocForUser unqual (
734 vcat (map (ppr . thingDecl) things')))
739 -----------------------------------------------------------------------------
740 -- Setting the module context
743 | all sensible mods = fn mods
744 | otherwise = throwDyn (CmdLineError "syntax: :module [+/-] [*]M1 ... [*]Mn")
746 (fn, mods) = case str of
747 '+':stuff -> (addToContext, words stuff)
748 '-':stuff -> (removeFromContext, words stuff)
749 stuff -> (newContext, words stuff)
751 sensible ('*':m) = looksLikeModuleName m
752 sensible m = looksLikeModuleName m
756 dflags <- io getDynFlags
757 (as,bs) <- separate cms mods [] []
758 let bs' = if null as && prel `notElem` bs then prel:bs else bs
759 cms' <- io (cmSetContext cms dflags as bs')
762 separate cmstate [] as bs = return (as,bs)
763 separate cmstate (('*':m):ms) as bs = do
764 b <- io (cmModuleIsInterpreted cmstate m)
765 if b then separate cmstate ms (m:as) bs
766 else throwDyn (CmdLineError ("module `" ++ m ++ "' is not interpreted"))
767 separate cmstate (m:ms) as bs = separate cmstate ms as (m:bs)
772 addToContext mods = do
774 dflags <- io getDynFlags
775 (as,bs) <- io (cmGetContext cms)
777 (as',bs') <- separate cms mods [] []
779 let as_to_add = as' \\ (as ++ bs)
780 bs_to_add = bs' \\ (as ++ bs)
782 cms' <- io (cmSetContext cms dflags
783 (as ++ as_to_add) (bs ++ bs_to_add))
787 removeFromContext mods = do
789 dflags <- io getDynFlags
790 (as,bs) <- io (cmGetContext cms)
792 (as_to_remove,bs_to_remove) <- separate cms mods [] []
794 let as' = as \\ (as_to_remove ++ bs_to_remove)
795 bs' = bs \\ (as_to_remove ++ bs_to_remove)
797 cms' <- io (cmSetContext cms dflags as' bs')
800 ----------------------------------------------------------------------------
803 -- set options in the interpreter. Syntax is exactly the same as the
804 -- ghc command line, except that certain options aren't available (-C,
807 -- This is pretty fragile: most options won't work as expected. ToDo:
808 -- figure out which ones & disallow them.
810 setCmd :: String -> GHCi ()
812 = do st <- getGHCiState
813 let opts = options st
814 io $ putStrLn (showSDoc (
815 text "options currently set: " <>
818 else hsep (map (\o -> char '+' <> text (optToStr o)) opts)
822 ("args":args) -> setArgs args
823 ("prog":prog) -> setProg prog
824 wds -> setOptions wds
828 setGHCiState st{ args = args }
832 setGHCiState st{ progname = prog }
834 io (hPutStrLn stderr "syntax: :set prog <progname>")
837 do -- first, deal with the GHCi opts (+s, +t, etc.)
838 let (plus_opts, minus_opts) = partition isPlus wds
839 mapM_ setOpt plus_opts
841 -- now, the GHC flags
842 pkgs_before <- io (readIORef v_ExplicitPackages)
843 leftovers <- io (processArgs static_flags minus_opts [])
844 pkgs_after <- io (readIORef v_ExplicitPackages)
846 -- update things if the users wants more packages
847 let new_packages = pkgs_after \\ pkgs_before
848 when (not (null new_packages)) $
849 newPackages new_packages
851 -- don't forget about the extra command-line flags from the
852 -- extra_ghc_opts fields in the new packages
853 new_package_details <- io (getPackageDetails new_packages)
854 let pkg_extra_opts = concatMap extra_ghc_opts new_package_details
855 pkg_extra_dyn <- io (processArgs static_flags pkg_extra_opts [])
857 -- then, dynamic flags
860 leftovers <- processArgs dynamic_flags (leftovers ++ pkg_extra_dyn) []
863 if (not (null leftovers))
864 then throwDyn (CmdLineError ("unrecognised flags: " ++
869 unsetOptions :: String -> GHCi ()
871 = do -- first, deal with the GHCi opts (+s, +t, etc.)
873 (minus_opts, rest1) = partition isMinus opts
874 (plus_opts, rest2) = partition isPlus rest1
876 if (not (null rest2))
877 then io (putStrLn ("unknown option: `" ++ head rest2 ++ "'"))
880 mapM_ unsetOpt plus_opts
882 -- can't do GHC flags for now
883 if (not (null minus_opts))
884 then throwDyn (CmdLineError "can't unset GHC command-line flags")
887 isMinus ('-':s) = True
890 isPlus ('+':s) = True
894 = case strToGHCiOpt str of
895 Nothing -> io (putStrLn ("unknown option: `" ++ str ++ "'"))
896 Just o -> setOption o
899 = case strToGHCiOpt str of
900 Nothing -> io (putStrLn ("unknown option: `" ++ str ++ "'"))
901 Just o -> unsetOption o
903 strToGHCiOpt :: String -> (Maybe GHCiOption)
904 strToGHCiOpt "s" = Just ShowTiming
905 strToGHCiOpt "t" = Just ShowType
906 strToGHCiOpt "r" = Just RevertCAFs
907 strToGHCiOpt _ = Nothing
909 optToStr :: GHCiOption -> String
910 optToStr ShowTiming = "s"
911 optToStr ShowType = "t"
912 optToStr RevertCAFs = "r"
914 newPackages new_pkgs = do -- The new packages are already in v_Packages
915 state <- getGHCiState
916 dflags <- io getDynFlags
917 cmstate1 <- io (cmUnload (cmstate state) dflags)
918 setGHCiState state{ cmstate = cmstate1, targets = [] }
919 io (linkPackages dflags new_pkgs)
920 setContextAfterLoad []
922 -- ---------------------------------------------------------------------------
927 ["modules" ] -> showModules
928 ["bindings"] -> showBindings
929 ["linker"] -> io showLinkerState
930 _ -> throwDyn (CmdLineError "syntax: :show [modules|bindings]")
934 let (mg, hpt) = cmGetModInfo cms
935 mapM_ (showModule hpt) mg
938 showModule :: HomePackageTable -> ModSummary -> GHCi ()
939 showModule hpt mod_summary
940 = case lookupModuleEnv hpt mod of
941 Nothing -> panic "missing linkable"
942 Just mod_info -> io (putStrLn (showModMsg obj_linkable mod locn))
944 obj_linkable = isObjectLinkable (hm_linkable mod_info)
946 mod = ms_mod mod_summary
947 locn = ms_location mod_summary
952 unqual = cmGetPrintUnqual cms
953 showBinding b = putStrLn (showSDocForUser unqual (ppr (ifaceTyThing b)))
955 io (mapM_ showBinding (cmGetBindings cms))
959 -----------------------------------------------------------------------------
962 data GHCiState = GHCiState
966 targets :: [FilePath],
968 options :: [GHCiOption]
972 = ShowTiming -- show time/allocs after evaluation
973 | ShowType -- show the type of expressions
974 | RevertCAFs -- revert CAFs after every evaluation
977 newtype GHCi a = GHCi { unGHCi :: IORef GHCiState -> IO a }
979 startGHCi :: GHCi a -> GHCiState -> IO a
980 startGHCi g state = do ref <- newIORef state; unGHCi g ref
982 instance Monad GHCi where
983 (GHCi m) >>= k = GHCi $ \s -> m s >>= \a -> unGHCi (k a) s
984 return a = GHCi $ \s -> return a
986 ghciHandleDyn :: Typeable t => (t -> GHCi a) -> GHCi a -> GHCi a
987 ghciHandleDyn h (GHCi m) = GHCi $ \s ->
988 Exception.catchDyn (m s) (\e -> unGHCi (h e) s)
990 getGHCiState = GHCi $ \r -> readIORef r
991 setGHCiState s = GHCi $ \r -> writeIORef r s
993 -- for convenience...
994 getCmState = getGHCiState >>= return . cmstate
995 setCmState cms = do s <- getGHCiState; setGHCiState s{cmstate=cms}
997 isOptionSet :: GHCiOption -> GHCi Bool
999 = do st <- getGHCiState
1000 return (opt `elem` options st)
1002 setOption :: GHCiOption -> GHCi ()
1004 = do st <- getGHCiState
1005 setGHCiState (st{ options = opt : filter (/= opt) (options st) })
1007 unsetOption :: GHCiOption -> GHCi ()
1009 = do st <- getGHCiState
1010 setGHCiState (st{ options = filter (/= opt) (options st) })
1012 io :: IO a -> GHCi a
1013 io m = GHCi { unGHCi = \s -> m >>= return }
1015 -----------------------------------------------------------------------------
1016 -- recursive exception handlers
1018 -- Don't forget to unblock async exceptions in the handler, or if we're
1019 -- in an exception loop (eg. let a = error a in a) the ^C exception
1020 -- may never be delivered. Thanks to Marcin for pointing out the bug.
1022 ghciHandle :: (Exception -> GHCi a) -> GHCi a -> GHCi a
1023 ghciHandle h (GHCi m) = GHCi $ \s ->
1024 Exception.catch (m s)
1025 (\e -> unGHCi (ghciUnblock (h e)) s)
1027 ghciUnblock :: GHCi a -> GHCi a
1028 ghciUnblock (GHCi a) = GHCi $ \s -> Exception.unblock (a s)
1030 -----------------------------------------------------------------------------
1031 -- timing & statistics
1033 timeIt :: GHCi a -> GHCi a
1035 = do b <- isOptionSet ShowTiming
1038 else do allocs1 <- io $ getAllocations
1039 time1 <- io $ getCPUTime
1041 allocs2 <- io $ getAllocations
1042 time2 <- io $ getCPUTime
1043 io $ printTimes (allocs2 - allocs1) (time2 - time1)
1046 foreign import ccall "getAllocations" getAllocations :: IO Int
1048 printTimes :: Int -> Integer -> IO ()
1049 printTimes allocs psecs
1050 = do let secs = (fromIntegral psecs / (10^12)) :: Float
1051 secs_str = showFFloat (Just 2) secs
1052 putStrLn (showSDoc (
1053 parens (text (secs_str "") <+> text "secs" <> comma <+>
1054 int allocs <+> text "bytes")))
1056 -----------------------------------------------------------------------------
1063 -- Have to turn off buffering again, because we just
1064 -- reverted stdout, stderr & stdin to their defaults.
1066 foreign import ccall "revertCAFs" rts_revertCAFs :: IO ()
1067 -- Make it "safe", just in case
1069 -- -----------------------------------------------------------------------------
1072 expandPath :: String -> GHCi String
1074 case dropWhile isSpace path of
1076 tilde <- io (getEnv "HOME") -- will fail if HOME not defined
1077 return (tilde ++ '/':d)