1 -----------------------------------------------------------------------------
2 -- $Id: InteractiveUI.hs,v 1.3 2000/11/16 16:54:36 simonmar Exp $
4 -- GHC Interactive User Interface
6 -- (c) The GHC Team 2000
8 -----------------------------------------------------------------------------
10 module InteractiveUI (interactiveUI) where
12 #include "HsVersions.h"
34 import PrelGHC ( unsafeCoerce# )
36 -----------------------------------------------------------------------------
39 \ _____ __ __ ____ _________________________________________________\n\
40 \(| || || (| |) GHC Interactive, version 5.00 \n\
41 \|| __ ||___|| || () For Haskell 98. \n\
42 \|| |) ||---|| || || http://www.haskell.org/ghc \n\
43 \|| || || || || (| Bug reports to: glasgow-haskell-bugs@haskell.org \n\
44 \(|___|| || || (|__|) \\\\______________________________________________________\n"
46 commands :: [(String, String -> GHCi ())]
48 ("cd", changeDirectory),
52 ("reload", reloadModule),
59 shortHelpText = "use :? for help.\n"
62 \ <expr> evaluate <expr>\n\
63 \ :cd <dir> change directory to <dir>\n\
64 \ :help display this list of commands\n\
65 \ :? display this list of commands\n\
66 \ :load <filename> load a module (and it dependents)\n\
67 \ :reload reload the current program\n\
68 \ :set <opetion> ... set options\n\
69 \ :type <expr> show the type of <expr>\n\
71 \ :!<command> run the shell command <command>\n\
74 interactiveUI :: CmState -> IO ()
76 hPutStrLn stdout ghciWelcomeMsg
78 hSetBuffering stdout NoBuffering
80 -- link in the available packages
81 pkgs <- getPackageInfo
82 linkPackages (reverse pkgs)
87 _ <- (unGHCi uiLoop) GHCiState{ current_module = mkModuleName "Prelude",
96 l <- io (readline (moduleNameUserString (current_module st) ++ "> "))
98 l <- io (hGetLine stdin)
111 myCatchDyn (doCommand c)
113 PhaseFailed phase code ->
114 io ( putStrLn ("Phase " ++ phase ++ " failed (code "
115 ++ show code ++ ")"))
116 Interrupted -> io (putStrLn "Interrupted.")
117 _ -> io (putStrLn (show (dyn :: BarfKind)))
120 doCommand (':' : command) = specialCommand command
123 io (hPutStrLn stdout ("Run expression: " ++ expr))
124 let (mod,'.':str) = break (=='.') expr
125 case cmLookupSymbol (mkOrig varName (mkModuleName mod) (_PK_ str)) (cmstate st) of
126 Nothing -> io (putStrLn "nothing.")
127 Just e -> io (do unsafeCoerce# e :: IO ()
131 specialCommand str = do
132 let (cmd,rest) = break isSpace str
133 case [ (s,f) | (s,f) <- commands, prefixMatch cmd s ] of
134 [] -> io $ hPutStr stdout ("uknown command `:" ++ cmd ++ "'\n"
136 [(_,f)] -> f (dropWhile isSpace rest)
137 cs -> io $ hPutStrLn stdout ("prefix " ++ cmd ++
138 " matches multiple commands (" ++
139 foldr1 (\a b -> a ++ ',':b) (map fst cs)
142 noArgs c = io (hPutStrLn stdout ("command `:" ++ c ++ "' takes no arguments"))
144 -----------------------------------------------------------------------------
147 -- ToDo: don't forget to catch errors
149 help :: String -> GHCi ()
150 help _ = io (putStr helpText)
152 changeDirectory :: String -> GHCi ()
153 changeDirectory = io . setCurrentDirectory
155 loadModule :: String -> GHCi ()
157 state <- getGHCiState
158 (new_cmstate, mod) <- io (cmLoadModule (cmstate state) ({-ToDo!!-}mkModuleName path))
159 setGHCiState state{cmstate=new_cmstate, target=Just path}
161 reloadModule :: String -> GHCi ()
163 state <- getGHCiState
165 Nothing -> io (putStr "no current target\n")
166 Just path -> do (new_cmstate, mod) <- io (cmLoadModule (cmstate state) (mkModuleName path))
167 setGHCiState state{cmstate=new_cmstate}
168 reloadModule _ = noArgs ":reload"
170 setOptions :: String -> GHCi ()
171 setOptions = panic "setOptions"
173 typeOfExpr :: String -> GHCi ()
174 typeOfExpr = panic "typeOfExpr"
176 quit :: String -> GHCi ()
179 shellEscape :: String -> GHCi ()
180 shellEscape str = io (system str >> return ())
182 -----------------------------------------------------------------------------
185 data GHCiState = GHCiState
187 current_module :: ModuleName,
188 target :: Maybe FilePath,
192 newtype GHCi a = GHCi { unGHCi :: GHCiState -> IO (GHCiState, a) }
194 instance Monad GHCi where
195 (GHCi m) >>= k = GHCi $ \s -> m s >>= \(s,a) -> unGHCi (k a) s
196 return a = GHCi $ \s -> return (s,a)
198 getGHCiState = GHCi $ \s -> return (s,s)
199 setGHCiState s = GHCi $ \_ -> return (s,())
201 io m = GHCi $ \s -> m >>= \a -> return (s,a)
203 myCatch (GHCi m) h = GHCi $ \s ->
204 Exception.catch (m s) (\e -> unGHCi (h e) s)
205 myCatchDyn (GHCi m) h = GHCi $ \s ->
206 Exception.catchDyn (m s) (\e -> unGHCi (h e) s)
208 -----------------------------------------------------------------------------
211 linkPackages :: [Package] -> IO ()
212 linkPackages pkgs = mapM_ linkPackage pkgs
214 linkPackage :: Package -> IO ()
215 -- ignore rts and gmp for now (ToDo; better?)
216 linkPackage pkg | name pkg `elem` ["rts", "gmp"] = return ()
218 putStr ("Loading package " ++ name pkg ++ " ... ")
219 let dirs = library_dirs pkg
220 let objs = map (++".o") (hs_libraries pkg ++ extra_libraries pkg)
221 mapM (linkOneObj dirs) objs
222 putStr "resolving ... "
226 linkOneObj dirs obj = do
227 filename <- findFile dirs obj
230 findFile [] obj = throwDyn (OtherError ("can't find " ++ obj))
231 findFile (d:ds) obj = do
232 let path = d ++ '/':obj
233 b <- doesFileExist path
234 if b then return path else findFile ds obj