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(..), Phase,
21 GhcException(..), showGhcException,
22 CheckedModule(..), SrcLoc )
26 -- for createtags (should these come via GHC?)
27 import Module( moduleUserString )
28 import Name( nameSrcLoc, nameModule, nameOccName )
29 import OccName( pprOccName )
30 import SrcLoc( isGoodSrcLoc, srcLocFile, srcLocLine, srcLocCol )
32 -- Other random utilities
33 import BasicTypes ( failed, successIf )
34 import Panic ( panic, installSignalHandlers )
36 import StaticFlags ( opt_IgnoreDotGhci )
37 import Linker ( showLinkerState )
38 import Util ( removeSpaces, handle, global, toArgs,
39 looksLikeModuleName, prefixMatch, sortLe )
40 import ErrUtils ( printErrorsAndWarnings )
42 #ifndef mingw32_HOST_OS
44 #if __GLASGOW_HASKELL__ > 504
48 import GHC.ConsoleHandler ( flushConsole )
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
64 import Data.Int ( Int64 )
65 import Data.Maybe ( isJust, fromMaybe, catMaybes )
68 import System.Environment
69 import System.Exit ( exitWith, ExitCode(..) )
70 import System.Directory
72 import System.IO.Error as IO
74 import Control.Monad as Monad
75 import Foreign.StablePtr ( newStablePtr )
77 import GHC.Exts ( unsafeCoerce# )
78 import GHC.IOBase ( IOErrorType(InvalidArgument) )
80 import Data.IORef ( IORef, newIORef, readIORef, writeIORef )
82 import System.Posix.Internals ( setNonBlockingFD )
84 -----------------------------------------------------------------------------
88 " / _ \\ /\\ /\\/ __(_)\n"++
89 " / /_\\// /_/ / / | | GHC Interactive, version " ++ cProjectVersion ++ ", for Haskell 98.\n"++
90 "/ /_\\\\/ __ / /___| | http://www.haskell.org/ghc/\n"++
91 "\\____/\\/ /_/\\____/|_| Type :? for help.\n"
93 GLOBAL_VAR(commands, builtin_commands, [(String, String -> GHCi Bool)])
95 builtin_commands :: [(String, String -> GHCi Bool)]
97 ("add", keepGoingPaths addModule),
98 ("browse", keepGoing browseCmd),
99 ("cd", keepGoing changeDirectory),
100 ("def", keepGoing defineMacro),
101 ("help", keepGoing help),
102 ("?", keepGoing help),
103 ("info", keepGoing info),
104 ("load", keepGoingPaths loadModule_),
105 ("module", keepGoing setContext),
106 ("reload", keepGoing reloadModule),
107 ("check", keepGoing checkModule),
108 ("set", keepGoing setCmd),
109 ("show", keepGoing showCmd),
110 ("etags", keepGoing createETagsFileCmd),
111 ("ctags", keepGoing createCTagsFileCmd),
112 ("type", keepGoing typeOfExpr),
113 ("kind", keepGoing kindOfType),
114 ("unset", keepGoing unsetOptions),
115 ("undef", keepGoing undefineMacro),
119 keepGoing :: (String -> GHCi ()) -> (String -> GHCi Bool)
120 keepGoing a str = a str >> return False
122 keepGoingPaths :: ([FilePath] -> GHCi ()) -> (String -> GHCi Bool)
123 keepGoingPaths a str = a (toArgs str) >> return False
125 shortHelpText = "use :? for help.\n"
127 -- NOTE: spaces at the end of each line to workaround CPP/string gap bug.
129 " Commands available from the prompt:\n" ++
131 " <stmt> evaluate/run <stmt>\n" ++
132 " :add <filename> ... add module(s) to the current target set\n" ++
133 " :browse [*]<module> display the names defined by <module>\n" ++
134 " :cd <dir> change directory to <dir>\n" ++
135 " :def <cmd> <expr> define a command :<cmd>\n" ++
136 " :help, :? display this list of commands\n" ++
137 " :info [<name> ...] display information about the given names\n" ++
138 " :load <filename> ... load module(s) and their dependents\n" ++
139 " :module [+/-] [*]<mod> ... set the context for expression evaluation\n" ++
140 " :reload reload the current module set\n" ++
142 " :set <option> ... set options\n" ++
143 " :set args <arg> ... set the arguments returned by System.getArgs\n" ++
144 " :set prog <progname> set the value returned by System.getProgName\n" ++
146 " :show modules show the currently loaded modules\n" ++
147 " :show bindings show the current bindings made at the prompt\n" ++
149 " :ctags [<file>] create tags file for Vi (default: \"tags\")\n" ++
150 " :etags [<file>] create tags file for Emacs (defauilt: \"TAGS\")\n" ++
151 " :type <expr> show the type of <expr>\n" ++
152 " :kind <type> show the kind of <type>\n" ++
153 " :undef <cmd> undefine user-defined command :<cmd>\n" ++
154 " :unset <option> ... unset options\n" ++
155 " :quit exit GHCi\n" ++
156 " :!<command> run the shell command <command>\n" ++
158 " Options for ':set' and ':unset':\n" ++
160 " +r revert top-level expressions after each evaluation\n" ++
161 " +s print timing/memory stats after each evaluation\n" ++
162 " +t print type after evaluation\n" ++
163 " -<flags> most GHC command line flags can also be set here\n" ++
164 " (eg. -v2, -fglasgow-exts, etc.)\n"
167 interactiveUI :: Session -> [(FilePath, Maybe Phase)] -> Maybe String -> IO ()
168 interactiveUI session srcs maybe_expr = do
170 -- HACK! If we happen to get into an infinite loop (eg the user
171 -- types 'let x=x in x' at the prompt), then the thread will block
172 -- on a blackhole, and become unreachable during GC. The GC will
173 -- detect that it is unreachable and send it the NonTermination
174 -- exception. However, since the thread is unreachable, everything
175 -- it refers to might be finalized, including the standard Handles.
176 -- This sounds like a bug, but we don't have a good solution right
183 hSetBuffering stdout NoBuffering
185 -- Initialise buffering for the *interpreted* I/O system
186 initInterpBuffering session
188 -- We don't want the cmd line to buffer any input that might be
189 -- intended for the program, so unbuffer stdin.
190 hSetBuffering stdin NoBuffering
192 -- initial context is just the Prelude
193 GHC.setContext session [] [prelude_mod]
199 #if defined(mingw32_HOST_OS)
200 -- The win32 Console API mutates the first character of
201 -- type-ahead when reading from it in a non-buffered manner. Work
202 -- around this by flushing the input buffer of type-ahead characters.
204 GHC.ConsoleHandler.flushConsole stdin
206 startGHCi (runGHCi srcs maybe_expr)
207 GHCiState{ progname = "<interactive>",
213 Readline.resetTerminal Nothing
218 runGHCi :: [(FilePath, Maybe Phase)] -> Maybe String -> GHCi ()
219 runGHCi paths maybe_expr = do
220 let read_dot_files = not opt_IgnoreDotGhci
222 when (read_dot_files) $ do
225 exists <- io (doesFileExist file)
227 dir_ok <- io (checkPerms ".")
228 file_ok <- io (checkPerms file)
229 when (dir_ok && file_ok) $ do
230 either_hdl <- io (IO.try (openFile "./.ghci" ReadMode))
233 Right hdl -> fileLoop hdl False
235 when (read_dot_files) $ do
236 -- Read in $HOME/.ghci
237 either_dir <- io (IO.try (getEnv "HOME"))
241 cwd <- io (getCurrentDirectory)
242 when (dir /= cwd) $ do
243 let file = dir ++ "/.ghci"
244 ok <- io (checkPerms file)
246 either_hdl <- io (IO.try (openFile file ReadMode))
249 Right hdl -> fileLoop hdl False
251 -- Perform a :load for files given on the GHCi command line
252 -- When in -e mode, if the load fails then we want to stop
253 -- immediately rather than going on to evaluate the expression.
254 when (not (null paths)) $ do
255 ok <- ghciHandle (\e -> do showException e; return Failed) $
257 when (isJust maybe_expr && failed ok) $
258 io (exitWith (ExitFailure 1))
260 -- if verbosity is greater than 0, or we are connected to a
261 -- terminal, display the prompt in the interactive loop.
262 is_tty <- io (hIsTerminalDevice stdin)
263 dflags <- getDynFlags
264 let show_prompt = verbosity dflags > 0 || is_tty
268 -- enter the interactive loop
269 interactiveLoop is_tty show_prompt
271 -- just evaluate the expression we were given
276 io $ do when (verbosity dflags > 0) $ putStrLn "Leaving GHCi."
279 interactiveLoop is_tty show_prompt = do
280 -- Ignore ^C exceptions caught here
281 ghciHandleDyn (\e -> case e of
282 Interrupted -> ghciUnblock (
283 #if defined(mingw32_HOST_OS)
286 interactiveLoop is_tty show_prompt)
287 _other -> return ()) $ do
289 -- read commands from stdin
293 else fileLoop stdin show_prompt
295 fileLoop stdin show_prompt
299 -- NOTE: We only read .ghci files if they are owned by the current user,
300 -- and aren't world writable. Otherwise, we could be accidentally
301 -- running code planted by a malicious third party.
303 -- Furthermore, We only read ./.ghci if . is owned by the current user
304 -- and isn't writable by anyone else. I think this is sufficient: we
305 -- don't need to check .. and ../.. etc. because "." always refers to
306 -- the same directory while a process is running.
308 checkPerms :: String -> IO Bool
310 #ifdef mingw32_HOST_OS
313 Util.handle (\_ -> return False) $ do
314 st <- getFileStatus name
316 if fileOwner st /= me then do
317 putStrLn $ "WARNING: " ++ name ++ " is owned by someone else, IGNORING!"
320 let mode = fileMode st
321 if (groupWriteMode == (mode `intersectFileModes` groupWriteMode))
322 || (otherWriteMode == (mode `intersectFileModes` otherWriteMode))
324 putStrLn $ "*** WARNING: " ++ name ++
325 " is writable by someone else, IGNORING!"
330 fileLoop :: Handle -> Bool -> GHCi ()
331 fileLoop hdl prompt = do
332 session <- getSession
333 (mod,imports) <- io (GHC.getContext session)
334 when prompt (io (putStr (mkPrompt mod imports)))
335 l <- io (IO.try (hGetLine hdl))
337 Left e | isEOFError e -> return ()
338 | InvalidArgument <- etype -> return ()
339 | otherwise -> io (ioError e)
340 where etype = ioeGetErrorType e
341 -- treat InvalidArgument in the same way as EOF:
342 -- this can happen if the user closed stdin, or
343 -- perhaps did getContents which closes stdin at
346 case removeSpaces l of
347 "" -> fileLoop hdl prompt
348 l -> do quit <- runCommand l
349 if quit then return () else fileLoop hdl prompt
351 stringLoop :: [String] -> GHCi ()
352 stringLoop [] = return ()
353 stringLoop (s:ss) = do
354 case removeSpaces s of
356 l -> do quit <- runCommand l
357 if quit then return () else stringLoop ss
359 mkPrompt toplevs exports
360 = showSDoc (hsep (map (\m -> char '*' <> pprModule m) toplevs)
361 <+> hsep (map pprModule exports)
365 readlineLoop :: GHCi ()
367 session <- getSession
368 (mod,imports) <- io (GHC.getContext session)
370 l <- io (readline (mkPrompt mod imports)
371 `finally` setNonBlockingFD 0)
372 -- readline sometimes puts stdin into blocking mode,
373 -- so we need to put it back for the IO library
377 case removeSpaces l of
382 if quit then return () else readlineLoop
385 runCommand :: String -> GHCi Bool
386 runCommand c = ghciHandle handler (doCommand c)
388 doCommand (':' : command) = specialCommand command
390 = do timeIt (do nms <- runStmt stmt; finishEvalExpr nms)
393 -- This version is for the GHC command-line option -e. The only difference
394 -- from runCommand is that it catches the ExitException exception and
395 -- exits, rather than printing out the exception.
396 runCommandEval c = ghciHandle handleEval (doCommand c)
398 handleEval (ExitException code) = io (exitWith code)
399 handleEval e = do showException e
400 io (exitWith (ExitFailure 1))
402 doCommand (':' : command) = specialCommand command
404 = do nms <- runStmt stmt
406 Nothing -> io (exitWith (ExitFailure 1))
407 -- failure to run the command causes exit(1) for ghc -e.
408 _ -> finishEvalExpr nms
410 -- This is the exception handler for exceptions generated by the
411 -- user's code; it normally just prints out the exception. The
412 -- handler must be recursive, in case showing the exception causes
413 -- more exceptions to be raised.
415 -- Bugfix: if the user closed stdout or stderr, the flushing will fail,
416 -- raising another exception. We therefore don't put the recursive
417 -- handler arond the flushing operation, so if stderr is closed
418 -- GHCi will just die gracefully rather than going into an infinite loop.
419 handler :: Exception -> GHCi Bool
420 handler exception = do
422 io installSignalHandlers
423 ghciHandle handler (showException exception >> return False)
425 showException (DynException dyn) =
426 case fromDynamic dyn of
427 Nothing -> io (putStrLn ("*** Exception: (unknown)"))
428 Just Interrupted -> io (putStrLn "Interrupted.")
429 Just (CmdLineError s) -> io (putStrLn s) -- omit the location for CmdLineError
430 Just ph@PhaseFailed{} -> io (putStrLn (showGhcException ph "")) -- ditto
431 Just other_ghc_ex -> io (print other_ghc_ex)
433 showException other_exception
434 = io (putStrLn ("*** Exception: " ++ show other_exception))
436 runStmt :: String -> GHCi (Maybe [Name])
438 | null (filter (not.isSpace) stmt) = return (Just [])
440 = do st <- getGHCiState
441 session <- getSession
442 result <- io $ withProgName (progname st) $ withArgs (args st) $
443 GHC.runStmt session stmt
445 GHC.RunFailed -> return Nothing
446 GHC.RunException e -> throw e -- this is caught by runCommand(Eval)
447 GHC.RunOk names -> return (Just names)
449 -- possibly print the type and revert CAFs after evaluating an expression
450 finishEvalExpr mb_names
451 = do b <- isOptionSet ShowType
452 session <- getSession
455 Just names -> when b (mapM_ (showTypeOfName session) names)
458 io installSignalHandlers
459 b <- isOptionSet RevertCAFs
460 io (when b revertCAFs)
463 showTypeOfName :: Session -> Name -> GHCi ()
464 showTypeOfName session n
465 = do maybe_tything <- io (GHC.lookupName session n)
466 case maybe_tything of
468 Just thing -> showTyThing thing
470 showForUser :: SDoc -> GHCi String
472 session <- getSession
473 unqual <- io (GHC.getPrintUnqual session)
474 return $! showSDocForUser unqual doc
476 specialCommand :: String -> GHCi Bool
477 specialCommand ('!':str) = shellEscape (dropWhile isSpace str)
478 specialCommand str = do
479 let (cmd,rest) = break isSpace str
480 cmds <- io (readIORef commands)
481 case [ (s,f) | (s,f) <- cmds, prefixMatch cmd s ] of
482 [] -> io (hPutStr stdout ("unknown command ':" ++ cmd ++ "'\n"
483 ++ shortHelpText) >> return False)
484 [(_,f)] -> f (dropWhile isSpace rest)
485 cs -> io (hPutStrLn stdout ("prefix " ++ cmd ++
486 " matches multiple commands (" ++
487 foldr1 (\a b -> a ++ ',':b) (map fst cs)
488 ++ ")") >> return False)
490 -----------------------------------------------------------------------------
491 -- To flush buffers for the *interpreted* computation we need
492 -- to refer to *its* stdout/stderr handles
494 GLOBAL_VAR(flush_interp, error "no flush_interp", IO ())
495 GLOBAL_VAR(turn_off_buffering, error "no flush_stdout", IO ())
497 no_buf_cmd = "System.IO.hSetBuffering System.IO.stdout System.IO.NoBuffering" ++
498 " Prelude.>> System.IO.hSetBuffering System.IO.stderr System.IO.NoBuffering"
499 flush_cmd = "System.IO.hFlush System.IO.stdout Prelude.>> System.IO.hFlush IO.stderr"
501 initInterpBuffering :: Session -> IO ()
502 initInterpBuffering session
503 = do maybe_hval <- GHC.compileExpr session no_buf_cmd
506 Just hval -> writeIORef turn_off_buffering (unsafeCoerce# hval :: IO ())
507 other -> panic "interactiveUI:setBuffering"
509 maybe_hval <- GHC.compileExpr session flush_cmd
511 Just hval -> writeIORef flush_interp (unsafeCoerce# hval :: IO ())
512 _ -> panic "interactiveUI:flush"
514 turnOffBuffering -- Turn it off right now
519 flushInterpBuffers :: GHCi ()
521 = io $ do Monad.join (readIORef flush_interp)
524 turnOffBuffering :: IO ()
526 = do Monad.join (readIORef turn_off_buffering)
529 -----------------------------------------------------------------------------
532 help :: String -> GHCi ()
533 help _ = io (putStr helpText)
535 info :: String -> GHCi ()
536 info "" = throwDyn (CmdLineError "syntax: ':i <thing-you-want-info-about>'")
537 info s = do { let names = words s
538 ; session <- getSession
539 ; dflags <- getDynFlags
540 ; let exts = dopt Opt_GlasgowExts dflags
541 ; mapM_ (infoThing exts session) names }
543 infoThing exts session str = io $ do
544 names <- GHC.parseName session str
545 let filtered = filterOutChildren names
546 mb_stuffs <- mapM (GHC.getInfo session) filtered
547 unqual <- GHC.getPrintUnqual session
548 putStrLn (showSDocForUser unqual $
549 vcat (intersperse (text "") $
550 [ pprInfo exts stuff | Just stuff <- mb_stuffs ]))
552 -- Filter out names whose parent is also there Good
553 -- example is '[]', which is both a type and data
554 -- constructor in the same type
555 filterOutChildren :: [Name] -> [Name]
556 filterOutChildren names = filter (not . parent_is_there) names
557 where parent_is_there n
558 | Just p <- GHC.nameParent_maybe n = p `elem` names
561 pprInfo exts (thing, fixity, insts)
562 = pprTyThingInContextLoc exts thing
563 $$ show_fixity fixity
564 $$ vcat (map GHC.pprInstance insts)
567 | fix == GHC.defaultFixity = empty
568 | otherwise = ppr fix <+> ppr (GHC.getName thing)
570 -----------------------------------------------------------------------------
573 addModule :: [FilePath] -> GHCi ()
575 io (revertCAFs) -- always revert CAFs on load/add.
576 files <- mapM expandPath files
577 targets <- mapM (\m -> io (GHC.guessTarget m Nothing)) files
578 session <- getSession
579 io (mapM_ (GHC.addTarget session) targets)
580 ok <- io (GHC.load session LoadAllTargets)
583 changeDirectory :: String -> GHCi ()
584 changeDirectory dir = do
585 session <- getSession
586 graph <- io (GHC.getModuleGraph session)
587 when (not (null graph)) $
588 io $ putStr "Warning: changing directory causes all loaded modules to be unloaded,\nbecause the search path has changed.\n"
589 io (GHC.setTargets session [])
590 io (GHC.load session LoadAllTargets)
591 setContextAfterLoad []
592 io (GHC.workingDirectoryChanged session)
593 dir <- expandPath dir
594 io (setCurrentDirectory dir)
596 defineMacro :: String -> GHCi ()
598 let (macro_name, definition) = break isSpace s
599 cmds <- io (readIORef commands)
601 then throwDyn (CmdLineError "invalid macro name")
603 if (macro_name `elem` map fst cmds)
604 then throwDyn (CmdLineError
605 ("command '" ++ macro_name ++ "' is already defined"))
608 -- give the expression a type signature, so we can be sure we're getting
609 -- something of the right type.
610 let new_expr = '(' : definition ++ ") :: String -> IO String"
612 -- compile the expression
614 maybe_hv <- io (GHC.compileExpr cms new_expr)
617 Just hv -> io (writeIORef commands --
618 ((macro_name, keepGoing (runMacro hv)) : cmds))
620 runMacro :: GHC.HValue{-String -> IO String-} -> String -> GHCi ()
622 str <- io ((unsafeCoerce# fun :: String -> IO String) s)
623 stringLoop (lines str)
625 undefineMacro :: String -> GHCi ()
626 undefineMacro macro_name = do
627 cmds <- io (readIORef commands)
628 if (macro_name `elem` map fst builtin_commands)
629 then throwDyn (CmdLineError
630 ("command '" ++ macro_name ++ "' cannot be undefined"))
632 if (macro_name `notElem` map fst cmds)
633 then throwDyn (CmdLineError
634 ("command '" ++ macro_name ++ "' not defined"))
636 io (writeIORef commands (filter ((/= macro_name) . fst) cmds))
639 loadModule :: [(FilePath, Maybe Phase)] -> GHCi SuccessFlag
640 loadModule fs = timeIt (loadModule' fs)
642 loadModule_ :: [FilePath] -> GHCi ()
643 loadModule_ fs = do loadModule (zip fs (repeat Nothing)); return ()
645 loadModule' :: [(FilePath, Maybe Phase)] -> GHCi SuccessFlag
646 loadModule' files = do
647 session <- getSession
650 io (GHC.setTargets session [])
651 io (GHC.load session LoadAllTargets)
654 let (filenames, phases) = unzip files
655 exp_filenames <- mapM expandPath filenames
656 let files' = zip exp_filenames phases
657 targets <- io (mapM (uncurry GHC.guessTarget) files')
659 -- NOTE: we used to do the dependency anal first, so that if it
660 -- fails we didn't throw away the current set of modules. This would
661 -- require some re-working of the GHC interface, so we'll leave it
662 -- as a ToDo for now.
664 io (GHC.setTargets session targets)
665 ok <- io (GHC.load session LoadAllTargets)
669 checkModule :: String -> GHCi ()
671 let modl = mkModule m
672 session <- getSession
673 result <- io (GHC.checkModule session modl printErrorsAndWarnings)
675 Nothing -> io $ putStrLn "Nothing"
676 Just r -> io $ putStrLn (showSDoc (
677 case checkedModuleInfo r of
678 Just cm | Just scope <- GHC.modInfoTopLevelScope cm ->
680 (local,global) = partition ((== modl) . GHC.nameModule) scope
682 (text "global names: " <+> ppr global) $$
683 (text "local names: " <+> ppr local)
685 afterLoad (successIf (isJust result)) session
687 reloadModule :: String -> GHCi ()
689 io (revertCAFs) -- always revert CAFs on reload.
690 session <- getSession
691 ok <- io (GHC.load session LoadAllTargets)
694 io (revertCAFs) -- always revert CAFs on reload.
695 session <- getSession
696 ok <- io (GHC.load session (LoadUpTo (mkModule m)))
699 afterLoad ok session = do
700 io (revertCAFs) -- always revert CAFs on load.
701 graph <- io (GHC.getModuleGraph session)
702 let mods = map GHC.ms_mod graph
703 mods' <- filterM (io . GHC.isLoaded session) mods
704 setContextAfterLoad mods'
705 modulesLoadedMsg ok mods'
707 setContextAfterLoad [] = do
708 session <- getSession
709 io (GHC.setContext session [] [prelude_mod])
710 setContextAfterLoad (m:_) = do
711 session <- getSession
712 b <- io (GHC.moduleIsInterpreted session m)
713 if b then io (GHC.setContext session [m] [])
714 else io (GHC.setContext session [] [prelude_mod,m])
716 modulesLoadedMsg :: SuccessFlag -> [Module] -> GHCi ()
717 modulesLoadedMsg ok mods = do
718 dflags <- getDynFlags
719 when (verbosity dflags > 0) $ do
721 | null mods = text "none."
723 punctuate comma (map pprModule mods)) <> text "."
726 io (putStrLn (showSDoc (text "Failed, modules loaded: " <> mod_commas)))
728 io (putStrLn (showSDoc (text "Ok, modules loaded: " <> mod_commas)))
731 typeOfExpr :: String -> GHCi ()
733 = do cms <- getSession
734 maybe_ty <- io (GHC.exprType cms str)
737 Just ty -> do ty' <- cleanType ty
738 tystr <- showForUser (ppr ty')
739 io (putStrLn (str ++ " :: " ++ tystr))
741 kindOfType :: String -> GHCi ()
743 = do cms <- getSession
744 maybe_ty <- io (GHC.typeKind cms str)
747 Just ty -> do tystr <- showForUser (ppr ty)
748 io (putStrLn (str ++ " :: " ++ tystr))
750 quit :: String -> GHCi Bool
753 shellEscape :: String -> GHCi Bool
754 shellEscape str = io (system str >> return False)
756 -----------------------------------------------------------------------------
757 -- create tags file for currently loaded modules.
759 createETagsFileCmd, createCTagsFileCmd :: String -> GHCi ()
761 createCTagsFileCmd "" = ghciCreateTagsFile CTags "tags"
762 createCTagsFileCmd file = ghciCreateTagsFile CTags file
764 createETagsFileCmd "" = ghciCreateTagsFile ETags "TAGS"
765 createETagsFileCmd file = ghciCreateTagsFile ETags file
767 data TagsKind = ETags | CTags
769 ghciCreateTagsFile :: TagsKind -> FilePath -> GHCi ()
770 ghciCreateTagsFile kind file = do
771 session <- getSession
772 io $ createTagsFile session kind file
775 -- - remove restriction that all modules must be interpreted
776 -- (problem: we don't know source locations for entities unless
777 -- we compiled the module.
779 -- - extract createTagsFile so it can be used from the command-line
780 -- (probably need to fix first problem before this is useful).
782 createTagsFile :: Session -> TagsKind -> FilePath -> IO ()
783 createTagsFile session tagskind tagFile = do
784 graph <- GHC.getModuleGraph session
785 let ms = map GHC.ms_mod graph
787 is_interpreted <- GHC.moduleIsInterpreted session m
788 -- should we just skip these?
789 when (not is_interpreted) $
790 throwDyn (CmdLineError ("module '" ++ moduleUserString m ++ "' is not interpreted"))
792 mbModInfo <- GHC.getModuleInfo session m
794 | Just modinfo <- mbModInfo,
795 Just unqual <- GHC.modInfoPrintUnqualified modinfo = unqual
796 | otherwise = GHC.alwaysQualify
799 Just modInfo -> return $! listTags unqual modInfo
802 mtags <- mapM tagModule ms
803 either_res <- collateAndWriteTags tagskind tagFile $ concat mtags
805 Left e -> hPutStrLn stderr $ ioeGetErrorString e
808 listTags :: PrintUnqualified -> GHC.ModuleInfo -> [TagInfo]
809 listTags unqual modInfo =
810 [ tagInfo unqual name loc
811 | name <- GHC.modInfoExports modInfo
812 , let loc = nameSrcLoc name
816 type TagInfo = (String -- tag name
819 ,Int -- column number
822 -- get tag info, for later translation into Vim or Emacs style
823 tagInfo :: PrintUnqualified -> Name -> SrcLoc -> TagInfo
824 tagInfo unqual name loc
825 = ( showSDocForUser unqual $ pprOccName (nameOccName name)
826 , showSDocForUser unqual $ ftext (srcLocFile loc)
831 collateAndWriteTags :: TagsKind -> FilePath -> [TagInfo] -> IO (Either IOError ())
832 collateAndWriteTags CTags file tagInfos = do -- ctags style, Vim et al
833 let tags = unlines $ sortLe (<=) $ nub $ map showTag tagInfos
834 IO.try (writeFile file tags)
835 collateAndWriteTags ETags file tagInfos = do -- etags style, Emacs/XEmacs
836 let byFile op (_,f1,_,_) (_,f2,_,_) = f1 `op` f2
837 groups = groupBy (byFile (==)) $ sortLe (byFile (<=)) tagInfos
838 tagGroups <- mapM tagFileGroup groups
839 IO.try (writeFile file $ concat tagGroups)
841 tagFileGroup group@[] = throwDyn (CmdLineError "empty tag file group??")
842 tagFileGroup group@((_,fileName,_,_):_) = do
843 file <- readFile fileName -- need to get additional info from sources..
844 let byLine (_,_,l1,_) (_,_,l2,_) = l1 <= l2
845 sortedGroup = sortLe byLine group
846 tags = unlines $ perFile sortedGroup 1 0 $ lines file
847 return $ "\x0c\n" ++ fileName ++ "," ++ show (length tags) ++ "\n" ++ tags
848 perFile (tagInfo@(tag,file,lNo,colNo):tags) count pos (line:lines) | lNo>count =
849 perFile (tagInfo:tags) (count+1) (pos+length line) lines
850 perFile (tagInfo@(tag,file,lNo,colNo):tags) count pos lines@(line:_) | lNo==count =
851 showETag tagInfo line pos : perFile tags count pos lines
852 perFile tags count pos lines = []
854 -- simple ctags format, for Vim et al
855 showTag :: TagInfo -> String
856 showTag (tag,file,lineNo,colNo)
857 = tag ++ "\t" ++ file ++ "\t" ++ show lineNo
859 -- etags format, for Emacs/XEmacs
860 showETag :: TagInfo -> String -> Int -> String
861 showETag (tag,file,lineNo,colNo) line charPos
862 = take colNo line ++ tag
864 ++ "\x01" ++ show lineNo
865 ++ "," ++ show charPos
867 -----------------------------------------------------------------------------
868 -- Browsing a module's contents
870 browseCmd :: String -> GHCi ()
873 ['*':m] | looksLikeModuleName m -> browseModule m False
874 [m] | looksLikeModuleName m -> browseModule m True
875 _ -> throwDyn (CmdLineError "syntax: :browse <module>")
877 browseModule m exports_only = do
880 let modl = mkModule m
881 is_interpreted <- io (GHC.moduleIsInterpreted s modl)
882 when (not is_interpreted && not exports_only) $
883 throwDyn (CmdLineError ("module '" ++ m ++ "' is not interpreted"))
885 -- Temporarily set the context to the module we're interested in,
886 -- just so we can get an appropriate PrintUnqualified
887 (as,bs) <- io (GHC.getContext s)
888 io (if exports_only then GHC.setContext s [] [prelude_mod,modl]
889 else GHC.setContext s [modl] [])
890 unqual <- io (GHC.getPrintUnqual s)
891 io (GHC.setContext s as bs)
893 mb_mod_info <- io $ GHC.getModuleInfo s modl
895 Nothing -> throwDyn (CmdLineError ("unknown module: " ++ m))
898 | exports_only = GHC.modInfoExports mod_info
899 | otherwise = fromMaybe [] (GHC.modInfoTopLevelScope mod_info)
901 filtered = filterOutChildren names
903 things <- io $ mapM (GHC.lookupName s) filtered
905 dflags <- getDynFlags
906 let exts = dopt Opt_GlasgowExts dflags
907 io (putStrLn (showSDocForUser unqual (
908 vcat (map (pprTyThingInContext exts) (catMaybes things))
910 -- ToDo: modInfoInstances currently throws an exception for
911 -- package modules. When it works, we can do this:
912 -- $$ vcat (map GHC.pprInstance (GHC.modInfoInstances mod_info))
914 -----------------------------------------------------------------------------
915 -- Setting the module context
918 | all sensible mods = fn mods
919 | otherwise = throwDyn (CmdLineError "syntax: :module [+/-] [*]M1 ... [*]Mn")
921 (fn, mods) = case str of
922 '+':stuff -> (addToContext, words stuff)
923 '-':stuff -> (removeFromContext, words stuff)
924 stuff -> (newContext, words stuff)
926 sensible ('*':m) = looksLikeModuleName m
927 sensible m = looksLikeModuleName m
930 session <- getSession
931 (as,bs) <- separate session mods [] []
932 let bs' = if null as && prelude_mod `notElem` bs then prelude_mod:bs else bs
933 io (GHC.setContext session as bs')
935 separate :: Session -> [String] -> [Module] -> [Module]
936 -> GHCi ([Module],[Module])
937 separate session [] as bs = return (as,bs)
938 separate session (('*':m):ms) as bs = do
939 let modl = mkModule m
940 b <- io (GHC.moduleIsInterpreted session modl)
941 if b then separate session ms (modl:as) bs
942 else throwDyn (CmdLineError ("module '" ++ m ++ "' is not interpreted"))
943 separate session (m:ms) as bs = separate session ms as (mkModule m:bs)
945 prelude_mod = mkModule "Prelude"
948 addToContext mods = do
950 (as,bs) <- io (GHC.getContext cms)
952 (as',bs') <- separate cms mods [] []
954 let as_to_add = as' \\ (as ++ bs)
955 bs_to_add = bs' \\ (as ++ bs)
957 io (GHC.setContext cms (as ++ as_to_add) (bs ++ bs_to_add))
960 removeFromContext mods = do
962 (as,bs) <- io (GHC.getContext cms)
964 (as_to_remove,bs_to_remove) <- separate cms mods [] []
966 let as' = as \\ (as_to_remove ++ bs_to_remove)
967 bs' = bs \\ (as_to_remove ++ bs_to_remove)
969 io (GHC.setContext cms as' bs')
971 ----------------------------------------------------------------------------
974 -- set options in the interpreter. Syntax is exactly the same as the
975 -- ghc command line, except that certain options aren't available (-C,
978 -- This is pretty fragile: most options won't work as expected. ToDo:
979 -- figure out which ones & disallow them.
981 setCmd :: String -> GHCi ()
983 = do st <- getGHCiState
984 let opts = options st
985 io $ putStrLn (showSDoc (
986 text "options currently set: " <>
989 else hsep (map (\o -> char '+' <> text (optToStr o)) opts)
993 ("args":args) -> setArgs args
994 ("prog":prog) -> setProg prog
995 wds -> setOptions wds
999 setGHCiState st{ args = args }
1003 setGHCiState st{ progname = prog }
1005 io (hPutStrLn stderr "syntax: :set prog <progname>")
1008 do -- first, deal with the GHCi opts (+s, +t, etc.)
1009 let (plus_opts, minus_opts) = partition isPlus wds
1010 mapM_ setOpt plus_opts
1012 -- then, dynamic flags
1013 dflags <- getDynFlags
1014 (dflags',leftovers) <- io $ GHC.parseDynamicFlags dflags minus_opts
1017 -- update things if the users wants more packages
1019 let new_packages = pkgs_after \\ pkgs_before
1020 when (not (null new_packages)) $
1021 newPackages new_packages
1024 if (not (null leftovers))
1025 then throwDyn (CmdLineError ("unrecognised flags: " ++
1030 unsetOptions :: String -> GHCi ()
1032 = do -- first, deal with the GHCi opts (+s, +t, etc.)
1033 let opts = words str
1034 (minus_opts, rest1) = partition isMinus opts
1035 (plus_opts, rest2) = partition isPlus rest1
1037 if (not (null rest2))
1038 then io (putStrLn ("unknown option: '" ++ head rest2 ++ "'"))
1041 mapM_ unsetOpt plus_opts
1043 -- can't do GHC flags for now
1044 if (not (null minus_opts))
1045 then throwDyn (CmdLineError "can't unset GHC command-line flags")
1048 isMinus ('-':s) = True
1051 isPlus ('+':s) = True
1055 = case strToGHCiOpt str of
1056 Nothing -> io (putStrLn ("unknown option: '" ++ str ++ "'"))
1057 Just o -> setOption o
1060 = case strToGHCiOpt str of
1061 Nothing -> io (putStrLn ("unknown option: '" ++ str ++ "'"))
1062 Just o -> unsetOption o
1064 strToGHCiOpt :: String -> (Maybe GHCiOption)
1065 strToGHCiOpt "s" = Just ShowTiming
1066 strToGHCiOpt "t" = Just ShowType
1067 strToGHCiOpt "r" = Just RevertCAFs
1068 strToGHCiOpt _ = Nothing
1070 optToStr :: GHCiOption -> String
1071 optToStr ShowTiming = "s"
1072 optToStr ShowType = "t"
1073 optToStr RevertCAFs = "r"
1076 newPackages new_pkgs = do -- The new packages are already in v_Packages
1077 session <- getSession
1078 io (GHC.setTargets session [])
1079 io (GHC.load session Nothing)
1080 dflags <- getDynFlags
1081 io (linkPackages dflags new_pkgs)
1082 setContextAfterLoad []
1085 -- ---------------------------------------------------------------------------
1090 ["modules" ] -> showModules
1091 ["bindings"] -> showBindings
1092 ["linker"] -> io showLinkerState
1093 _ -> throwDyn (CmdLineError "syntax: :show [modules|bindings]")
1096 session <- getSession
1097 let show_one ms = do m <- io (GHC.showModule session ms)
1099 graph <- io (GHC.getModuleGraph session)
1100 mapM_ show_one graph
1104 unqual <- io (GHC.getPrintUnqual s)
1105 bindings <- io (GHC.getBindings s)
1106 mapM_ showTyThing bindings
1109 showTyThing (AnId id) = do
1110 ty' <- cleanType (GHC.idType id)
1111 str <- showForUser (ppr id <> text " :: " <> ppr ty')
1113 showTyThing _ = return ()
1115 -- if -fglasgow-exts is on we show the foralls, otherwise we don't.
1116 cleanType :: Type -> GHCi Type
1118 dflags <- getDynFlags
1119 if dopt Opt_GlasgowExts dflags
1121 else return $! GHC.dropForAlls ty
1123 -----------------------------------------------------------------------------
1126 data GHCiState = GHCiState
1130 session :: GHC.Session,
1131 options :: [GHCiOption]
1135 = ShowTiming -- show time/allocs after evaluation
1136 | ShowType -- show the type of expressions
1137 | RevertCAFs -- revert CAFs after every evaluation
1140 newtype GHCi a = GHCi { unGHCi :: IORef GHCiState -> IO a }
1142 startGHCi :: GHCi a -> GHCiState -> IO a
1143 startGHCi g state = do ref <- newIORef state; unGHCi g ref
1145 instance Monad GHCi where
1146 (GHCi m) >>= k = GHCi $ \s -> m s >>= \a -> unGHCi (k a) s
1147 return a = GHCi $ \s -> return a
1149 ghciHandleDyn :: Typeable t => (t -> GHCi a) -> GHCi a -> GHCi a
1150 ghciHandleDyn h (GHCi m) = GHCi $ \s ->
1151 Exception.catchDyn (m s) (\e -> unGHCi (h e) s)
1153 getGHCiState = GHCi $ \r -> readIORef r
1154 setGHCiState s = GHCi $ \r -> writeIORef r s
1156 -- for convenience...
1157 getSession = getGHCiState >>= return . session
1161 io (GHC.getSessionDynFlags s)
1162 setDynFlags dflags = do
1164 io (GHC.setSessionDynFlags s dflags)
1166 isOptionSet :: GHCiOption -> GHCi Bool
1168 = do st <- getGHCiState
1169 return (opt `elem` options st)
1171 setOption :: GHCiOption -> GHCi ()
1173 = do st <- getGHCiState
1174 setGHCiState (st{ options = opt : filter (/= opt) (options st) })
1176 unsetOption :: GHCiOption -> GHCi ()
1178 = do st <- getGHCiState
1179 setGHCiState (st{ options = filter (/= opt) (options st) })
1181 io :: IO a -> GHCi a
1182 io m = GHCi { unGHCi = \s -> m >>= return }
1184 -----------------------------------------------------------------------------
1185 -- recursive exception handlers
1187 -- Don't forget to unblock async exceptions in the handler, or if we're
1188 -- in an exception loop (eg. let a = error a in a) the ^C exception
1189 -- may never be delivered. Thanks to Marcin for pointing out the bug.
1191 ghciHandle :: (Exception -> GHCi a) -> GHCi a -> GHCi a
1192 ghciHandle h (GHCi m) = GHCi $ \s ->
1193 Exception.catch (m s)
1194 (\e -> unGHCi (ghciUnblock (h e)) s)
1196 ghciUnblock :: GHCi a -> GHCi a
1197 ghciUnblock (GHCi a) = GHCi $ \s -> Exception.unblock (a s)
1199 -----------------------------------------------------------------------------
1200 -- timing & statistics
1202 timeIt :: GHCi a -> GHCi a
1204 = do b <- isOptionSet ShowTiming
1207 else do allocs1 <- io $ getAllocations
1208 time1 <- io $ getCPUTime
1210 allocs2 <- io $ getAllocations
1211 time2 <- io $ getCPUTime
1212 io $ printTimes (fromIntegral (allocs2 - allocs1))
1216 foreign import ccall unsafe "getAllocations" getAllocations :: IO Int64
1217 -- defined in ghc/rts/Stats.c
1219 printTimes :: Integer -> Integer -> IO ()
1220 printTimes allocs psecs
1221 = do let secs = (fromIntegral psecs / (10^12)) :: Float
1222 secs_str = showFFloat (Just 2) secs
1223 putStrLn (showSDoc (
1224 parens (text (secs_str "") <+> text "secs" <> comma <+>
1225 text (show allocs) <+> text "bytes")))
1227 -----------------------------------------------------------------------------
1234 -- Have to turn off buffering again, because we just
1235 -- reverted stdout, stderr & stdin to their defaults.
1237 foreign import ccall "revertCAFs" rts_revertCAFs :: IO ()
1238 -- Make it "safe", just in case
1240 -- -----------------------------------------------------------------------------
1243 expandPath :: String -> GHCi String
1245 case dropWhile isSpace path of
1247 tilde <- io (getEnv "HOME") -- will fail if HOME not defined
1248 return (tilde ++ '/':d)