2 % (c) The AQUA Project, Glasgow University, 1994-1996
5 \section[IOBase]{Module @IOBase@}
7 Definitions for the @IO@ monad and its friends. Everything is exported
8 concretely; the @IO@ module itself exports abstractly.
13 {-# OPTIONS -fno-implicit-prelude #-}
20 import PackedString ( unpackCString )
24 infixr 1 `thenIO_Prim`
27 %*********************************************************
29 \subsection{The @IO@ monad}
31 %*********************************************************
34 newtype IO a = IO (PrimIO (Either IOError a))
36 instance Functor IO where
37 map f x = x >>= (return . f)
39 instance Monad IO where
40 {- No inlining for now... until we can inline some of the
41 imports, like $, these functions are pretty big.
46 m >> k = m >>= \ _ -> k
47 return x = IO $ ST $ \ s@(S# _) -> (Right x, s)
51 let (r, new_s) = m s in
53 Left err -> (Left err, new_s)
54 Right x -> case (k x) of { IO (ST k2) ->
57 fixIO :: (a -> IO a) -> IO a
58 -- not required but worth having around
60 fixIO k = IO $ ST $ \ s ->
62 (IO (ST k_loop)) = k loop
64 (Right loop, _) = result
68 fail :: IOError -> IO a
69 fail err = IO $ ST $ \ s -> (Left err, s)
71 userError :: String -> IOError
72 userError str = UserError str
74 catch :: IO a -> (IOError -> IO a) -> IO a
75 catch (IO (ST m)) k = IO $ ST $ \ s ->
76 case (m s) of { (r, new_s) ->
79 Left err -> case (k err) of { IO (ST k_err) ->
82 instance Show (IO a) where
83 showsPrec p f = showString "<<IO action>>"
84 showList = showList__ (showsPrec 0)
87 %*********************************************************
89 \subsection{Coercions to @ST@ and @PrimIO@}
91 %*********************************************************
94 stToIO :: ST RealWorld a -> IO a
95 primIOToIO :: PrimIO a -> IO a
96 ioToST :: IO a -> ST RealWorld a
97 ioToPrimIO :: IO a -> PrimIO a
99 primIOToIO = stToIO -- for backwards compatibility
102 stToIO (ST m) = IO $ ST $ \ s ->
103 case (m s) of { (r, new_s) ->
106 ioToST (IO (ST io)) = ST $ \ s ->
107 case (io s) of { (r, new_s) ->
109 Right a -> (a, new_s)
110 Left e -> error ("I/O Error (ioToST): " ++ showsPrec 0 e "\n")
114 @thenIO_Prim@ is a useful little number for doing _ccall_s in IO-land:
117 thenIO_Prim :: PrimIO a -> (a -> IO b) -> IO b
118 {-# INLINE thenIO_Prim #-}
120 thenIO_Prim (ST m) k = IO $ ST $ \ s ->
121 case (m s) of { (m_res, new_s) ->
122 case (k m_res) of { (IO (ST k_m_res)) ->
127 %*********************************************************
129 \subsection{Error/trace-ish functions}
131 %*********************************************************
134 errorIO :: PrimIO () -> a
137 = case (errorIO# io) of
140 bottom = bottom -- Never evaluated
142 -- error stops execution and displays an error message
144 error s = error__ ( \ x -> _ccall_ ErrorHdrHook x ) s
146 error__ :: (Addr{-FILE *-} -> PrimIO ()) -> String -> a
149 #ifdef __PARALLEL_HASKELL__
150 = errorIO (msg_hdr sTDERR{-msg hdr-} >>
151 _ccall_ fflush sTDERR >>
153 _ccall_ fflush sTDERR >>
154 _ccall_ stg_exit (1::Int)
157 = errorIO (msg_hdr sTDERR{-msg hdr-} >>
158 _ccall_ fflush sTDERR >>
160 _ccall_ fflush sTDERR >>
161 _ccall_ getErrorHandler >>= \ errorHandler ->
162 if errorHandler == (-1::Int) then
163 _ccall_ stg_exit (1::Int)
165 _casm_ ``%r = (StgStablePtr)(%0);'' errorHandler
167 _ccall_ decrementErrorCount >>= \ () ->
168 deRefStablePtr osptr >>= \ oact ->
171 #endif {- !parallel -}
173 sTDERR = (``stderr'' :: Addr)
177 {-# GENERATE_SPECS _trace a #-}
178 trace :: String -> a -> a
181 = unsafePerformPrimIO (
182 ((_ccall_ PreTraceHook sTDERR{-msg-}):: PrimIO ()) >>
183 fputs sTDERR string >>
184 ((_ccall_ PostTraceHook sTDERR{-msg-}):: PrimIO ()) >>
187 sTDERR = (``stderr'' :: Addr)
191 %*********************************************************
193 \subsection{Utility functions}
195 %*********************************************************
197 The construct $try comp$ exposes errors which occur within a
198 computation, and which are not fully handled. It always succeeds.
199 This one didn't make it into the 1.3 defn
202 tryIO :: IO a -> IO (Either IOError a)
203 tryIO p = catch (p >>= (return . Right)) (return . Left)
206 I'm not sure why this little function is here...
209 fputs :: Addr{-FILE*-} -> String -> PrimIO Bool
211 fputs stream [] = return True
213 fputs stream (c : cs)
214 = _ccall_ stg_putc c stream >> -- stg_putc expands to putc
215 fputs stream cs -- (just does some casting stream)
219 %*********************************************************
221 \subsection{Type @IOError@}
223 %*********************************************************
227 = AlreadyExists String
228 | HardwareFault String
229 | IllegalOperation String
230 | InappropriateType String
232 | InvalidArgument String
235 | PermissionDenied String
236 | ProtocolError String
237 | ResourceBusy String
238 | ResourceExhausted String
239 | ResourceVanished String
242 | UnsatisfiedConstraints String
243 | UnsupportedOperation String
247 instance Eq IOError where
248 -- I don't know what the (pointless) idea is here,
249 -- presumably just compare them by their tags (WDP)
250 a == b = tag a == tag b
252 tag (AlreadyExists _) = (1::Int)
253 tag (HardwareFault _) = 2
254 tag (IllegalOperation _) = 3
255 tag (InappropriateType _) = 4
256 tag (Interrupted _) = 5
257 tag (InvalidArgument _) = 6
258 tag (NoSuchThing _) = 7
259 tag (OtherError _) = 8
260 tag (PermissionDenied _) = 9
261 tag (ProtocolError _) = 10
262 tag (ResourceBusy _) = 11
263 tag (ResourceExhausted _) = 12
264 tag (ResourceVanished _) = 13
265 tag (SystemError _) = 14
266 tag (TimeExpired _) = 15
267 tag (UnsatisfiedConstraints _) = 16
268 tag (UnsupportedOperation _) = 17
269 tag (UserError _) = 18
273 Predicates on IOError; almost no effort made on these so far...
277 isAlreadyExistsError (AlreadyExists _) = True
278 isAlreadyExistsError _ = False
280 isAlreadyInUseError (ResourceBusy _) = True
281 isAlreadyInUseError _ = False
283 isFullError (ResourceExhausted _) = True
284 isFullError _ = False
286 isEOFError EOF = True
289 isIllegalOperation (IllegalOperation _) = True
290 isIllegalOperation _ = False
292 isPermissionError (PermissionDenied _) = True
293 isPermissionError _ = False
295 isUserError (UserError s) = Just s
296 isUserError _ = Nothing
302 instance Show IOError where
303 showsPrec p (AlreadyExists s) = show2 "AlreadyExists: " s
304 showsPrec p (HardwareFault s) = show2 "HardwareFault: " s
305 showsPrec p (IllegalOperation s) = show2 "IllegalOperation: " s
306 showsPrec p (InappropriateType s) = show2 "InappropriateType: " s
307 showsPrec p (Interrupted s) = show2 "Interrupted: " s
308 showsPrec p (InvalidArgument s) = show2 "InvalidArgument: " s
309 showsPrec p (NoSuchThing s) = show2 "NoSuchThing: " s
310 showsPrec p (OtherError s) = show2 "OtherError: " s
311 showsPrec p (PermissionDenied s) = show2 "PermissionDenied: " s
312 showsPrec p (ProtocolError s) = show2 "ProtocolError: " s
313 showsPrec p (ResourceBusy s) = show2 "ResourceBusy: " s
314 showsPrec p (ResourceExhausted s) = show2 "ResourceExhausted: " s
315 showsPrec p (ResourceVanished s) = show2 "ResourceVanished: " s
316 showsPrec p (SystemError s) = show2 "SystemError: " s
317 showsPrec p (TimeExpired s) = show2 "TimeExpired: " s
318 showsPrec p (UnsatisfiedConstraints s) = show2 "UnsatisfiedConstraints: " s
319 showsPrec p (UnsupportedOperation s)= show2 "UnsupportedOperation: " s
320 showsPrec p (UserError s) = showString s
321 showsPrec p EOF = showString "EOF"
323 show2 x y = showString x . showString y
327 The @String@ part of an @IOError@ is platform-dependent. However, to
328 provide a uniform mechanism for distinguishing among errors within
329 these broad categories, each platform-specific standard shall specify
330 the exact strings to be used for particular errors. For errors not
331 explicitly mentioned in the standard, any descriptive string may be
334 SOF 4/96 - added argument to indicate function that flagged error
336 constructErrorAndFail :: String -> IO a
337 constructError :: String -> PrimIO IOError
339 constructErrorAndFail call_site
340 = stToIO (constructError call_site) >>= \ io_error ->
343 constructError call_site
344 = _casm_ ``%r = ghc_errtype;'' >>= \ (I# errtype#) ->
345 _casm_ ``%r = ghc_errstr;'' >>= \ str ->
347 msg = call_site ++ ':' : ' ' : unpackCString str
349 return (case errtype# of
350 ERR_ALREADYEXISTS# -> AlreadyExists msg
351 ERR_HARDWAREFAULT# -> HardwareFault msg
352 ERR_ILLEGALOPERATION# -> IllegalOperation msg
353 ERR_INAPPROPRIATETYPE# -> InappropriateType msg
354 ERR_INTERRUPTED# -> Interrupted msg
355 ERR_INVALIDARGUMENT# -> InvalidArgument msg
356 ERR_NOSUCHTHING# -> NoSuchThing msg
357 ERR_OTHERERROR# -> OtherError msg
358 ERR_PERMISSIONDENIED# -> PermissionDenied msg
359 ERR_PROTOCOLERROR# -> ProtocolError msg
360 ERR_RESOURCEBUSY# -> ResourceBusy msg
361 ERR_RESOURCEEXHAUSTED# -> ResourceExhausted msg
362 ERR_RESOURCEVANISHED# -> ResourceVanished msg
363 ERR_SYSTEMERROR# -> SystemError msg
364 ERR_TIMEEXPIRED# -> TimeExpired msg
365 ERR_UNSATISFIEDCONSTRAINTS# -> UnsatisfiedConstraints msg
366 ERR_UNSUPPORTEDOPERATION# -> UnsupportedOperation msg
368 _ -> OtherError "bad error construct"