Implement tryAtomicReadMVar.
[packages/base.git] / GHC / Exception.lhs
1 \begin{code}
2 {-# LANGUAGE Trustworthy #-}
3 {-# LANGUAGE NoImplicitPrelude
4            , ExistentialQuantification
5            , MagicHash
6            , DeriveDataTypeable
7   #-}
8 {-# OPTIONS_HADDOCK hide #-}
9
10 -----------------------------------------------------------------------------
11 -- |
12 -- Module      :  GHC.Exception
13 -- Copyright   :  (c) The University of Glasgow, 1998-2002
14 -- License     :  see libraries/base/LICENSE
15 -- 
16 -- Maintainer  :  cvs-ghc@haskell.org
17 -- Stability   :  internal
18 -- Portability :  non-portable (GHC extensions)
19 --
20 -- Exceptions and exception-handling functions.
21 -- 
22 -----------------------------------------------------------------------------
23
24 -- #hide
25 module GHC.Exception
26        ( Exception(..)    -- Class
27        , throw
28        , SomeException(..), ErrorCall(..), ArithException(..)
29        , divZeroException, overflowException, ratioZeroDenomException
30        , errorCallException
31        ) where
32
33 import Data.Maybe
34 import Data.Typeable (Typeable, cast)
35    -- loop: Data.Typeable -> GHC.Err -> GHC.Exception
36 import GHC.Base
37 import GHC.Show
38 \end{code}
39
40 %*********************************************************
41 %*                                                      *
42 \subsection{Exceptions}
43 %*                                                      *
44 %*********************************************************
45
46 \begin{code}
47 {- |
48 The @SomeException@ type is the root of the exception type hierarchy.
49 When an exception of type @e@ is thrown, behind the scenes it is
50 encapsulated in a @SomeException@.
51 -}
52 data SomeException = forall e . Exception e => SomeException e
53     deriving Typeable
54
55 instance Show SomeException where
56     showsPrec p (SomeException e) = showsPrec p e
57
58 {- |
59 Any type that you wish to throw or catch as an exception must be an
60 instance of the @Exception@ class. The simplest case is a new exception
61 type directly below the root:
62
63 > data MyException = ThisException | ThatException
64 >     deriving (Show, Typeable)
65 >
66 > instance Exception MyException
67
68 The default method definitions in the @Exception@ class do what we need
69 in this case. You can now throw and catch @ThisException@ and
70 @ThatException@ as exceptions:
71
72 @
73 *Main> throw ThisException \`catch\` \\e -> putStrLn (\"Caught \" ++ show (e :: MyException))
74 Caught ThisException
75 @
76
77 In more complicated examples, you may wish to define a whole hierarchy
78 of exceptions:
79
80 > ---------------------------------------------------------------------
81 > -- Make the root exception type for all the exceptions in a compiler
82 >
83 > data SomeCompilerException = forall e . Exception e => SomeCompilerException e
84 >     deriving Typeable
85 >
86 > instance Show SomeCompilerException where
87 >     show (SomeCompilerException e) = show e
88 >
89 > instance Exception SomeCompilerException
90 >
91 > compilerExceptionToException :: Exception e => e -> SomeException
92 > compilerExceptionToException = toException . SomeCompilerException
93 >
94 > compilerExceptionFromException :: Exception e => SomeException -> Maybe e
95 > compilerExceptionFromException x = do
96 >     SomeCompilerException a <- fromException x
97 >     cast a
98 >
99 > ---------------------------------------------------------------------
100 > -- Make a subhierarchy for exceptions in the frontend of the compiler
101 >
102 > data SomeFrontendException = forall e . Exception e => SomeFrontendException e
103 >     deriving Typeable
104 >
105 > instance Show SomeFrontendException where
106 >     show (SomeFrontendException e) = show e
107 >
108 > instance Exception SomeFrontendException where
109 >     toException = compilerExceptionToException
110 >     fromException = compilerExceptionFromException
111 >
112 > frontendExceptionToException :: Exception e => e -> SomeException
113 > frontendExceptionToException = toException . SomeFrontendException
114 >
115 > frontendExceptionFromException :: Exception e => SomeException -> Maybe e
116 > frontendExceptionFromException x = do
117 >     SomeFrontendException a <- fromException x
118 >     cast a
119 >
120 > ---------------------------------------------------------------------
121 > -- Make an exception type for a particular frontend compiler exception
122 >
123 > data MismatchedParentheses = MismatchedParentheses
124 >     deriving (Typeable, Show)
125 >
126 > instance Exception MismatchedParentheses where
127 >     toException   = frontendExceptionToException
128 >     fromException = frontendExceptionFromException
129
130 We can now catch a @MismatchedParentheses@ exception as
131 @MismatchedParentheses@, @SomeFrontendException@ or
132 @SomeCompilerException@, but not other types, e.g. @IOException@:
133
134 @
135 *Main> throw MismatchedParentheses `catch` \e -> putStrLn (\"Caught \" ++ show (e :: MismatchedParentheses))
136 Caught MismatchedParentheses
137 *Main> throw MismatchedParentheses `catch` \e -> putStrLn (\"Caught \" ++ show (e :: SomeFrontendException))
138 Caught MismatchedParentheses
139 *Main> throw MismatchedParentheses `catch` \e -> putStrLn (\"Caught \" ++ show (e :: SomeCompilerException))
140 Caught MismatchedParentheses
141 *Main> throw MismatchedParentheses `catch` \e -> putStrLn (\"Caught \" ++ show (e :: IOException))
142 *** Exception: MismatchedParentheses
143 @
144
145 -}
146 class (Typeable e, Show e) => Exception e where
147     toException   :: e -> SomeException
148     fromException :: SomeException -> Maybe e
149
150     toException = SomeException
151     fromException (SomeException e) = cast e
152
153 instance Exception SomeException where
154     toException se = se
155     fromException = Just
156 \end{code}
157
158 %*********************************************************
159 %*                                                      *
160 \subsection{Primitive throw}
161 %*                                                      *
162 %*********************************************************
163
164 \begin{code}
165 -- | Throw an exception.  Exceptions may be thrown from purely
166 -- functional code, but may only be caught within the 'IO' monad.
167 throw :: Exception e => e -> a
168 throw e = raise# (toException e)
169 \end{code}
170
171 \begin{code}
172 -- |This is thrown when the user calls 'error'. The @String@ is the
173 -- argument given to 'error'.
174 newtype ErrorCall = ErrorCall String
175     deriving (Eq, Ord, Typeable)
176
177 instance Exception ErrorCall
178
179 instance Show ErrorCall where
180     showsPrec _ (ErrorCall err) = showString err
181
182 errorCallException :: String -> SomeException
183 errorCallException s = toException (ErrorCall s)
184
185 -----
186
187 -- |Arithmetic exceptions.
188 data ArithException
189   = Overflow
190   | Underflow
191   | LossOfPrecision
192   | DivideByZero
193   | Denormal
194   | RatioZeroDenominator
195   deriving (Eq, Ord, Typeable)
196
197 divZeroException, overflowException, ratioZeroDenomException  :: SomeException
198 divZeroException        = toException DivideByZero
199 overflowException       = toException Overflow
200 ratioZeroDenomException = toException RatioZeroDenominator
201
202 instance Exception ArithException
203
204 instance Show ArithException where
205   showsPrec _ Overflow        = showString "arithmetic overflow"
206   showsPrec _ Underflow       = showString "arithmetic underflow"
207   showsPrec _ LossOfPrecision = showString "loss of precision"
208   showsPrec _ DivideByZero    = showString "divide by zero"
209   showsPrec _ Denormal        = showString "denormal"
210   showsPrec _ RatioZeroDenominator = showString "Ratio has zero denominator"
211 \end{code}