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 )
34 -- Other random utilities
36 import BasicTypes hiding (isTopLevel)
37 import Panic hiding (showException)
47 import Var ( globaliseId )
55 #ifndef mingw32_HOST_OS
57 #if __GLASGOW_HASKELL__ > 504
61 import GHC.ConsoleHandler ( flushConsole )
62 import System.Win32 ( setConsoleCP, setConsoleOutputCP )
63 import qualified System.Win32
67 import Control.Concurrent ( yield ) -- Used in readline loop
68 import System.Console.Readline as Readline
73 import Control.Exception as Exception
74 -- import Control.Concurrent
77 import Data.Maybe ( isJust, isNothing, fromMaybe, catMaybes )
79 import System.Environment
80 import System.Exit ( exitWith, ExitCode(..) )
81 import System.Directory
83 import System.IO.Error as IO
87 import Control.Monad as Monad
88 import Foreign.StablePtr ( StablePtr, newStablePtr, deRefStablePtr, freeStablePtr )
90 import GHC.Exts ( unsafeCoerce# )
91 import GHC.IOBase ( IOErrorType(InvalidArgument), IO(IO) )
93 import Data.IORef ( IORef, readIORef, writeIORef )
95 import System.Posix.Internals ( setNonBlockingFD )
97 -- these are needed by the new ghci debugger
98 import ByteCodeLink (HValue)
99 import ByteCodeInstr (BreakInfo (..))
103 -----------------------------------------------------------------------------
107 " / _ \\ /\\ /\\/ __(_)\n"++
108 " / /_\\// /_/ / / | | GHC Interactive, version " ++ cProjectVersion ++ ", for Haskell 98.\n"++
109 "/ /_\\\\/ __ / /___| | http://www.haskell.org/ghc/\n"++
110 "\\____/\\/ /_/\\____/|_| Type :? for help.\n"
112 type Command = (String, String -> GHCi Bool, Bool, String -> IO [String])
113 cmdName (n,_,_,_) = n
115 GLOBAL_VAR(commands, builtin_commands, [Command])
117 builtin_commands :: [Command]
119 -- Hugs users are accustomed to :e, so make sure it doesn't overlap
120 ("?", keepGoing help, False, completeNone),
121 ("add", tlC$ keepGoingPaths addModule, False, completeFilename),
122 ("break", breakCmd, False, completeNone),
123 ("browse", keepGoing browseCmd, False, completeModule),
124 ("cd", tlC$ keepGoing changeDirectory, False, completeFilename),
125 ("check", keepGoing checkModule, False, completeHomeModule),
126 ("continue", continueCmd, False, completeNone),
127 ("ctags", keepGoing createCTagsFileCmd, False, completeFilename),
128 ("def", keepGoing defineMacro, False, completeIdentifier),
129 ("delete", deleteCmd, False, completeNone),
130 ("e", keepGoing editFile, False, completeFilename),
131 ("edit", keepGoing editFile, False, completeFilename),
132 ("etags", keepGoing createETagsFileCmd, False, completeFilename),
133 ("force", keepGoing (pprintClosureCommand False True), False, completeIdentifier),
134 ("help", keepGoing help, False, completeNone),
135 ("info", keepGoing info, False, completeIdentifier),
136 ("kind", keepGoing kindOfType, False, completeIdentifier),
137 ("load", tlC$ keepGoingPaths loadModule_,False, completeHomeModuleOrFile),
138 ("module", keepGoing setContext, False, completeModule),
139 ("main", tlC$ keepGoing runMain, False, completeIdentifier),
140 ("print", keepGoing (pprintClosureCommand True False), False, completeIdentifier),
141 ("quit", quit, False, completeNone),
142 ("reload", tlC$ keepGoing reloadModule, False, completeNone),
143 ("set", keepGoing setCmd, True, completeSetOptions),
144 ("show", keepGoing showCmd, False, completeNone),
145 ("sprint", keepGoing (pprintClosureCommand False False),False, completeIdentifier),
146 ("step", stepCmd, False, completeNone),
147 ("type", keepGoing typeOfExpr, False, completeIdentifier),
148 ("undef", keepGoing undefineMacro, False, completeMacro),
149 ("unset", keepGoing unsetOptions, True, completeSetOptions)
152 keepGoing :: (String -> GHCi ()) -> (String -> GHCi Bool)
153 keepGoing a str = a str >> return False
155 -- tlC: Top Level Command, not allowed in inferior sessions
156 tlC :: (String -> GHCi Bool) -> (String -> GHCi Bool)
158 top_level <- isTopLevel
160 then throwDyn (CmdLineError "Command only allowed at Top Level")
163 keepGoingPaths :: ([FilePath] -> GHCi ()) -> (String -> GHCi Bool)
164 keepGoingPaths a str = a (toArgs str) >> return False
166 shortHelpText = "use :? for help.\n"
168 -- NOTE: spaces at the end of each line to workaround CPP/string gap bug.
170 " Commands available from the prompt:\n" ++
172 " <stmt> evaluate/run <stmt>\n" ++
173 " :add <filename> ... add module(s) to the current target set\n" ++
174 " :browse [*]<module> display the names defined by <module>\n" ++
175 " :cd <dir> change directory to <dir>\n" ++
176 " :def <cmd> <expr> define a command :<cmd>\n" ++
177 " :edit <file> edit file\n" ++
178 " :edit edit last module\n" ++
179 " :help, :? display this list of commands\n" ++
180 " :info [<name> ...] display information about the given names\n" ++
181 " :print [<name> ...] prints a value without forcing its computation\n" ++
182 " :sprint [<name> ...] simplified version of :print\n" ++
183 " :load <filename> ... load module(s) and their dependents\n" ++
184 " :module [+/-] [*]<mod> ... set the context for expression evaluation\n" ++
185 " :main [<arguments> ...] run the main function with the given arguments\n" ++
186 " :reload reload the current module set\n" ++
188 " :set <option> ... set options\n" ++
189 " :set args <arg> ... set the arguments returned by System.getArgs\n" ++
190 " :set prog <progname> set the value returned by System.getProgName\n" ++
191 " :set prompt <prompt> set the prompt used in GHCi\n" ++
192 " :set editor <cmd> set the command used for :edit\n" ++
194 " :show modules show the currently loaded modules\n" ++
195 " :show bindings show the current bindings made at the prompt\n" ++
197 " :ctags [<file>] create tags file for Vi (default: \"tags\")\n" ++
198 " :etags [<file>] create tags file for Emacs (default: \"TAGS\")\n" ++
199 " :type <expr> show the type of <expr>\n" ++
200 " :kind <type> show the kind of <type>\n" ++
201 " :undef <cmd> undefine user-defined command :<cmd>\n" ++
202 " :unset <option> ... unset options\n" ++
203 " :quit exit GHCi\n" ++
204 " :!<command> run the shell command <command>\n" ++
206 " Options for ':set' and ':unset':\n" ++
208 " +r revert top-level expressions after each evaluation\n" ++
209 " +s print timing/memory stats after each evaluation\n" ++
210 " +t print type after evaluation\n" ++
211 " -<flags> most GHC command line flags can also be set here\n" ++
212 " (eg. -v2, -fglasgow-exts, etc.)\n" ++
214 -- Todo: add help for breakpoint commands here
220 win <- System.Win32.getWindowsDirectory
221 return (win `joinFileName` "notepad.exe")
226 interactiveUI :: Session -> [(FilePath, Maybe Phase)] -> Maybe String -> IO ()
227 interactiveUI session srcs maybe_expr = do
228 -- HACK! If we happen to get into an infinite loop (eg the user
229 -- types 'let x=x in x' at the prompt), then the thread will block
230 -- on a blackhole, and become unreachable during GC. The GC will
231 -- detect that it is unreachable and send it the NonTermination
232 -- exception. However, since the thread is unreachable, everything
233 -- it refers to might be finalized, including the standard Handles.
234 -- This sounds like a bug, but we don't have a good solution right
240 -- Initialise buffering for the *interpreted* I/O system
241 initInterpBuffering session
243 when (isNothing maybe_expr) $ do
244 -- Only for GHCi (not runghc and ghc -e):
245 -- Turn buffering off for the compiled program's stdout/stderr
247 -- Turn buffering off for GHCi's stdout
249 hSetBuffering stdout NoBuffering
250 -- We don't want the cmd line to buffer any input that might be
251 -- intended for the program, so unbuffer stdin.
252 hSetBuffering stdin NoBuffering
254 -- initial context is just the Prelude
255 prel_mod <- GHC.findModule session prel_name (Just basePackageId)
256 GHC.setContext session [] [prel_mod]
260 Readline.setAttemptedCompletionFunction (Just completeWord)
261 --Readline.parseAndBind "set show-all-if-ambiguous 1"
263 let symbols = "!#$%&*+/<=>?@\\^|-~"
264 specials = "(),;[]`{}"
266 word_break_chars = spaces ++ specials ++ symbols
268 Readline.setBasicWordBreakCharacters word_break_chars
269 Readline.setCompleterWordBreakCharacters word_break_chars
272 default_editor <- findEditor
274 startGHCi (runGHCi srcs maybe_expr)
275 GHCiState{ progname = "<interactive>",
278 editor = default_editor,
284 breaks = emptyActiveBreakPoints
288 Readline.resetTerminal Nothing
293 prel_name = GHC.mkModuleName "Prelude"
295 runGHCi :: [(FilePath, Maybe Phase)] -> Maybe String -> GHCi ()
296 runGHCi paths maybe_expr = do
297 let read_dot_files = not opt_IgnoreDotGhci
299 when (read_dot_files) $ do
302 exists <- io (doesFileExist file)
304 dir_ok <- io (checkPerms ".")
305 file_ok <- io (checkPerms file)
306 when (dir_ok && file_ok) $ do
307 either_hdl <- io (IO.try (openFile "./.ghci" ReadMode))
310 Right hdl -> fileLoop hdl False
312 when (read_dot_files) $ do
313 -- Read in $HOME/.ghci
314 either_dir <- io (IO.try (getEnv "HOME"))
318 cwd <- io (getCurrentDirectory)
319 when (dir /= cwd) $ do
320 let file = dir ++ "/.ghci"
321 ok <- io (checkPerms file)
323 either_hdl <- io (IO.try (openFile file ReadMode))
326 Right hdl -> fileLoop hdl False
328 -- Perform a :load for files given on the GHCi command line
329 -- When in -e mode, if the load fails then we want to stop
330 -- immediately rather than going on to evaluate the expression.
331 when (not (null paths)) $ do
332 ok <- ghciHandle (\e -> do showException e; return Failed) $
334 when (isJust maybe_expr && failed ok) $
335 io (exitWith (ExitFailure 1))
337 -- if verbosity is greater than 0, or we are connected to a
338 -- terminal, display the prompt in the interactive loop.
339 is_tty <- io (hIsTerminalDevice stdin)
340 dflags <- getDynFlags
341 let show_prompt = verbosity dflags > 0 || is_tty
346 #if defined(mingw32_HOST_OS)
347 -- The win32 Console API mutates the first character of
348 -- type-ahead when reading from it in a non-buffered manner. Work
349 -- around this by flushing the input buffer of type-ahead characters,
350 -- but only if stdin is available.
351 flushed <- io (IO.try (GHC.ConsoleHandler.flushConsole stdin))
353 Left err | isDoesNotExistError err -> return ()
354 | otherwise -> io (ioError err)
355 Right () -> return ()
357 -- initialise the console if necessary
360 -- enter the interactive loop
361 interactiveLoop is_tty show_prompt
363 -- just evaluate the expression we were given
368 io $ do when (verbosity dflags > 0) $ putStrLn "Leaving GHCi."
371 interactiveLoop is_tty show_prompt =
372 -- Ignore ^C exceptions caught here
373 ghciHandleDyn (\e -> case e of
375 #if defined(mingw32_HOST_OS)
378 interactiveLoop is_tty show_prompt
379 _other -> return ()) $
381 ghciUnblock $ do -- unblock necessary if we recursed from the
382 -- exception handler above.
384 -- read commands from stdin
388 else fileLoop stdin show_prompt
390 fileLoop stdin show_prompt
394 -- NOTE: We only read .ghci files if they are owned by the current user,
395 -- and aren't world writable. Otherwise, we could be accidentally
396 -- running code planted by a malicious third party.
398 -- Furthermore, We only read ./.ghci if . is owned by the current user
399 -- and isn't writable by anyone else. I think this is sufficient: we
400 -- don't need to check .. and ../.. etc. because "." always refers to
401 -- the same directory while a process is running.
403 checkPerms :: String -> IO Bool
405 #ifdef mingw32_HOST_OS
408 Util.handle (\_ -> return False) $ do
409 st <- getFileStatus name
411 if fileOwner st /= me then do
412 putStrLn $ "WARNING: " ++ name ++ " is owned by someone else, IGNORING!"
415 let mode = fileMode st
416 if (groupWriteMode == (mode `intersectFileModes` groupWriteMode))
417 || (otherWriteMode == (mode `intersectFileModes` otherWriteMode))
419 putStrLn $ "*** WARNING: " ++ name ++
420 " is writable by someone else, IGNORING!"
425 fileLoop :: Handle -> Bool -> GHCi ()
426 fileLoop hdl show_prompt = do
427 session <- getSession
428 (mod,imports) <- io (GHC.getContext session)
430 when show_prompt (io (putStr (mkPrompt mod imports (prompt st))))
431 l <- io (IO.try (hGetLine hdl))
433 Left e | isEOFError e -> return ()
434 | InvalidArgument <- etype -> return ()
435 | otherwise -> io (ioError e)
436 where etype = ioeGetErrorType e
437 -- treat InvalidArgument in the same way as EOF:
438 -- this can happen if the user closed stdin, or
439 -- perhaps did getContents which closes stdin at
442 case removeSpaces l of
443 "" -> fileLoop hdl show_prompt
444 l -> do quit <- runCommand l
445 if quit then return () else fileLoop hdl show_prompt
447 stringLoop :: [String] -> GHCi Bool{-True: we quit-}
448 stringLoop [] = return False
449 stringLoop (s:ss) = do
450 case removeSpaces s of
452 l -> do quit <- runCommand l
453 if quit then return True else stringLoop ss
455 mkPrompt toplevs exports prompt
456 = showSDoc $ f prompt
458 f ('%':'s':xs) = perc_s <> f xs
459 f ('%':'%':xs) = char '%' <> f xs
460 f (x:xs) = char x <> f xs
463 perc_s = hsep (map (\m -> char '*' <> ppr (GHC.moduleName m)) toplevs) <+>
464 hsep (map (ppr . GHC.moduleName) exports)
468 readlineLoop :: GHCi ()
470 session <- getSession
471 (mod,imports) <- io (GHC.getContext session)
473 saveSession -- for use by completion
475 l <- io (readline (mkPrompt mod imports (prompt st))
476 `finally` setNonBlockingFD 0)
477 -- readline sometimes puts stdin into blocking mode,
478 -- so we need to put it back for the IO library
483 case removeSpaces l of
488 if quit then return () else readlineLoop
491 runCommand :: String -> GHCi Bool
492 runCommand c = ghciHandle handler (doCommand c)
494 doCommand (':' : command) = specialCommand command
496 = do timeIt (do nms <- runStmt stmt; finishEvalExpr nms)
499 -- This version is for the GHC command-line option -e. The only difference
500 -- from runCommand is that it catches the ExitException exception and
501 -- exits, rather than printing out the exception.
502 runCommandEval c = ghciHandle handleEval (doCommand c)
504 handleEval (ExitException code) = io (exitWith code)
505 handleEval e = do handler e
506 io (exitWith (ExitFailure 1))
508 doCommand (':' : command) = specialCommand command
510 = do nms <- runStmt stmt
512 Nothing -> io (exitWith (ExitFailure 1))
513 -- failure to run the command causes exit(1) for ghc -e.
514 _ -> finishEvalExpr nms
516 runStmt :: String -> GHCi (Maybe [Name])
518 | null (filter (not.isSpace) stmt) = return (Just [])
520 = do st <- getGHCiState
521 session <- getSession
522 result <- io $ withProgName (progname st) $ withArgs (args st) $
523 GHC.runStmt session stmt
524 switchOnRunResult result
526 switchOnRunResult :: GHC.RunResult -> GHCi (Maybe [Name])
527 switchOnRunResult GHC.RunFailed = return Nothing
528 switchOnRunResult (GHC.RunException e) = throw e
529 switchOnRunResult (GHC.RunOk names) = return $ Just names
530 switchOnRunResult (GHC.RunBreak apStack _threadId info resume) = do -- Todo: we don't use threadID, perhaps delete?
531 session <- getSession
532 Just mod_info <- io $ GHC.getModuleInfo session (breakInfo_module info)
533 let modBreaks = GHC.modInfoModBreaks mod_info
534 let ticks = modBreaks_ticks modBreaks
535 io $ displayBreakInfo session ticks info
536 io $ extendEnvironment session apStack (breakInfo_vars info)
540 displayBreakInfo :: Session -> Array Int SrcSpan -> BreakInfo -> IO ()
541 displayBreakInfo session ticks info = do
542 unqual <- GHC.getPrintUnqual session
543 let location = ticks ! breakInfo_number info
544 printForUser stdout unqual $
545 ptext SLIT("Stopped at") <+> ppr location $$ localsMsg
547 vars = map fst $ breakInfo_vars info
548 localsMsg = if null vars
549 then text "No locals in scope."
550 else text "Locals:" <+> (pprWithCommas showId vars)
551 showId id = ppr (idName id) <+> dcolon <+> ppr (idType id)
553 -- Todo: turn this into a primop, and provide special version(s) for unboxed things
554 foreign import ccall "rts_getApStackVal" getApStackVal :: StablePtr a -> Int -> IO (StablePtr b)
556 getIdValFromApStack :: a -> (Id, Int) -> IO (Id, HValue)
557 getIdValFromApStack apStack (identifier, stackDepth) = do
558 -- ToDo: check the type of the identifer and decide whether it is unboxed or not
559 apSptr <- newStablePtr apStack
560 resultSptr <- getApStackVal apSptr (stackDepth - 1)
561 result <- deRefStablePtr resultSptr
563 freeStablePtr resultSptr
564 return (identifier, unsafeCoerce# result)
566 extendEnvironment :: Session -> a -> [(Id, Int)] -> IO ()
567 extendEnvironment s@(Session ref) apStack idsOffsets = do
568 idsVals <- mapM (getIdValFromApStack apStack) idsOffsets
569 let (ids, hValues) = unzip idsVals
570 let names = map idName ids
571 let global_ids = map globaliseAndTidy ids
572 typed_ids <- mapM instantiateIdType global_ids
573 hsc_env <- readIORef ref
574 let ictxt = hsc_IC hsc_env
575 rn_env = ic_rn_local_env ictxt
576 type_env = ic_type_env ictxt
577 bound_names = map idName typed_ids
578 new_rn_env = extendLocalRdrEnv rn_env bound_names
579 -- Remove any shadowed bindings from the type_env;
580 -- they are inaccessible but might, I suppose, cause
581 -- a space leak if we leave them there
582 shadowed = [ n | name <- bound_names,
583 let rdr_name = mkRdrUnqual (nameOccName name),
584 Just n <- [lookupLocalRdrEnv rn_env rdr_name] ]
585 filtered_type_env = delListFromNameEnv type_env shadowed
586 new_type_env = extendTypeEnvWithIds filtered_type_env (typed_ids)
587 new_ic = ictxt { ic_rn_local_env = new_rn_env,
588 ic_type_env = new_type_env }
589 writeIORef ref (hsc_env { hsc_IC = new_ic })
590 extendLinkEnv (zip names hValues) -- ToDo: we must remember to restore the old env after we finish a breakpoint
592 globaliseAndTidy :: Id -> Id
594 = let tidied_type = tidyTopType$ idType id
595 in setIdType (globaliseId VanillaGlobal id) tidied_type
597 -- | Instantiate the tyVars with GHC.Base.Unknown
598 instantiateIdType :: Id -> IO Id
599 instantiateIdType id = do
600 instantiatedType <- instantiateTyVarsToUnknown s (idType id)
601 return$ setIdType id instantiatedType
603 -- possibly print the type and revert CAFs after evaluating an expression
604 finishEvalExpr mb_names
605 = do b <- isOptionSet ShowType
606 session <- getSession
609 Just names -> when b (mapM_ (showTypeOfName session) names)
612 io installSignalHandlers
613 b <- isOptionSet RevertCAFs
614 io (when b revertCAFs)
617 showTypeOfName :: Session -> Name -> GHCi ()
618 showTypeOfName session n
619 = do maybe_tything <- io (GHC.lookupName session n)
620 case maybe_tything of
622 Just thing -> showTyThing thing
624 specialCommand :: String -> GHCi Bool
625 specialCommand ('!':str) = shellEscape (dropWhile isSpace str)
626 specialCommand str = do
627 let (cmd,rest) = break isSpace str
628 maybe_cmd <- io (lookupCommand cmd)
630 Nothing -> io (hPutStr stdout ("unknown command ':" ++ cmd ++ "'\n"
631 ++ shortHelpText) >> return False)
632 Just (_,f,_,_) -> f (dropWhile isSpace rest)
634 lookupCommand :: String -> IO (Maybe Command)
635 lookupCommand str = do
636 cmds <- readIORef commands
637 -- look for exact match first, then the first prefix match
638 case [ c | c <- cmds, str == cmdName c ] of
639 c:_ -> return (Just c)
640 [] -> case [ c | c@(s,_,_,_) <- cmds, prefixMatch str s ] of
642 c:_ -> return (Just c)
644 -----------------------------------------------------------------------------
647 help :: String -> GHCi ()
648 help _ = io (putStr helpText)
650 info :: String -> GHCi ()
651 info "" = throwDyn (CmdLineError "syntax: ':i <thing-you-want-info-about>'")
652 info s = do { let names = words s
653 ; session <- getSession
654 ; dflags <- getDynFlags
655 ; let exts = dopt Opt_GlasgowExts dflags
656 ; mapM_ (infoThing exts session) names }
658 infoThing exts session str = io $ do
659 names <- GHC.parseName session str
660 let filtered = filterOutChildren names
661 mb_stuffs <- mapM (GHC.getInfo session) filtered
662 unqual <- GHC.getPrintUnqual session
663 putStrLn (showSDocForUser unqual $
664 vcat (intersperse (text "") $
665 [ pprInfo exts stuff | Just stuff <- mb_stuffs ]))
667 -- Filter out names whose parent is also there Good
668 -- example is '[]', which is both a type and data
669 -- constructor in the same type
670 filterOutChildren :: [Name] -> [Name]
671 filterOutChildren names = filter (not . parent_is_there) names
672 where parent_is_there n
673 -- | Just p <- GHC.nameParent_maybe n = p `elem` names
677 pprInfo exts (thing, fixity, insts)
678 = pprTyThingInContextLoc exts thing
679 $$ show_fixity fixity
680 $$ vcat (map GHC.pprInstance insts)
683 | fix == GHC.defaultFixity = empty
684 | otherwise = ppr fix <+> ppr (GHC.getName thing)
686 -----------------------------------------------------------------------------
689 runMain :: String -> GHCi ()
691 let ss = concat $ intersperse "," (map (\ s -> ('"':s)++"\"") (toArgs args))
692 runCommand $ '[': ss ++ "] `System.Environment.withArgs` main"
695 addModule :: [FilePath] -> GHCi ()
697 io (revertCAFs) -- always revert CAFs on load/add.
698 files <- mapM expandPath files
699 targets <- mapM (\m -> io (GHC.guessTarget m Nothing)) files
700 session <- getSession
701 io (mapM_ (GHC.addTarget session) targets)
702 ok <- io (GHC.load session LoadAllTargets)
705 changeDirectory :: String -> GHCi ()
706 changeDirectory dir = do
707 session <- getSession
708 graph <- io (GHC.getModuleGraph session)
709 when (not (null graph)) $
710 io $ putStr "Warning: changing directory causes all loaded modules to be unloaded,\nbecause the search path has changed.\n"
711 io (GHC.setTargets session [])
712 io (GHC.load session LoadAllTargets)
713 setContextAfterLoad session []
714 io (GHC.workingDirectoryChanged session)
715 dir <- expandPath dir
716 io (setCurrentDirectory dir)
718 editFile :: String -> GHCi ()
721 -- find the name of the "topmost" file loaded
722 session <- getSession
723 graph0 <- io (GHC.getModuleGraph session)
724 graph1 <- filterM (io . GHC.isLoaded session . GHC.ms_mod_name) graph0
725 let graph2 = flattenSCCs (GHC.topSortModuleGraph True graph1 Nothing)
726 case GHC.ml_hs_file (GHC.ms_location (last graph2)) of
727 Just file -> do_edit file
728 Nothing -> throwDyn (CmdLineError "unknown file name")
729 | otherwise = do_edit str
735 throwDyn (CmdLineError "editor not set, use :set editor")
736 io $ system (cmd ++ ' ':file)
739 defineMacro :: String -> GHCi ()
741 let (macro_name, definition) = break isSpace s
742 cmds <- io (readIORef commands)
744 then throwDyn (CmdLineError "invalid macro name")
746 if (macro_name `elem` map cmdName cmds)
747 then throwDyn (CmdLineError
748 ("command '" ++ macro_name ++ "' is already defined"))
751 -- give the expression a type signature, so we can be sure we're getting
752 -- something of the right type.
753 let new_expr = '(' : definition ++ ") :: String -> IO String"
755 -- compile the expression
757 maybe_hv <- io (GHC.compileExpr cms new_expr)
760 Just hv -> io (writeIORef commands --
761 (cmds ++ [(macro_name, runMacro hv, False, completeNone)]))
763 runMacro :: GHC.HValue{-String -> IO String-} -> String -> GHCi Bool
765 str <- io ((unsafeCoerce# fun :: String -> IO String) s)
766 stringLoop (lines str)
768 undefineMacro :: String -> GHCi ()
769 undefineMacro macro_name = do
770 cmds <- io (readIORef commands)
771 if (macro_name `elem` map cmdName builtin_commands)
772 then throwDyn (CmdLineError
773 ("command '" ++ macro_name ++ "' cannot be undefined"))
775 if (macro_name `notElem` map cmdName cmds)
776 then throwDyn (CmdLineError
777 ("command '" ++ macro_name ++ "' not defined"))
779 io (writeIORef commands (filter ((/= macro_name) . cmdName) cmds))
782 loadModule :: [(FilePath, Maybe Phase)] -> GHCi SuccessFlag
783 loadModule fs = timeIt (loadModule' fs)
785 loadModule_ :: [FilePath] -> GHCi ()
786 loadModule_ fs = do loadModule (zip fs (repeat Nothing)); return ()
788 loadModule' :: [(FilePath, Maybe Phase)] -> GHCi SuccessFlag
789 loadModule' files = do
790 session <- getSession
793 io (GHC.setTargets session [])
794 io (GHC.load session LoadAllTargets)
797 let (filenames, phases) = unzip files
798 exp_filenames <- mapM expandPath filenames
799 let files' = zip exp_filenames phases
800 targets <- io (mapM (uncurry GHC.guessTarget) files')
802 -- NOTE: we used to do the dependency anal first, so that if it
803 -- fails we didn't throw away the current set of modules. This would
804 -- require some re-working of the GHC interface, so we'll leave it
805 -- as a ToDo for now.
807 io (GHC.setTargets session targets)
808 ok <- io (GHC.load session LoadAllTargets)
812 checkModule :: String -> GHCi ()
814 let modl = GHC.mkModuleName m
815 session <- getSession
816 result <- io (GHC.checkModule session modl)
818 Nothing -> io $ putStrLn "Nothing"
819 Just r -> io $ putStrLn (showSDoc (
820 case GHC.checkedModuleInfo r of
821 Just cm | Just scope <- GHC.modInfoTopLevelScope cm ->
823 (local,global) = partition ((== modl) . GHC.moduleName . GHC.nameModule) scope
825 (text "global names: " <+> ppr global) $$
826 (text "local names: " <+> ppr local)
828 afterLoad (successIf (isJust result)) session
830 reloadModule :: String -> GHCi ()
832 io (revertCAFs) -- always revert CAFs on reload.
833 session <- getSession
834 ok <- io (GHC.load session LoadAllTargets)
837 io (revertCAFs) -- always revert CAFs on reload.
838 session <- getSession
839 ok <- io (GHC.load session (LoadUpTo (GHC.mkModuleName m)))
842 afterLoad ok session = do
843 io (revertCAFs) -- always revert CAFs on load.
844 graph <- io (GHC.getModuleGraph session)
845 graph' <- filterM (io . GHC.isLoaded session . GHC.ms_mod_name) graph
846 setContextAfterLoad session graph'
847 modulesLoadedMsg ok (map GHC.ms_mod_name graph')
849 setContextAfterLoad session [] = do
850 prel_mod <- getPrelude
851 io (GHC.setContext session [] [prel_mod])
852 setContextAfterLoad session ms = do
853 -- load a target if one is available, otherwise load the topmost module.
854 targets <- io (GHC.getTargets session)
855 case [ m | Just m <- map (findTarget ms) targets ] of
857 let graph' = flattenSCCs (GHC.topSortModuleGraph True ms Nothing) in
858 load_this (last graph')
863 = case filter (`matches` t) ms of
867 summary `matches` Target (TargetModule m) _
868 = GHC.ms_mod_name summary == m
869 summary `matches` Target (TargetFile f _) _
870 | Just f' <- GHC.ml_hs_file (GHC.ms_location summary) = f == f'
871 summary `matches` target
874 load_this summary | m <- GHC.ms_mod summary = do
875 b <- io (GHC.moduleIsInterpreted session m)
876 if b then io (GHC.setContext session [m] [])
878 prel_mod <- getPrelude
879 io (GHC.setContext session [] [prel_mod,m])
882 modulesLoadedMsg :: SuccessFlag -> [ModuleName] -> GHCi ()
883 modulesLoadedMsg ok mods = do
884 dflags <- getDynFlags
885 when (verbosity dflags > 0) $ do
887 | null mods = text "none."
889 punctuate comma (map ppr mods)) <> text "."
892 io (putStrLn (showSDoc (text "Failed, modules loaded: " <> mod_commas)))
894 io (putStrLn (showSDoc (text "Ok, modules loaded: " <> mod_commas)))
897 typeOfExpr :: String -> GHCi ()
899 = do cms <- getSession
900 maybe_ty <- io (GHC.exprType cms str)
903 Just ty -> do ty' <- cleanType ty
904 tystr <- showForUser (ppr ty')
905 io (putStrLn (str ++ " :: " ++ tystr))
907 kindOfType :: String -> GHCi ()
909 = do cms <- getSession
910 maybe_ty <- io (GHC.typeKind cms str)
913 Just ty -> do tystr <- showForUser (ppr ty)
914 io (putStrLn (str ++ " :: " ++ tystr))
916 quit :: String -> GHCi Bool
919 shellEscape :: String -> GHCi Bool
920 shellEscape str = io (system str >> return False)
922 -----------------------------------------------------------------------------
923 -- create tags file for currently loaded modules.
925 createETagsFileCmd, createCTagsFileCmd :: String -> GHCi ()
927 createCTagsFileCmd "" = ghciCreateTagsFile CTags "tags"
928 createCTagsFileCmd file = ghciCreateTagsFile CTags file
930 createETagsFileCmd "" = ghciCreateTagsFile ETags "TAGS"
931 createETagsFileCmd file = ghciCreateTagsFile ETags file
933 data TagsKind = ETags | CTags
935 ghciCreateTagsFile :: TagsKind -> FilePath -> GHCi ()
936 ghciCreateTagsFile kind file = do
937 session <- getSession
938 io $ createTagsFile session kind file
941 -- - remove restriction that all modules must be interpreted
942 -- (problem: we don't know source locations for entities unless
943 -- we compiled the module.
945 -- - extract createTagsFile so it can be used from the command-line
946 -- (probably need to fix first problem before this is useful).
948 createTagsFile :: Session -> TagsKind -> FilePath -> IO ()
949 createTagsFile session tagskind tagFile = do
950 graph <- GHC.getModuleGraph session
951 let ms = map GHC.ms_mod graph
953 is_interpreted <- GHC.moduleIsInterpreted session m
954 -- should we just skip these?
955 when (not is_interpreted) $
956 throwDyn (CmdLineError ("module '"
957 ++ GHC.moduleNameString (GHC.moduleName m)
958 ++ "' is not interpreted"))
959 mbModInfo <- GHC.getModuleInfo session m
961 | Just modinfo <- mbModInfo,
962 Just unqual <- GHC.modInfoPrintUnqualified modinfo = unqual
963 | otherwise = GHC.alwaysQualify
966 Just modInfo -> return $! listTags unqual modInfo
969 mtags <- mapM tagModule ms
970 either_res <- collateAndWriteTags tagskind tagFile $ concat mtags
972 Left e -> hPutStrLn stderr $ ioeGetErrorString e
975 listTags :: PrintUnqualified -> GHC.ModuleInfo -> [TagInfo]
976 listTags unqual modInfo =
977 [ tagInfo unqual name loc
978 | name <- GHC.modInfoExports modInfo
979 , let loc = nameSrcLoc name
983 type TagInfo = (String -- tag name
986 ,Int -- column number
989 -- get tag info, for later translation into Vim or Emacs style
990 tagInfo :: PrintUnqualified -> Name -> SrcLoc -> TagInfo
991 tagInfo unqual name loc
992 = ( showSDocForUser unqual $ pprOccName (nameOccName name)
993 , showSDocForUser unqual $ ftext (srcLocFile loc)
998 collateAndWriteTags :: TagsKind -> FilePath -> [TagInfo] -> IO (Either IOError ())
999 collateAndWriteTags CTags file tagInfos = do -- ctags style, Vim et al
1000 let tags = unlines $ sortLe (<=) $ nub $ map showTag tagInfos
1001 IO.try (writeFile file tags)
1002 collateAndWriteTags ETags file tagInfos = do -- etags style, Emacs/XEmacs
1003 let byFile op (_,f1,_,_) (_,f2,_,_) = f1 `op` f2
1004 groups = groupBy (byFile (==)) $ sortLe (byFile (<=)) tagInfos
1005 tagGroups <- mapM tagFileGroup groups
1006 IO.try (writeFile file $ concat tagGroups)
1008 tagFileGroup group@[] = throwDyn (CmdLineError "empty tag file group??")
1009 tagFileGroup group@((_,fileName,_,_):_) = do
1010 file <- readFile fileName -- need to get additional info from sources..
1011 let byLine (_,_,l1,_) (_,_,l2,_) = l1 <= l2
1012 sortedGroup = sortLe byLine group
1013 tags = unlines $ perFile sortedGroup 1 0 $ lines file
1014 return $ "\x0c\n" ++ fileName ++ "," ++ show (length tags) ++ "\n" ++ tags
1015 perFile (tagInfo@(tag,file,lNo,colNo):tags) count pos (line:lines) | lNo>count =
1016 perFile (tagInfo:tags) (count+1) (pos+length line) lines
1017 perFile (tagInfo@(tag,file,lNo,colNo):tags) count pos lines@(line:_) | lNo==count =
1018 showETag tagInfo line pos : perFile tags count pos lines
1019 perFile tags count pos lines = []
1021 -- simple ctags format, for Vim et al
1022 showTag :: TagInfo -> String
1023 showTag (tag,file,lineNo,colNo)
1024 = tag ++ "\t" ++ file ++ "\t" ++ show lineNo
1026 -- etags format, for Emacs/XEmacs
1027 showETag :: TagInfo -> String -> Int -> String
1028 showETag (tag,file,lineNo,colNo) line charPos
1029 = take colNo line ++ tag
1031 ++ "\x01" ++ show lineNo
1032 ++ "," ++ show charPos
1034 -----------------------------------------------------------------------------
1035 -- Browsing a module's contents
1037 browseCmd :: String -> GHCi ()
1040 ['*':m] | looksLikeModuleName m -> browseModule m False
1041 [m] | looksLikeModuleName m -> browseModule m True
1042 _ -> throwDyn (CmdLineError "syntax: :browse <module>")
1044 browseModule m exports_only = do
1046 modl <- io $ GHC.findModule s (GHC.mkModuleName m) Nothing
1047 is_interpreted <- io (GHC.moduleIsInterpreted s modl)
1048 when (not is_interpreted && not exports_only) $
1049 throwDyn (CmdLineError ("module '" ++ m ++ "' is not interpreted"))
1051 -- Temporarily set the context to the module we're interested in,
1052 -- just so we can get an appropriate PrintUnqualified
1053 (as,bs) <- io (GHC.getContext s)
1054 prel_mod <- getPrelude
1055 io (if exports_only then GHC.setContext s [] [prel_mod,modl]
1056 else GHC.setContext s [modl] [])
1057 unqual <- io (GHC.getPrintUnqual s)
1058 io (GHC.setContext s as bs)
1060 mb_mod_info <- io $ GHC.getModuleInfo s modl
1062 Nothing -> throwDyn (CmdLineError ("unknown module: " ++ m))
1065 | exports_only = GHC.modInfoExports mod_info
1066 | otherwise = fromMaybe [] (GHC.modInfoTopLevelScope mod_info)
1068 filtered = filterOutChildren names
1070 things <- io $ mapM (GHC.lookupName s) filtered
1072 dflags <- getDynFlags
1073 let exts = dopt Opt_GlasgowExts dflags
1074 io (putStrLn (showSDocForUser unqual (
1075 vcat (map (pprTyThingInContext exts) (catMaybes things))
1077 -- ToDo: modInfoInstances currently throws an exception for
1078 -- package modules. When it works, we can do this:
1079 -- $$ vcat (map GHC.pprInstance (GHC.modInfoInstances mod_info))
1081 -----------------------------------------------------------------------------
1082 -- Setting the module context
1085 | all sensible mods = fn mods
1086 | otherwise = throwDyn (CmdLineError "syntax: :module [+/-] [*]M1 ... [*]Mn")
1088 (fn, mods) = case str of
1089 '+':stuff -> (addToContext, words stuff)
1090 '-':stuff -> (removeFromContext, words stuff)
1091 stuff -> (newContext, words stuff)
1093 sensible ('*':m) = looksLikeModuleName m
1094 sensible m = looksLikeModuleName m
1096 separate :: Session -> [String] -> [Module] -> [Module]
1097 -> GHCi ([Module],[Module])
1098 separate session [] as bs = return (as,bs)
1099 separate session (('*':str):ms) as bs = do
1100 m <- io $ GHC.findModule session (GHC.mkModuleName str) Nothing
1101 b <- io $ GHC.moduleIsInterpreted session m
1102 if b then separate session ms (m:as) bs
1103 else throwDyn (CmdLineError ("module '"
1104 ++ GHC.moduleNameString (GHC.moduleName m)
1105 ++ "' is not interpreted"))
1106 separate session (str:ms) as bs = do
1107 m <- io $ GHC.findModule session (GHC.mkModuleName str) Nothing
1108 separate session ms as (m:bs)
1110 newContext :: [String] -> GHCi ()
1111 newContext strs = do
1113 (as,bs) <- separate s strs [] []
1114 prel_mod <- getPrelude
1115 let bs' = if null as && prel_mod `notElem` bs then prel_mod:bs else bs
1116 io $ GHC.setContext s as bs'
1119 addToContext :: [String] -> GHCi ()
1120 addToContext strs = do
1122 (as,bs) <- io $ GHC.getContext s
1124 (new_as,new_bs) <- separate s strs [] []
1126 let as_to_add = new_as \\ (as ++ bs)
1127 bs_to_add = new_bs \\ (as ++ bs)
1129 io $ GHC.setContext s (as ++ as_to_add) (bs ++ bs_to_add)
1132 removeFromContext :: [String] -> GHCi ()
1133 removeFromContext strs = do
1135 (as,bs) <- io $ GHC.getContext s
1137 (as_to_remove,bs_to_remove) <- separate s strs [] []
1139 let as' = as \\ (as_to_remove ++ bs_to_remove)
1140 bs' = bs \\ (as_to_remove ++ bs_to_remove)
1142 io $ GHC.setContext s as' bs'
1144 ----------------------------------------------------------------------------
1147 -- set options in the interpreter. Syntax is exactly the same as the
1148 -- ghc command line, except that certain options aren't available (-C,
1151 -- This is pretty fragile: most options won't work as expected. ToDo:
1152 -- figure out which ones & disallow them.
1154 setCmd :: String -> GHCi ()
1156 = do st <- getGHCiState
1157 let opts = options st
1158 io $ putStrLn (showSDoc (
1159 text "options currently set: " <>
1162 else hsep (map (\o -> char '+' <> text (optToStr o)) opts)
1165 = case toArgs str of
1166 ("args":args) -> setArgs args
1167 ("prog":prog) -> setProg prog
1168 ("prompt":prompt) -> setPrompt (after 6)
1169 ("editor":cmd) -> setEditor (after 6)
1170 wds -> setOptions wds
1171 where after n = dropWhile isSpace $ drop n $ dropWhile isSpace str
1175 setGHCiState st{ args = args }
1179 setGHCiState st{ progname = prog }
1181 io (hPutStrLn stderr "syntax: :set prog <progname>")
1185 setGHCiState st{ editor = cmd }
1187 setPrompt value = do
1190 then io $ hPutStrLn stderr $ "syntax: :set prompt <prompt>, currently \"" ++ prompt st ++ "\""
1191 else setGHCiState st{ prompt = remQuotes value }
1193 remQuotes ('\"':xs) | not (null xs) && last xs == '\"' = init xs
1197 do -- first, deal with the GHCi opts (+s, +t, etc.)
1198 let (plus_opts, minus_opts) = partition isPlus wds
1199 mapM_ setOpt plus_opts
1201 -- then, dynamic flags
1202 dflags <- getDynFlags
1203 let pkg_flags = packageFlags dflags
1204 (dflags',leftovers) <- io $ GHC.parseDynamicFlags dflags minus_opts
1206 if (not (null leftovers))
1207 then throwDyn (CmdLineError ("unrecognised flags: " ++
1211 new_pkgs <- setDynFlags dflags'
1213 -- if the package flags changed, we should reset the context
1214 -- and link the new packages.
1215 dflags <- getDynFlags
1216 when (packageFlags dflags /= pkg_flags) $ do
1217 io $ hPutStrLn stderr "package flags have changed, ressetting and loading new packages..."
1218 session <- getSession
1219 io (GHC.setTargets session [])
1220 io (GHC.load session LoadAllTargets)
1221 io (linkPackages dflags new_pkgs)
1222 setContextAfterLoad session []
1226 unsetOptions :: String -> GHCi ()
1228 = do -- first, deal with the GHCi opts (+s, +t, etc.)
1229 let opts = words str
1230 (minus_opts, rest1) = partition isMinus opts
1231 (plus_opts, rest2) = partition isPlus rest1
1233 if (not (null rest2))
1234 then io (putStrLn ("unknown option: '" ++ head rest2 ++ "'"))
1237 mapM_ unsetOpt plus_opts
1239 -- can't do GHC flags for now
1240 if (not (null minus_opts))
1241 then throwDyn (CmdLineError "can't unset GHC command-line flags")
1244 isMinus ('-':s) = True
1247 isPlus ('+':s) = True
1251 = case strToGHCiOpt str of
1252 Nothing -> io (putStrLn ("unknown option: '" ++ str ++ "'"))
1253 Just o -> setOption o
1256 = case strToGHCiOpt str of
1257 Nothing -> io (putStrLn ("unknown option: '" ++ str ++ "'"))
1258 Just o -> unsetOption o
1260 strToGHCiOpt :: String -> (Maybe GHCiOption)
1261 strToGHCiOpt "s" = Just ShowTiming
1262 strToGHCiOpt "t" = Just ShowType
1263 strToGHCiOpt "r" = Just RevertCAFs
1264 strToGHCiOpt _ = Nothing
1266 optToStr :: GHCiOption -> String
1267 optToStr ShowTiming = "s"
1268 optToStr ShowType = "t"
1269 optToStr RevertCAFs = "r"
1271 -- ---------------------------------------------------------------------------
1276 ["modules" ] -> showModules
1277 ["bindings"] -> showBindings
1278 ["linker"] -> io showLinkerState
1279 ["breaks"] -> showBkptTable
1280 _ -> throwDyn (CmdLineError "syntax: :show [modules|bindings]")
1283 session <- getSession
1284 let show_one ms = do m <- io (GHC.showModule session ms)
1286 graph <- io (GHC.getModuleGraph session)
1287 mapM_ show_one graph
1291 unqual <- io (GHC.getPrintUnqual s)
1292 bindings <- io (GHC.getBindings s)
1293 mapM_ showTyThing bindings
1296 showTyThing (AnId id) = do
1297 ty' <- cleanType (GHC.idType id)
1298 str <- showForUser (ppr id <> text " :: " <> ppr ty')
1300 showTyThing _ = return ()
1302 -- if -fglasgow-exts is on we show the foralls, otherwise we don't.
1303 cleanType :: Type -> GHCi Type
1305 dflags <- getDynFlags
1306 if dopt Opt_GlasgowExts dflags
1308 else return $! GHC.dropForAlls ty
1310 showBkptTable :: GHCi ()
1312 activeBreaks <- getActiveBreakPoints
1313 str <- showForUser $ ppr activeBreaks
1316 -- -----------------------------------------------------------------------------
1319 completeNone :: String -> IO [String]
1320 completeNone w = return []
1323 completeWord :: String -> Int -> Int -> IO (Maybe (String, [String]))
1324 completeWord w start end = do
1325 line <- Readline.getLineBuffer
1327 ':':_ | all isSpace (take (start-1) line) -> wrapCompleter completeCmd w
1329 | Just c <- is_cmd line -> do
1330 maybe_cmd <- lookupCommand c
1331 let (n,w') = selectWord (words' 0 line)
1333 Nothing -> return Nothing
1334 Just (_,_,False,complete) -> wrapCompleter complete w
1335 Just (_,_,True,complete) -> let complete' w = do rets <- complete w
1336 return (map (drop n) rets)
1337 in wrapCompleter complete' w'
1339 --printf "complete %s, start = %d, end = %d\n" w start end
1340 wrapCompleter completeIdentifier w
1341 where words' _ [] = []
1342 words' n str = let (w,r) = break isSpace str
1343 (s,r') = span isSpace r
1344 in (n,w):words' (n+length w+length s) r'
1345 -- In a Haskell expression we want to parse 'a-b' as three words
1346 -- where a compiler flag (ie. -fno-monomorphism-restriction) should
1347 -- only be a single word.
1348 selectWord [] = (0,w)
1349 selectWord ((offset,x):xs)
1350 | offset+length x >= start = (start-offset,take (end-offset) x)
1351 | otherwise = selectWord xs
1354 | ((':':w) : _) <- words (dropWhile isSpace line) = Just w
1355 | otherwise = Nothing
1358 cmds <- readIORef commands
1359 return (filter (w `isPrefixOf`) (map (':':) (map cmdName cmds)))
1361 completeMacro w = do
1362 cmds <- readIORef commands
1363 let cmds' = [ cmd | cmd <- map cmdName cmds, cmd `elem` map cmdName builtin_commands ]
1364 return (filter (w `isPrefixOf`) cmds')
1366 completeIdentifier w = do
1368 rdrs <- GHC.getRdrNamesInScope s
1369 return (filter (w `isPrefixOf`) (map (showSDoc.ppr) rdrs))
1371 completeModule w = do
1373 dflags <- GHC.getSessionDynFlags s
1374 let pkg_mods = allExposedModules dflags
1375 return (filter (w `isPrefixOf`) (map (showSDoc.ppr) pkg_mods))
1377 completeHomeModule w = do
1379 g <- GHC.getModuleGraph s
1380 let home_mods = map GHC.ms_mod_name g
1381 return (filter (w `isPrefixOf`) (map (showSDoc.ppr) home_mods))
1383 completeSetOptions w = do
1384 return (filter (w `isPrefixOf`) options)
1385 where options = "args":"prog":allFlags
1387 completeFilename = Readline.filenameCompletionFunction
1389 completeHomeModuleOrFile = unionComplete completeHomeModule completeFilename
1391 unionComplete :: (String -> IO [String]) -> (String -> IO [String]) -> String -> IO [String]
1392 unionComplete f1 f2 w = do
1397 wrapCompleter :: (String -> IO [String]) -> String -> IO (Maybe (String,[String]))
1398 wrapCompleter fun w = do
1401 [] -> return Nothing
1402 [x] -> return (Just (x,[]))
1403 xs -> case getCommonPrefix xs of
1404 "" -> return (Just ("",xs))
1405 pref -> return (Just (pref,xs))
1407 getCommonPrefix :: [String] -> String
1408 getCommonPrefix [] = ""
1409 getCommonPrefix (s:ss) = foldl common s ss
1410 where common s "" = ""
1412 common (c:cs) (d:ds)
1413 | c == d = c : common cs ds
1416 allExposedModules :: DynFlags -> [ModuleName]
1417 allExposedModules dflags
1418 = map GHC.mkModuleName (concat (map exposedModules (filter exposed (eltsUFM pkg_db))))
1420 pkg_db = pkgIdMap (pkgState dflags)
1422 completeCmd = completeNone
1423 completeMacro = completeNone
1424 completeIdentifier = completeNone
1425 completeModule = completeNone
1426 completeHomeModule = completeNone
1427 completeSetOptions = completeNone
1428 completeFilename = completeNone
1429 completeHomeModuleOrFile=completeNone
1430 completeBkpt = completeNone
1433 -- ---------------------------------------------------------------------------
1434 -- User code exception handling
1436 -- This is the exception handler for exceptions generated by the
1437 -- user's code and exceptions coming from children sessions;
1438 -- it normally just prints out the exception. The
1439 -- handler must be recursive, in case showing the exception causes
1440 -- more exceptions to be raised.
1442 -- Bugfix: if the user closed stdout or stderr, the flushing will fail,
1443 -- raising another exception. We therefore don't put the recursive
1444 -- handler arond the flushing operation, so if stderr is closed
1445 -- GHCi will just die gracefully rather than going into an infinite loop.
1446 handler :: Exception -> GHCi Bool
1448 handler exception = do
1450 io installSignalHandlers
1451 ghciHandle handler (showException exception >> return False)
1453 showException (DynException dyn) =
1454 case fromDynamic dyn of
1455 Nothing -> io (putStrLn ("*** Exception: (unknown)"))
1456 Just Interrupted -> io (putStrLn "Interrupted.")
1457 Just (CmdLineError s) -> io (putStrLn s) -- omit the location for CmdLineError
1458 Just ph@PhaseFailed{} -> io (putStrLn (showGhcException ph "")) -- ditto
1459 Just other_ghc_ex -> io (print other_ghc_ex)
1461 showException other_exception
1462 = io (putStrLn ("*** Exception: " ++ show other_exception))
1464 -----------------------------------------------------------------------------
1465 -- recursive exception handlers
1467 -- Don't forget to unblock async exceptions in the handler, or if we're
1468 -- in an exception loop (eg. let a = error a in a) the ^C exception
1469 -- may never be delivered. Thanks to Marcin for pointing out the bug.
1471 ghciHandle :: (Exception -> GHCi a) -> GHCi a -> GHCi a
1472 ghciHandle h (GHCi m) = GHCi $ \s ->
1473 Exception.catch (m s)
1474 (\e -> unGHCi (ghciUnblock (h e)) s)
1476 ghciUnblock :: GHCi a -> GHCi a
1477 ghciUnblock (GHCi a) = GHCi $ \s -> Exception.unblock (a s)
1480 -- ----------------------------------------------------------------------------
1483 expandPath :: String -> GHCi String
1485 case dropWhile isSpace path of
1487 tilde <- io (getEnv "HOME") -- will fail if HOME not defined
1488 return (tilde ++ '/':d)
1492 -- ----------------------------------------------------------------------------
1493 -- Windows console setup
1495 setUpConsole :: IO ()
1497 #ifdef mingw32_HOST_OS
1498 -- On Windows we need to set a known code page, otherwise the characters
1499 -- we read from the console will be be in some strange encoding, and
1500 -- similarly for characters we write to the console.
1502 -- At the moment, GHCi pretends all input is Latin-1. In the
1503 -- future we should support UTF-8, but for now we set the code pages
1506 -- It seems you have to set the font in the console window to
1507 -- a Unicode font in order for output to work properly,
1508 -- otherwise non-ASCII characters are mapped wrongly. sigh.
1509 -- (see MSDN for SetConsoleOutputCP()).
1511 setConsoleCP 28591 -- ISO Latin-1
1512 setConsoleOutputCP 28591 -- ISO Latin-1
1516 -- commands for debugger
1517 foreign import ccall "rts_setStepFlag" setStepFlag :: IO ()
1519 stepCmd :: String -> GHCi Bool
1520 stepCmd [] = doContinue setStepFlag
1521 stepCmd expression = do
1523 runCommand expression
1525 continueCmd :: String -> GHCi Bool
1526 continueCmd [] = doContinue $ return ()
1527 continueCmd other = do
1528 io $ putStrLn "The continue command accepts no arguments."
1531 doContinue :: IO () -> GHCi Bool
1532 doContinue actionBeforeCont = do
1533 resumeAction <- getResume
1535 case resumeAction of
1537 io $ putStrLn "There is no computation running."
1540 io $ actionBeforeCont
1541 runResult <- io action
1542 names <- switchOnRunResult runResult
1543 finishEvalExpr names
1546 deleteCmd :: String -> GHCi Bool
1547 deleteCmd argLine = do
1548 deleteSwitch $ words argLine
1551 deleteSwitch :: [String] -> GHCi ()
1553 io $ putStrLn "The delete command requires at least one argument."
1554 -- delete all break points
1555 deleteSwitch ("*":_rest) = clearActiveBreakPoints
1556 deleteSwitch idents = do
1557 mapM_ deleteOneBreak idents
1559 deleteOneBreak :: String -> GHCi ()
1561 | all isDigit str = deleteBreak (read str)
1562 | otherwise = return ()
1564 -- handle the "break" command
1565 breakCmd :: String -> GHCi Bool
1566 breakCmd argLine = do
1567 session <- getSession
1568 breakSwitch session $ words argLine
1570 breakSwitch :: Session -> [String] -> GHCi Bool
1571 breakSwitch _session [] = do
1572 io $ putStrLn "The break command requires at least one argument."
1574 breakSwitch session args@(arg1:rest)
1575 | looksLikeModule arg1 = do
1576 mod <- lookupModule session arg1
1577 breakByModule mod rest
1580 (toplevel, _) <- io $ GHC.getContext session
1582 (mod : _) -> breakByModule mod args
1584 io $ putStrLn "Cannot find default module for breakpoint."
1585 io $ putStrLn "Perhaps no modules are loaded for debugging?"
1588 -- Todo there may be a nicer way to test this
1589 looksLikeModule :: String -> Bool
1590 looksLikeModule [] = False
1591 looksLikeModule (x:_) = isUpper x
1593 breakByModule :: Module -> [String] -> GHCi ()
1594 breakByModule mod args@(arg1:rest)
1595 | all isDigit arg1 = do -- looks like a line number
1596 breakByModuleLine mod (read arg1) rest
1597 | looksLikeVar arg1 = do
1598 -- break by a function definition
1599 io $ putStrLn "Break by function definition not implemented."
1600 | otherwise = io $ putStrLn "Invalid arguments to break command."
1602 -- Todo there may be a nicer way to test this
1603 looksLikeVar :: String -> Bool
1604 looksLikeVar [] = False
1605 looksLikeVar (x:_) = isLower x || x `elem` "~!@#$%^&*-+"
1607 breakByModuleLine :: Module -> Int -> [String] -> GHCi ()
1608 breakByModuleLine mod line args
1609 | [] <- args = findBreakAndSet mod $ lookupTickTreeLine line
1610 | [col] <- args, all isDigit col =
1611 findBreakAndSet mod $ lookupTickTreeCoord (line, read col)
1612 | otherwise = io $ putStrLn "Invalid arguments to break command."
1614 findBreakAndSet :: Module -> (TickTree -> Maybe (Int, SrcSpan)) -> GHCi ()
1615 findBreakAndSet mod lookupTickTree = do
1616 (breakArray, ticks) <- getModBreak mod
1617 let tickTree = tickTreeFromList (assocs ticks)
1618 case lookupTickTree tickTree of
1619 Nothing -> io $ putStrLn $ "No breakpoints found at that location."
1620 Just (tick, span) -> do
1621 success <- io $ setBreakFlag True breakArray tick
1622 session <- getSession
1623 unqual <- io $ GHC.getPrintUnqual session
1627 recordBreak $ BreakLocation
1632 io $ printForUser stdout unqual $
1633 text "Breakpoint " <> ppr nm <>
1635 then text " was already set at " <> ppr span
1636 else text " activated at " <> ppr span
1638 str <- showForUser $ text "Breakpoint could not be activated at"
1642 getModBreak :: Module -> GHCi (BreakArray, Array Int SrcSpan)
1643 getModBreak mod = do
1644 session <- getSession
1645 Just mod_info <- io $ GHC.getModuleInfo session mod
1646 let modBreaks = GHC.modInfoModBreaks mod_info
1647 let array = modBreaks_array modBreaks
1648 let ticks = modBreaks_ticks modBreaks
1649 return (array, ticks)
1651 lookupModule :: Session -> String -> GHCi Module
1652 lookupModule session modName
1653 = io (GHC.findModule session (GHC.mkModuleName modName) Nothing)
1655 setBreakFlag :: Bool -> BreakArray -> Int -> IO Bool
1656 setBreakFlag toggle array index
1657 | toggle = setBreakOn array index
1658 | otherwise = setBreakOff array index
1661 {- these should probably go to the GHC API at some point -}
1662 enableBreakPoint :: Session -> Module -> Int -> IO ()
1663 enableBreakPoint session mod index = return ()
1665 disableBreakPoint :: Session -> Module -> Int -> IO ()
1666 disableBreakPoint session mod index = return ()
1668 activeBreakPoints :: Session -> IO [(Module,Int)]
1669 activeBreakPoints session = return []
1671 enableSingleStep :: Session -> IO ()
1672 enableSingleStep session = return ()
1674 disableSingleStep :: Session -> IO ()
1675 disableSingleStep session = return ()