1 {-# OPTIONS -#include "Linker.h" -#include "SchedAPI.h" #-}
2 -----------------------------------------------------------------------------
3 -- $Id: InteractiveUI.hs,v 1.107 2002/01/22 13:04:13 simonmar Exp $
5 -- GHC Interactive User Interface
7 -- (c) The GHC Team 2000
9 -----------------------------------------------------------------------------
10 module InteractiveUI ( interactiveUI, ghciWelcomeMsg ) where
12 #include "../includes/config.h"
13 #include "HsVersions.h"
17 import HscTypes ( TyThing(..) )
18 import MkIface ( ifaceTyThing )
21 import DriverUtil ( handle, remove_spaces )
23 import Finder ( flushPackageCache )
25 import Id ( isRecordSelector, recordSelectorFieldLabel,
26 isDataConWrapId, idName )
27 import Class ( className )
28 import TyCon ( tyConName, tyConClass_maybe, isPrimTyCon )
29 import FieldLabel ( fieldLabelTyCon )
30 import SrcLoc ( isGoodSrcLoc )
31 import Name ( Name, isHomePackageName, nameSrcLoc, nameOccName,
33 import OccName ( isSymOcc )
34 import BasicTypes ( defaultFixity )
36 import CmdLineOpts ( DynFlag(..), getDynFlags, saveDynFlags, restoreDynFlags,
38 import Panic ( GhcException(..), showGhcException )
41 #ifndef mingw32_TARGET_OS
47 #if HAVE_READLINE_HEADERS && HAVE_READLINE_LIBS
61 import Monad ( when, join )
63 import PrelGHC ( unsafeCoerce# )
64 import Foreign ( nullPtr )
65 import CString ( peekCString )
67 -----------------------------------------------------------------------------
71 \ / _ \\ /\\ /\\/ __(_)\n\
72 \ / /_\\// /_/ / / | | GHC Interactive, version " ++ cProjectVersion ++ ", for Haskell 98.\n\
73 \/ /_\\\\/ __ / /___| | http://www.haskell.org/ghc/\n\
74 \\\____/\\/ /_/\\____/|_| Type :? for help.\n"
76 GLOBAL_VAR(commands, builtin_commands, [(String, String -> GHCi Bool)])
78 builtin_commands :: [(String, String -> GHCi Bool)]
80 ("add", keepGoing addModule),
81 ("cd", keepGoing changeDirectory),
82 ("def", keepGoing defineMacro),
83 ("help", keepGoing help),
84 ("?", keepGoing help),
85 ("info", keepGoing info),
86 ("import", keepGoing importModules),
87 ("load", keepGoing loadModule),
88 ("module", keepGoing setContext),
89 ("reload", keepGoing reloadModule),
90 ("set", keepGoing setCmd),
91 ("type", keepGoing typeOfExpr),
92 ("unset", keepGoing unsetOptions),
93 ("undef", keepGoing undefineMacro),
97 keepGoing :: (String -> GHCi ()) -> (String -> GHCi Bool)
98 keepGoing a str = a str >> return False
100 shortHelpText = "use :? for help.\n"
103 \ Commands available from the prompt:\n\
105 \ <stmt> evaluate/run <stmt>\n\
106 \ :add <filename> ... add module(s) to the current target set\n\
107 \ :cd <dir> change directory to <dir>\n\
108 \ :def <cmd> <expr> define a command :<cmd>\n\
109 \ :help, :? display this list of commands\n\
110 \ :info [<name> ...] display information about the given names\n\
111 \ :load <filename> ... load module(s) and their dependents\n\
112 \ :module <mod> set the context for expression evaluation to <mod>\n\
113 \ :reload reload the current module set\n\
114 \ :set <option> ... set options\n\
115 \ :set args <arg> ... set the arguments returned by System.getArgs\n\
116 \ :set prog <progname> set the value returned by System.getProgName\n\
117 \ :undef <cmd> undefine user-defined command :<cmd>\n\
118 \ :type <expr> show the type of <expr>\n\
119 \ :unset <option> ... unset options\n\
121 \ :!<command> run the shell command <command>\n\
123 \ Options for `:set' and `:unset':\n\
125 \ +r revert top-level expressions after each evaluation\n\
126 \ +s print timing/memory stats after each evaluation\n\
127 \ +t print type after evaluation\n\
128 \ -<flags> most GHC command line flags can also be set here\n\
129 \ (eg. -v2, -fglasgow-exts, etc.)\n\
132 interactiveUI :: CmState -> [FilePath] -> [LibrarySpec] -> IO ()
133 interactiveUI cmstate paths cmdline_libs = do
135 hSetBuffering stdout NoBuffering
137 -- link in the available packages
138 pkgs <- getPackageInfo
140 linkPackages cmdline_libs pkgs
142 dflags <- getDynFlags
144 (cmstate, maybe_hval)
145 <- cmCompileExpr cmstate dflags "IO.hSetBuffering IO.stdout IO.NoBuffering Prelude.>> IO.hSetBuffering IO.stderr IO.NoBuffering"
147 Just hval -> unsafeCoerce# hval :: IO ()
148 _ -> panic "interactiveUI:buffering"
150 (cmstate, maybe_hval)
151 <- cmCompileExpr cmstate dflags "IO.hFlush PrelHandle.stderr"
153 Just hval -> writeIORef flush_stderr (unsafeCoerce# hval :: IO ())
154 _ -> panic "interactiveUI:stderr"
156 (cmstate, maybe_hval)
157 <- cmCompileExpr cmstate dflags "IO.hFlush PrelHandle.stdout"
159 Just hval -> writeIORef flush_stdout (unsafeCoerce# hval :: IO ())
160 _ -> panic "interactiveUI:stdout"
162 -- initial context is just the Prelude
163 cmstate <- cmSetContext cmstate dflags [] ["Prelude"]
165 #if HAVE_READLINE_HEADERS && HAVE_READLINE_LIBS
169 startGHCi (runGHCi paths)
170 GHCiState{ progname = "<interactive>",
176 #if HAVE_READLINE_HEADERS && HAVE_READLINE_LIBS
177 Readline.resetTerminal Nothing
183 runGHCi :: [FilePath] -> GHCi ()
185 read_dot_files <- io (readIORef v_Read_DotGHCi)
187 when (read_dot_files) $ do
190 exists <- io (doesFileExist file)
192 dir_ok <- io (checkPerms ".")
193 file_ok <- io (checkPerms file)
194 when (dir_ok && file_ok) $ do
195 either_hdl <- io (IO.try (openFile "./.ghci" ReadMode))
198 Right hdl -> fileLoop hdl False
200 when (read_dot_files) $ do
201 -- Read in $HOME/.ghci
202 either_dir <- io (IO.try (getEnv "HOME"))
206 cwd <- io (getCurrentDirectory)
207 when (dir /= cwd) $ do
208 let file = dir ++ "/.ghci"
209 ok <- io (checkPerms file)
211 either_hdl <- io (IO.try (openFile file ReadMode))
214 Right hdl -> fileLoop hdl False
216 -- perform a :load for files given on the GHCi command line
217 when (not (null paths)) $
218 ghciHandle showException $
219 loadModule (unwords paths)
221 -- enter the interactive loop
225 io $ do putStrLn "Leaving GHCi."
229 -- ignore ^C exceptions caught here
230 ghciHandleDyn (\e -> case e of Interrupted -> ghciUnblock interactiveLoop
231 _other -> return ()) $ do
233 -- read commands from stdin
234 #if HAVE_READLINE_HEADERS && HAVE_READLINE_LIBS
241 -- NOTE: We only read .ghci files if they are owned by the current user,
242 -- and aren't world writable. Otherwise, we could be accidentally
243 -- running code planted by a malicious third party.
245 -- Furthermore, We only read ./.ghci if . is owned by the current user
246 -- and isn't writable by anyone else. I think this is sufficient: we
247 -- don't need to check .. and ../.. etc. because "." always refers to
248 -- the same directory while a process is running.
250 checkPerms :: String -> IO Bool
252 handle (\_ -> return False) $ do
253 #ifdef mingw32_TARGET_OS
256 st <- getFileStatus name
258 if fileOwner st /= me then do
259 putStrLn $ "WARNING: " ++ name ++ " is owned by someone else, IGNORING!"
262 let mode = fileMode st
263 if (groupWriteMode == (mode `intersectFileModes` groupWriteMode))
264 || (otherWriteMode == (mode `intersectFileModes` otherWriteMode))
266 putStrLn $ "*** WARNING: " ++ name ++
267 " is writable by someone else, IGNORING!"
272 fileLoop :: Handle -> Bool -> GHCi ()
273 fileLoop hdl prompt = do
275 (mod,imports) <- io (cmGetContext (cmstate st))
276 when prompt (io (putStr (mkPrompt mod imports)))
277 l <- io (IO.try (hGetLine hdl))
279 Left e | isEOFError e -> return ()
280 | otherwise -> throw e
282 case remove_spaces l of
283 "" -> fileLoop hdl prompt
284 l -> do quit <- runCommand l
285 if quit then return () else fileLoop hdl prompt
287 stringLoop :: [String] -> GHCi ()
288 stringLoop [] = return ()
289 stringLoop (s:ss) = do
291 case remove_spaces s of
293 l -> do quit <- runCommand l
294 if quit then return () else stringLoop ss
296 mkPrompt toplevs exports
297 = concat (intersperse "," toplevs)
298 ++ (if not (null exports)
299 then "[" ++ concat (intersperse "," exports) ++ "]"
303 #if HAVE_READLINE_HEADERS && HAVE_READLINE_LIBS
304 readlineLoop :: GHCi ()
307 (mod,imports) <- io (cmGetContext (cmstate st))
309 l <- io (readline (mkPrompt mod imports))
313 case remove_spaces l of
318 if quit then return () else readlineLoop
321 -- Top level exception handler, just prints out the exception
323 runCommand :: String -> GHCi Bool
325 ghciHandle ( \exception -> do
327 showException exception
332 showException (DynException dyn) =
333 case fromDynamic dyn of
334 Nothing -> io (putStrLn ("*** Exception: (unknown)"))
335 Just Interrupted -> io (putStrLn "Interrupted.")
336 Just (CmdLineError s) -> io (putStrLn s) -- omit the location for CmdLineError
337 Just ph@PhaseFailed{} -> io (putStrLn (showGhcException ph "")) -- ditto
338 Just other_ghc_ex -> io (print other_ghc_ex)
340 showException other_exception
341 = io (putStrLn ("*** Exception: " ++ show other_exception))
343 doCommand (':' : command) = specialCommand command
345 = do timeIt (do nms <- runStmt stmt; finishEvalExpr nms)
348 runStmt :: String -> GHCi [Name]
350 | null (filter (not.isSpace) stmt) = return []
352 = do st <- getGHCiState
353 dflags <- io getDynFlags
354 let dflags' = dopt_unset dflags Opt_WarnUnusedBinds
355 (new_cmstate, result) <-
356 io $ withProgName (progname st) $ withArgs (args st) $
357 cmRunStmt (cmstate st) dflags' stmt
358 setGHCiState st{cmstate = new_cmstate}
360 CmRunFailed -> return []
361 CmRunException e -> showException e >> return []
362 CmRunDeadlocked -> io (putStrLn "Deadlocked.") >> return []
363 CmRunOk names -> return names
365 -- possibly print the type and revert CAFs after evaluating an expression
367 = do b <- isOptionSet ShowType
369 when b (mapM_ (showTypeOfName (cmstate st)) names)
371 b <- isOptionSet RevertCAFs
372 io (when b revertCAFs)
376 showTypeOfName :: CmState -> Name -> GHCi ()
377 showTypeOfName cmstate n
378 = do maybe_str <- io (cmTypeOfName cmstate n)
381 Just str -> io (putStrLn (showSDoc (ppr n) ++ " :: " ++ str))
383 flushEverything :: GHCi ()
385 = io $ do Monad.join (readIORef flush_stdout)
386 Monad.join (readIORef flush_stderr)
389 specialCommand :: String -> GHCi Bool
390 specialCommand ('!':str) = shellEscape (dropWhile isSpace str)
391 specialCommand str = do
392 let (cmd,rest) = break isSpace str
393 cmds <- io (readIORef commands)
394 case [ (s,f) | (s,f) <- cmds, prefixMatch cmd s ] of
395 [] -> io (hPutStr stdout ("unknown command `:" ++ cmd ++ "'\n"
396 ++ shortHelpText) >> return False)
397 [(_,f)] -> f (dropWhile isSpace rest)
398 cs -> io (hPutStrLn stdout ("prefix " ++ cmd ++
399 " matches multiple commands (" ++
400 foldr1 (\a b -> a ++ ',':b) (map fst cs)
401 ++ ")") >> return False)
403 noArgs c = throwDyn (CmdLineError ("command `" ++ c ++ "' takes no arguments"))
405 -----------------------------------------------------------------------------
408 help :: String -> GHCi ()
409 help _ = io (putStr helpText)
411 info :: String -> GHCi ()
412 info "" = throwDyn (CmdLineError "syntax: `:i <thing-you-want-info-about>'")
415 state <- getGHCiState
416 dflags <- io getDynFlags
418 infoThings cms [] = return cms
419 infoThings cms (name:names) = do
420 (cms, unqual, stuff) <- io (cmInfoThing cms dflags name)
421 io (putStrLn (showSDocForUser unqual (
422 vcat (intersperse (text "") (map showThing stuff))))
426 showThing (ty_thing, fixity)
427 = vcat [ text "-- " <> showTyThing ty_thing,
428 showFixity fixity (getName ty_thing),
429 ppr (ifaceTyThing ty_thing) ]
432 | fix == defaultFixity = empty
433 | otherwise = ppr fix <+>
434 (if isSymOcc (nameOccName name)
436 else char '`' <> ppr name <> char '`')
438 showTyThing (AClass cl)
439 = hcat [ppr cl, text " is a class", showSrcLoc (className cl)]
440 showTyThing (ATyCon ty)
442 = hcat [ppr ty, text " is a primitive type constructor"]
444 = hcat [ppr ty, text " is a type constructor", showSrcLoc (tyConName ty)]
445 showTyThing (AnId id)
446 = hcat [ppr id, text " is a ", idDescr id, showSrcLoc (idName id)]
449 | isRecordSelector id =
450 case tyConClass_maybe (fieldLabelTyCon (
451 recordSelectorFieldLabel id)) of
452 Nothing -> text "record selector"
453 Just c -> text "method in class " <> ppr c
454 | isDataConWrapId id = text "data constructor"
455 | otherwise = text "variable"
457 -- also print out the source location for home things
459 | isHomePackageName name && isGoodSrcLoc loc
460 = hsep [ text ", defined at", ppr loc ]
463 where loc = nameSrcLoc name
465 cms <- infoThings (cmstate state) names
466 setGHCiState state{ cmstate = cms }
469 addModule :: String -> GHCi ()
471 let files = words str
472 state <- getGHCiState
473 dflags <- io (getDynFlags)
474 io (revertCAFs) -- always revert CAFs on load/add.
475 let new_targets = files ++ targets state
476 graph <- io (cmDepAnal (cmstate state) dflags new_targets)
477 (cmstate1, ok, mods) <- io (cmLoadModules (cmstate state) dflags graph)
478 setGHCiState state{ cmstate = cmstate1, targets = new_targets }
479 setContextAfterLoad mods
480 modulesLoadedMsg ok mods
482 changeDirectory :: String -> GHCi ()
483 changeDirectory ('~':d) = do
484 tilde <- io (getEnv "HOME") -- will fail if HOME not defined
485 io (setCurrentDirectory (tilde ++ '/':d))
486 changeDirectory d = io (setCurrentDirectory d)
488 defineMacro :: String -> GHCi ()
490 let (macro_name, definition) = break isSpace s
491 cmds <- io (readIORef commands)
493 then throwDyn (CmdLineError "invalid macro name")
495 if (macro_name `elem` map fst cmds)
496 then throwDyn (CmdLineError
497 ("command `" ++ macro_name ++ "' is already defined"))
500 -- give the expression a type signature, so we can be sure we're getting
501 -- something of the right type.
502 let new_expr = '(' : definition ++ ") :: String -> IO String"
504 -- compile the expression
506 dflags <- io getDynFlags
507 (new_cmstate, maybe_hv) <- io (cmCompileExpr (cmstate st) dflags new_expr)
508 setGHCiState st{cmstate = new_cmstate}
511 Just hv -> io (writeIORef commands --
512 ((macro_name, keepGoing (runMacro hv)) : cmds))
514 runMacro :: HValue{-String -> IO String-} -> String -> GHCi ()
516 str <- io ((unsafeCoerce# fun :: String -> IO String) s)
517 stringLoop (lines str)
519 undefineMacro :: String -> GHCi ()
520 undefineMacro macro_name = do
521 cmds <- io (readIORef commands)
522 if (macro_name `elem` map fst builtin_commands)
523 then throwDyn (CmdLineError
524 ("command `" ++ macro_name ++ "' cannot be undefined"))
526 if (macro_name `notElem` map fst cmds)
527 then throwDyn (CmdLineError
528 ("command `" ++ macro_name ++ "' not defined"))
530 io (writeIORef commands (filter ((/= macro_name) . fst) cmds))
533 importModules :: String -> GHCi ()
534 importModules str = return ()
537 loadModule :: String -> GHCi ()
538 loadModule str = timeIt (loadModule' str)
541 let files = words str
542 state <- getGHCiState
543 dflags <- io getDynFlags
545 -- do the dependency anal first, so that if it fails we don't throw
546 -- away the current set of modules.
547 graph <- io (cmDepAnal (cmstate state) dflags files)
549 -- Dependency anal ok, now unload everything
550 cmstate1 <- io (cmUnload (cmstate state) dflags)
551 setGHCiState state{ cmstate = cmstate1, targets = [] }
553 io (revertCAFs) -- always revert CAFs on load.
554 (cmstate2, ok, mods) <- io (cmLoadModules cmstate1 dflags graph)
555 setGHCiState state{ cmstate = cmstate2, targets = files }
557 setContextAfterLoad mods
558 modulesLoadedMsg ok mods
561 reloadModule :: String -> GHCi ()
563 state <- getGHCiState
564 dflags <- io getDynFlags
565 case targets state of
566 [] -> io (putStr "no current target\n")
568 -- do the dependency anal first, so that if it fails we don't throw
569 -- away the current set of modules.
570 graph <- io (cmDepAnal (cmstate state) dflags paths)
572 io (revertCAFs) -- always revert CAFs on reload.
574 <- io (cmLoadModules (cmstate state) dflags graph)
575 setGHCiState state{ cmstate=cmstate1 }
576 setContextAfterLoad mods
577 modulesLoadedMsg ok mods
579 reloadModule _ = noArgs ":reload"
581 setContextAfterLoad [] = setContext prel
582 setContextAfterLoad (m:_) = setContext m
584 modulesLoadedMsg ok mods = do
586 | null mods = text "none."
588 punctuate comma (map text mods)) <> text "."
591 io (putStrLn (showSDoc (text "Failed, modules loaded: " <> mod_commas)))
593 io (putStrLn (showSDoc (text "Ok, modules loaded: " <> mod_commas)))
596 typeOfExpr :: String -> GHCi ()
598 = do st <- getGHCiState
599 dflags <- io getDynFlags
600 (new_cmstate, maybe_tystr) <- io (cmTypeOfExpr (cmstate st) dflags str)
601 setGHCiState st{cmstate = new_cmstate}
604 Just tystr -> io (putStrLn tystr)
606 quit :: String -> GHCi Bool
609 shellEscape :: String -> GHCi Bool
610 shellEscape str = io (system str >> return False)
612 -----------------------------------------------------------------------------
613 -- Setting the module context
616 | all sensible mods = newContext mods -- default is to set the empty context
617 | all plusminus mods = adjustContext mods
619 = throwDyn (CmdLineError "syntax: :module M1 .. Mn | :module [+/-]M1 ... [+/-]Mn")
623 sensible (c:cs) = isUpper c && all isAlphaNumEx cs
624 isAlphaNumEx c = isAlphaNum c || c == '_'
626 plusminus ('-':mod) = sensible mod
627 plusminus ('+':mod) = sensible mod
631 state@GHCiState{cmstate=cmstate} <- getGHCiState
632 dflags <- io getDynFlags
634 let separate [] as bs = return (as,bs)
635 separate (m:ms) as bs = do
636 b <- io (cmModuleIsInterpreted cmstate m)
637 if b then separate ms (m:as) bs
638 else separate ms as (m:bs)
640 (as,bs) <- separate mods [] []
641 let bs' = if null as && prel `notElem` bs then prel:bs else bs
642 cmstate' <- io (cmSetContext cmstate dflags as bs')
643 setGHCiState state{cmstate=cmstate'}
647 adjustContext mods = do
648 state@GHCiState{cmstate=cmstate} <- getGHCiState
649 dflags <- io getDynFlags
651 let adjust [] as bs = return (as,bs)
652 adjust (('-':m) : ms) as bs
653 | m `elem` as = adjust ms (delete m as) bs
654 | m `elem` bs = adjust ms as (delete m bs)
655 | otherwise = throwDyn (CmdLineError ("module `" ++ m ++ "' is not currently in scope"))
656 adjust (('+':m) : ms) as bs
657 | m `elem` as || m `elem` bs = adjust ms as bs -- continue silently
658 | otherwise = do b <- io (cmModuleIsInterpreted cmstate m)
659 if b then adjust ms (m:as) bs
660 else adjust ms as (m:bs)
662 (as,bs) <- io (cmGetContext cmstate)
663 (as,bs) <- adjust mods as bs
664 let bs' = if null as && prel `notElem` bs then prel:bs else bs
665 cmstate' <- io (cmSetContext cmstate dflags as bs')
666 setGHCiState state{cmstate=cmstate'}
668 ----------------------------------------------------------------------------
671 -- set options in the interpreter. Syntax is exactly the same as the
672 -- ghc command line, except that certain options aren't available (-C,
675 -- This is pretty fragile: most options won't work as expected. ToDo:
676 -- figure out which ones & disallow them.
678 setCmd :: String -> GHCi ()
680 = do st <- getGHCiState
681 let opts = options st
682 io $ putStrLn (showSDoc (
683 text "options currently set: " <>
686 else hsep (map (\o -> char '+' <> text (optToStr o)) opts)
690 ("args":args) -> setArgs args
691 ("prog":prog) -> setProg prog
692 wds -> setOptions wds
696 setGHCiState st{ args = args }
700 setGHCiState st{ progname = prog }
702 io (hPutStrLn stderr "syntax: :set prog <progname>")
705 do -- first, deal with the GHCi opts (+s, +t, etc.)
706 let (plus_opts, minus_opts) = partition isPlus wds
707 mapM setOpt plus_opts
709 -- now, the GHC flags
710 pkgs_before <- io (readIORef v_Packages)
711 leftovers <- io (processArgs static_flags minus_opts [])
712 pkgs_after <- io (readIORef v_Packages)
714 -- update things if the users wants more packages
715 when (pkgs_before /= pkgs_after) $
716 newPackages (pkgs_after \\ pkgs_before)
718 -- then, dynamic flags
721 leftovers <- processArgs dynamic_flags leftovers []
724 if (not (null leftovers))
725 then throwDyn (CmdLineError ("unrecognised flags: " ++
730 unsetOptions :: String -> GHCi ()
732 = do -- first, deal with the GHCi opts (+s, +t, etc.)
734 (minus_opts, rest1) = partition isMinus opts
735 (plus_opts, rest2) = partition isPlus rest1
737 if (not (null rest2))
738 then io (putStrLn ("unknown option: `" ++ head rest2 ++ "'"))
741 mapM unsetOpt plus_opts
743 -- can't do GHC flags for now
744 if (not (null minus_opts))
745 then throwDyn (CmdLineError "can't unset GHC command-line flags")
748 isMinus ('-':s) = True
751 isPlus ('+':s) = True
755 = case strToGHCiOpt str of
756 Nothing -> io (putStrLn ("unknown option: `" ++ str ++ "'"))
757 Just o -> setOption o
760 = case strToGHCiOpt str of
761 Nothing -> io (putStrLn ("unknown option: `" ++ str ++ "'"))
762 Just o -> unsetOption o
764 strToGHCiOpt :: String -> (Maybe GHCiOption)
765 strToGHCiOpt "s" = Just ShowTiming
766 strToGHCiOpt "t" = Just ShowType
767 strToGHCiOpt "r" = Just RevertCAFs
768 strToGHCiOpt _ = Nothing
770 optToStr :: GHCiOption -> String
771 optToStr ShowTiming = "s"
772 optToStr ShowType = "t"
773 optToStr RevertCAFs = "r"
775 newPackages new_pkgs = do
776 state <- getGHCiState
777 dflags <- io getDynFlags
778 cmstate1 <- io (cmUnload (cmstate state) dflags)
779 setGHCiState state{ cmstate = cmstate1, targets = [] }
782 pkgs <- getPackageInfo
783 flushPackageCache pkgs
785 new_pkg_info <- getPackageDetails new_pkgs
786 mapM_ linkPackage (reverse new_pkg_info)
788 -----------------------------------------------------------------------------
791 data GHCiState = GHCiState
795 targets :: [FilePath],
797 options :: [GHCiOption]
801 = ShowTiming -- show time/allocs after evaluation
802 | ShowType -- show the type of expressions
803 | RevertCAFs -- revert CAFs after every evaluation
806 GLOBAL_VAR(flush_stdout, error "no flush_stdout", IO ())
807 GLOBAL_VAR(flush_stderr, error "no flush_stdout", IO ())
809 newtype GHCi a = GHCi { unGHCi :: IORef GHCiState -> IO a }
811 startGHCi :: GHCi a -> GHCiState -> IO a
812 startGHCi g state = do ref <- newIORef state; unGHCi g ref
814 instance Monad GHCi where
815 (GHCi m) >>= k = GHCi $ \s -> m s >>= \a -> unGHCi (k a) s
816 return a = GHCi $ \s -> return a
818 ghciHandleDyn :: Typeable t => (t -> GHCi a) -> GHCi a -> GHCi a
819 ghciHandleDyn h (GHCi m) = GHCi $ \s ->
820 Exception.catchDyn (m s) (\e -> unGHCi (h e) s)
822 getGHCiState = GHCi $ \r -> readIORef r
823 setGHCiState s = GHCi $ \r -> writeIORef r s
825 isOptionSet :: GHCiOption -> GHCi Bool
827 = do st <- getGHCiState
828 return (opt `elem` options st)
830 setOption :: GHCiOption -> GHCi ()
832 = do st <- getGHCiState
833 setGHCiState (st{ options = opt : filter (/= opt) (options st) })
835 unsetOption :: GHCiOption -> GHCi ()
837 = do st <- getGHCiState
838 setGHCiState (st{ options = filter (/= opt) (options st) })
841 io m = GHCi { unGHCi = \s -> m >>= return }
843 -----------------------------------------------------------------------------
844 -- recursive exception handlers
846 -- Don't forget to unblock async exceptions in the handler, or if we're
847 -- in an exception loop (eg. let a = error a in a) the ^C exception
848 -- may never be delivered. Thanks to Marcin for pointing out the bug.
850 ghciHandle :: (Exception -> GHCi a) -> GHCi a -> GHCi a
851 ghciHandle h (GHCi m) = GHCi $ \s ->
852 Exception.catch (m s)
853 (\e -> unGHCi (ghciHandle h (ghciUnblock (h e))) s)
855 ghciUnblock :: GHCi a -> GHCi a
856 ghciUnblock (GHCi a) = GHCi $ \s -> Exception.unblock (a s)
858 -----------------------------------------------------------------------------
861 -- Left: full path name of a .o file, including trailing .o
862 -- Right: "unadorned" name of a .DLL/.so
863 -- e.g. On unix "qt" denotes "libqt.so"
864 -- On WinDoze "burble" denotes "burble.DLL"
865 -- addDLL is platform-specific and adds the lib/.so/.DLL
866 -- suffixes platform-dependently; we don't do that here.
868 -- For dynamic objects only, try to find the object file in all the
869 -- directories specified in v_Library_Paths before giving up.
872 = Either FilePath String
874 showLS (Left nm) = "(static) " ++ nm
875 showLS (Right nm) = "(dynamic) " ++ nm
877 linkPackages :: [LibrarySpec] -> [PackageConfig] -> IO ()
878 linkPackages cmdline_lib_specs pkgs
879 = do mapM_ linkPackage (reverse pkgs)
880 lib_paths <- readIORef v_Library_paths
881 mapM_ (preloadLib lib_paths) cmdline_lib_specs
882 if (null cmdline_lib_specs)
884 else do putStr "final link ... "
886 if ok then putStrLn "done."
887 else throwDyn (InstallationError
888 "linking extra libraries/objects failed")
890 preloadLib :: [String] -> LibrarySpec -> IO ()
891 preloadLib lib_paths lib_spec
892 = do putStr ("Loading object " ++ showLS lib_spec ++ " ... ")
895 -> do b <- preload_static lib_paths static_ish
896 putStrLn (if b then "done." else "not found")
898 -> -- We add "" to the set of paths to try, so that
899 -- if none of the real paths match, we force addDLL
900 -- to look in the default dynamic-link search paths.
901 do maybe_errstr <- preload_dynamic (lib_paths++[""])
905 Just mm -> preloadFailed mm lib_paths lib_spec
908 preloadFailed :: String -> [String] -> LibrarySpec -> IO ()
909 preloadFailed sys_errmsg paths spec
910 = do putStr ("failed.\nDynamic linker error message was:\n "
911 ++ sys_errmsg ++ "\nWhilst trying to load: "
912 ++ showLS spec ++ "\nDirectories to search are:\n"
913 ++ unlines (map (" "++) paths) )
916 -- not interested in the paths in the static case.
917 preload_static paths name
918 = do b <- doesFileExist name
919 if not b then return False
920 else loadObj name >> return True
922 -- return Nothing == success, else Just error message from addDLL
923 preload_dynamic [] name
925 preload_dynamic (path:paths) rootname
926 = do -- addDLL returns NULL on success
927 maybe_errmsg <- addDLL path rootname
928 if maybe_errmsg == nullPtr
929 then preload_dynamic paths rootname
930 else do str <- peekCString maybe_errmsg
934 = (throwDyn . CmdLineError)
935 "user specified .o/.so/.DLL could not be loaded."
937 -- Packages that don't need loading, because the compiler shares them with
938 -- the interpreted program.
939 dont_load_these = [ "gmp", "rts" ]
941 -- Packages that are already linked into GHCi. For mingw32, we only
942 -- skip gmp and rts, since std and after need to load the msvcrt.dll
943 -- library which std depends on.
945 # ifndef mingw32_TARGET_OS
946 = [ "std", "concurrent", "posix", "text", "util" ]
951 linkPackage :: PackageConfig -> IO ()
953 | name pkg `elem` dont_load_these = return ()
956 -- For each obj, try obj.o and if that fails, obj.so.
957 -- Complication: all the .so's must be loaded before any of the .o's.
958 let dirs = library_dirs pkg
959 let objs = hs_libraries pkg ++ extra_libraries pkg
960 classifieds <- mapM (locateOneObj dirs) objs
962 -- Don't load the .so libs if this is a package GHCi is already
963 -- linked against, because we'll already have the .so linked in.
964 let (so_libs, obj_libs) = partition isRight classifieds
965 let sos_first | name pkg `elem` loaded_in_ghci = obj_libs
966 | otherwise = so_libs ++ obj_libs
968 putStr ("Loading package " ++ name pkg ++ " ... ")
969 mapM loadClassified sos_first
970 putStr "linking ... "
972 if ok then putStrLn "done."
973 else panic ("can't load package `" ++ name pkg ++ "'")
975 isRight (Right _) = True
976 isRight (Left _) = False
978 loadClassified :: LibrarySpec -> IO ()
979 loadClassified (Left obj_absolute_filename)
980 = do loadObj obj_absolute_filename
981 loadClassified (Right dll_unadorned)
982 = do maybe_errmsg <- addDLL "" dll_unadorned -- doesn't seem right to me
983 if maybe_errmsg == nullPtr
985 else do str <- peekCString maybe_errmsg
986 throwDyn (CmdLineError ("can't load .so/.DLL for: "
987 ++ dll_unadorned ++ " (" ++ str ++ ")" ))
989 locateOneObj :: [FilePath] -> String -> IO LibrarySpec
991 = return (Right obj) -- we assume
992 locateOneObj (d:ds) obj
993 = do let path = d ++ '/':obj ++ ".o"
994 b <- doesFileExist path
995 if b then return (Left path) else locateOneObj ds obj
997 -----------------------------------------------------------------------------
998 -- timing & statistics
1000 timeIt :: GHCi a -> GHCi a
1002 = do b <- isOptionSet ShowTiming
1005 else do allocs1 <- io $ getAllocations
1006 time1 <- io $ getCPUTime
1008 allocs2 <- io $ getAllocations
1009 time2 <- io $ getCPUTime
1010 io $ printTimes (allocs2 - allocs1) (time2 - time1)
1013 foreign import "getAllocations" getAllocations :: IO Int
1015 printTimes :: Int -> Integer -> IO ()
1016 printTimes allocs psecs
1017 = do let secs = (fromIntegral psecs / (10^12)) :: Float
1018 secs_str = showFFloat (Just 2) secs
1019 putStrLn (showSDoc (
1020 parens (text (secs_str "") <+> text "secs" <> comma <+>
1021 int allocs <+> text "bytes")))
1023 -----------------------------------------------------------------------------
1026 foreign import revertCAFs :: IO () -- make it "safe", just in case