X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;f=ghc%2Fcompiler%2Fghci%2FInteractiveUI.hs;h=a1ec76433b4285af3989ab3f78668bd28e8156d3;hb=58fa6794af94c320f2481bec4fba31b18c308d0a;hp=366a435bc82666b3857bcb126c9c0d96b032254e;hpb=fe548aebdad3520e51d92fcda6bec9d26d69aa4a;p=ghc-hetmet.git diff --git a/ghc/compiler/ghci/InteractiveUI.hs b/ghc/compiler/ghci/InteractiveUI.hs index 366a435..a1ec764 100644 --- a/ghc/compiler/ghci/InteractiveUI.hs +++ b/ghc/compiler/ghci/InteractiveUI.hs @@ -1,6 +1,6 @@ {-# OPTIONS -#include "Linker.h" #-} ----------------------------------------------------------------------------- --- $Id: InteractiveUI.hs,v 1.152 2003/05/07 08:29:48 simonpj Exp $ +-- $Id: InteractiveUI.hs,v 1.162 2003/12/10 14:15:21 simonmar Exp $ -- -- GHC Interactive User Interface -- @@ -8,7 +8,7 @@ -- ----------------------------------------------------------------------------- module InteractiveUI ( - interactiveUI, -- :: CmState -> [FilePath] -> [LibrarySpec] -> IO () + interactiveUI, -- :: CmState -> [FilePath] -> IO () ghciWelcomeMsg ) where @@ -17,22 +17,13 @@ module InteractiveUI ( import CompManager import HscTypes ( TyThing(..), HomeModInfo(hm_linkable), HomePackageTable, - isObjectLinkable ) -import HsSyn ( TyClDecl(..), ConDecl(..), Sig(..) ) -import MkIface ( ifaceTyThing ) + isObjectLinkable, GhciMode(..) ) +import IfaceSyn ( IfaceDecl( ifName ) ) import DriverFlags import DriverState -import DriverUtil ( remove_spaces, handle ) -import Linker ( initLinker, showLinkerState, linkLibraries, - linkPackages ) +import DriverUtil ( remove_spaces ) +import Linker ( showLinkerState, linkPackages ) import Util -import IdInfo ( GlobalIdDetails(..) ) -import Id ( isImplicitId, idName, globalIdDetails ) -import Class ( className ) -import TyCon ( tyConName, tyConClass_maybe, isPrimTyCon, DataConDetails(..) ) -import DataCon ( dataConName ) -import FieldLabel ( fieldLabelTyCon ) -import SrcLoc ( isGoodSrcLoc ) import Module ( showModMsg, lookupModuleEnv ) import Name ( Name, isHomePackageName, nameSrcLoc, nameOccName, NamedThing(..) ) @@ -46,6 +37,7 @@ import Panic hiding ( showException ) import Config #ifndef mingw32_HOST_OS +import DriverUtil( handle ) import System.Posix #if __GLASGOW_HASKELL__ > 504 hiding (getEnv) @@ -155,40 +147,33 @@ helpText = "\ \ (eg. -v2, -fglasgow-exts, etc.)\n\ \" -interactiveUI :: CmState -> [FilePath] -> [FilePath] -> IO () -interactiveUI cmstate paths cmdline_objs = do - hFlush stdout - hSetBuffering stdout NoBuffering - +interactiveUI :: [FilePath] -> Maybe String -> IO () +interactiveUI srcs maybe_expr = do dflags <- getDynFlags - initLinker + cmstate <- cmInit Interactive dflags; - -- link packages requested explicitly on the command-line - expl <- readIORef v_ExplicitPackages - linkPackages dflags expl - - -- link libraries from the command-line - linkLibraries dflags cmdline_objs + hFlush stdout + hSetBuffering stdout NoBuffering -- Initialise buffering for the *interpreted* I/O system - cmstate <- initInterpBuffering cmstate dflags + initInterpBuffering cmstate -- We don't want the cmd line to buffer any input that might be -- intended for the program, so unbuffer stdin. hSetBuffering stdin NoBuffering -- initial context is just the Prelude - cmstate <- cmSetContext cmstate dflags [] ["Prelude"] + cmstate <- cmSetContext cmstate [] ["Prelude"] #if HAVE_READLINE_HEADERS && HAVE_READLINE_LIBS Readline.initialize #endif - startGHCi (runGHCi paths dflags) + startGHCi (runGHCi srcs dflags maybe_expr) GHCiState{ progname = "", args = [], - targets = paths, + targets = srcs, cmstate = cmstate, options = [] } @@ -198,8 +183,8 @@ interactiveUI cmstate paths cmdline_objs = do return () -runGHCi :: [FilePath] -> DynFlags -> GHCi () -runGHCi paths dflags = do +runGHCi :: [FilePath] -> DynFlags -> Maybe String -> GHCi () +runGHCi paths dflags maybe_expr = do read_dot_files <- io (readIORef v_Read_DotGHCi) when (read_dot_files) $ do @@ -231,38 +216,42 @@ runGHCi paths dflags = do Left e -> return () Right hdl -> fileLoop hdl False - -- perform a :load for files given on the GHCi command line + -- Perform a :load for files given on the GHCi command line when (not (null paths)) $ ghciHandle showException $ loadModule paths - -- enter the interactive loop -#if defined(mingw32_HOST_OS) - -- always show prompt, since hIsTerminalDevice returns True for Consoles - -- only, which we may or may not be running under (cf. Emacs sub-shells.) - interactiveLoop True -#else + -- if verbosity is greater than 0, or we are connected to a + -- terminal, display the prompt in the interactive loop. is_tty <- io (hIsTerminalDevice stdin) - interactiveLoop is_tty -#endif + let show_prompt = verbosity dflags > 0 || is_tty + + case maybe_expr of + Nothing -> + -- enter the interactive loop + interactiveLoop is_tty show_prompt + Just expr -> do + -- just evaluate the expression we were given + runCommand expr + return () -- and finally, exit io $ do when (verbosity dflags > 0) $ putStrLn "Leaving GHCi." -interactiveLoop is_tty = do - -- ignore ^C exceptions caught here +interactiveLoop is_tty show_prompt = do + -- Ignore ^C exceptions caught here ghciHandleDyn (\e -> case e of - Interrupted -> ghciUnblock (interactiveLoop is_tty) + Interrupted -> ghciUnblock (interactiveLoop is_tty show_prompt) _other -> return ()) $ do -- read commands from stdin #if HAVE_READLINE_HEADERS && HAVE_READLINE_LIBS if (is_tty) then readlineLoop - else fileLoop stdin False -- turn off prompt for non-TTY input + else fileLoop stdin show_prompt #else - fileLoop stdin is_tty + fileLoop stdin show_prompt #endif @@ -384,10 +373,11 @@ runStmt stmt | otherwise = do st <- getGHCiState dflags <- io getDynFlags - let dflags' = dopt_unset dflags Opt_WarnUnusedBinds + let cm_state' = cmSetDFlags (cmstate st) + (dopt_unset dflags Opt_WarnUnusedBinds) (new_cmstate, result) <- io $ withProgName (progname st) $ withArgs (args st) $ - cmRunStmt (cmstate st) dflags' stmt + cmRunStmt cm_state' stmt setGHCiState st{cmstate = new_cmstate} case result of CmRunFailed -> return [] @@ -441,22 +431,22 @@ no_buf_cmd = "IO.hSetBuffering IO.stdout IO.NoBuffering" ++ " Prelude.>> IO.hSetBuffering IO.stderr IO.NoBuffering" flush_cmd = "IO.hFlush IO.stdout Prelude.>> IO.hFlush IO.stderr" -initInterpBuffering :: CmState -> DynFlags -> IO CmState -initInterpBuffering cmstate dflags - = do (cmstate, maybe_hval) <- cmCompileExpr cmstate dflags no_buf_cmd +initInterpBuffering :: CmState -> IO () +initInterpBuffering cmstate + = do maybe_hval <- cmCompileExpr cmstate no_buf_cmd case maybe_hval of Just hval -> writeIORef turn_off_buffering (unsafeCoerce# hval :: IO ()) other -> panic "interactiveUI:setBuffering" - (cmstate, maybe_hval) <- cmCompileExpr cmstate dflags flush_cmd + maybe_hval <- cmCompileExpr cmstate flush_cmd case maybe_hval of Just hval -> writeIORef flush_interp (unsafeCoerce# hval :: IO ()) _ -> panic "interactiveUI:flush" turnOffBuffering -- Turn it off right now - return cmstate + return () flushInterpBuffers :: GHCi () @@ -480,11 +470,10 @@ info "" = throwDyn (CmdLineError "syntax: `:i '") info s = do let names = words s init_cms <- getCmState - dflags <- io getDynFlags let infoThings cms [] = return cms infoThings cms (name:names) = do - (cms, stuff) <- io (cmInfoThing cms dflags name) + stuff <- io (cmInfoThing cms name) io (putStrLn (showSDocForUser unqual ( vcat (intersperse (text "") (map showThing stuff)))) ) @@ -492,18 +481,21 @@ info s = do unqual = cmGetPrintUnqual init_cms - showThing (ty_thing, fixity) - = vcat [ text "-- " <> showTyThing ty_thing, - showFixity fixity (getName ty_thing), - ppr (ifaceTyThing ty_thing) ] + showThing (decl, fixity) + = vcat [ text "-- " <> showTyThing decl, + showFixity fixity (ifName decl), + showTyThing decl ] showFixity fix name | fix == defaultFixity = empty | otherwise = ppr fix <+> - (if isSymOcc (nameOccName name) + (if isSymOcc name then ppr name else char '`' <> ppr name <> char '`') + showTyThing decl = ppr decl + +{- showTyThing (AClass cl) = hcat [ppr cl, text " is a class", showSrcLoc (className cl)] showTyThing (ADataCon dc) @@ -529,26 +521,33 @@ info s = do | otherwise = empty where loc = nameSrcLoc name +-} - cms <- infoThings init_cms names - setCmState cms + infoThings init_cms names return () addModule :: [FilePath] -> GHCi () addModule files = do state <- getGHCiState - dflags <- io (getDynFlags) io (revertCAFs) -- always revert CAFs on load/add. files <- mapM expandPath files let new_targets = files ++ targets state - graph <- io (cmDepAnal (cmstate state) dflags new_targets) - (cmstate1, ok, mods) <- io (cmLoadModules (cmstate state) dflags graph) + graph <- io (cmDepAnal (cmstate state) new_targets) + (cmstate1, ok, mods) <- io (cmLoadModules (cmstate state) graph) setGHCiState state{ cmstate = cmstate1, targets = new_targets } setContextAfterLoad mods + dflags <- io getDynFlags modulesLoadedMsg ok mods dflags changeDirectory :: String -> GHCi () changeDirectory dir = do + state <- getGHCiState + when (targets state /= []) $ + io $ putStr "Warning: changing directory causes all loaded modules to be unloaded, \n\ + \because the search path has changed.\n" + cmstate1 <- io (cmUnload (cmstate state)) + setGHCiState state{ cmstate = cmstate1, targets = [] } + setContextAfterLoad [] dir <- expandPath dir io (setCurrentDirectory dir) @@ -570,9 +569,7 @@ defineMacro s = do -- compile the expression cms <- getCmState - dflags <- io getDynFlags - (new_cmstate, maybe_hv) <- io (cmCompileExpr cms dflags new_expr) - setCmState new_cmstate + maybe_hv <- io (cmCompileExpr cms new_expr) case maybe_hv of Nothing -> return () Just hv -> io (writeIORef commands -- @@ -603,43 +600,43 @@ loadModule fs = timeIt (loadModule' fs) loadModule' :: [FilePath] -> GHCi () loadModule' files = do state <- getGHCiState - dflags <- io getDynFlags -- expand tildes files <- mapM expandPath files -- do the dependency anal first, so that if it fails we don't throw -- away the current set of modules. - graph <- io (cmDepAnal (cmstate state) dflags files) + graph <- io (cmDepAnal (cmstate state) files) -- Dependency anal ok, now unload everything - cmstate1 <- io (cmUnload (cmstate state) dflags) + cmstate1 <- io (cmUnload (cmstate state)) setGHCiState state{ cmstate = cmstate1, targets = [] } io (revertCAFs) -- always revert CAFs on load. - (cmstate2, ok, mods) <- io (cmLoadModules cmstate1 dflags graph) + (cmstate2, ok, mods) <- io (cmLoadModules cmstate1 graph) setGHCiState state{ cmstate = cmstate2, targets = files } setContextAfterLoad mods + dflags <- io (getDynFlags) modulesLoadedMsg ok mods dflags reloadModule :: String -> GHCi () reloadModule "" = do state <- getGHCiState - dflags <- io getDynFlags case targets state of [] -> io (putStr "no current target\n") paths -> do -- do the dependency anal first, so that if it fails we don't throw -- away the current set of modules. - graph <- io (cmDepAnal (cmstate state) dflags paths) + graph <- io (cmDepAnal (cmstate state) paths) io (revertCAFs) -- always revert CAFs on reload. (cmstate1, ok, mods) - <- io (cmLoadModules (cmstate state) dflags graph) + <- io (cmLoadModules (cmstate state) graph) setGHCiState state{ cmstate=cmstate1 } setContextAfterLoad mods + dflags <- io getDynFlags modulesLoadedMsg ok mods dflags reloadModule _ = noArgs ":reload" @@ -666,9 +663,7 @@ modulesLoadedMsg ok mods dflags = typeOfExpr :: String -> GHCi () typeOfExpr str = do cms <- getCmState - dflags <- io getDynFlags - (new_cmstate, maybe_tystr) <- io (cmTypeOfExpr cms dflags str) - setCmState new_cmstate + maybe_tystr <- io (cmTypeOfExpr cms str) case maybe_tystr of Nothing -> return () Just tystr -> io (putStrLn tystr) @@ -691,58 +686,25 @@ browseCmd m = browseModule m exports_only = do cms <- getCmState - dflags <- io getDynFlags is_interpreted <- io (cmModuleIsInterpreted cms m) when (not is_interpreted && not exports_only) $ throwDyn (CmdLineError ("module `" ++ m ++ "' is not interpreted")) - -- temporarily set the context to the module we're interested in, + -- Temporarily set the context to the module we're interested in, -- just so we can get an appropriate PrintUnqualified (as,bs) <- io (cmGetContext cms) - cms1 <- io (if exports_only then cmSetContext cms dflags [] [prel,m] - else cmSetContext cms dflags [m] []) - cms2 <- io (cmSetContext cms1 dflags as bs) - - (cms3, things) <- io (cmBrowseModule cms2 dflags m exports_only) + cms1 <- io (if exports_only then cmSetContext cms [] [prel,m] + else cmSetContext cms [m] []) + cms2 <- io (cmSetContext cms1 as bs) - setCmState cms3 + things <- io (cmBrowseModule cms2 m exports_only) let unqual = cmGetPrintUnqual cms1 -- NOTE: cms1 with the new context - things' = filter wantToSee things - - wantToSee (AnId id) = not (isImplicitId id) - wantToSee (ADataCon _) = False -- They'll come via their TyCon - wantToSee _ = True - - thing_names = map getName things - - thingDecl thing@(AnId id) = ifaceTyThing thing - - thingDecl thing@(AClass c) = - let rn_decl = ifaceTyThing thing in - case rn_decl of - ClassDecl { tcdSigs = cons } -> - rn_decl{ tcdSigs = filter methodIsVisible cons } - other -> other - where - methodIsVisible (ClassOpSig n _ _ _) = n `elem` thing_names - - thingDecl thing@(ATyCon t) = - let rn_decl = ifaceTyThing thing in - case rn_decl of - TyData { tcdCons = DataCons cons } -> - rn_decl{ tcdCons = DataCons (filter conIsVisible cons) } - other -> other - where - conIsVisible (ConDecl n _ _ _ _) = n `elem` thing_names - io (putStrLn (showSDocForUser unqual ( - vcat (map (ppr . thingDecl) things'))) - ) - - where + vcat (map ppr things) + ))) ----------------------------------------------------------------------------- -- Setting the module context @@ -761,10 +723,9 @@ setContext str newContext mods = do cms <- getCmState - dflags <- io getDynFlags (as,bs) <- separate cms mods [] [] let bs' = if null as && prel `notElem` bs then prel:bs else bs - cms' <- io (cmSetContext cms dflags as bs') + cms' <- io (cmSetContext cms as bs') setCmState cms' separate cmstate [] as bs = return (as,bs) @@ -779,7 +740,6 @@ prel = "Prelude" addToContext mods = do cms <- getCmState - dflags <- io getDynFlags (as,bs) <- io (cmGetContext cms) (as',bs') <- separate cms mods [] [] @@ -787,14 +747,13 @@ addToContext mods = do let as_to_add = as' \\ (as ++ bs) bs_to_add = bs' \\ (as ++ bs) - cms' <- io (cmSetContext cms dflags + cms' <- io (cmSetContext cms (as ++ as_to_add) (bs ++ bs_to_add)) setCmState cms' removeFromContext mods = do cms <- getCmState - dflags <- io getDynFlags (as,bs) <- io (cmGetContext cms) (as_to_remove,bs_to_remove) <- separate cms mods [] [] @@ -802,7 +761,7 @@ removeFromContext mods = do let as' = as \\ (as_to_remove ++ bs_to_remove) bs' = bs \\ (as_to_remove ++ bs_to_remove) - cms' <- io (cmSetContext cms dflags as' bs') + cms' <- io (cmSetContext cms as' bs') setCmState cms' ---------------------------------------------------------------------------- @@ -921,9 +880,9 @@ optToStr RevertCAFs = "r" newPackages new_pkgs = do -- The new packages are already in v_Packages state <- getGHCiState - dflags <- io getDynFlags - cmstate1 <- io (cmUnload (cmstate state) dflags) + cmstate1 <- io (cmUnload (cmstate state)) setGHCiState state{ cmstate = cmstate1, targets = [] } + dflags <- io getDynFlags io (linkPackages dflags new_pkgs) setContextAfterLoad [] @@ -958,7 +917,8 @@ showBindings = do cms <- getCmState let unqual = cmGetPrintUnqual cms - showBinding b = putStrLn (showSDocForUser unqual (ppr (ifaceTyThing b))) +-- showBinding b = putStrLn (showSDocForUser unqual (ppr (ifaceTyThing b))) + showBinding b = putStrLn (showSDocForUser unqual (ppr (getName b))) io (mapM_ showBinding (cmGetBindings cms)) return ()