1 {-# OPTIONS -#include "Linker.h" #-}
2 -----------------------------------------------------------------------------
4 -- GHC Interactive User Interface
6 -- (c) The GHC Team 2005-2006
8 -----------------------------------------------------------------------------
14 #include "HsVersions.h"
20 import GHC ( Session, LoadHowMuch(..), Target(..), TargetId(..),
21 Type, Module, ModuleName, TyThing(..), Phase,
30 import Module -- for ModuleEnv
37 -- Other random utilities
39 import BasicTypes hiding (isTopLevel)
40 import Panic hiding (showException)
46 #ifndef mingw32_HOST_OS
48 #if __GLASGOW_HASKELL__ > 504
52 import GHC.ConsoleHandler ( flushConsole )
53 import System.Win32 ( setConsoleCP, setConsoleOutputCP )
54 import qualified System.Win32
58 import Control.Concurrent ( yield ) -- Used in readline loop
59 import System.Console.Readline as Readline
64 import Control.Exception as Exception
65 -- import Control.Concurrent
70 import System.Environment
71 import System.Exit ( exitWith, ExitCode(..) )
72 import System.Directory
74 import System.IO.Error as IO
78 import Control.Monad as Monad
80 import Foreign.StablePtr ( newStablePtr )
81 import GHC.Exts ( unsafeCoerce# )
82 import GHC.IOBase ( IOErrorType(InvalidArgument), IO(IO) )
84 import Data.IORef ( IORef, readIORef, writeIORef )
86 import System.Posix.Internals ( setNonBlockingFD )
88 -- these are needed by the new ghci debugger
89 import ByteCodeLink (HValue)
90 import ByteCodeInstr (BreakInfo (..))
93 -----------------------------------------------------------------------------
97 " / _ \\ /\\ /\\/ __(_)\n"++
98 " / /_\\// /_/ / / | | GHC Interactive, version " ++ cProjectVersion ++ ", for Haskell 98.\n"++
99 "/ /_\\\\/ __ / /___| | http://www.haskell.org/ghc/\n"++
100 "\\____/\\/ /_/\\____/|_| Type :? for help.\n"
102 type Command = (String, String -> GHCi Bool, Bool, String -> IO [String])
103 cmdName (n,_,_,_) = n
105 GLOBAL_VAR(commands, builtin_commands, [Command])
107 builtin_commands :: [Command]
109 -- Hugs users are accustomed to :e, so make sure it doesn't overlap
110 ("?", keepGoing help, False, completeNone),
111 ("add", keepGoingPaths addModule, False, completeFilename),
112 ("break", breakCmd, False, completeNone),
113 ("browse", keepGoing browseCmd, False, completeModule),
114 ("cd", keepGoing changeDirectory, False, completeFilename),
115 ("check", keepGoing checkModule, False, completeHomeModule),
116 ("continue", continueCmd, False, completeNone),
117 ("ctags", keepGoing createCTagsFileCmd, False, completeFilename),
118 ("def", keepGoing defineMacro, False, completeIdentifier),
119 ("delete", deleteCmd, False, completeNone),
120 ("e", keepGoing editFile, False, completeFilename),
121 ("edit", keepGoing editFile, False, completeFilename),
122 ("etags", keepGoing createETagsFileCmd, False, completeFilename),
123 ("force", keepGoing (pprintClosureCommand False True), False, completeIdentifier),
124 ("help", keepGoing help, False, completeNone),
125 ("info", keepGoing info, False, completeIdentifier),
126 ("kind", keepGoing kindOfType, False, completeIdentifier),
127 ("load", keepGoingPaths loadModule_,False, completeHomeModuleOrFile),
128 ("module", keepGoing setContext, False, completeModule),
129 ("main", keepGoing runMain, False, completeIdentifier),
130 ("print", keepGoing (pprintClosureCommand True False), False, completeIdentifier),
131 ("quit", quit, False, completeNone),
132 ("reload", keepGoing reloadModule, False, completeNone),
133 ("set", keepGoing setCmd, True, completeSetOptions),
134 ("show", keepGoing showCmd, False, completeNone),
135 ("sprint", keepGoing (pprintClosureCommand False False),False, completeIdentifier),
136 ("step", stepCmd, False, completeNone),
137 ("type", keepGoing typeOfExpr, False, completeIdentifier),
138 ("undef", keepGoing undefineMacro, False, completeMacro),
139 ("unset", keepGoing unsetOptions, True, completeSetOptions)
142 keepGoing :: (String -> GHCi ()) -> (String -> GHCi Bool)
143 keepGoing a str = a str >> return False
145 keepGoingPaths :: ([FilePath] -> GHCi ()) -> (String -> GHCi Bool)
146 keepGoingPaths a str = a (toArgs str) >> return False
148 shortHelpText = "use :? for help.\n"
150 -- NOTE: spaces at the end of each line to workaround CPP/string gap bug.
152 " Commands available from the prompt:\n" ++
154 " <stmt> evaluate/run <stmt>\n" ++
155 " :add <filename> ... add module(s) to the current target set\n" ++
156 " :browse [*]<module> display the names defined by <module>\n" ++
157 " :cd <dir> change directory to <dir>\n" ++
158 " :def <cmd> <expr> define a command :<cmd>\n" ++
159 " :edit <file> edit file\n" ++
160 " :edit edit last module\n" ++
161 " :help, :? display this list of commands\n" ++
162 " :info [<name> ...] display information about the given names\n" ++
163 " :print [<name> ...] prints a value without forcing its computation\n" ++
164 " :sprint [<name> ...] simplified version of :print\n" ++
165 " :load <filename> ... load module(s) and their dependents\n" ++
166 " :module [+/-] [*]<mod> ... set the context for expression evaluation\n" ++
167 " :main [<arguments> ...] run the main function with the given arguments\n" ++
168 " :reload reload the current module set\n" ++
170 " :set <option> ... set options\n" ++
171 " :set args <arg> ... set the arguments returned by System.getArgs\n" ++
172 " :set prog <progname> set the value returned by System.getProgName\n" ++
173 " :set prompt <prompt> set the prompt used in GHCi\n" ++
174 " :set editor <cmd> set the command used for :edit\n" ++
176 " :show modules show the currently loaded modules\n" ++
177 " :show bindings show the current bindings made at the prompt\n" ++
179 " :ctags [<file>] create tags file for Vi (default: \"tags\")\n" ++
180 " :etags [<file>] create tags file for Emacs (default: \"TAGS\")\n" ++
181 " :type <expr> show the type of <expr>\n" ++
182 " :kind <type> show the kind of <type>\n" ++
183 " :undef <cmd> undefine user-defined command :<cmd>\n" ++
184 " :unset <option> ... unset options\n" ++
185 " :quit exit GHCi\n" ++
186 " :!<command> run the shell command <command>\n" ++
188 " Options for ':set' and ':unset':\n" ++
190 " +r revert top-level expressions after each evaluation\n" ++
191 " +s print timing/memory stats after each evaluation\n" ++
192 " +t print type after evaluation\n" ++
193 " -<flags> most GHC command line flags can also be set here\n" ++
194 " (eg. -v2, -fglasgow-exts, etc.)\n" ++
196 -- Todo: add help for breakpoint commands here
202 win <- System.Win32.getWindowsDirectory
203 return (win `joinFileName` "notepad.exe")
208 interactiveUI :: Session -> [(FilePath, Maybe Phase)] -> Maybe String -> IO ()
209 interactiveUI session srcs maybe_expr = do
210 -- HACK! If we happen to get into an infinite loop (eg the user
211 -- types 'let x=x in x' at the prompt), then the thread will block
212 -- on a blackhole, and become unreachable during GC. The GC will
213 -- detect that it is unreachable and send it the NonTermination
214 -- exception. However, since the thread is unreachable, everything
215 -- it refers to might be finalized, including the standard Handles.
216 -- This sounds like a bug, but we don't have a good solution right
222 -- Initialise buffering for the *interpreted* I/O system
223 initInterpBuffering session
225 when (isNothing maybe_expr) $ do
226 -- Only for GHCi (not runghc and ghc -e):
227 -- Turn buffering off for the compiled program's stdout/stderr
229 -- Turn buffering off for GHCi's stdout
231 hSetBuffering stdout NoBuffering
232 -- We don't want the cmd line to buffer any input that might be
233 -- intended for the program, so unbuffer stdin.
234 hSetBuffering stdin NoBuffering
236 -- initial context is just the Prelude
237 prel_mod <- GHC.findModule session prel_name (Just basePackageId)
238 GHC.setContext session [] [prel_mod]
242 Readline.setAttemptedCompletionFunction (Just completeWord)
243 --Readline.parseAndBind "set show-all-if-ambiguous 1"
245 let symbols = "!#$%&*+/<=>?@\\^|-~"
246 specials = "(),;[]`{}"
248 word_break_chars = spaces ++ specials ++ symbols
250 Readline.setBasicWordBreakCharacters word_break_chars
251 Readline.setCompleterWordBreakCharacters word_break_chars
254 default_editor <- findEditor
256 startGHCi (runGHCi srcs maybe_expr)
257 GHCiState{ progname = "<interactive>",
260 editor = default_editor,
265 breaks = emptyActiveBreakPoints,
266 tickarrays = emptyModuleEnv
270 Readline.resetTerminal Nothing
275 prel_name = GHC.mkModuleName "Prelude"
277 runGHCi :: [(FilePath, Maybe Phase)] -> Maybe String -> GHCi ()
278 runGHCi paths maybe_expr = do
279 let read_dot_files = not opt_IgnoreDotGhci
281 when (read_dot_files) $ do
284 exists <- io (doesFileExist file)
286 dir_ok <- io (checkPerms ".")
287 file_ok <- io (checkPerms file)
288 when (dir_ok && file_ok) $ do
289 either_hdl <- io (IO.try (openFile "./.ghci" ReadMode))
292 Right hdl -> fileLoop hdl False
294 when (read_dot_files) $ do
295 -- Read in $HOME/.ghci
296 either_dir <- io (IO.try (getEnv "HOME"))
300 cwd <- io (getCurrentDirectory)
301 when (dir /= cwd) $ do
302 let file = dir ++ "/.ghci"
303 ok <- io (checkPerms file)
305 either_hdl <- io (IO.try (openFile file ReadMode))
308 Right hdl -> fileLoop hdl False
310 -- Perform a :load for files given on the GHCi command line
311 -- When in -e mode, if the load fails then we want to stop
312 -- immediately rather than going on to evaluate the expression.
313 when (not (null paths)) $ do
314 ok <- ghciHandle (\e -> do showException e; return Failed) $
316 when (isJust maybe_expr && failed ok) $
317 io (exitWith (ExitFailure 1))
319 -- if verbosity is greater than 0, or we are connected to a
320 -- terminal, display the prompt in the interactive loop.
321 is_tty <- io (hIsTerminalDevice stdin)
322 dflags <- getDynFlags
323 let show_prompt = verbosity dflags > 0 || is_tty
328 #if defined(mingw32_HOST_OS)
329 -- The win32 Console API mutates the first character of
330 -- type-ahead when reading from it in a non-buffered manner. Work
331 -- around this by flushing the input buffer of type-ahead characters,
332 -- but only if stdin is available.
333 flushed <- io (IO.try (GHC.ConsoleHandler.flushConsole stdin))
335 Left err | isDoesNotExistError err -> return ()
336 | otherwise -> io (ioError err)
337 Right () -> return ()
339 -- initialise the console if necessary
342 -- enter the interactive loop
343 interactiveLoop is_tty show_prompt
345 -- just evaluate the expression we were given
350 io $ do when (verbosity dflags > 0) $ putStrLn "Leaving GHCi."
353 interactiveLoop is_tty show_prompt =
354 -- Ignore ^C exceptions caught here
355 ghciHandleDyn (\e -> case e of
357 #if defined(mingw32_HOST_OS)
360 interactiveLoop is_tty show_prompt
361 _other -> return ()) $
363 ghciUnblock $ do -- unblock necessary if we recursed from the
364 -- exception handler above.
366 -- read commands from stdin
370 else fileLoop stdin show_prompt
372 fileLoop stdin show_prompt
376 -- NOTE: We only read .ghci files if they are owned by the current user,
377 -- and aren't world writable. Otherwise, we could be accidentally
378 -- running code planted by a malicious third party.
380 -- Furthermore, We only read ./.ghci if . is owned by the current user
381 -- and isn't writable by anyone else. I think this is sufficient: we
382 -- don't need to check .. and ../.. etc. because "." always refers to
383 -- the same directory while a process is running.
385 checkPerms :: String -> IO Bool
387 #ifdef mingw32_HOST_OS
390 Util.handle (\_ -> return False) $ do
391 st <- getFileStatus name
393 if fileOwner st /= me then do
394 putStrLn $ "WARNING: " ++ name ++ " is owned by someone else, IGNORING!"
397 let mode = fileMode st
398 if (groupWriteMode == (mode `intersectFileModes` groupWriteMode))
399 || (otherWriteMode == (mode `intersectFileModes` otherWriteMode))
401 putStrLn $ "*** WARNING: " ++ name ++
402 " is writable by someone else, IGNORING!"
407 fileLoop :: Handle -> Bool -> GHCi ()
408 fileLoop hdl show_prompt = do
409 session <- getSession
410 (mod,imports) <- io (GHC.getContext session)
412 when show_prompt (io (putStr (mkPrompt mod imports (prompt st))))
413 l <- io (IO.try (hGetLine hdl))
415 Left e | isEOFError e -> return ()
416 | InvalidArgument <- etype -> return ()
417 | otherwise -> io (ioError e)
418 where etype = ioeGetErrorType e
419 -- treat InvalidArgument in the same way as EOF:
420 -- this can happen if the user closed stdin, or
421 -- perhaps did getContents which closes stdin at
424 case removeSpaces l of
425 "" -> fileLoop hdl show_prompt
426 l -> do quit <- runCommand l
427 if quit then return () else fileLoop hdl show_prompt
429 stringLoop :: [String] -> GHCi Bool{-True: we quit-}
430 stringLoop [] = return False
431 stringLoop (s:ss) = do
432 case removeSpaces s of
434 l -> do quit <- runCommand l
435 if quit then return True else stringLoop ss
437 mkPrompt toplevs exports prompt
438 = showSDoc $ f prompt
440 f ('%':'s':xs) = perc_s <> f xs
441 f ('%':'%':xs) = char '%' <> f xs
442 f (x:xs) = char x <> f xs
445 perc_s = hsep (map (\m -> char '*' <> ppr (GHC.moduleName m)) toplevs) <+>
446 hsep (map (ppr . GHC.moduleName) exports)
450 readlineLoop :: GHCi ()
452 session <- getSession
453 (mod,imports) <- io (GHC.getContext session)
455 saveSession -- for use by completion
457 l <- io (readline (mkPrompt mod imports (prompt st))
458 `finally` setNonBlockingFD 0)
459 -- readline sometimes puts stdin into blocking mode,
460 -- so we need to put it back for the IO library
465 case removeSpaces l of
470 if quit then return () else readlineLoop
473 runCommand :: String -> GHCi Bool
474 runCommand c = ghciHandle handler (doCommand c)
476 doCommand (':' : command) = specialCommand command
478 = do timeIt (do nms <- runStmt stmt; finishEvalExpr nms)
481 -- This version is for the GHC command-line option -e. The only difference
482 -- from runCommand is that it catches the ExitException exception and
483 -- exits, rather than printing out the exception.
484 runCommandEval c = ghciHandle handleEval (doCommand c)
486 handleEval (ExitException code) = io (exitWith code)
487 handleEval e = do handler e
488 io (exitWith (ExitFailure 1))
490 doCommand (':' : command) = specialCommand command
492 = do nms <- runStmt stmt
494 Nothing -> io (exitWith (ExitFailure 1))
495 -- failure to run the command causes exit(1) for ghc -e.
496 _ -> finishEvalExpr nms
498 runStmt :: String -> GHCi (Maybe (Bool,[Name]))
500 | null (filter (not.isSpace) stmt) = return (Just (False,[]))
502 = do st <- getGHCiState
503 session <- getSession
504 result <- io $ withProgName (progname st) $ withArgs (args st) $
505 GHC.runStmt session stmt
506 switchOnRunResult result
508 switchOnRunResult :: GHC.RunResult -> GHCi (Maybe (Bool,[Name]))
509 switchOnRunResult GHC.RunFailed = return Nothing
510 switchOnRunResult (GHC.RunException e) = throw e
511 switchOnRunResult (GHC.RunOk names) = return $ Just (False,names)
512 switchOnRunResult (GHC.RunBreak threadId names info resume) = do
513 session <- getSession
514 Just mod_info <- io $ GHC.getModuleInfo session (breakInfo_module info)
515 let modBreaks = GHC.modInfoModBreaks mod_info
516 let ticks = GHC.modBreaks_locs modBreaks
518 -- display information about the breakpoint
519 let location = ticks ! breakInfo_number info
520 unqual <- io $ GHC.getPrintUnqual session
521 io $ printForUser stdout unqual $
522 ptext SLIT("Stopped at") <+> ppr location
524 pushResume location threadId resume
525 return (Just (True,names))
527 -- possibly print the type and revert CAFs after evaluating an expression
528 finishEvalExpr mb_names
529 = do show_types <- isOptionSet ShowType
530 session <- getSession
533 Just (is_break,names) ->
534 when (is_break || show_types) $
535 mapM_ (showTypeOfName session) names
538 io installSignalHandlers
539 b <- isOptionSet RevertCAFs
540 io (when b revertCAFs)
543 showTypeOfName :: Session -> Name -> GHCi ()
544 showTypeOfName session n
545 = do maybe_tything <- io (GHC.lookupName session n)
546 case maybe_tything of
548 Just thing -> showTyThing thing
550 specialCommand :: String -> GHCi Bool
551 specialCommand ('!':str) = shellEscape (dropWhile isSpace str)
552 specialCommand str = do
553 let (cmd,rest) = break isSpace str
554 maybe_cmd <- io (lookupCommand cmd)
556 Nothing -> io (hPutStr stdout ("unknown command ':" ++ cmd ++ "'\n"
557 ++ shortHelpText) >> return False)
558 Just (_,f,_,_) -> f (dropWhile isSpace rest)
560 lookupCommand :: String -> IO (Maybe Command)
561 lookupCommand str = do
562 cmds <- readIORef commands
563 -- look for exact match first, then the first prefix match
564 case [ c | c <- cmds, str == cmdName c ] of
565 c:_ -> return (Just c)
566 [] -> case [ c | c@(s,_,_,_) <- cmds, prefixMatch str s ] of
568 c:_ -> return (Just c)
570 -----------------------------------------------------------------------------
573 help :: String -> GHCi ()
574 help _ = io (putStr helpText)
576 info :: String -> GHCi ()
577 info "" = throwDyn (CmdLineError "syntax: ':i <thing-you-want-info-about>'")
578 info s = do { let names = words s
579 ; session <- getSession
580 ; dflags <- getDynFlags
581 ; let exts = dopt Opt_GlasgowExts dflags
582 ; mapM_ (infoThing exts session) names }
584 infoThing exts session str = io $ do
585 names <- GHC.parseName session str
586 let filtered = filterOutChildren names
587 mb_stuffs <- mapM (GHC.getInfo session) filtered
588 unqual <- GHC.getPrintUnqual session
589 putStrLn (showSDocForUser unqual $
590 vcat (intersperse (text "") $
591 [ pprInfo exts stuff | Just stuff <- mb_stuffs ]))
593 -- Filter out names whose parent is also there Good
594 -- example is '[]', which is both a type and data
595 -- constructor in the same type
596 filterOutChildren :: [Name] -> [Name]
597 filterOutChildren names = filter (not . parent_is_there) names
598 where parent_is_there n
599 -- | Just p <- GHC.nameParent_maybe n = p `elem` names
603 pprInfo exts (thing, fixity, insts)
604 = pprTyThingInContextLoc exts thing
605 $$ show_fixity fixity
606 $$ vcat (map GHC.pprInstance insts)
609 | fix == GHC.defaultFixity = empty
610 | otherwise = ppr fix <+> ppr (GHC.getName thing)
612 -----------------------------------------------------------------------------
615 runMain :: String -> GHCi ()
617 let ss = concat $ intersperse "," (map (\ s -> ('"':s)++"\"") (toArgs args))
618 runCommand $ '[': ss ++ "] `System.Environment.withArgs` main"
621 addModule :: [FilePath] -> GHCi ()
623 io (revertCAFs) -- always revert CAFs on load/add.
624 files <- mapM expandPath files
625 targets <- mapM (\m -> io (GHC.guessTarget m Nothing)) files
626 session <- getSession
627 io (mapM_ (GHC.addTarget session) targets)
628 ok <- io (GHC.load session LoadAllTargets)
631 changeDirectory :: String -> GHCi ()
632 changeDirectory dir = do
633 session <- getSession
634 graph <- io (GHC.getModuleGraph session)
635 when (not (null graph)) $
636 io $ putStr "Warning: changing directory causes all loaded modules to be unloaded,\nbecause the search path has changed.\n"
637 io (GHC.setTargets session [])
638 io (GHC.load session LoadAllTargets)
639 setContextAfterLoad session []
640 io (GHC.workingDirectoryChanged session)
641 dir <- expandPath dir
642 io (setCurrentDirectory dir)
644 editFile :: String -> GHCi ()
647 -- find the name of the "topmost" file loaded
648 session <- getSession
649 graph0 <- io (GHC.getModuleGraph session)
650 graph1 <- filterM (io . GHC.isLoaded session . GHC.ms_mod_name) graph0
651 let graph2 = flattenSCCs (GHC.topSortModuleGraph True graph1 Nothing)
652 case GHC.ml_hs_file (GHC.ms_location (last graph2)) of
653 Just file -> do_edit file
654 Nothing -> throwDyn (CmdLineError "unknown file name")
655 | otherwise = do_edit str
661 throwDyn (CmdLineError "editor not set, use :set editor")
662 io $ system (cmd ++ ' ':file)
665 defineMacro :: String -> GHCi ()
667 let (macro_name, definition) = break isSpace s
668 cmds <- io (readIORef commands)
670 then throwDyn (CmdLineError "invalid macro name")
672 if (macro_name `elem` map cmdName cmds)
673 then throwDyn (CmdLineError
674 ("command '" ++ macro_name ++ "' is already defined"))
677 -- give the expression a type signature, so we can be sure we're getting
678 -- something of the right type.
679 let new_expr = '(' : definition ++ ") :: String -> IO String"
681 -- compile the expression
683 maybe_hv <- io (GHC.compileExpr cms new_expr)
686 Just hv -> io (writeIORef commands --
687 (cmds ++ [(macro_name, runMacro hv, False, completeNone)]))
689 runMacro :: GHC.HValue{-String -> IO String-} -> String -> GHCi Bool
691 str <- io ((unsafeCoerce# fun :: String -> IO String) s)
692 stringLoop (lines str)
694 undefineMacro :: String -> GHCi ()
695 undefineMacro macro_name = do
696 cmds <- io (readIORef commands)
697 if (macro_name `elem` map cmdName builtin_commands)
698 then throwDyn (CmdLineError
699 ("command '" ++ macro_name ++ "' cannot be undefined"))
701 if (macro_name `notElem` map cmdName cmds)
702 then throwDyn (CmdLineError
703 ("command '" ++ macro_name ++ "' not defined"))
705 io (writeIORef commands (filter ((/= macro_name) . cmdName) cmds))
708 loadModule :: [(FilePath, Maybe Phase)] -> GHCi SuccessFlag
709 loadModule fs = timeIt (loadModule' fs)
711 loadModule_ :: [FilePath] -> GHCi ()
712 loadModule_ fs = do loadModule (zip fs (repeat Nothing)); return ()
714 loadModule' :: [(FilePath, Maybe Phase)] -> GHCi SuccessFlag
715 loadModule' files = do
716 session <- getSession
719 io (GHC.setTargets session [])
720 io (GHC.load session LoadAllTargets)
723 let (filenames, phases) = unzip files
724 exp_filenames <- mapM expandPath filenames
725 let files' = zip exp_filenames phases
726 targets <- io (mapM (uncurry GHC.guessTarget) files')
728 -- NOTE: we used to do the dependency anal first, so that if it
729 -- fails we didn't throw away the current set of modules. This would
730 -- require some re-working of the GHC interface, so we'll leave it
731 -- as a ToDo for now.
733 io (GHC.setTargets session targets)
734 ok <- io (GHC.load session LoadAllTargets)
738 checkModule :: String -> GHCi ()
740 let modl = GHC.mkModuleName m
741 session <- getSession
742 result <- io (GHC.checkModule session modl)
744 Nothing -> io $ putStrLn "Nothing"
745 Just r -> io $ putStrLn (showSDoc (
746 case GHC.checkedModuleInfo r of
747 Just cm | Just scope <- GHC.modInfoTopLevelScope cm ->
749 (local,global) = partition ((== modl) . GHC.moduleName . GHC.nameModule) scope
751 (text "global names: " <+> ppr global) $$
752 (text "local names: " <+> ppr local)
754 afterLoad (successIf (isJust result)) session
756 reloadModule :: String -> GHCi ()
758 io (revertCAFs) -- always revert CAFs on reload.
759 session <- getSession
760 ok <- io (GHC.load session LoadAllTargets)
763 io (revertCAFs) -- always revert CAFs on reload.
764 session <- getSession
765 ok <- io (GHC.load session (LoadUpTo (GHC.mkModuleName m)))
768 afterLoad ok session = do
769 io (revertCAFs) -- always revert CAFs on load.
772 discardActiveBreakPoints
773 graph <- io (GHC.getModuleGraph session)
774 graph' <- filterM (io . GHC.isLoaded session . GHC.ms_mod_name) graph
775 setContextAfterLoad session graph'
776 modulesLoadedMsg ok (map GHC.ms_mod_name graph')
778 setContextAfterLoad session [] = do
779 prel_mod <- getPrelude
780 io (GHC.setContext session [] [prel_mod])
781 setContextAfterLoad session ms = do
782 -- load a target if one is available, otherwise load the topmost module.
783 targets <- io (GHC.getTargets session)
784 case [ m | Just m <- map (findTarget ms) targets ] of
786 let graph' = flattenSCCs (GHC.topSortModuleGraph True ms Nothing) in
787 load_this (last graph')
792 = case filter (`matches` t) ms of
796 summary `matches` Target (TargetModule m) _
797 = GHC.ms_mod_name summary == m
798 summary `matches` Target (TargetFile f _) _
799 | Just f' <- GHC.ml_hs_file (GHC.ms_location summary) = f == f'
800 summary `matches` target
803 load_this summary | m <- GHC.ms_mod summary = do
804 b <- io (GHC.moduleIsInterpreted session m)
805 if b then io (GHC.setContext session [m] [])
807 prel_mod <- getPrelude
808 io (GHC.setContext session [] [prel_mod,m])
811 modulesLoadedMsg :: SuccessFlag -> [ModuleName] -> GHCi ()
812 modulesLoadedMsg ok mods = do
813 dflags <- getDynFlags
814 when (verbosity dflags > 0) $ do
816 | null mods = text "none."
818 punctuate comma (map ppr mods)) <> text "."
821 io (putStrLn (showSDoc (text "Failed, modules loaded: " <> mod_commas)))
823 io (putStrLn (showSDoc (text "Ok, modules loaded: " <> mod_commas)))
826 typeOfExpr :: String -> GHCi ()
828 = do cms <- getSession
829 maybe_ty <- io (GHC.exprType cms str)
832 Just ty -> do ty' <- cleanType ty
833 tystr <- showForUser (ppr ty')
834 io (putStrLn (str ++ " :: " ++ tystr))
836 kindOfType :: String -> GHCi ()
838 = do cms <- getSession
839 maybe_ty <- io (GHC.typeKind cms str)
842 Just ty -> do tystr <- showForUser (ppr ty)
843 io (putStrLn (str ++ " :: " ++ tystr))
845 quit :: String -> GHCi Bool
848 shellEscape :: String -> GHCi Bool
849 shellEscape str = io (system str >> return False)
851 -----------------------------------------------------------------------------
852 -- create tags file for currently loaded modules.
854 createETagsFileCmd, createCTagsFileCmd :: String -> GHCi ()
856 createCTagsFileCmd "" = ghciCreateTagsFile CTags "tags"
857 createCTagsFileCmd file = ghciCreateTagsFile CTags file
859 createETagsFileCmd "" = ghciCreateTagsFile ETags "TAGS"
860 createETagsFileCmd file = ghciCreateTagsFile ETags file
862 data TagsKind = ETags | CTags
864 ghciCreateTagsFile :: TagsKind -> FilePath -> GHCi ()
865 ghciCreateTagsFile kind file = do
866 session <- getSession
867 io $ createTagsFile session kind file
870 -- - remove restriction that all modules must be interpreted
871 -- (problem: we don't know source locations for entities unless
872 -- we compiled the module.
874 -- - extract createTagsFile so it can be used from the command-line
875 -- (probably need to fix first problem before this is useful).
877 createTagsFile :: Session -> TagsKind -> FilePath -> IO ()
878 createTagsFile session tagskind tagFile = do
879 graph <- GHC.getModuleGraph session
880 let ms = map GHC.ms_mod graph
882 is_interpreted <- GHC.moduleIsInterpreted session m
883 -- should we just skip these?
884 when (not is_interpreted) $
885 throwDyn (CmdLineError ("module '"
886 ++ GHC.moduleNameString (GHC.moduleName m)
887 ++ "' is not interpreted"))
888 mbModInfo <- GHC.getModuleInfo session m
890 | Just modinfo <- mbModInfo,
891 Just unqual <- GHC.modInfoPrintUnqualified modinfo = unqual
892 | otherwise = GHC.alwaysQualify
895 Just modInfo -> return $! listTags unqual modInfo
898 mtags <- mapM tagModule ms
899 either_res <- collateAndWriteTags tagskind tagFile $ concat mtags
901 Left e -> hPutStrLn stderr $ ioeGetErrorString e
904 listTags :: PrintUnqualified -> GHC.ModuleInfo -> [TagInfo]
905 listTags unqual modInfo =
906 [ tagInfo unqual name loc
907 | name <- GHC.modInfoExports modInfo
908 , let loc = nameSrcLoc name
912 type TagInfo = (String -- tag name
915 ,Int -- column number
918 -- get tag info, for later translation into Vim or Emacs style
919 tagInfo :: PrintUnqualified -> Name -> SrcLoc -> TagInfo
920 tagInfo unqual name loc
921 = ( showSDocForUser unqual $ pprOccName (nameOccName name)
922 , showSDocForUser unqual $ ftext (srcLocFile loc)
927 collateAndWriteTags :: TagsKind -> FilePath -> [TagInfo] -> IO (Either IOError ())
928 collateAndWriteTags CTags file tagInfos = do -- ctags style, Vim et al
929 let tags = unlines $ sortLe (<=) $ nub $ map showTag tagInfos
930 IO.try (writeFile file tags)
931 collateAndWriteTags ETags file tagInfos = do -- etags style, Emacs/XEmacs
932 let byFile op (_,f1,_,_) (_,f2,_,_) = f1 `op` f2
933 groups = groupBy (byFile (==)) $ sortLe (byFile (<=)) tagInfos
934 tagGroups <- mapM tagFileGroup groups
935 IO.try (writeFile file $ concat tagGroups)
937 tagFileGroup group@[] = throwDyn (CmdLineError "empty tag file group??")
938 tagFileGroup group@((_,fileName,_,_):_) = do
939 file <- readFile fileName -- need to get additional info from sources..
940 let byLine (_,_,l1,_) (_,_,l2,_) = l1 <= l2
941 sortedGroup = sortLe byLine group
942 tags = unlines $ perFile sortedGroup 1 0 $ lines file
943 return $ "\x0c\n" ++ fileName ++ "," ++ show (length tags) ++ "\n" ++ tags
944 perFile (tagInfo@(tag,file,lNo,colNo):tags) count pos (line:lines) | lNo>count =
945 perFile (tagInfo:tags) (count+1) (pos+length line) lines
946 perFile (tagInfo@(tag,file,lNo,colNo):tags) count pos lines@(line:_) | lNo==count =
947 showETag tagInfo line pos : perFile tags count pos lines
948 perFile tags count pos lines = []
950 -- simple ctags format, for Vim et al
951 showTag :: TagInfo -> String
952 showTag (tag,file,lineNo,colNo)
953 = tag ++ "\t" ++ file ++ "\t" ++ show lineNo
955 -- etags format, for Emacs/XEmacs
956 showETag :: TagInfo -> String -> Int -> String
957 showETag (tag,file,lineNo,colNo) line charPos
958 = take colNo line ++ tag
960 ++ "\x01" ++ show lineNo
961 ++ "," ++ show charPos
963 -----------------------------------------------------------------------------
964 -- Browsing a module's contents
966 browseCmd :: String -> GHCi ()
969 ['*':m] | looksLikeModuleName m -> browseModule m False
970 [m] | looksLikeModuleName m -> browseModule m True
971 _ -> throwDyn (CmdLineError "syntax: :browse <module>")
973 browseModule m exports_only = do
975 modl <- if exports_only then lookupModule s m
976 else wantInterpretedModule s m
978 -- Temporarily set the context to the module we're interested in,
979 -- just so we can get an appropriate PrintUnqualified
980 (as,bs) <- io (GHC.getContext s)
981 prel_mod <- getPrelude
982 io (if exports_only then GHC.setContext s [] [prel_mod,modl]
983 else GHC.setContext s [modl] [])
984 unqual <- io (GHC.getPrintUnqual s)
985 io (GHC.setContext s as bs)
987 mb_mod_info <- io $ GHC.getModuleInfo s modl
989 Nothing -> throwDyn (CmdLineError ("unknown module: " ++ m))
992 | exports_only = GHC.modInfoExports mod_info
993 | otherwise = fromMaybe [] (GHC.modInfoTopLevelScope mod_info)
995 filtered = filterOutChildren names
997 things <- io $ mapM (GHC.lookupName s) filtered
999 dflags <- getDynFlags
1000 let exts = dopt Opt_GlasgowExts dflags
1001 io (putStrLn (showSDocForUser unqual (
1002 vcat (map (pprTyThingInContext exts) (catMaybes things))
1004 -- ToDo: modInfoInstances currently throws an exception for
1005 -- package modules. When it works, we can do this:
1006 -- $$ vcat (map GHC.pprInstance (GHC.modInfoInstances mod_info))
1008 -----------------------------------------------------------------------------
1009 -- Setting the module context
1012 | all sensible mods = fn mods
1013 | otherwise = throwDyn (CmdLineError "syntax: :module [+/-] [*]M1 ... [*]Mn")
1015 (fn, mods) = case str of
1016 '+':stuff -> (addToContext, words stuff)
1017 '-':stuff -> (removeFromContext, words stuff)
1018 stuff -> (newContext, words stuff)
1020 sensible ('*':m) = looksLikeModuleName m
1021 sensible m = looksLikeModuleName m
1023 separate :: Session -> [String] -> [Module] -> [Module]
1024 -> GHCi ([Module],[Module])
1025 separate session [] as bs = return (as,bs)
1026 separate session (('*':str):ms) as bs = do
1027 m <- io $ GHC.findModule session (GHC.mkModuleName str) Nothing
1028 b <- io $ GHC.moduleIsInterpreted session m
1029 if b then separate session ms (m:as) bs
1030 else throwDyn (CmdLineError ("module '"
1031 ++ GHC.moduleNameString (GHC.moduleName m)
1032 ++ "' is not interpreted"))
1033 separate session (str:ms) as bs = do
1034 m <- io $ GHC.findModule session (GHC.mkModuleName str) Nothing
1035 separate session ms as (m:bs)
1037 newContext :: [String] -> GHCi ()
1038 newContext strs = do
1040 (as,bs) <- separate s strs [] []
1041 prel_mod <- getPrelude
1042 let bs' = if null as && prel_mod `notElem` bs then prel_mod:bs else bs
1043 io $ GHC.setContext s as bs'
1046 addToContext :: [String] -> GHCi ()
1047 addToContext strs = do
1049 (as,bs) <- io $ GHC.getContext s
1051 (new_as,new_bs) <- separate s strs [] []
1053 let as_to_add = new_as \\ (as ++ bs)
1054 bs_to_add = new_bs \\ (as ++ bs)
1056 io $ GHC.setContext s (as ++ as_to_add) (bs ++ bs_to_add)
1059 removeFromContext :: [String] -> GHCi ()
1060 removeFromContext strs = do
1062 (as,bs) <- io $ GHC.getContext s
1064 (as_to_remove,bs_to_remove) <- separate s strs [] []
1066 let as' = as \\ (as_to_remove ++ bs_to_remove)
1067 bs' = bs \\ (as_to_remove ++ bs_to_remove)
1069 io $ GHC.setContext s as' bs'
1071 ----------------------------------------------------------------------------
1074 -- set options in the interpreter. Syntax is exactly the same as the
1075 -- ghc command line, except that certain options aren't available (-C,
1078 -- This is pretty fragile: most options won't work as expected. ToDo:
1079 -- figure out which ones & disallow them.
1081 setCmd :: String -> GHCi ()
1083 = do st <- getGHCiState
1084 let opts = options st
1085 io $ putStrLn (showSDoc (
1086 text "options currently set: " <>
1089 else hsep (map (\o -> char '+' <> text (optToStr o)) opts)
1092 = case toArgs str of
1093 ("args":args) -> setArgs args
1094 ("prog":prog) -> setProg prog
1095 ("prompt":prompt) -> setPrompt (after 6)
1096 ("editor":cmd) -> setEditor (after 6)
1097 wds -> setOptions wds
1098 where after n = dropWhile isSpace $ drop n $ dropWhile isSpace str
1102 setGHCiState st{ args = args }
1106 setGHCiState st{ progname = prog }
1108 io (hPutStrLn stderr "syntax: :set prog <progname>")
1112 setGHCiState st{ editor = cmd }
1114 setPrompt value = do
1117 then io $ hPutStrLn stderr $ "syntax: :set prompt <prompt>, currently \"" ++ prompt st ++ "\""
1118 else setGHCiState st{ prompt = remQuotes value }
1120 remQuotes ('\"':xs) | not (null xs) && last xs == '\"' = init xs
1124 do -- first, deal with the GHCi opts (+s, +t, etc.)
1125 let (plus_opts, minus_opts) = partition isPlus wds
1126 mapM_ setOpt plus_opts
1128 -- then, dynamic flags
1129 dflags <- getDynFlags
1130 let pkg_flags = packageFlags dflags
1131 (dflags',leftovers) <- io $ GHC.parseDynamicFlags dflags minus_opts
1133 if (not (null leftovers))
1134 then throwDyn (CmdLineError ("unrecognised flags: " ++
1138 new_pkgs <- setDynFlags dflags'
1140 -- if the package flags changed, we should reset the context
1141 -- and link the new packages.
1142 dflags <- getDynFlags
1143 when (packageFlags dflags /= pkg_flags) $ do
1144 io $ hPutStrLn stderr "package flags have changed, ressetting and loading new packages..."
1145 session <- getSession
1146 io (GHC.setTargets session [])
1147 io (GHC.load session LoadAllTargets)
1148 io (linkPackages dflags new_pkgs)
1149 setContextAfterLoad session []
1153 unsetOptions :: String -> GHCi ()
1155 = do -- first, deal with the GHCi opts (+s, +t, etc.)
1156 let opts = words str
1157 (minus_opts, rest1) = partition isMinus opts
1158 (plus_opts, rest2) = partition isPlus rest1
1160 if (not (null rest2))
1161 then io (putStrLn ("unknown option: '" ++ head rest2 ++ "'"))
1164 mapM_ unsetOpt plus_opts
1166 -- can't do GHC flags for now
1167 if (not (null minus_opts))
1168 then throwDyn (CmdLineError "can't unset GHC command-line flags")
1171 isMinus ('-':s) = True
1174 isPlus ('+':s) = True
1178 = case strToGHCiOpt str of
1179 Nothing -> io (putStrLn ("unknown option: '" ++ str ++ "'"))
1180 Just o -> setOption o
1183 = case strToGHCiOpt str of
1184 Nothing -> io (putStrLn ("unknown option: '" ++ str ++ "'"))
1185 Just o -> unsetOption o
1187 strToGHCiOpt :: String -> (Maybe GHCiOption)
1188 strToGHCiOpt "s" = Just ShowTiming
1189 strToGHCiOpt "t" = Just ShowType
1190 strToGHCiOpt "r" = Just RevertCAFs
1191 strToGHCiOpt _ = Nothing
1193 optToStr :: GHCiOption -> String
1194 optToStr ShowTiming = "s"
1195 optToStr ShowType = "t"
1196 optToStr RevertCAFs = "r"
1198 -- ---------------------------------------------------------------------------
1203 ["modules" ] -> showModules
1204 ["bindings"] -> showBindings
1205 ["linker"] -> io showLinkerState
1206 ["breaks"] -> showBkptTable
1207 _ -> throwDyn (CmdLineError "syntax: :show [modules|bindings]")
1210 session <- getSession
1211 let show_one ms = do m <- io (GHC.showModule session ms)
1213 graph <- io (GHC.getModuleGraph session)
1214 mapM_ show_one graph
1218 unqual <- io (GHC.getPrintUnqual s)
1219 bindings <- io (GHC.getBindings s)
1220 mapM_ showTyThing bindings
1223 showTyThing (AnId id) = do
1224 ty' <- cleanType (GHC.idType id)
1225 str <- showForUser (ppr id <> text " :: " <> ppr ty')
1227 showTyThing _ = return ()
1229 -- if -fglasgow-exts is on we show the foralls, otherwise we don't.
1230 cleanType :: Type -> GHCi Type
1232 dflags <- getDynFlags
1233 if dopt Opt_GlasgowExts dflags
1235 else return $! GHC.dropForAlls ty
1237 showBkptTable :: GHCi ()
1239 activeBreaks <- getActiveBreakPoints
1240 str <- showForUser $ ppr activeBreaks
1243 -- -----------------------------------------------------------------------------
1246 completeNone :: String -> IO [String]
1247 completeNone w = return []
1250 completeWord :: String -> Int -> Int -> IO (Maybe (String, [String]))
1251 completeWord w start end = do
1252 line <- Readline.getLineBuffer
1254 ':':_ | all isSpace (take (start-1) line) -> wrapCompleter completeCmd w
1256 | Just c <- is_cmd line -> do
1257 maybe_cmd <- lookupCommand c
1258 let (n,w') = selectWord (words' 0 line)
1260 Nothing -> return Nothing
1261 Just (_,_,False,complete) -> wrapCompleter complete w
1262 Just (_,_,True,complete) -> let complete' w = do rets <- complete w
1263 return (map (drop n) rets)
1264 in wrapCompleter complete' w'
1266 --printf "complete %s, start = %d, end = %d\n" w start end
1267 wrapCompleter completeIdentifier w
1268 where words' _ [] = []
1269 words' n str = let (w,r) = break isSpace str
1270 (s,r') = span isSpace r
1271 in (n,w):words' (n+length w+length s) r'
1272 -- In a Haskell expression we want to parse 'a-b' as three words
1273 -- where a compiler flag (ie. -fno-monomorphism-restriction) should
1274 -- only be a single word.
1275 selectWord [] = (0,w)
1276 selectWord ((offset,x):xs)
1277 | offset+length x >= start = (start-offset,take (end-offset) x)
1278 | otherwise = selectWord xs
1281 | ((':':w) : _) <- words (dropWhile isSpace line) = Just w
1282 | otherwise = Nothing
1285 cmds <- readIORef commands
1286 return (filter (w `isPrefixOf`) (map (':':) (map cmdName cmds)))
1288 completeMacro w = do
1289 cmds <- readIORef commands
1290 let cmds' = [ cmd | cmd <- map cmdName cmds, cmd `elem` map cmdName builtin_commands ]
1291 return (filter (w `isPrefixOf`) cmds')
1293 completeIdentifier w = do
1295 rdrs <- GHC.getRdrNamesInScope s
1296 return (filter (w `isPrefixOf`) (map (showSDoc.ppr) rdrs))
1298 completeModule w = do
1300 dflags <- GHC.getSessionDynFlags s
1301 let pkg_mods = allExposedModules dflags
1302 return (filter (w `isPrefixOf`) (map (showSDoc.ppr) pkg_mods))
1304 completeHomeModule w = do
1306 g <- GHC.getModuleGraph s
1307 let home_mods = map GHC.ms_mod_name g
1308 return (filter (w `isPrefixOf`) (map (showSDoc.ppr) home_mods))
1310 completeSetOptions w = do
1311 return (filter (w `isPrefixOf`) options)
1312 where options = "args":"prog":allFlags
1314 completeFilename = Readline.filenameCompletionFunction
1316 completeHomeModuleOrFile = unionComplete completeHomeModule completeFilename
1318 unionComplete :: (String -> IO [String]) -> (String -> IO [String]) -> String -> IO [String]
1319 unionComplete f1 f2 w = do
1324 wrapCompleter :: (String -> IO [String]) -> String -> IO (Maybe (String,[String]))
1325 wrapCompleter fun w = do
1328 [] -> return Nothing
1329 [x] -> return (Just (x,[]))
1330 xs -> case getCommonPrefix xs of
1331 "" -> return (Just ("",xs))
1332 pref -> return (Just (pref,xs))
1334 getCommonPrefix :: [String] -> String
1335 getCommonPrefix [] = ""
1336 getCommonPrefix (s:ss) = foldl common s ss
1337 where common s "" = ""
1339 common (c:cs) (d:ds)
1340 | c == d = c : common cs ds
1343 allExposedModules :: DynFlags -> [ModuleName]
1344 allExposedModules dflags
1345 = map GHC.mkModuleName (concat (map exposedModules (filter exposed (eltsUFM pkg_db))))
1347 pkg_db = pkgIdMap (pkgState dflags)
1349 completeCmd = completeNone
1350 completeMacro = completeNone
1351 completeIdentifier = completeNone
1352 completeModule = completeNone
1353 completeHomeModule = completeNone
1354 completeSetOptions = completeNone
1355 completeFilename = completeNone
1356 completeHomeModuleOrFile=completeNone
1357 completeBkpt = completeNone
1360 -- ---------------------------------------------------------------------------
1361 -- User code exception handling
1363 -- This is the exception handler for exceptions generated by the
1364 -- user's code and exceptions coming from children sessions;
1365 -- it normally just prints out the exception. The
1366 -- handler must be recursive, in case showing the exception causes
1367 -- more exceptions to be raised.
1369 -- Bugfix: if the user closed stdout or stderr, the flushing will fail,
1370 -- raising another exception. We therefore don't put the recursive
1371 -- handler arond the flushing operation, so if stderr is closed
1372 -- GHCi will just die gracefully rather than going into an infinite loop.
1373 handler :: Exception -> GHCi Bool
1375 handler exception = do
1377 io installSignalHandlers
1378 ghciHandle handler (showException exception >> return False)
1380 showException (DynException dyn) =
1381 case fromDynamic dyn of
1382 Nothing -> io (putStrLn ("*** Exception: (unknown)"))
1383 Just Interrupted -> io (putStrLn "Interrupted.")
1384 Just (CmdLineError s) -> io (putStrLn s) -- omit the location for CmdLineError
1385 Just ph@PhaseFailed{} -> io (putStrLn (showGhcException ph "")) -- ditto
1386 Just other_ghc_ex -> io (print other_ghc_ex)
1388 showException other_exception
1389 = io (putStrLn ("*** Exception: " ++ show other_exception))
1391 -----------------------------------------------------------------------------
1392 -- recursive exception handlers
1394 -- Don't forget to unblock async exceptions in the handler, or if we're
1395 -- in an exception loop (eg. let a = error a in a) the ^C exception
1396 -- may never be delivered. Thanks to Marcin for pointing out the bug.
1398 ghciHandle :: (Exception -> GHCi a) -> GHCi a -> GHCi a
1399 ghciHandle h (GHCi m) = GHCi $ \s ->
1400 Exception.catch (m s)
1401 (\e -> unGHCi (ghciUnblock (h e)) s)
1403 ghciUnblock :: GHCi a -> GHCi a
1404 ghciUnblock (GHCi a) = GHCi $ \s -> Exception.unblock (a s)
1407 -- ----------------------------------------------------------------------------
1410 expandPath :: String -> GHCi String
1412 case dropWhile isSpace path of
1414 tilde <- io (getEnv "HOME") -- will fail if HOME not defined
1415 return (tilde ++ '/':d)
1419 -- ----------------------------------------------------------------------------
1420 -- Windows console setup
1422 setUpConsole :: IO ()
1424 #ifdef mingw32_HOST_OS
1425 -- On Windows we need to set a known code page, otherwise the characters
1426 -- we read from the console will be be in some strange encoding, and
1427 -- similarly for characters we write to the console.
1429 -- At the moment, GHCi pretends all input is Latin-1. In the
1430 -- future we should support UTF-8, but for now we set the code pages
1433 -- It seems you have to set the font in the console window to
1434 -- a Unicode font in order for output to work properly,
1435 -- otherwise non-ASCII characters are mapped wrongly. sigh.
1436 -- (see MSDN for SetConsoleOutputCP()).
1438 setConsoleCP 28591 -- ISO Latin-1
1439 setConsoleOutputCP 28591 -- ISO Latin-1
1443 -- commands for debugger
1444 foreign import ccall "rts_setStepFlag" setStepFlag :: IO ()
1446 stepCmd :: String -> GHCi Bool
1447 stepCmd [] = doContinue setStepFlag
1448 stepCmd expression = do
1450 runCommand expression
1452 continueCmd :: String -> GHCi Bool
1453 continueCmd [] = doContinue $ return ()
1454 continueCmd other = do
1455 io $ putStrLn "The continue command accepts no arguments."
1458 doContinue :: IO () -> GHCi Bool
1459 doContinue actionBeforeCont = do
1460 resumeAction <- popResume
1461 case resumeAction of
1463 io $ putStrLn "There is no computation running."
1465 Just (_,_,handle) -> do
1466 io $ actionBeforeCont
1467 session <- getSession
1468 runResult <- io $ GHC.resume session handle
1469 names <- switchOnRunResult runResult
1470 finishEvalExpr names
1473 deleteCmd :: String -> GHCi Bool
1474 deleteCmd argLine = do
1475 deleteSwitch $ words argLine
1478 deleteSwitch :: [String] -> GHCi ()
1480 io $ putStrLn "The delete command requires at least one argument."
1481 -- delete all break points
1482 deleteSwitch ("*":_rest) = discardActiveBreakPoints
1483 deleteSwitch idents = do
1484 mapM_ deleteOneBreak idents
1486 deleteOneBreak :: String -> GHCi ()
1488 | all isDigit str = deleteBreak (read str)
1489 | otherwise = return ()
1491 -- handle the "break" command
1492 breakCmd :: String -> GHCi Bool
1493 breakCmd argLine = do
1494 session <- getSession
1495 breakSwitch session $ words argLine
1497 breakSwitch :: Session -> [String] -> GHCi Bool
1498 breakSwitch _session [] = do
1499 io $ putStrLn "The break command requires at least one argument."
1501 breakSwitch session args@(arg1:rest)
1502 | looksLikeModule arg1 = do
1503 mod <- wantInterpretedModule session arg1
1504 breakByModule mod rest
1507 (toplevel, _) <- io $ GHC.getContext session
1509 (mod : _) -> breakByModule mod args
1511 io $ putStrLn "Cannot find default module for breakpoint."
1512 io $ putStrLn "Perhaps no modules are loaded for debugging?"
1515 -- Todo there may be a nicer way to test this
1516 looksLikeModule :: String -> Bool
1517 looksLikeModule [] = False
1518 looksLikeModule (x:_) = isUpper x
1520 wantInterpretedModule :: Session -> String -> GHCi Module
1521 wantInterpretedModule session str = do
1522 modl <- io $ GHC.findModule session (GHC.mkModuleName str) Nothing
1523 is_interpreted <- io (GHC.moduleIsInterpreted session modl)
1524 when (not is_interpreted) $
1525 throwDyn (CmdLineError ("module '" ++ str ++ "' is not interpreted"))
1528 breakByModule :: Module -> [String] -> GHCi ()
1529 breakByModule mod args@(arg1:rest)
1530 | all isDigit arg1 = do -- looks like a line number
1531 breakByModuleLine mod (read arg1) rest
1532 | looksLikeVar arg1 = do
1533 -- break by a function definition
1534 io $ putStrLn "Break by function definition not implemented."
1535 | otherwise = io $ putStrLn "Invalid arguments to break command."
1537 -- Todo there may be a nicer way to test this
1538 looksLikeVar :: String -> Bool
1539 looksLikeVar [] = False
1540 looksLikeVar (x:_) = isLower x || x `elem` "~!@#$%^&*-+"
1542 breakByModuleLine :: Module -> Int -> [String] -> GHCi ()
1543 breakByModuleLine mod line args
1544 | [] <- args = findBreakAndSet mod $ findBreakByLine line
1545 | [col] <- args, all isDigit col =
1546 findBreakAndSet mod $ findBreakByCoord (line, read col)
1547 | otherwise = io $ putStrLn "Invalid arguments to break command."
1549 findBreakAndSet :: Module -> (TickArray -> Maybe (Int, SrcSpan)) -> GHCi ()
1550 findBreakAndSet mod lookupTickTree = do
1551 tickArray <- getTickArray mod
1552 (breakArray, _) <- getModBreak mod
1553 case lookupTickTree tickArray of
1554 Nothing -> io $ putStrLn $ "No breakpoints found at that location."
1555 Just (tick, span) -> do
1556 success <- io $ setBreakFlag True breakArray tick
1557 session <- getSession
1558 unqual <- io $ GHC.getPrintUnqual session
1562 recordBreak $ BreakLocation
1567 io $ printForUser stdout unqual $
1568 text "Breakpoint " <> ppr nm <>
1570 then text " was already set at " <> ppr span
1571 else text " activated at " <> ppr span
1573 str <- showForUser $ text "Breakpoint could not be activated at"
1577 -- When a line number is specified, the current policy for choosing
1578 -- the best breakpoint is this:
1579 -- - the leftmost complete subexpression on the specified line, or
1580 -- - the leftmost subexpression starting on the specified line, or
1581 -- - the rightmost subexpression enclosing the specified line
1583 findBreakByLine :: Int -> TickArray -> Maybe (BreakIndex,SrcSpan)
1584 findBreakByLine line arr =
1585 listToMaybe (sortBy leftmost complete) `mplus`
1586 listToMaybe (sortBy leftmost incomplete) `mplus`
1587 listToMaybe (sortBy rightmost ticks)
1591 starts_here = [ tick | tick@(nm,span) <- ticks,
1592 srcSpanStartLine span == line ]
1594 (complete,incomplete) = partition ends_here starts_here
1595 where ends_here (nm,span) = srcSpanEndLine span == line
1597 findBreakByCoord :: (Int,Int) -> TickArray -> Maybe (BreakIndex,SrcSpan)
1598 findBreakByCoord (line, col) arr =
1599 listToMaybe (sortBy rightmost contains)
1603 -- the ticks that span this coordinate
1604 contains = [ tick | tick@(nm,span) <- ticks, span `spans` (line,col) ]
1606 leftmost (_,a) (_,b) = a `compare` b
1607 rightmost (_,a) (_,b) = b `compare` a
1609 spans :: SrcSpan -> (Int,Int) -> Bool
1610 spans span (l,c) = srcSpanStart span <= loc && loc <= srcSpanEnd span
1611 where loc = mkSrcLoc (srcSpanFile span) l c
1614 -- --------------------------------------------------------------------------
1617 getTickArray :: Module -> GHCi TickArray
1618 getTickArray modl = do
1620 let arrmap = tickarrays st
1621 case lookupModuleEnv arrmap modl of
1622 Just arr -> return arr
1624 (breakArray, ticks) <- getModBreak modl
1625 let arr = mkTickArray (assocs ticks)
1626 setGHCiState st{tickarrays = extendModuleEnv arrmap modl arr}
1629 discardTickArrays :: GHCi ()
1630 discardTickArrays = do
1632 setGHCiState st{tickarrays = emptyModuleEnv}
1634 mkTickArray :: [(BreakIndex,SrcSpan)] -> TickArray
1636 = accumArray (flip (:)) [] (1, max_line)
1637 [ (line, (nm,span)) | (nm,span) <- ticks,
1638 line <- srcSpanLines span ]
1640 max_line = maximum (map srcSpanEndLine (map snd ticks))
1641 srcSpanLines span = [ srcSpanStartLine span .. srcSpanEndLine span ]
1643 getModBreak :: Module -> GHCi (BreakArray, Array Int SrcSpan)
1644 getModBreak mod = do
1645 session <- getSession
1646 Just mod_info <- io $ GHC.getModuleInfo session mod
1647 let modBreaks = GHC.modInfoModBreaks mod_info
1648 let array = GHC.modBreaks_flags modBreaks
1649 let ticks = GHC.modBreaks_locs modBreaks
1650 return (array, ticks)
1652 lookupModule :: Session -> String -> GHCi Module
1653 lookupModule session modName
1654 = io (GHC.findModule session (GHC.mkModuleName modName) Nothing)
1656 setBreakFlag :: Bool -> BreakArray -> Int -> IO Bool
1657 setBreakFlag toggle array index
1658 | toggle = setBreakOn array index
1659 | otherwise = setBreakOff array index
1662 {- these should probably go to the GHC API at some point -}
1663 enableBreakPoint :: Session -> Module -> Int -> IO ()
1664 enableBreakPoint session mod index = return ()
1666 disableBreakPoint :: Session -> Module -> Int -> IO ()
1667 disableBreakPoint session mod index = return ()
1669 activeBreakPoints :: Session -> IO [(Module,Int)]
1670 activeBreakPoints session = return []
1672 enableSingleStep :: Session -> IO ()
1673 enableSingleStep session = return ()
1675 disableSingleStep :: Session -> IO ()
1676 disableSingleStep session = return ()