\begin{code}
module Panic
(
- GhcException(..), showGhcException, ghcError, progName,
+ GhcException(..), showGhcException, throwGhcException, handleGhcException,
+ ghcError, progName,
pgmError,
panic, panicFastInt, assertPanic, trace,
- Exception.Exception(..), showException, try, tryJust, tryMost, tryUser,
- catchJust, ioErrors, throwTo,
+ Exception.Exception(..), showException, try, tryMost, throwTo,
installSignalHandlers, interruptTargetThread
) where
import Data.Dynamic
import Debug.Trace ( trace )
import System.IO.Unsafe ( unsafePerformIO )
-import System.IO.Error ( isUserError )
import System.Exit
import System.Environment
\end{code}
\begin{code}
ghcError :: GhcException -> a
-ghcError e = Exception.throwDyn e
+ghcError e = Exception.throw e
-- error messages all take the form
--
| ProgramError String -- error in the user's code, probably
deriving Eq
+instance Exception GhcException
+
progName :: String
progName = unsafePerformIO (getProgName)
{-# NOINLINE progName #-}
short_usage :: String
short_usage = "Usage: For basic information, try the `--help' option."
-
-showException :: Exception.Exception -> String
--- Show expected dynamic exceptions specially
-showException (Exception.DynException d) | Just e <- fromDynamic d
- = show (e::GhcException)
-showException other_exn = show other_exn
+
+showException :: Exception e => e -> String
+showException = show
instance Show GhcException where
showsPrec _ e@(ProgramError _) = showGhcException e
++ s ++ "\n\n"
++ "Please report this as a GHC bug: http://www.haskell.org/ghc/reportabug\n")
+throwGhcException :: GhcException -> a
+throwGhcException = Exception.throw
+
+handleGhcException :: ExceptionMonad m => (GhcException -> m a) -> m a -> m a
+handleGhcException = ghandle
+
ghcExceptionTc :: TyCon
ghcExceptionTc = mkTyCon "GhcException"
{-# NOINLINE ghcExceptionTc #-}
\begin{code}
panic, pgmError :: String -> a
-panic x = Exception.throwDyn (Panic x)
-pgmError x = Exception.throwDyn (ProgramError x)
+panic x = throwGhcException (Panic x)
+pgmError x = throwGhcException (ProgramError x)
-- #-versions because panic can't return an unboxed int, and that's
-- what TAG_ is with GHC at the moment. Ugh. (Simon)
-- exceptions. Used when we want soft failures when reading interface
-- files, for example.
-tryMost :: IO a -> IO (Either Exception.Exception a)
-tryMost action = do r <- try action; filter r
- where
- filter (Left e@(Exception.DynException d))
- | Just ghc_ex <- fromDynamic d
- = case ghc_ex of
- Interrupted -> Exception.throw e
- Panic _ -> Exception.throw e
- _other -> return (Left e)
- filter other
- = return other
-
--- | tryUser is like try, but catches only UserErrors.
--- These are the ones that are thrown by the TcRn monad
--- to signal an error in the program being compiled
-tryUser :: IO a -> IO (Either Exception.Exception a)
-tryUser action = tryJust tc_errors action
- where
- tc_errors e@(Exception.IOException ioe) | isUserError ioe = Just e
- tc_errors _other = Nothing
+-- XXX I'm not entirely sure if this is catching what we really want to catch
+tryMost :: IO a -> IO (Either SomeException a)
+tryMost action = do r <- try action
+ case r of
+ Left se ->
+ case fromException se of
+ -- Some GhcException's we rethrow,
+ Just Interrupted -> throwIO se
+ Just (Panic _) -> throwIO se
+ -- others we return
+ Just _ -> return (Left se)
+ Nothing ->
+ case fromException se of
+ -- All IOExceptions are returned
+ Just (_ :: IOException) ->
+ return (Left se)
+ -- Anything else is rethrown
+ Nothing -> throwIO se
+ Right v -> return (Right v)
\end{code}
Standard signal handlers for catching ^C, which just throw an
installSignalHandlers :: IO ()
installSignalHandlers = do
let
- interrupt_exn = Exception.DynException (toDyn Interrupted)
+ interrupt_exn = (toException Interrupted)
interrupt = do
withMVar interruptTargetThread $ \targets ->