summaryrefslogtreecommitdiff
path: root/libraries/base/Control/Exception.hs
diff options
context:
space:
mode:
Diffstat (limited to 'libraries/base/Control/Exception.hs')
-rw-r--r--libraries/base/Control/Exception.hs226
1 files changed, 226 insertions, 0 deletions
diff --git a/libraries/base/Control/Exception.hs b/libraries/base/Control/Exception.hs
new file mode 100644
index 0000000000..444ac876f6
--- /dev/null
+++ b/libraries/base/Control/Exception.hs
@@ -0,0 +1,226 @@
+-----------------------------------------------------------------------------
+--
+-- Module : Control.Exception
+-- Copyright : (c) The University of Glasgow 2001
+-- License : BSD-style (see the file libraries/core/LICENSE)
+--
+-- Maintainer : libraries@haskell.org
+-- Stability : experimental
+-- Portability : non-portable
+--
+-- $Id: Exception.hs,v 1.1 2001/06/28 14:15:01 simonmar Exp $
+--
+-- The External API for exceptions. The functions provided in this
+-- module allow catching of exceptions in the IO monad.
+--
+-----------------------------------------------------------------------------
+
+module Control.Exception (
+
+ Exception(..), -- instance Eq, Ord, Show, Typeable
+ IOException, -- instance Eq, Ord, Show, Typeable
+ ArithException(..), -- instance Eq, Ord, Show, Typeable
+ ArrayException(..), -- instance Eq, Ord, Show, Typeable
+ AsyncException(..), -- instance Eq, Ord, Show, Typeable
+
+ try, -- :: IO a -> IO (Either Exception a)
+ tryJust, -- :: (Exception -> Maybe b) -> a -> IO (Either b a)
+
+ catch, -- :: IO a -> (Exception -> IO a) -> IO a
+ catchJust, -- :: (Exception -> Maybe b) -> IO a -> (b -> IO a) -> IO a
+
+ evaluate, -- :: a -> IO a
+
+ -- Exception predicates (for catchJust, tryJust)
+
+ ioErrors, -- :: Exception -> Maybe IOError
+ arithExceptions, -- :: Exception -> Maybe ArithException
+ errorCalls, -- :: Exception -> Maybe String
+ dynExceptions, -- :: Exception -> Maybe Dynamic
+ assertions, -- :: Exception -> Maybe String
+ asyncExceptions, -- :: Exception -> Maybe AsyncException
+ userErrors, -- :: Exception -> Maybe String
+
+ -- Throwing exceptions
+
+ throw, -- :: Exception -> a
+#ifndef __STGHUGS__
+ -- for now
+ throwTo, -- :: ThreadId -> Exception -> a
+#endif
+
+ -- Dynamic exceptions
+
+ throwDyn, -- :: Typeable ex => ex -> b
+ throwDynTo, -- :: Typeable ex => ThreadId -> ex -> b
+ catchDyn, -- :: Typeable ex => IO a -> (ex -> IO a) -> IO a
+
+ -- Async exception control
+
+ block, -- :: IO a -> IO a
+ unblock, -- :: IO a -> IO a
+
+ -- Assertions
+
+ -- for now
+ assert, -- :: Bool -> a -> a
+
+ -- Utilities
+
+ finally, -- :: IO a -> IO b -> IO b
+
+ bracket, -- :: IO a -> (a -> IO b) -> (a -> IO c) -> IO ()
+ bracket_, -- :: IO a -> IO b -> IO c -> IO ()
+
+ ) where
+
+#ifdef __GLASGOW_HASKELL__
+import Prelude hiding (catch)
+import GHC.Prim ( assert )
+import GHC.Exception hiding (try, catch, bracket, bracket_)
+import GHC.Conc ( throwTo, ThreadId )
+import GHC.IOBase ( IO(..) )
+#endif
+
+#ifdef __HUGS__
+import Prelude hiding ( catch )
+import PrelPrim ( catchException
+ , Exception(..)
+ , throw
+ , ArithException(..)
+ , AsyncException(..)
+ , assert
+ )
+#endif
+
+import Data.Dynamic
+
+#include "Dynamic.h"
+INSTANCE_TYPEABLE0(Exception,exceptionTc,"Exception")
+INSTANCE_TYPEABLE0(IOException,ioExceptionTc,"IOException")
+INSTANCE_TYPEABLE0(ArithException,arithExceptionTc,"ArithException")
+INSTANCE_TYPEABLE0(ArrayException,arrayExceptionTc,"ArrayException")
+INSTANCE_TYPEABLE0(AsyncException,asyncExceptionTc,"AsyncException")
+
+-----------------------------------------------------------------------------
+-- Catching exceptions
+
+-- PrelException defines 'catchException' for us.
+
+catch :: IO a -> (Exception -> IO a) -> IO a
+catch = catchException
+
+catchJust :: (Exception -> Maybe b) -> IO a -> (b -> IO a) -> IO a
+catchJust p a handler = catch a handler'
+ where handler' e = case p e of
+ Nothing -> throw e
+ Just b -> handler b
+
+-----------------------------------------------------------------------------
+-- evaluate
+
+evaluate :: a -> IO a
+evaluate a = a `seq` return a
+
+-----------------------------------------------------------------------------
+-- 'try' and variations.
+
+try :: IO a -> IO (Either Exception a)
+try a = catch (a >>= \ v -> return (Right v)) (\e -> return (Left e))
+
+tryJust :: (Exception -> Maybe b) -> IO a -> IO (Either b a)
+tryJust p a = do
+ r <- try a
+ case r of
+ Right v -> return (Right v)
+ Left e -> case p e of
+ Nothing -> throw e
+ Just b -> return (Left b)
+
+-----------------------------------------------------------------------------
+-- Dynamic exception types. Since one of the possible kinds of exception
+-- is a dynamically typed value, we can effectively have polymorphic
+-- exceptions.
+
+-- throwDyn will raise any value as an exception, provided it is in the
+-- Typeable class (see Dynamic.lhs).
+
+-- catchDyn will catch any exception of a given type (determined by the
+-- handler function). Any raised exceptions that don't match are
+-- re-raised.
+
+throwDyn :: Typeable exception => exception -> b
+throwDyn exception = throw (DynException (toDyn exception))
+
+throwDynTo :: Typeable exception => ThreadId -> exception -> IO ()
+throwDynTo t exception = throwTo t (DynException (toDyn exception))
+
+catchDyn :: Typeable exception => IO a -> (exception -> IO a) -> IO a
+catchDyn m k = catchException m handle
+ where handle ex = case ex of
+ (DynException dyn) ->
+ case fromDynamic dyn of
+ Just exception -> k exception
+ Nothing -> throw ex
+ _ -> throw ex
+
+-----------------------------------------------------------------------------
+-- Exception Predicates
+
+ioErrors :: Exception -> Maybe IOError
+arithExceptions :: Exception -> Maybe ArithException
+errorCalls :: Exception -> Maybe String
+dynExceptions :: Exception -> Maybe Dynamic
+assertions :: Exception -> Maybe String
+asyncExceptions :: Exception -> Maybe AsyncException
+userErrors :: Exception -> Maybe String
+
+ioErrors e@(IOException _) = Just e
+ioErrors _ = Nothing
+
+arithExceptions (ArithException e) = Just e
+arithExceptions _ = Nothing
+
+errorCalls (ErrorCall e) = Just e
+errorCalls _ = Nothing
+
+assertions (AssertionFailed e) = Just e
+assertions _ = Nothing
+
+dynExceptions (DynException e) = Just e
+dynExceptions _ = Nothing
+
+asyncExceptions (AsyncException e) = Just e
+asyncExceptions _ = Nothing
+
+userErrors (UserError e) = Just e
+userErrors _ = Nothing
+
+-----------------------------------------------------------------------------
+-- Some Useful Functions
+
+bracket :: IO a -> (a -> IO b) -> (a -> IO c) -> IO c
+bracket before after thing =
+ block (do
+ a <- before
+ r <- catch
+ (unblock (thing a))
+ (\e -> do { after a; throw e })
+ after a
+ return r
+ )
+
+-- finally is an instance of bracket, but it's quite common
+-- so we give the specialised version for efficiency.
+finally :: IO a -> IO b -> IO a
+a `finally` sequel =
+ block (do
+ r <- catch
+ (unblock a)
+ (\e -> do { sequel; throw e })
+ sequel
+ return r
+ )
+
+bracket_ :: IO a -> IO b -> IO c -> IO c
+bracket_ before after thing = bracket before (const after) (const thing)