Dynamic breakpoints in GHCi
[ghc.git] / compiler / ghci / InteractiveUI.hs
1 {-# OPTIONS -#include "Linker.h" #-}
2 -----------------------------------------------------------------------------
3 --
4 -- GHC Interactive User Interface
5 --
6 -- (c) The GHC Team 2005-2006
7 --
8 -----------------------------------------------------------------------------
9 module InteractiveUI (
10 interactiveUI,
11 ghciWelcomeMsg
12 ) where
13
14 #include "HsVersions.h"
15
16 import GhciMonad
17
18 -- The GHC interface
19 import qualified GHC
20 import GHC ( Session, LoadHowMuch(..), Target(..), TargetId(..),
21 Type, Module, ModuleName, TyThing(..), Phase )
22 import DynFlags
23 import Packages
24 import PackageConfig
25 import UniqFM
26 import PprTyThing
27 import Outputable
28
29 -- for createtags
30 import Name
31 import OccName
32 import SrcLoc
33
34 -- Other random utilities
35 import Digraph
36 import BasicTypes hiding (isTopLevel)
37 import Panic hiding (showException)
38 import Config
39 import StaticFlags
40 import Linker
41 import Util
42
43 -- The debugger
44 import Breakpoints
45 import Debugger hiding ( addModule )
46 import HscTypes
47 import Id
48 import Var ( globaliseId )
49 import IdInfo
50 import NameEnv
51 import RdrName
52 import Module
53 import Type
54 import TcType
55
56 #ifndef mingw32_HOST_OS
57 import System.Posix
58 #if __GLASGOW_HASKELL__ > 504
59 hiding (getEnv)
60 #endif
61 #else
62 import GHC.ConsoleHandler ( flushConsole )
63 import System.Win32 ( setConsoleCP, setConsoleOutputCP )
64 import qualified System.Win32
65 #endif
66
67 #ifdef USE_READLINE
68 import Control.Concurrent ( yield ) -- Used in readline loop
69 import System.Console.Readline as Readline
70 #endif
71
72 --import SystemExts
73
74 import Control.Exception as Exception
75 -- import Control.Concurrent
76
77 import Numeric
78 import Data.List
79 import Data.Int ( Int64 )
80 import Data.Maybe ( isJust, isNothing, fromMaybe, catMaybes )
81 import System.Cmd
82 import System.Environment
83 import System.Exit ( exitWith, ExitCode(..) )
84 import System.Directory
85 import System.IO
86 import System.IO.Error as IO
87 import Data.Char
88 import Control.Monad as Monad
89 import Foreign.StablePtr ( newStablePtr )
90
91 import GHC.Exts ( unsafeCoerce# )
92 import GHC.IOBase ( IOErrorType(InvalidArgument) )
93
94 import Data.IORef ( IORef, newIORef, readIORef, writeIORef )
95
96 import System.Posix.Internals ( setNonBlockingFD )
97
98 -----------------------------------------------------------------------------
99
100 ghciWelcomeMsg =
101 " ___ ___ _\n"++
102 " / _ \\ /\\ /\\/ __(_)\n"++
103 " / /_\\// /_/ / / | | GHC Interactive, version " ++ cProjectVersion ++ ", for Haskell 98.\n"++
104 "/ /_\\\\/ __ / /___| | http://www.haskell.org/ghc/\n"++
105 "\\____/\\/ /_/\\____/|_| Type :? for help.\n"
106
107 type Command = (String, String -> GHCi Bool, Bool, String -> IO [String])
108 cmdName (n,_,_,_) = n
109
110 GLOBAL_VAR(commands, builtin_commands, [Command])
111
112 builtin_commands :: [Command]
113 builtin_commands = [
114 ("add", tlC$ keepGoingPaths addModule, False, completeFilename),
115 ("browse", keepGoing browseCmd, False, completeModule),
116 ("cd", keepGoing changeDirectory, False, completeFilename),
117 ("def", keepGoing defineMacro, False, completeIdentifier),
118 ("e", keepGoing editFile, False, completeFilename),
119 -- Hugs users are accustomed to :e, so make sure it doesn't overlap
120 ("edit", keepGoing editFile, False, completeFilename),
121 ("help", keepGoing help, False, completeNone),
122 ("?", keepGoing help, False, completeNone),
123 ("info", keepGoing info, False, completeIdentifier),
124 ("load", tlC$ keepGoingPaths loadModule_,False, completeHomeModuleOrFile),
125 ("module", keepGoing setContext, False, completeModule),
126 ("main", tlC$ keepGoing runMain, False, completeIdentifier),
127 ("reload", tlC$ keepGoing reloadModule, False, completeNone),
128 ("check", keepGoing checkModule, False, completeHomeModule),
129 ("set", keepGoing setCmd, True, completeSetOptions),
130 ("show", keepGoing showCmd, False, completeNone),
131 ("etags", keepGoing createETagsFileCmd, False, completeFilename),
132 ("ctags", keepGoing createCTagsFileCmd, False, completeFilename),
133 ("type", keepGoing typeOfExpr, False, completeIdentifier),
134 #if defined(GHCI)
135 ("breakpoint",keepGoing bkptOptions, False, completeBkpt),
136 #endif
137 ("kind", keepGoing kindOfType, False, completeIdentifier),
138 ("unset", keepGoing unsetOptions, True, completeSetOptions),
139 ("undef", keepGoing undefineMacro, False, completeMacro),
140 ("quit", quit, False, completeNone)
141 ]
142
143 keepGoing :: (String -> GHCi ()) -> (String -> GHCi Bool)
144 keepGoing a str = a str >> return False
145
146 -- tlC: Top Level Command
147 tlC :: (String -> GHCi Bool) -> (String -> GHCi Bool)
148 tlC a str = do
149 top_level <- isTopLevel
150 if not top_level
151 then throwDyn (CmdLineError "Command only allowed at Top Level")
152 else a str
153
154 keepGoingPaths :: ([FilePath] -> GHCi ()) -> (String -> GHCi Bool)
155 keepGoingPaths a str = a (toArgs str) >> return False
156
157 shortHelpText = "use :? for help.\n"
158
159 -- NOTE: spaces at the end of each line to workaround CPP/string gap bug.
160 helpText =
161 " Commands available from the prompt:\n" ++
162 "\n" ++
163 " <stmt> evaluate/run <stmt>\n" ++
164 " :add <filename> ... add module(s) to the current target set\n" ++
165 " :breakpoint <option> commands for the GHCi debugger\n" ++
166 " :browse [*]<module> display the names defined by <module>\n" ++
167 " :cd <dir> change directory to <dir>\n" ++
168 " :def <cmd> <expr> define a command :<cmd>\n" ++
169 " :edit <file> edit file\n" ++
170 " :edit edit last module\n" ++
171 " :help, :? display this list of commands\n" ++
172 " :info [<name> ...] display information about the given names\n" ++
173 " :load <filename> ... load module(s) and their dependents\n" ++
174 " :module [+/-] [*]<mod> ... set the context for expression evaluation\n" ++
175 " :main [<arguments> ...] run the main function with the given arguments\n" ++
176 " :reload reload the current module set\n" ++
177 "\n" ++
178 " :set <option> ... set options\n" ++
179 " :set args <arg> ... set the arguments returned by System.getArgs\n" ++
180 " :set prog <progname> set the value returned by System.getProgName\n" ++
181 " :set prompt <prompt> set the prompt used in GHCi\n" ++
182 " :set editor <cmd> set the command used for :edit\n" ++
183 "\n" ++
184 " :show modules show the currently loaded modules\n" ++
185 " :show bindings show the current bindings made at the prompt\n" ++
186 "\n" ++
187 " :ctags [<file>] create tags file for Vi (default: \"tags\")\n" ++
188 " :etags [<file>] create tags file for Emacs (default: \"TAGS\")\n" ++
189 " :type <expr> show the type of <expr>\n" ++
190 " :kind <type> show the kind of <type>\n" ++
191 " :undef <cmd> undefine user-defined command :<cmd>\n" ++
192 " :unset <option> ... unset options\n" ++
193 " :quit exit GHCi\n" ++
194 " :!<command> run the shell command <command>\n" ++
195 "\n" ++
196 " Options for ':set' and ':unset':\n" ++
197 "\n" ++
198 " +r revert top-level expressions after each evaluation\n" ++
199 " +s print timing/memory stats after each evaluation\n" ++
200 " +t print type after evaluation\n" ++
201 " -<flags> most GHC command line flags can also be set here\n" ++
202 " (eg. -v2, -fglasgow-exts, etc.)\n" ++
203 "\n" ++
204 " Options for ':breakpoint':\n" ++
205 " list list the current breakpoints\n" ++
206 " add Module line [col] add a new breakpoint\n" ++
207 " del (breakpoint# | Module line [col]) delete a breakpoint\n" ++
208 " stop Stop a computation and return to the top level\n" ++
209 " step [count] Step by step execution (DISABLED)\n"
210
211 findEditor = do
212 getEnv "EDITOR"
213 `IO.catch` \_ -> do
214 #if mingw32_HOST_OS
215 win <- System.Win32.getWindowsDirectory
216 return (win `joinFileName` "notepad.exe")
217 #else
218 return ""
219 #endif
220
221 interactiveUI :: Session -> [(FilePath, Maybe Phase)] -> Maybe String -> IO ()
222 interactiveUI session srcs maybe_expr = do
223 -- HACK! If we happen to get into an infinite loop (eg the user
224 -- types 'let x=x in x' at the prompt), then the thread will block
225 -- on a blackhole, and become unreachable during GC. The GC will
226 -- detect that it is unreachable and send it the NonTermination
227 -- exception. However, since the thread is unreachable, everything
228 -- it refers to might be finalized, including the standard Handles.
229 -- This sounds like a bug, but we don't have a good solution right
230 -- now.
231 newStablePtr stdin
232 newStablePtr stdout
233 newStablePtr stderr
234
235 -- Initialise buffering for the *interpreted* I/O system
236 initInterpBuffering session
237
238 when (isNothing maybe_expr) $ do
239 -- Only for GHCi (not runghc and ghc -e):
240 -- Turn buffering off for the compiled program's stdout/stderr
241 turnOffBuffering
242 -- Turn buffering off for GHCi's stdout
243 hFlush stdout
244 hSetBuffering stdout NoBuffering
245 -- We don't want the cmd line to buffer any input that might be
246 -- intended for the program, so unbuffer stdin.
247 hSetBuffering stdin NoBuffering
248
249 -- initial context is just the Prelude
250 prel_mod <- GHC.findModule session prel_name Nothing
251 GHC.setContext session [] [prel_mod]
252
253 #ifdef USE_READLINE
254 Readline.initialize
255 Readline.setAttemptedCompletionFunction (Just completeWord)
256 --Readline.parseAndBind "set show-all-if-ambiguous 1"
257
258 let symbols = "!#$%&*+/<=>?@\\^|-~"
259 specials = "(),;[]`{}"
260 spaces = " \t\n"
261 word_break_chars = spaces ++ specials ++ symbols
262
263 Readline.setBasicWordBreakCharacters word_break_chars
264 Readline.setCompleterWordBreakCharacters word_break_chars
265 #endif
266
267 bkptTable <- newIORef emptyBkptTable
268 GHC.setBreakpointHandler session (instrumentationBkptHandler bkptTable)
269 default_editor <- findEditor
270
271 startGHCi (runGHCi srcs maybe_expr)
272 GHCiState{ progname = "<interactive>",
273 args = [],
274 prompt = "%s> ",
275 editor = default_editor,
276 session = session,
277 options = [],
278 prelude = prel_mod,
279 bkptTable = bkptTable,
280 topLevel = True
281 }
282
283 #ifdef USE_READLINE
284 Readline.resetTerminal Nothing
285 #endif
286
287 return ()
288
289 prel_name = GHC.mkModuleName "Prelude"
290
291 runGHCi :: [(FilePath, Maybe Phase)] -> Maybe String -> GHCi ()
292 runGHCi paths maybe_expr = do
293 let read_dot_files = not opt_IgnoreDotGhci
294
295 when (read_dot_files) $ do
296 -- Read in ./.ghci.
297 let file = "./.ghci"
298 exists <- io (doesFileExist file)
299 when exists $ do
300 dir_ok <- io (checkPerms ".")
301 file_ok <- io (checkPerms file)
302 when (dir_ok && file_ok) $ do
303 either_hdl <- io (IO.try (openFile "./.ghci" ReadMode))
304 case either_hdl of
305 Left e -> return ()
306 Right hdl -> fileLoop hdl False
307
308 when (read_dot_files) $ do
309 -- Read in $HOME/.ghci
310 either_dir <- io (IO.try (getEnv "HOME"))
311 case either_dir of
312 Left e -> return ()
313 Right dir -> do
314 cwd <- io (getCurrentDirectory)
315 when (dir /= cwd) $ do
316 let file = dir ++ "/.ghci"
317 ok <- io (checkPerms file)
318 when ok $ do
319 either_hdl <- io (IO.try (openFile file ReadMode))
320 case either_hdl of
321 Left e -> return ()
322 Right hdl -> fileLoop hdl False
323
324 -- Perform a :load for files given on the GHCi command line
325 -- When in -e mode, if the load fails then we want to stop
326 -- immediately rather than going on to evaluate the expression.
327 when (not (null paths)) $ do
328 ok <- ghciHandle (\e -> do showException e; return Failed) $
329 loadModule paths
330 when (isJust maybe_expr && failed ok) $
331 io (exitWith (ExitFailure 1))
332
333 -- if verbosity is greater than 0, or we are connected to a
334 -- terminal, display the prompt in the interactive loop.
335 is_tty <- io (hIsTerminalDevice stdin)
336 dflags <- getDynFlags
337 let show_prompt = verbosity dflags > 0 || is_tty
338
339 case maybe_expr of
340 Nothing ->
341 do
342 #if defined(mingw32_HOST_OS)
343 -- The win32 Console API mutates the first character of
344 -- type-ahead when reading from it in a non-buffered manner. Work
345 -- around this by flushing the input buffer of type-ahead characters,
346 -- but only if stdin is available.
347 flushed <- io (IO.try (GHC.ConsoleHandler.flushConsole stdin))
348 case flushed of
349 Left err | isDoesNotExistError err -> return ()
350 | otherwise -> io (ioError err)
351 Right () -> return ()
352 #endif
353 -- initialise the console if necessary
354 io setUpConsole
355
356 -- enter the interactive loop
357 interactiveLoop is_tty show_prompt
358 Just expr -> do
359 -- just evaluate the expression we were given
360 runCommandEval expr
361 return ()
362
363 -- and finally, exit
364 io $ do when (verbosity dflags > 0) $ putStrLn "Leaving GHCi."
365
366
367 interactiveLoop is_tty show_prompt =
368 -- Ignore ^C exceptions caught here
369 ghciHandleDyn (\e -> case e of
370 Interrupted -> do
371 #if defined(mingw32_HOST_OS)
372 io (putStrLn "")
373 #endif
374 interactiveLoop is_tty show_prompt
375 _other -> return ()) $
376
377 ghciUnblock $ do -- unblock necessary if we recursed from the
378 -- exception handler above.
379
380 -- read commands from stdin
381 #ifdef USE_READLINE
382 if (is_tty)
383 then readlineLoop
384 else fileLoop stdin show_prompt
385 #else
386 fileLoop stdin show_prompt
387 #endif
388
389
390 -- NOTE: We only read .ghci files if they are owned by the current user,
391 -- and aren't world writable. Otherwise, we could be accidentally
392 -- running code planted by a malicious third party.
393
394 -- Furthermore, We only read ./.ghci if . is owned by the current user
395 -- and isn't writable by anyone else. I think this is sufficient: we
396 -- don't need to check .. and ../.. etc. because "." always refers to
397 -- the same directory while a process is running.
398
399 checkPerms :: String -> IO Bool
400 checkPerms name =
401 #ifdef mingw32_HOST_OS
402 return True
403 #else
404 Util.handle (\_ -> return False) $ do
405 st <- getFileStatus name
406 me <- getRealUserID
407 if fileOwner st /= me then do
408 putStrLn $ "WARNING: " ++ name ++ " is owned by someone else, IGNORING!"
409 return False
410 else do
411 let mode = fileMode st
412 if (groupWriteMode == (mode `intersectFileModes` groupWriteMode))
413 || (otherWriteMode == (mode `intersectFileModes` otherWriteMode))
414 then do
415 putStrLn $ "*** WARNING: " ++ name ++
416 " is writable by someone else, IGNORING!"
417 return False
418 else return True
419 #endif
420
421 fileLoop :: Handle -> Bool -> GHCi ()
422 fileLoop hdl show_prompt = do
423 session <- getSession
424 (mod,imports) <- io (GHC.getContext session)
425 st <- getGHCiState
426 when show_prompt (io (putStr (mkPrompt mod imports (prompt st))))
427 l <- io (IO.try (hGetLine hdl))
428 case l of
429 Left e | isEOFError e -> return ()
430 | InvalidArgument <- etype -> return ()
431 | otherwise -> io (ioError e)
432 where etype = ioeGetErrorType e
433 -- treat InvalidArgument in the same way as EOF:
434 -- this can happen if the user closed stdin, or
435 -- perhaps did getContents which closes stdin at
436 -- EOF.
437 Right l ->
438 case removeSpaces l of
439 "" -> fileLoop hdl show_prompt
440 l -> do quit <- runCommand l
441 if quit then return () else fileLoop hdl show_prompt
442
443 stringLoop :: [String] -> GHCi Bool{-True: we quit-}
444 stringLoop [] = return False
445 stringLoop (s:ss) = do
446 case removeSpaces s of
447 "" -> stringLoop ss
448 l -> do quit <- runCommand l
449 if quit then return True else stringLoop ss
450
451 mkPrompt toplevs exports prompt
452 = showSDoc $ f prompt
453 where
454 f ('%':'s':xs) = perc_s <> f xs
455 f ('%':'%':xs) = char '%' <> f xs
456 f (x:xs) = char x <> f xs
457 f [] = empty
458
459 perc_s = hsep (map (\m -> char '*' <> ppr (GHC.moduleName m)) toplevs) <+>
460 hsep (map (ppr . GHC.moduleName) exports)
461
462
463 #ifdef USE_READLINE
464 readlineLoop :: GHCi ()
465 readlineLoop = do
466 session <- getSession
467 (mod,imports) <- io (GHC.getContext session)
468 io yield
469 saveSession -- for use by completion
470 st <- getGHCiState
471 l <- io (readline (mkPrompt mod imports (prompt st))
472 `finally` setNonBlockingFD 0)
473 -- readline sometimes puts stdin into blocking mode,
474 -- so we need to put it back for the IO library
475 splatSavedSession
476 case l of
477 Nothing -> return ()
478 Just l ->
479 case removeSpaces l of
480 "" -> readlineLoop
481 l -> do
482 io (addHistory l)
483 quit <- runCommand l
484 if quit then return () else readlineLoop
485 #endif
486
487 runCommand :: String -> GHCi Bool
488 runCommand c = ghciHandle handler (doCommand c)
489 where
490 doCommand (':' : command) = specialCommand command
491 doCommand stmt
492 = do timeIt (do nms <- runStmt stmt; finishEvalExpr nms)
493 return False
494
495 -- This version is for the GHC command-line option -e. The only difference
496 -- from runCommand is that it catches the ExitException exception and
497 -- exits, rather than printing out the exception.
498 runCommandEval c = ghciHandle handleEval (doCommand c)
499 where
500 handleEval (ExitException code) = io (exitWith code)
501 handleEval e = do handler e
502 io (exitWith (ExitFailure 1))
503
504 doCommand (':' : command) = specialCommand command
505 doCommand stmt
506 = do nms <- runStmt stmt
507 case nms of
508 Nothing -> io (exitWith (ExitFailure 1))
509 -- failure to run the command causes exit(1) for ghc -e.
510 _ -> finishEvalExpr nms
511
512 runStmt :: String -> GHCi (Maybe [Name])
513 runStmt stmt
514 | null (filter (not.isSpace) stmt) = return (Just [])
515 | otherwise
516 = do st <- getGHCiState
517 session <- getSession
518 result <- io $ withProgName (progname st) $ withArgs (args st) $
519 GHC.runStmt session stmt
520 case result of
521 GHC.RunFailed -> return Nothing
522 GHC.RunException e -> throw e -- this is caught by runCommand(Eval)
523 GHC.RunOk names -> return (Just names)
524
525 -- possibly print the type and revert CAFs after evaluating an expression
526 finishEvalExpr mb_names
527 = do b <- isOptionSet ShowType
528 session <- getSession
529 case mb_names of
530 Nothing -> return ()
531 Just names -> when b (mapM_ (showTypeOfName session) names)
532
533 flushInterpBuffers
534 io installSignalHandlers
535 b <- isOptionSet RevertCAFs
536 io (when b revertCAFs)
537 return True
538
539 showTypeOfName :: Session -> Name -> GHCi ()
540 showTypeOfName session n
541 = do maybe_tything <- io (GHC.lookupName session n)
542 case maybe_tything of
543 Nothing -> return ()
544 Just thing -> showTyThing thing
545
546 specialCommand :: String -> GHCi Bool
547 specialCommand ('!':str) = shellEscape (dropWhile isSpace str)
548 specialCommand str = do
549 let (cmd,rest) = break isSpace str
550 maybe_cmd <- io (lookupCommand cmd)
551 case maybe_cmd of
552 Nothing -> io (hPutStr stdout ("unknown command ':" ++ cmd ++ "'\n"
553 ++ shortHelpText) >> return False)
554 Just (_,f,_,_) -> f (dropWhile isSpace rest)
555
556 lookupCommand :: String -> IO (Maybe Command)
557 lookupCommand str = do
558 cmds <- readIORef commands
559 -- look for exact match first, then the first prefix match
560 case [ c | c <- cmds, str == cmdName c ] of
561 c:_ -> return (Just c)
562 [] -> case [ c | c@(s,_,_,_) <- cmds, prefixMatch str s ] of
563 [] -> return Nothing
564 c:_ -> return (Just c)
565
566 -----------------------------------------------------------------------------
567 -- Commands
568
569 help :: String -> GHCi ()
570 help _ = io (putStr helpText)
571
572 info :: String -> GHCi ()
573 info "" = throwDyn (CmdLineError "syntax: ':i <thing-you-want-info-about>'")
574 info s = do { let names = words s
575 ; session <- getSession
576 ; dflags <- getDynFlags
577 ; let exts = dopt Opt_GlasgowExts dflags
578 ; mapM_ (infoThing exts session) names }
579 where
580 infoThing exts session str = io $ do
581 names <- GHC.parseName session str
582 let filtered = filterOutChildren names
583 mb_stuffs <- mapM (GHC.getInfo session) filtered
584 unqual <- GHC.getPrintUnqual session
585 putStrLn (showSDocForUser unqual $
586 vcat (intersperse (text "") $
587 [ pprInfo exts stuff | Just stuff <- mb_stuffs ]))
588
589 -- Filter out names whose parent is also there Good
590 -- example is '[]', which is both a type and data
591 -- constructor in the same type
592 filterOutChildren :: [Name] -> [Name]
593 filterOutChildren names = filter (not . parent_is_there) names
594 where parent_is_there n
595 -- | Just p <- GHC.nameParent_maybe n = p `elem` names
596 -- ToDo!!
597 | otherwise = False
598
599 pprInfo exts (thing, fixity, insts)
600 = pprTyThingInContextLoc exts thing
601 $$ show_fixity fixity
602 $$ vcat (map GHC.pprInstance insts)
603 where
604 show_fixity fix
605 | fix == GHC.defaultFixity = empty
606 | otherwise = ppr fix <+> ppr (GHC.getName thing)
607
608 -----------------------------------------------------------------------------
609 -- Commands
610
611 runMain :: String -> GHCi ()
612 runMain args = do
613 let ss = concat $ intersperse "," (map (\ s -> ('"':s)++"\"") (toArgs args))
614 runCommand $ '[': ss ++ "] `System.Environment.withArgs` main"
615 return ()
616
617 addModule :: [FilePath] -> GHCi ()
618 addModule files = do
619 io (revertCAFs) -- always revert CAFs on load/add.
620 files <- mapM expandPath files
621 targets <- mapM (\m -> io (GHC.guessTarget m Nothing)) files
622 session <- getSession
623 io (mapM_ (GHC.addTarget session) targets)
624 ok <- io (GHC.load session LoadAllTargets)
625 afterLoad ok session
626
627 changeDirectory :: String -> GHCi ()
628 changeDirectory dir = do
629 session <- getSession
630 graph <- io (GHC.getModuleGraph session)
631 when (not (null graph)) $
632 io $ putStr "Warning: changing directory causes all loaded modules to be unloaded,\nbecause the search path has changed.\n"
633 io (GHC.setTargets session [])
634 io (GHC.load session LoadAllTargets)
635 setContextAfterLoad session []
636 io (GHC.workingDirectoryChanged session)
637 dir <- expandPath dir
638 io (setCurrentDirectory dir)
639
640 editFile :: String -> GHCi ()
641 editFile str
642 | null str = do
643 -- find the name of the "topmost" file loaded
644 session <- getSession
645 graph0 <- io (GHC.getModuleGraph session)
646 graph1 <- filterM (io . GHC.isLoaded session . GHC.ms_mod_name) graph0
647 let graph2 = flattenSCCs (GHC.topSortModuleGraph True graph1 Nothing)
648 case GHC.ml_hs_file (GHC.ms_location (last graph2)) of
649 Just file -> do_edit file
650 Nothing -> throwDyn (CmdLineError "unknown file name")
651 | otherwise = do_edit str
652 where
653 do_edit file = do
654 st <- getGHCiState
655 let cmd = editor st
656 when (null cmd) $
657 throwDyn (CmdLineError "editor not set, use :set editor")
658 io $ system (cmd ++ ' ':file)
659 return ()
660
661 defineMacro :: String -> GHCi ()
662 defineMacro s = do
663 let (macro_name, definition) = break isSpace s
664 cmds <- io (readIORef commands)
665 if (null macro_name)
666 then throwDyn (CmdLineError "invalid macro name")
667 else do
668 if (macro_name `elem` map cmdName cmds)
669 then throwDyn (CmdLineError
670 ("command '" ++ macro_name ++ "' is already defined"))
671 else do
672
673 -- give the expression a type signature, so we can be sure we're getting
674 -- something of the right type.
675 let new_expr = '(' : definition ++ ") :: String -> IO String"
676
677 -- compile the expression
678 cms <- getSession
679 maybe_hv <- io (GHC.compileExpr cms new_expr)
680 case maybe_hv of
681 Nothing -> return ()
682 Just hv -> io (writeIORef commands --
683 (cmds ++ [(macro_name, runMacro hv, False, completeNone)]))
684
685 runMacro :: GHC.HValue{-String -> IO String-} -> String -> GHCi Bool
686 runMacro fun s = do
687 str <- io ((unsafeCoerce# fun :: String -> IO String) s)
688 stringLoop (lines str)
689
690 undefineMacro :: String -> GHCi ()
691 undefineMacro macro_name = do
692 cmds <- io (readIORef commands)
693 if (macro_name `elem` map cmdName builtin_commands)
694 then throwDyn (CmdLineError
695 ("command '" ++ macro_name ++ "' cannot be undefined"))
696 else do
697 if (macro_name `notElem` map cmdName cmds)
698 then throwDyn (CmdLineError
699 ("command '" ++ macro_name ++ "' not defined"))
700 else do
701 io (writeIORef commands (filter ((/= macro_name) . cmdName) cmds))
702
703
704 loadModule :: [(FilePath, Maybe Phase)] -> GHCi SuccessFlag
705 loadModule fs = timeIt (loadModule' fs)
706
707 loadModule_ :: [FilePath] -> GHCi ()
708 loadModule_ fs = do loadModule (zip fs (repeat Nothing)); return ()
709
710 loadModule' :: [(FilePath, Maybe Phase)] -> GHCi SuccessFlag
711 loadModule' files = do
712 session <- getSession
713
714 -- unload first
715 io (GHC.setTargets session [])
716 io (GHC.load session LoadAllTargets)
717
718 -- expand tildes
719 let (filenames, phases) = unzip files
720 exp_filenames <- mapM expandPath filenames
721 let files' = zip exp_filenames phases
722 targets <- io (mapM (uncurry GHC.guessTarget) files')
723
724 -- NOTE: we used to do the dependency anal first, so that if it
725 -- fails we didn't throw away the current set of modules. This would
726 -- require some re-working of the GHC interface, so we'll leave it
727 -- as a ToDo for now.
728
729 io (GHC.setTargets session targets)
730 ok <- io (GHC.load session LoadAllTargets)
731 afterLoad ok session
732 return ok
733
734 checkModule :: String -> GHCi ()
735 checkModule m = do
736 let modl = GHC.mkModuleName m
737 session <- getSession
738 result <- io (GHC.checkModule session modl)
739 case result of
740 Nothing -> io $ putStrLn "Nothing"
741 Just r -> io $ putStrLn (showSDoc (
742 case GHC.checkedModuleInfo r of
743 Just cm | Just scope <- GHC.modInfoTopLevelScope cm ->
744 let
745 (local,global) = partition ((== modl) . GHC.moduleName . GHC.nameModule) scope
746 in
747 (text "global names: " <+> ppr global) $$
748 (text "local names: " <+> ppr local)
749 _ -> empty))
750 afterLoad (successIf (isJust result)) session
751
752 reloadModule :: String -> GHCi ()
753 reloadModule "" = do
754 io (revertCAFs) -- always revert CAFs on reload.
755 session <- getSession
756 ok <- io (GHC.load session LoadAllTargets)
757 afterLoad ok session
758 reloadModule m = do
759 io (revertCAFs) -- always revert CAFs on reload.
760 session <- getSession
761 ok <- io (GHC.load session (LoadUpTo (GHC.mkModuleName m)))
762 afterLoad ok session
763
764 afterLoad ok session = do
765 io (revertCAFs) -- always revert CAFs on load.
766 graph <- io (GHC.getModuleGraph session)
767 graph' <- filterM (io . GHC.isLoaded session . GHC.ms_mod_name) graph
768 setContextAfterLoad session graph'
769 refreshBkptTable graph'
770 modulesLoadedMsg ok (map GHC.ms_mod_name graph')
771
772 setContextAfterLoad session [] = do
773 prel_mod <- getPrelude
774 io (GHC.setContext session [] [prel_mod])
775 setContextAfterLoad session ms = do
776 -- load a target if one is available, otherwise load the topmost module.
777 targets <- io (GHC.getTargets session)
778 case [ m | Just m <- map (findTarget ms) targets ] of
779 [] ->
780 let graph' = flattenSCCs (GHC.topSortModuleGraph True ms Nothing) in
781 load_this (last graph')
782 (m:_) ->
783 load_this m
784 where
785 findTarget ms t
786 = case filter (`matches` t) ms of
787 [] -> Nothing
788 (m:_) -> Just m
789
790 summary `matches` Target (TargetModule m) _
791 = GHC.ms_mod_name summary == m
792 summary `matches` Target (TargetFile f _) _
793 | Just f' <- GHC.ml_hs_file (GHC.ms_location summary) = f == f'
794 summary `matches` target
795 = False
796
797 load_this summary | m <- GHC.ms_mod summary = do
798 b <- io (GHC.moduleIsInterpreted session m)
799 if b then io (GHC.setContext session [m] [])
800 else do
801 prel_mod <- getPrelude
802 io (GHC.setContext session [] [prel_mod,m])
803
804
805 modulesLoadedMsg :: SuccessFlag -> [ModuleName] -> GHCi ()
806 modulesLoadedMsg ok mods = do
807 dflags <- getDynFlags
808 when (verbosity dflags > 0) $ do
809 let mod_commas
810 | null mods = text "none."
811 | otherwise = hsep (
812 punctuate comma (map ppr mods)) <> text "."
813 case ok of
814 Failed ->
815 io (putStrLn (showSDoc (text "Failed, modules loaded: " <> mod_commas)))
816 Succeeded ->
817 io (putStrLn (showSDoc (text "Ok, modules loaded: " <> mod_commas)))
818
819
820 typeOfExpr :: String -> GHCi ()
821 typeOfExpr str
822 = do cms <- getSession
823 maybe_ty <- io (GHC.exprType cms str)
824 case maybe_ty of
825 Nothing -> return ()
826 Just ty -> do ty' <- cleanType ty
827 tystr <- showForUser (ppr ty')
828 io (putStrLn (str ++ " :: " ++ tystr))
829
830 kindOfType :: String -> GHCi ()
831 kindOfType str
832 = do cms <- getSession
833 maybe_ty <- io (GHC.typeKind cms str)
834 case maybe_ty of
835 Nothing -> return ()
836 Just ty -> do tystr <- showForUser (ppr ty)
837 io (putStrLn (str ++ " :: " ++ tystr))
838
839 quit :: String -> GHCi Bool
840 quit _ = return True
841
842 shellEscape :: String -> GHCi Bool
843 shellEscape str = io (system str >> return False)
844
845 -----------------------------------------------------------------------------
846 -- create tags file for currently loaded modules.
847
848 createETagsFileCmd, createCTagsFileCmd :: String -> GHCi ()
849
850 createCTagsFileCmd "" = ghciCreateTagsFile CTags "tags"
851 createCTagsFileCmd file = ghciCreateTagsFile CTags file
852
853 createETagsFileCmd "" = ghciCreateTagsFile ETags "TAGS"
854 createETagsFileCmd file = ghciCreateTagsFile ETags file
855
856 data TagsKind = ETags | CTags
857
858 ghciCreateTagsFile :: TagsKind -> FilePath -> GHCi ()
859 ghciCreateTagsFile kind file = do
860 session <- getSession
861 io $ createTagsFile session kind file
862
863 -- ToDo:
864 -- - remove restriction that all modules must be interpreted
865 -- (problem: we don't know source locations for entities unless
866 -- we compiled the module.
867 --
868 -- - extract createTagsFile so it can be used from the command-line
869 -- (probably need to fix first problem before this is useful).
870 --
871 createTagsFile :: Session -> TagsKind -> FilePath -> IO ()
872 createTagsFile session tagskind tagFile = do
873 graph <- GHC.getModuleGraph session
874 let ms = map GHC.ms_mod graph
875 tagModule m = do
876 is_interpreted <- GHC.moduleIsInterpreted session m
877 -- should we just skip these?
878 when (not is_interpreted) $
879 throwDyn (CmdLineError ("module '"
880 ++ GHC.moduleNameString (GHC.moduleName m)
881 ++ "' is not interpreted"))
882 mbModInfo <- GHC.getModuleInfo session m
883 let unqual
884 | Just modinfo <- mbModInfo,
885 Just unqual <- GHC.modInfoPrintUnqualified modinfo = unqual
886 | otherwise = GHC.alwaysQualify
887
888 case mbModInfo of
889 Just modInfo -> return $! listTags unqual modInfo
890 _ -> return []
891
892 mtags <- mapM tagModule ms
893 either_res <- collateAndWriteTags tagskind tagFile $ concat mtags
894 case either_res of
895 Left e -> hPutStrLn stderr $ ioeGetErrorString e
896 Right _ -> return ()
897
898 listTags :: PrintUnqualified -> GHC.ModuleInfo -> [TagInfo]
899 listTags unqual modInfo =
900 [ tagInfo unqual name loc
901 | name <- GHC.modInfoExports modInfo
902 , let loc = nameSrcLoc name
903 , isGoodSrcLoc loc
904 ]
905
906 type TagInfo = (String -- tag name
907 ,String -- file name
908 ,Int -- line number
909 ,Int -- column number
910 )
911
912 -- get tag info, for later translation into Vim or Emacs style
913 tagInfo :: PrintUnqualified -> Name -> SrcLoc -> TagInfo
914 tagInfo unqual name loc
915 = ( showSDocForUser unqual $ pprOccName (nameOccName name)
916 , showSDocForUser unqual $ ftext (srcLocFile loc)
917 , srcLocLine loc
918 , srcLocCol loc
919 )
920
921 collateAndWriteTags :: TagsKind -> FilePath -> [TagInfo] -> IO (Either IOError ())
922 collateAndWriteTags CTags file tagInfos = do -- ctags style, Vim et al
923 let tags = unlines $ sortLe (<=) $ nub $ map showTag tagInfos
924 IO.try (writeFile file tags)
925 collateAndWriteTags ETags file tagInfos = do -- etags style, Emacs/XEmacs
926 let byFile op (_,f1,_,_) (_,f2,_,_) = f1 `op` f2
927 groups = groupBy (byFile (==)) $ sortLe (byFile (<=)) tagInfos
928 tagGroups <- mapM tagFileGroup groups
929 IO.try (writeFile file $ concat tagGroups)
930 where
931 tagFileGroup group@[] = throwDyn (CmdLineError "empty tag file group??")
932 tagFileGroup group@((_,fileName,_,_):_) = do
933 file <- readFile fileName -- need to get additional info from sources..
934 let byLine (_,_,l1,_) (_,_,l2,_) = l1 <= l2
935 sortedGroup = sortLe byLine group
936 tags = unlines $ perFile sortedGroup 1 0 $ lines file
937 return $ "\x0c\n" ++ fileName ++ "," ++ show (length tags) ++ "\n" ++ tags
938 perFile (tagInfo@(tag,file,lNo,colNo):tags) count pos (line:lines) | lNo>count =
939 perFile (tagInfo:tags) (count+1) (pos+length line) lines
940 perFile (tagInfo@(tag,file,lNo,colNo):tags) count pos lines@(line:_) | lNo==count =
941 showETag tagInfo line pos : perFile tags count pos lines
942 perFile tags count pos lines = []
943
944 -- simple ctags format, for Vim et al
945 showTag :: TagInfo -> String
946 showTag (tag,file,lineNo,colNo)
947 = tag ++ "\t" ++ file ++ "\t" ++ show lineNo
948
949 -- etags format, for Emacs/XEmacs
950 showETag :: TagInfo -> String -> Int -> String
951 showETag (tag,file,lineNo,colNo) line charPos
952 = take colNo line ++ tag
953 ++ "\x7f" ++ tag
954 ++ "\x01" ++ show lineNo
955 ++ "," ++ show charPos
956
957 -----------------------------------------------------------------------------
958 -- Browsing a module's contents
959
960 browseCmd :: String -> GHCi ()
961 browseCmd m =
962 case words m of
963 ['*':m] | looksLikeModuleName m -> browseModule m False
964 [m] | looksLikeModuleName m -> browseModule m True
965 _ -> throwDyn (CmdLineError "syntax: :browse <module>")
966
967 browseModule m exports_only = do
968 s <- getSession
969 modl <- io $ GHC.findModule s (GHC.mkModuleName m) Nothing
970 is_interpreted <- io (GHC.moduleIsInterpreted s modl)
971 when (not is_interpreted && not exports_only) $
972 throwDyn (CmdLineError ("module '" ++ m ++ "' is not interpreted"))
973
974 -- Temporarily set the context to the module we're interested in,
975 -- just so we can get an appropriate PrintUnqualified
976 (as,bs) <- io (GHC.getContext s)
977 prel_mod <- getPrelude
978 io (if exports_only then GHC.setContext s [] [prel_mod,modl]
979 else GHC.setContext s [modl] [])
980 unqual <- io (GHC.getPrintUnqual s)
981 io (GHC.setContext s as bs)
982
983 mb_mod_info <- io $ GHC.getModuleInfo s modl
984 case mb_mod_info of
985 Nothing -> throwDyn (CmdLineError ("unknown module: " ++ m))
986 Just mod_info -> do
987 let names
988 | exports_only = GHC.modInfoExports mod_info
989 | otherwise = fromMaybe [] (GHC.modInfoTopLevelScope mod_info)
990
991 filtered = filterOutChildren names
992
993 things <- io $ mapM (GHC.lookupName s) filtered
994
995 dflags <- getDynFlags
996 let exts = dopt Opt_GlasgowExts dflags
997 io (putStrLn (showSDocForUser unqual (
998 vcat (map (pprTyThingInContext exts) (catMaybes things))
999 )))
1000 -- ToDo: modInfoInstances currently throws an exception for
1001 -- package modules. When it works, we can do this:
1002 -- $$ vcat (map GHC.pprInstance (GHC.modInfoInstances mod_info))
1003
1004 -----------------------------------------------------------------------------
1005 -- Setting the module context
1006
1007 setContext str
1008 | all sensible mods = fn mods
1009 | otherwise = throwDyn (CmdLineError "syntax: :module [+/-] [*]M1 ... [*]Mn")
1010 where
1011 (fn, mods) = case str of
1012 '+':stuff -> (addToContext, words stuff)
1013 '-':stuff -> (removeFromContext, words stuff)
1014 stuff -> (newContext, words stuff)
1015
1016 sensible ('*':m) = looksLikeModuleName m
1017 sensible m = looksLikeModuleName m
1018
1019 separate :: Session -> [String] -> [Module] -> [Module]
1020 -> GHCi ([Module],[Module])
1021 separate session [] as bs = return (as,bs)
1022 separate session (('*':str):ms) as bs = do
1023 m <- io $ GHC.findModule session (GHC.mkModuleName str) Nothing
1024 b <- io $ GHC.moduleIsInterpreted session m
1025 if b then separate session ms (m:as) bs
1026 else throwDyn (CmdLineError ("module '"
1027 ++ GHC.moduleNameString (GHC.moduleName m)
1028 ++ "' is not interpreted"))
1029 separate session (str:ms) as bs = do
1030 m <- io $ GHC.findModule session (GHC.mkModuleName str) Nothing
1031 separate session ms as (m:bs)
1032
1033 newContext :: [String] -> GHCi ()
1034 newContext strs = do
1035 s <- getSession
1036 (as,bs) <- separate s strs [] []
1037 prel_mod <- getPrelude
1038 let bs' = if null as && prel_mod `notElem` bs then prel_mod:bs else bs
1039 io $ GHC.setContext s as bs'
1040
1041
1042 addToContext :: [String] -> GHCi ()
1043 addToContext strs = do
1044 s <- getSession
1045 (as,bs) <- io $ GHC.getContext s
1046
1047 (new_as,new_bs) <- separate s strs [] []
1048
1049 let as_to_add = new_as \\ (as ++ bs)
1050 bs_to_add = new_bs \\ (as ++ bs)
1051
1052 io $ GHC.setContext s (as ++ as_to_add) (bs ++ bs_to_add)
1053
1054
1055 removeFromContext :: [String] -> GHCi ()
1056 removeFromContext strs = do
1057 s <- getSession
1058 (as,bs) <- io $ GHC.getContext s
1059
1060 (as_to_remove,bs_to_remove) <- separate s strs [] []
1061
1062 let as' = as \\ (as_to_remove ++ bs_to_remove)
1063 bs' = bs \\ (as_to_remove ++ bs_to_remove)
1064
1065 io $ GHC.setContext s as' bs'
1066
1067 ----------------------------------------------------------------------------
1068 -- Code for `:set'
1069
1070 -- set options in the interpreter. Syntax is exactly the same as the
1071 -- ghc command line, except that certain options aren't available (-C,
1072 -- -E etc.)
1073 --
1074 -- This is pretty fragile: most options won't work as expected. ToDo:
1075 -- figure out which ones & disallow them.
1076
1077 setCmd :: String -> GHCi ()
1078 setCmd ""
1079 = do st <- getGHCiState
1080 let opts = options st
1081 io $ putStrLn (showSDoc (
1082 text "options currently set: " <>
1083 if null opts
1084 then text "none."
1085 else hsep (map (\o -> char '+' <> text (optToStr o)) opts)
1086 ))
1087 setCmd str
1088 = case toArgs str of
1089 ("args":args) -> setArgs args
1090 ("prog":prog) -> setProg prog
1091 ("prompt":prompt) -> setPrompt (after 6)
1092 ("editor":cmd) -> setEditor (after 6)
1093 wds -> setOptions wds
1094 where after n = dropWhile isSpace $ drop n $ dropWhile isSpace str
1095
1096 setArgs args = do
1097 st <- getGHCiState
1098 setGHCiState st{ args = args }
1099
1100 setProg [prog] = do
1101 st <- getGHCiState
1102 setGHCiState st{ progname = prog }
1103 setProg _ = do
1104 io (hPutStrLn stderr "syntax: :set prog <progname>")
1105
1106 setEditor cmd = do
1107 st <- getGHCiState
1108 setGHCiState st{ editor = cmd }
1109
1110 setPrompt value = do
1111 st <- getGHCiState
1112 if null value
1113 then io $ hPutStrLn stderr $ "syntax: :set prompt <prompt>, currently \"" ++ prompt st ++ "\""
1114 else setGHCiState st{ prompt = remQuotes value }
1115 where
1116 remQuotes ('\"':xs) | not (null xs) && last xs == '\"' = init xs
1117 remQuotes x = x
1118
1119 setOptions wds =
1120 do -- first, deal with the GHCi opts (+s, +t, etc.)
1121 let (plus_opts, minus_opts) = partition isPlus wds
1122 mapM_ setOpt plus_opts
1123
1124 -- then, dynamic flags
1125 dflags <- getDynFlags
1126 let pkg_flags = packageFlags dflags
1127 (dflags',leftovers) <- io $ GHC.parseDynamicFlags dflags minus_opts
1128
1129 if (not (null leftovers))
1130 then throwDyn (CmdLineError ("unrecognised flags: " ++
1131 unwords leftovers))
1132 else return ()
1133
1134 new_pkgs <- setDynFlags dflags'
1135
1136 -- if the package flags changed, we should reset the context
1137 -- and link the new packages.
1138 dflags <- getDynFlags
1139 when (packageFlags dflags /= pkg_flags) $ do
1140 io $ hPutStrLn stderr "package flags have changed, ressetting and loading new packages..."
1141 session <- getSession
1142 io (GHC.setTargets session [])
1143 io (GHC.load session LoadAllTargets)
1144 io (linkPackages dflags new_pkgs)
1145 setContextAfterLoad session []
1146 return ()
1147
1148
1149 unsetOptions :: String -> GHCi ()
1150 unsetOptions str
1151 = do -- first, deal with the GHCi opts (+s, +t, etc.)
1152 let opts = words str
1153 (minus_opts, rest1) = partition isMinus opts
1154 (plus_opts, rest2) = partition isPlus rest1
1155
1156 if (not (null rest2))
1157 then io (putStrLn ("unknown option: '" ++ head rest2 ++ "'"))
1158 else do
1159
1160 mapM_ unsetOpt plus_opts
1161
1162 -- can't do GHC flags for now
1163 if (not (null minus_opts))
1164 then throwDyn (CmdLineError "can't unset GHC command-line flags")
1165 else return ()
1166
1167 isMinus ('-':s) = True
1168 isMinus _ = False
1169
1170 isPlus ('+':s) = True
1171 isPlus _ = False
1172
1173 setOpt ('+':str)
1174 = case strToGHCiOpt str of
1175 Nothing -> io (putStrLn ("unknown option: '" ++ str ++ "'"))
1176 Just o -> setOption o
1177
1178 unsetOpt ('+':str)
1179 = case strToGHCiOpt str of
1180 Nothing -> io (putStrLn ("unknown option: '" ++ str ++ "'"))
1181 Just o -> unsetOption o
1182
1183 strToGHCiOpt :: String -> (Maybe GHCiOption)
1184 strToGHCiOpt "s" = Just ShowTiming
1185 strToGHCiOpt "t" = Just ShowType
1186 strToGHCiOpt "r" = Just RevertCAFs
1187 strToGHCiOpt _ = Nothing
1188
1189 optToStr :: GHCiOption -> String
1190 optToStr ShowTiming = "s"
1191 optToStr ShowType = "t"
1192 optToStr RevertCAFs = "r"
1193
1194 -- ---------------------------------------------------------------------------
1195 -- code for `:show'
1196
1197 showCmd str =
1198 case words str of
1199 ["modules" ] -> showModules
1200 ["bindings"] -> showBindings
1201 ["linker"] -> io showLinkerState
1202 ["breakpoints"] -> showBkptTable
1203 _ -> throwDyn (CmdLineError "syntax: :show [modules|bindings]")
1204
1205 showModules = do
1206 session <- getSession
1207 let show_one ms = do m <- io (GHC.showModule session ms)
1208 io (putStrLn m)
1209 graph <- io (GHC.getModuleGraph session)
1210 mapM_ show_one graph
1211
1212 showBindings = do
1213 s <- getSession
1214 unqual <- io (GHC.getPrintUnqual s)
1215 bindings <- io (GHC.getBindings s)
1216 mapM_ showTyThing bindings
1217 return ()
1218
1219 showTyThing (AnId id) = do
1220 ty' <- cleanType (GHC.idType id)
1221 str <- showForUser (ppr id <> text " :: " <> ppr ty')
1222 io (putStrLn str)
1223 showTyThing _ = return ()
1224
1225 -- if -fglasgow-exts is on we show the foralls, otherwise we don't.
1226 cleanType :: Type -> GHCi Type
1227 cleanType ty = do
1228 dflags <- getDynFlags
1229 if dopt Opt_GlasgowExts dflags
1230 then return ty
1231 else return $! GHC.dropForAlls ty
1232
1233 showBkptTable :: GHCi ()
1234 showBkptTable = do
1235 bt <- getBkptTable
1236 msg <- showForUser . vcat $
1237 [ ppr mod <> colon <+> fcat
1238 [ parens(int row <> comma <> int col) | (row,col) <- sites]
1239 | (mod, sites) <- sitesList bt ]
1240 io (putStrLn msg)
1241 -- -----------------------------------------------------------------------------
1242 -- Completion
1243
1244 completeNone :: String -> IO [String]
1245 completeNone w = return []
1246
1247 #ifdef USE_READLINE
1248 completeWord :: String -> Int -> Int -> IO (Maybe (String, [String]))
1249 completeWord w start end = do
1250 line <- Readline.getLineBuffer
1251 case w of
1252 ':':_ | all isSpace (take (start-1) line) -> wrapCompleter completeCmd w
1253 _other
1254 | Just c <- is_cmd line -> do
1255 maybe_cmd <- lookupCommand c
1256 let (n,w') = selectWord (words' 0 line)
1257 case maybe_cmd of
1258 Nothing -> return Nothing
1259 Just (_,_,False,complete) -> wrapCompleter complete w
1260 Just (_,_,True,complete) -> let complete' w = do rets <- complete w
1261 return (map (drop n) rets)
1262 in wrapCompleter complete' w'
1263 | otherwise -> do
1264 --printf "complete %s, start = %d, end = %d\n" w start end
1265 wrapCompleter completeIdentifier w
1266 where words' _ [] = []
1267 words' n str = let (w,r) = break isSpace str
1268 (s,r') = span isSpace r
1269 in (n,w):words' (n+length w+length s) r'
1270 -- In a Haskell expression we want to parse 'a-b' as three words
1271 -- where a compiler flag (ie. -fno-monomorphism-restriction) should
1272 -- only be a single word.
1273 selectWord [] = (0,w)
1274 selectWord ((offset,x):xs)
1275 | offset+length x >= start = (start-offset,take (end-offset) x)
1276 | otherwise = selectWord xs
1277
1278 is_cmd line
1279 | ((':':w) : _) <- words (dropWhile isSpace line) = Just w
1280 | otherwise = Nothing
1281
1282 completeCmd w = do
1283 cmds <- readIORef commands
1284 return (filter (w `isPrefixOf`) (map (':':) (map cmdName cmds)))
1285
1286 completeMacro w = do
1287 cmds <- readIORef commands
1288 let cmds' = [ cmd | cmd <- map cmdName cmds, cmd `elem` map cmdName builtin_commands ]
1289 return (filter (w `isPrefixOf`) cmds')
1290
1291 completeIdentifier w = do
1292 s <- restoreSession
1293 rdrs <- GHC.getRdrNamesInScope s
1294 return (filter (w `isPrefixOf`) (map (showSDoc.ppr) rdrs))
1295
1296 completeModule w = do
1297 s <- restoreSession
1298 dflags <- GHC.getSessionDynFlags s
1299 let pkg_mods = allExposedModules dflags
1300 return (filter (w `isPrefixOf`) (map (showSDoc.ppr) pkg_mods))
1301
1302 completeHomeModule w = do
1303 s <- restoreSession
1304 g <- GHC.getModuleGraph s
1305 let home_mods = map GHC.ms_mod_name g
1306 return (filter (w `isPrefixOf`) (map (showSDoc.ppr) home_mods))
1307
1308 completeSetOptions w = do
1309 return (filter (w `isPrefixOf`) options)
1310 where options = "args":"prog":allFlags
1311
1312 completeBkpt = unionComplete completeModule completeBkptCmds
1313
1314 completeBkptCmds w = do
1315 return (filter (w `isPrefixOf`) options)
1316 where options = ["add","del","list","stop"]
1317
1318 completeFilename = Readline.filenameCompletionFunction
1319
1320 completeHomeModuleOrFile = unionComplete completeHomeModule completeFilename
1321
1322 unionComplete :: (String -> IO [String]) -> (String -> IO [String]) -> String -> IO [String]
1323 unionComplete f1 f2 w = do
1324 s1 <- f1 w
1325 s2 <- f2 w
1326 return (s1 ++ s2)
1327
1328 wrapCompleter :: (String -> IO [String]) -> String -> IO (Maybe (String,[String]))
1329 wrapCompleter fun w = do
1330 strs <- fun w
1331 case strs of
1332 [] -> return Nothing
1333 [x] -> return (Just (x,[]))
1334 xs -> case getCommonPrefix xs of
1335 "" -> return (Just ("",xs))
1336 pref -> return (Just (pref,xs))
1337
1338 getCommonPrefix :: [String] -> String
1339 getCommonPrefix [] = ""
1340 getCommonPrefix (s:ss) = foldl common s ss
1341 where common s "" = s
1342 common "" s = ""
1343 common (c:cs) (d:ds)
1344 | c == d = c : common cs ds
1345 | otherwise = ""
1346
1347 allExposedModules :: DynFlags -> [ModuleName]
1348 allExposedModules dflags
1349 = map GHC.mkModuleName (concat (map exposedModules (filter exposed (eltsUFM pkg_db))))
1350 where
1351 pkg_db = pkgIdMap (pkgState dflags)
1352 #else
1353 completeCmd = completeNone
1354 completeMacro = completeNone
1355 completeIdentifier = completeNone
1356 completeModule = completeNone
1357 completeHomeModule = completeNone
1358 completeSetOptions = completeNone
1359 completeFilename = completeNone
1360 completeHomeModuleOrFile=completeNone
1361 completeBkpt = completeNone
1362 #endif
1363
1364 -- ----------------------------------------------------------------------------
1365 -- Utils
1366
1367 expandPath :: String -> GHCi String
1368 expandPath path =
1369 case dropWhile isSpace path of
1370 ('~':d) -> do
1371 tilde <- io (getEnv "HOME") -- will fail if HOME not defined
1372 return (tilde ++ '/':d)
1373 other ->
1374 return other
1375
1376 -- ----------------------------------------------------------------------------
1377 -- Windows console setup
1378
1379 setUpConsole :: IO ()
1380 setUpConsole = do
1381 #ifdef mingw32_HOST_OS
1382 -- On Windows we need to set a known code page, otherwise the characters
1383 -- we read from the console will be be in some strange encoding, and
1384 -- similarly for characters we write to the console.
1385 --
1386 -- At the moment, GHCi pretends all input is Latin-1. In the
1387 -- future we should support UTF-8, but for now we set the code pages
1388 -- to Latin-1.
1389 --
1390 -- It seems you have to set the font in the console window to
1391 -- a Unicode font in order for output to work properly,
1392 -- otherwise non-ASCII characters are mapped wrongly. sigh.
1393 -- (see MSDN for SetConsoleOutputCP()).
1394 --
1395 setConsoleCP 28591 -- ISO Latin-1
1396 setConsoleOutputCP 28591 -- ISO Latin-1
1397 #endif
1398 return ()
1399
1400
1401 instrumentationBkptHandler :: IORef (BkptTable Module) -> BkptHandler Module
1402 instrumentationBkptHandler ref_bkptTable = BkptHandler {
1403 isAutoBkptEnabled = \sess bkptLoc -> do
1404 bktpTable <- readIORef ref_bkptTable
1405 return$ isBkptEnabled bktpTable bkptLoc
1406
1407 , handleBreakpoint = doBreakpoint ref_bkptTable
1408 }
1409
1410 doBreakpoint :: IORef (BkptTable Module)-> Session -> [(Id,HValue)] -> BkptLocation Module -> String -> b -> IO b
1411 doBreakpoint ref_bkptTable s@(Session ref) values _ locMsg b = do
1412 let (ids, hValues) = unzip values
1413 names = map idName ids
1414 ASSERT (length names == length hValues) return ()
1415 let global_ids = map globaliseAndTidy ids
1416 printScopeMsg locMsg global_ids
1417 typed_ids <- mapM instantiateIdType global_ids
1418 hsc_env <- readIORef ref
1419 let ictxt = hsc_IC hsc_env
1420 rn_env = ic_rn_local_env ictxt
1421 type_env = ic_type_env ictxt
1422 bound_names = map idName typed_ids
1423 new_rn_env = extendLocalRdrEnv rn_env bound_names
1424 -- Remove any shadowed bindings from the type_env;
1425 -- they are inaccessible but might, I suppose, cause
1426 -- a space leak if we leave them there
1427 shadowed = [ n | name <- bound_names,
1428 let rdr_name = mkRdrUnqual (nameOccName name),
1429 Just n <- [lookupLocalRdrEnv rn_env rdr_name] ]
1430 filtered_type_env = delListFromNameEnv type_env shadowed
1431 new_type_env = extendTypeEnvWithIds filtered_type_env (typed_ids)
1432 new_ic = ictxt { ic_rn_local_env = new_rn_env,
1433 ic_type_env = new_type_env }
1434 writeIORef ref (hsc_env { hsc_IC = new_ic })
1435 is_tty <- hIsTerminalDevice stdin
1436 prel_mod <- GHC.findModule s prel_name Nothing
1437 withExtendedLinkEnv (zip names hValues) $
1438 startGHCi (interactiveLoop is_tty True) GHCiState{
1439 progname = "<interactive>",
1440 args = [],
1441 prompt = locMsg ++ "> ",
1442 session = s,
1443 options = [],
1444 bkptTable= ref_bkptTable,
1445 prelude = prel_mod,
1446 topLevel = False }
1447 `catchDyn` (
1448 \StopChildSession -> evaluate$
1449 throwDyn (ChildSessionStopped "You may need to reload your modules")
1450 ) `finally` do
1451 writeIORef ref hsc_env
1452 putStrLn $ "Returning to normal execution..."
1453 return b
1454 where
1455 printScopeMsg :: String -> [Id] -> IO ()
1456 printScopeMsg location ids = do
1457 unqual <- GHC.getPrintUnqual s
1458 printForUser stdout unqual $
1459 text "Local bindings in scope:" $$
1460 nest 2 (pprWithCommas showId ids)
1461 where
1462 showId id =
1463 ppr (idName id) <+> dcolon <+> ppr (idType id)
1464
1465 -- | Give the Id a Global Name, and tidy its type
1466 globaliseAndTidy :: Id -> Id
1467 globaliseAndTidy id
1468 = let tidied_type = tidyTopType$ idType id
1469 in setIdType (globaliseId VanillaGlobal id) tidied_type
1470
1471 -- | Instantiate the tyVars with GHC.Base.Unknown
1472 instantiateIdType :: Id -> IO Id
1473 instantiateIdType id = do
1474 instantiatedType <- instantiateTyVarsToUnknown s (idType id)
1475 return$ setIdType id instantiatedType
1476
1477