Commit 453aaabd authored by Andrew Gibiansky's avatar Andrew Gibiansky

Merge pull request #449 from gibiansky/show-module-compilation-errors

Improving module loading; fixes #312
parents a489c9bb 2f11f85e
...@@ -18,7 +18,7 @@ import ClassyPrelude hiding (init, last, liftIO, head, hGetContents, t ...@@ -18,7 +18,7 @@ import ClassyPrelude hiding (init, last, liftIO, head, hGetContents, t
import Control.Concurrent (forkIO, threadDelay) import Control.Concurrent (forkIO, threadDelay)
import Prelude (putChar, head, tail, last, init, (!!)) import Prelude (putChar, head, tail, last, init, (!!))
import Data.List.Utils import Data.List.Utils
import Data.List (findIndex, and, foldl1) import Data.List (findIndex, and, foldl1, nubBy)
import Data.String.Utils import Data.String.Utils
import Text.Printf import Text.Printf
import Data.Char as Char import Data.Char as Char
...@@ -397,7 +397,6 @@ evalCommand _ (Module contents) state = wrapExecution state $ do ...@@ -397,7 +397,6 @@ evalCommand _ (Module contents) state = wrapExecution state $ do
-- Write the module contents to a temporary file in our work directory -- Write the module contents to a temporary file in our work directory
namePieces <- getModuleName contents namePieces <- getModuleName contents
liftIO (print namePieces)
let directory = "./" ++ intercalate "/" (init namePieces) ++ "/" let directory = "./" ++ intercalate "/" (init namePieces) ++ "/"
filename = last namePieces ++ ".hs" filename = last namePieces ++ ".hs"
liftIO $ do liftIO $ do
...@@ -557,15 +556,17 @@ evalCommand _ (Directive GetKind expr) state = wrapExecution state $ do ...@@ -557,15 +556,17 @@ evalCommand _ (Directive GetKind expr) state = wrapExecution state $ do
let typeStr = showSDocUnqual flags $ ppr kind let typeStr = showSDocUnqual flags $ ppr kind
return $ formatType $ expr ++ " :: " ++ typeStr return $ formatType $ expr ++ " :: " ++ typeStr
evalCommand _ (Directive LoadFile name) state = wrapExecution state $ do evalCommand _ (Directive LoadFile names) state = wrapExecution state $ do
write state $ "Load: " ++ name write state $ "Load: " ++ names
let filename = if endswith ".hs" name displays <- forM (words names) $ \name -> do
then name let filename = if endswith ".hs" name
else name ++ ".hs" then name
contents <- readFile $ fpFromString filename else name ++ ".hs"
modName <- intercalate "." <$> getModuleName contents contents <- readFile $ fpFromString filename
doLoadModule filename modName modName <- intercalate "." <$> getModuleName contents
doLoadModule filename modName
return (ManyDisplay displays)
evalCommand publish (Directive ShellCmd ('!':cmd)) state = wrapExecution state $ evalCommand publish (Directive ShellCmd ('!':cmd)) state = wrapExecution state $
case words cmd of case words cmd of
...@@ -1001,26 +1002,6 @@ hoogleResults state results = ...@@ -1001,26 +1002,6 @@ hoogleResults state results =
fmt = Hoogle.HTML fmt = Hoogle.HTML
output = unlines $ map (Hoogle.render fmt) results output = unlines $ map (Hoogle.render fmt) results
-- Read from a file handle until we hit a delimiter or until we've read as many characters as
-- requested
readChars :: Handle -> String -> Int -> IO String
-- If we're done reading, return nothing.
readChars handle delims 0 = return []
readChars handle delims nchars = do
-- Try reading a single character. It will throw an exception if the handle is already closed.
tryRead <- gtry $ hGetChar handle :: IO (Either SomeException Char)
case tryRead of
Right char ->
-- If this is a delimiter, stop reading.
if char `elem` delims
then return [char]
else do
next <- readChars handle delims (nchars - 1)
return $ char : next
-- An error occurs at the end of the stream, so just stop reading.
Left _ -> return []
doLoadModule :: String -> String -> Ghc Display doLoadModule :: String -> String -> Ghc Display
doLoadModule name modName = do doLoadModule name modName = do
-- Remember which modules we've loaded before. -- Remember which modules we've loaded before.
...@@ -1029,32 +1010,43 @@ doLoadModule name modName = do ...@@ -1029,32 +1010,43 @@ doLoadModule name modName = do
flip gcatch (unload importedModules) $ do flip gcatch (unload importedModules) $ do
-- Compile loaded modules. -- Compile loaded modules.
flags <- getSessionDynFlags flags <- getSessionDynFlags
setSessionDynFlags flags { hscTarget = objTarget flags } errRef <- liftIO $ newIORef []
setSessionDynFlags
-- Clear old targets to be sure. flags
setTargets [] { hscTarget = objTarget flags
load LoadAllTargets , log_action = \dflags sev srcspan ppr msg -> modifyIORef errRef (showSDoc flags msg :)
}
-- Load the new target. -- Load the new target.
target <- guessTarget name Nothing target <- guessTarget name Nothing
oldTargets <- getTargets
-- Add a target, but make sure targets are unique!
addTarget target addTarget target
getTargets >>= return . (nubBy ((==) `on` targetId)) >>= setTargets
result <- load LoadAllTargets result <- load LoadAllTargets
-- Reset the context, since loading things screws it up. -- Reset the context, since loading things screws it up.
initializeItVariable initializeItVariable
-- Reset targets if we failed.
case result of
Failed -> setTargets oldTargets
Succeeded{} -> return ()
-- Add imports -- Add imports
importDecl <- parseImportDecl $ "import " ++ modName setContext $
let implicitImport = importDecl { ideclImplicit = True } case result of
setContext $ IIDecl implicitImport : importedModules Failed -> importedModules
Succeeded -> IIDecl (simpleImportDecl $ mkModuleName modName) : importedModules
-- Switch back to interpreted mode. -- Switch back to interpreted mode.
flags <- getSessionDynFlags setSessionDynFlags flags
setSessionDynFlags flags { hscTarget = HscInterpreted }
case result of case result of
Succeeded -> return mempty Succeeded -> return mempty
Failed -> return $ displayError $ "Failed to load module " ++ modName Failed -> do
errorStrs <- unlines <$> reverse <$> liftIO (readIORef errRef)
return $ displayError $ "Failed to load module " ++ modName ++ "\n" ++ errorStrs
where where
unload :: [InteractiveImport] -> SomeException -> Ghc Display unload :: [InteractiveImport] -> SomeException -> Ghc Display
...@@ -1154,27 +1146,6 @@ capturedStatement output stmt = do ...@@ -1154,27 +1146,6 @@ capturedStatement output stmt = do
fd <- head <$> unsafeCoerce hValues fd <- head <$> unsafeCoerce hValues
fdToHandle fd fdToHandle fd
-- Read from a file handle until we hit a delimiter or until we've read as many characters as
-- requested
let readChars :: Handle -> String -> Int -> IO String
-- If we're done reading, return nothing.
readChars handle delims 0 = return []
readChars handle delims nchars = do
-- Try reading a single character. It will throw an exception if the handle is already closed.
tryRead <- gtry $ hGetChar handle :: IO (Either SomeException Char)
case tryRead of
Right char ->
-- If this is a delimiter, stop reading.
if char `elem` delims
then return [char]
else do
next <- readChars handle delims (nchars - 1)
return $ char : next
-- An error occurs at the end of the stream, so just stop reading.
Left _ -> return []
-- Keep track of whether execution has completed. -- Keep track of whether execution has completed.
completed <- liftIO $ newMVar False completed <- liftIO $ newMVar False
...@@ -1232,6 +1203,26 @@ capturedStatement output stmt = do ...@@ -1232,6 +1203,26 @@ capturedStatement output stmt = do
printedOutput <- liftIO $ readMVar outputAccum printedOutput <- liftIO $ readMVar outputAccum
return (printedOutput, result) return (printedOutput, result)
-- Read from a file handle until we hit a delimiter or until we've read as many characters as
-- requested
readChars :: Handle -> String -> Int -> IO String
readChars handle delims 0 =
-- If we're done reading, return nothing.
return []
readChars handle delims nchars = do
-- Try reading a single character. It will throw an exception if the handle is already closed.
tryRead <- gtry $ hGetChar handle :: IO (Either SomeException Char)
case tryRead of
Right char ->
-- If this is a delimiter, stop reading.
if char `elem` delims
then return [char]
else do
next <- readChars handle delims (nchars - 1)
return $ char : next
-- An error occurs at the end of the stream, so just stop reading.
Left _ -> return []
formatError :: ErrMsg -> String formatError :: ErrMsg -> String
formatError = formatErrorWithClass "err-msg" formatError = formatErrorWithClass "err-msg"
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment