-----------------------------------------------------------------------------
--- $Id: InteractiveUI.hs,v 1.46 2001/02/13 15:51:57 sewardj Exp $
+-- $Id: InteractiveUI.hs,v 1.51 2001/02/14 11:36:07 sewardj Exp $
--
-- GHC Interactive User Interface
--
-----------------------------------------------------------------------------
{-# OPTIONS -#include "Linker.h" #-}
-module InteractiveUI (interactiveUI) where
+module InteractiveUI ( interactiveUI, ghciWelcomeMsg ) where
#include "HsVersions.h"
import PrelGHC ( unsafeCoerce# )
import PrelPack ( packString )
import PrelByteArr
-import Foreign ( Ptr, nullPtr )
+import Foreign ( nullPtr )
+import CString ( peekCString )
-----------------------------------------------------------------------------
\ (eg. -v2, -fglasgow-exts, etc.)\n\
\"
-interactiveUI :: CmState -> Maybe FilePath -> [String] -> IO ()
+interactiveUI :: CmState -> Maybe FilePath -> [LibrarySpec] -> IO ()
interactiveUI cmstate mod cmdline_libs = do
- hPutStrLn stdout ghciWelcomeMsg
hFlush stdout
hSetBuffering stdout NoBuffering
= do expr_expanded <- expandExpr expr
-- io (putStrLn ( "Before: " ++ expr ++ "\nAfter: " ++ expr_expanded))
expr_ok <- timeIt (do stuff <- evalExpr expr_expanded
- finishEvalExpr stuff)
+ finishEvalExpr expr_expanded stuff)
when expr_ok (rememberExpr expr_expanded)
return False
--- possibly print the type and revert CAFs after evaluating an expression
-finishEvalExpr Nothing = return False
-finishEvalExpr (Just (unqual,ty))
- = do b <- isOptionSet ShowType
- io (when b (printForUser stdout unqual (text "::" <+> ppr ty)))
- b <- isOptionSet RevertCAFs
- io (when b revertCAFs)
- return True
-
--- Returned Maybe indicates whether or not the expr was successfully
--- parsed, renamed and typechecked.
-evalExpr :: String -> GHCi (Maybe (PrintUnqualified,Type))
+-- Returns True if the expr was successfully parsed, renamed and
+-- typechecked.
+evalExpr :: String -> GHCi Bool
evalExpr expr
| null (filter (not.isSpace) expr)
- = return Nothing
+ = return False
| otherwise
= do st <- getGHCiState
dflags <- io (getDynFlags)
io (cmGetExpr (cmstate st) dflags True (current_module st) expr)
setGHCiState st{cmstate = new_cmstate}
case maybe_stuff of
- Nothing -> return Nothing
- Just (hv, unqual, ty) -> do io (cmRunExpr hv)
- flushEverything
- return (Just (unqual,ty))
+ Nothing -> return False
+ Just (hv, unqual, ty) ->
+ do io (cmRunExpr hv)
+ return True
+
+-- possibly print the type and revert CAFs after evaluating an expression
+finishEvalExpr _ False = return False
+finishEvalExpr expr True
+ = do b <- isOptionSet ShowType
+ -- re-typecheck, don't wrap with print this time
+ when b (io (putStr ":: ") >> typeOfExpr expr)
+ b <- isOptionSet RevertCAFs
+ io (when b revertCAFs)
+ flushEverything
+ return True
flushEverything :: GHCi ()
flushEverything
= throwDyn (OtherError "syntax: `:m <module>'")
setContext m | not (isUpper (head m)) || not (all isAlphaNum (tail m))
= throwDyn (OtherError ("strange looking module name: `" ++ m ++ "'"))
-setContext mn
- = do m <- io (moduleNameToModule (mkModuleName mn))
- st <- getGHCiState
+setContext str
+ = do st <- getGHCiState
+
+ let mn = mkModuleName str
+ m <- case [ m | m <- modules st, moduleName m == mn ] of
+ (m:_) -> return m
+ [] -> io (moduleNameToModule mn)
+
if (isHomeModule m && m `notElem` modules st)
then throwDyn (OtherError (showSDoc (quotes (ppr (moduleName m))
<+> text "is not currently loaded, use :load")))
moduleNameToModule mn
= do maybe_stuff <- findModule mn
case maybe_stuff of
- Nothing -> throwDyn (OtherError ("can't find module `"
- ++ moduleNameUserString mn ++ "'"))
- Just (m,_) -> return m
+ Nothing -> throwDyn (OtherError ("can't find module `"
+ ++ moduleNameUserString mn ++ "'"))
+ Just (m,_) -> return m
changeDirectory :: String -> GHCi ()
changeDirectory d = io (setCurrentDirectory d)
-----------------------------------------------------------------------------
-- package loader
-linkPackages :: [String] -> [Package] -> IO ()
-linkPackages cmdline_libs pkgs
- = do mapM preloadLib cmdline_libs
- mapM_ linkPackage pkgs
+-- Left: full path name of a .o file, including trailing .o
+-- Right: "unadorned" name of a .DLL/.so
+-- e.g. On unix "qt" denotes "libqt.so"
+-- On WinDoze "burble" denotes "burble.DLL"
+-- addDLL is platform-specific and adds the lib/.so/.DLL
+-- prefixes plaform-dependently; we don't do that here.
+type LibrarySpec
+ = Either FilePath String
+
+showLS (Left nm) = "(static) " ++ nm
+showLS (Right nm) = "(dynamic) " ++ nm
+
+linkPackages :: [LibrarySpec] -> [Package] -> IO ()
+linkPackages cmdline_lib_specs pkgs
+ = do mapM_ linkPackage pkgs
+ mapM_ preloadLib cmdline_lib_specs
where
- preloadLib orig_name
- = do putStr ("Loading object " ++ orig_name ++ " ... ")
- case classify orig_name of
+ preloadLib lib_spec
+ = do putStr ("Loading object " ++ showLS lib_spec ++ " ... ")
+ case lib_spec of
Left static_ish
-> do b <- doesFileExist static_ish
if not b
else do loadObj static_ish
putStr "done.\n"
Right dll_unadorned
- -> do dll_ok <- ocAddDLL (packString dll_unadorned)
- if dll_ok == 1
+ -> do maybe_errmsg <- addDLL dll_unadorned
+ if maybe_errmsg == nullPtr
then putStr "done.\n"
- else do putStr "not found.\n"
+ else do str <- peekCString maybe_errmsg
+ putStr ("failed (" ++ str ++ ")\n")
croak
- croak = throwDyn (OtherError "user specified .o/.so/.DLL cannot be found.")
-
- classify a_lib
- = let a_libr = reverse a_lib
- in
- case map toLower a_libr of
- ('o':'.':_)
- -> Left a_lib
- ('o':'s':'.':_)
- -> (Right . zap_leading_lib
- . reverse . drop 3 . reverse) a_lib
- ('l':'l':'d':'.':_)
- -> (Right . reverse . drop 4 . reverse) a_lib
- other
- -> -- Main.beginInteractive should not have let this through
- pprPanic "linkPackages" (text (show a_lib))
-
- zap_leading_lib str
- = if take 3 str == "lib" then drop 3 str else str
+ croak = throwDyn (OtherError "user specified .o/.so/.DLL could not be loaded.")
linkPackage :: Package -> IO ()
isRight (Right _) = True
isRight (Left _) = False
-loadClassified :: Either FilePath String -> IO ()
+loadClassified :: LibrarySpec -> IO ()
loadClassified (Left obj_absolute_filename)
= do loadObj obj_absolute_filename
loadClassified (Right dll_unadorned)
- = do dll_ok <- ocAddDLL (packString dll_unadorned)
- if dll_ok == 1
+ = do maybe_errmsg <- addDLL dll_unadorned
+ if maybe_errmsg == nullPtr
then return ()
- else throwDyn (OtherError ("can't find .o or .so/.DLL for: "
- ++ dll_unadorned))
+ else do str <- peekCString maybe_errmsg
+ throwDyn (OtherError ("can't find .o or .so/.DLL for: "
+ ++ dll_unadorned ++ " (" ++ str ++ ")" ))
-locateOneObj :: [FilePath] -> String -> IO (Either FilePath String)
+locateOneObj :: [FilePath] -> String -> IO LibrarySpec
locateOneObj [] obj
= return (Right obj) -- we assume
locateOneObj (d:ds) obj
b <- doesFileExist path
if b then return (Left path) else locateOneObj ds obj
-
-type PackedString = ByteArray Int
-foreign import "ocAddDLL" unsafe ocAddDLL :: PackedString -> IO Int
-
-----------------------------------------------------------------------------
-- timing & statistics