2 % (c) The AQUA Project, Glasgow University, 1994-1996
5 \section[PrelIOBase]{Module @PrelIOBase@}
7 Definitions for the @IO@ monad and its friends. Everything is exported
8 concretely; the @IO@ module itself exports abstractly.
11 {-# OPTIONS -fno-implicit-prelude #-}
14 module PrelIOBase where
16 import {-# SOURCE #-} PrelErr ( error )
21 import PrelPack ( unpackCString )
23 import PrelArr ( ByteArray(..), MutableVar )
28 %*********************************************************
30 \subsection{The @IO@ monad}
32 %*********************************************************
34 IO is no longer built on top of PrimIO (which used to be a specialised
35 version of the ST monad), instead it is now has its own type. This is
36 purely for efficiency purposes, since we get to remove several levels
37 of lifting in the type of the monad.
40 newtype IO a = IO (State# RealWorld -> IOResult a)
45 data IOResult a = IOok (State# RealWorld) a
46 | IOfail (State# RealWorld) IOError
48 instance Functor IO where
49 map f x = x >>= (return . f)
51 instance Monad IO where
55 m >> k = m >>= \ _ -> k
56 return x = IO $ \ s -> IOok s x
61 IOfail new_s err -> IOfail new_s err
62 IOok new_s a -> unIO (k a) new_s
64 fixIO :: (a -> IO a) -> IO a
65 -- not required but worth having around
75 fail :: IOError -> IO a
76 fail err = IO $ \ s -> IOfail s err
78 userError :: String -> IOError
79 userError str = IOError Nothing UserError str
81 catch :: IO a -> (IOError -> IO a) -> IO a
82 catch (IO m) k = IO $ \ s ->
84 IOok new_s a -> IOok new_s a
85 IOfail new_s e -> unIO (k e) new_s
87 instance Show (IO a) where
88 showsPrec p f = showString "<<IO action>>"
89 showList = showList__ (showsPrec 0)
92 %*********************************************************
94 \subsection{Coercions to @ST@}
96 %*********************************************************
99 stToIO :: ST RealWorld a -> IO a
100 stToIO (ST m) = IO $ \ s -> case (m s) of STret new_s r -> IOok new_s r
102 ioToST :: IO a -> ST RealWorld a
103 ioToST (IO io) = ST $ \ s ->
105 IOok new_s a -> STret new_s a
106 IOfail new_s e -> error ("I/O Error (ioToST): " ++ showsPrec 0 e "\n")
109 %*********************************************************
111 \subsection{Utility functions}
113 %*********************************************************
115 I'm not sure why this little function is here...
118 fputs :: Addr{-FILE*-} -> String -> IO Bool
120 fputs stream [] = return True
122 fputs stream (c : cs)
123 = _ccall_ stg_putc c stream >> -- stg_putc expands to putc
124 fputs stream cs -- (just does some casting stream)
128 %*********************************************************
130 \subsection{Type @IOError@}
132 %*********************************************************
134 A value @IOError@ encode errors occurred in the @IO@ monad.
135 An @IOError@ records a more specific error type, a descriptive
136 string and maybe the handle that was used when the error was
142 (Maybe Handle) -- the handle used by the action flagging the
144 IOErrorType -- what it was.
145 String -- error type specific information.
149 = AlreadyExists | HardwareFault
150 | IllegalOperation | InappropriateType
151 | Interrupted | InvalidArgument
152 | NoSuchThing | OtherError
153 | PermissionDenied | ProtocolError
154 | ResourceBusy | ResourceExhausted
155 | ResourceVanished | SystemError
156 | TimeExpired | UnsatisfiedConstraints
157 | UnsupportedOperation | UserError
163 Predicates on IOError; little effort made on these so far...
167 isAlreadyExistsError (IOError _ AlreadyExists _) = True
168 isAlreadyExistsError _ = False
170 isAlreadyInUseError (IOError _ ResourceBusy _) = True
171 isAlreadyInUseError _ = False
173 isFullError (IOError _ ResourceExhausted _) = True
174 isFullError _ = False
176 isEOFError (IOError _ EOF _) = True
179 isIllegalOperation (IOError _ IllegalOperation _) = True
180 isIllegalOperation _ = False
182 isPermissionError (IOError _ PermissionDenied _) = True
183 isPermissionError _ = False
185 isDoesNotExistError (IOError _ NoSuchThing _) = True
186 isDoesNotExistError _ = False
188 isUserError (IOError _ UserError _) = True
189 isUserError _ = False
195 instance Show IOError where
196 showsPrec p (IOError _ UserError s) rs =
199 showsPrec p (IOError _ EOF _) rs =
202 showsPrec p (IOError _ iot s) rs =
207 _ -> showString ": " $
212 The @String@ part of an @IOError@ is platform-dependent. However, to
213 provide a uniform mechanism for distinguishing among errors within
214 these broad categories, each platform-specific standard shall specify
215 the exact strings to be used for particular errors. For errors not
216 explicitly mentioned in the standard, any descriptive string may be
220 constructErrorAndFail :: String -> IO a
221 constructErrorAndFail call_site
222 = constructError call_site >>= \ io_error ->
225 constructErrorAndFailWithInfo :: String -> String -> IO a
226 constructErrorAndFailWithInfo call_site reason
227 = constructErrorMsg call_site (Just reason) >>= \ io_error ->
232 This doesn't seem to be documented/spelled out anywhere,
235 The implementation of the IO prelude uses various C stubs
236 to do the actual interaction with the OS. The bandwidth
237 \tr{C<->Haskell} is somewhat limited, so the general strategy
238 for flaggging any errors (apart from possibly using the
239 return code of the external call), is to set the @ghc_errtype@
240 to a value that is one of the \tr{#define}s in @includes/error.h@.
241 @ghc_errstr@ holds a character string providing error-specific
245 constructError :: String -> IO IOError
246 constructError call_site = constructErrorMsg call_site Nothing
248 constructErrorMsg :: String -> Maybe String -> IO IOError
249 constructErrorMsg call_site reason =
250 _casm_ ``%r = ghc_errtype;'' >>= \ (I# errtype#) ->
251 _casm_ ``%r = ghc_errstr;'' >>= \ str ->
255 ERR_ALREADYEXISTS# -> AlreadyExists
256 ERR_HARDWAREFAULT# -> HardwareFault
257 ERR_ILLEGALOPERATION# -> IllegalOperation
258 ERR_INAPPROPRIATETYPE# -> InappropriateType
259 ERR_INTERRUPTED# -> Interrupted
260 ERR_INVALIDARGUMENT# -> InvalidArgument
261 ERR_NOSUCHTHING# -> NoSuchThing
262 ERR_OTHERERROR# -> OtherError
263 ERR_PERMISSIONDENIED# -> PermissionDenied
264 ERR_PROTOCOLERROR# -> ProtocolError
265 ERR_RESOURCEBUSY# -> ResourceBusy
266 ERR_RESOURCEEXHAUSTED# -> ResourceExhausted
267 ERR_RESOURCEVANISHED# -> ResourceVanished
268 ERR_SYSTEMERROR# -> SystemError
269 ERR_TIMEEXPIRED# -> TimeExpired
270 ERR_UNSATISFIEDCONSTRAINTS# -> UnsatisfiedConstraints
271 ERR_UNSUPPORTEDOPERATION# -> UnsupportedOperation
276 call_site ++ ':' : ' ' : unpackCString str ++
278 OtherError -> "(error code: " ++ show (I# errtype#) ++ ")"
284 return (IOError Nothing iot msg)
287 %*********************************************************
289 \subsection{Types @Handle@, @Handle__@}
291 %*********************************************************
293 The type for @Handle@ is defined rather than in @IOHandle@
294 module, as the @IOError@ type uses it..all operations over
295 a handles reside in @IOHandle@.
300 Sigh, the MVar ops in ConcBase depend on IO, the IO
301 representation here depend on MVars for handles (when
302 compiling a concurrent way). Break the cycle by having
303 the definition of MVars go here:
306 data MVar a = MVar (SynchVar# RealWorld a)
309 Double sigh - ForeignObj is needed here too to break a cycle.
311 data ForeignObj = ForeignObj ForeignObj# -- another one
313 #if defined(__CONCURRENT_HASKELL__)
314 newtype Handle = Handle (MVar Handle__)
316 newtype Handle = Handle (MutableVar RealWorld Handle__)
320 = ErrorHandle IOError
322 #ifndef __PARALLEL_HASKELL__
323 | SemiClosedHandle ForeignObj (Addr, Int)
324 | ReadHandle ForeignObj (Maybe BufferMode) Bool
325 | WriteHandle ForeignObj (Maybe BufferMode) Bool
326 | AppendHandle ForeignObj (Maybe BufferMode) Bool
327 | ReadWriteHandle ForeignObj (Maybe BufferMode) Bool
329 | SemiClosedHandle Addr (Addr, Int)
330 | ReadHandle Addr (Maybe BufferMode) Bool
331 | WriteHandle Addr (Maybe BufferMode) Bool
332 | AppendHandle Addr (Maybe BufferMode) Bool
333 | ReadWriteHandle Addr (Maybe BufferMode) Bool
336 -- Standard Instances as defined by the Report..
337 -- instance Eq Handle (defined in IO)
338 -- instance Show Handle ""
342 %*********************************************************
344 \subsection[BufferMode]{Buffering modes}
346 %*********************************************************
348 Three kinds of buffering are supported: line-buffering,
349 block-buffering or no-buffering. These modes have the following
350 effects. For output, items are written out from the internal
351 buffer according to the buffer mode:
354 \item[line-buffering] the entire output buffer is written
355 out whenever a newline is output, the output buffer overflows,
356 a flush is issued, or the handle is closed.
358 \item[block-buffering] the entire output buffer is written out whenever
359 it overflows, a flush is issued, or the handle
362 \item[no-buffering] output is written immediately, and never stored
363 in the output buffer.
366 The output buffer is emptied as soon as it has been written out.
368 Similarly, input occurs according to the buffer mode for handle {\em hdl}.
370 \item[line-buffering] when the input buffer for {\em hdl} is not empty,
371 the next item is obtained from the buffer;
372 otherwise, when the input buffer is empty,
373 characters up to and including the next newline
374 character are read into the buffer. No characters
375 are available until the newline character is
377 \item[block-buffering] when the input buffer for {\em hdl} becomes empty,
378 the next block of data is read into this buffer.
379 \item[no-buffering] the next input item is read and returned.
381 For most implementations, physical files will normally be block-buffered
382 and terminals will normally be line-buffered.
386 = NoBuffering | LineBuffering | BlockBuffering (Maybe Int)
387 deriving (Eq, Ord, Show)
388 {- Read instance defined in IO. -}
394 performGC = _ccall_GC_ StgPerformGarbageCollection
397 %*********************************************************
399 \subsection{Unsafe @IO@ operations}
401 %*********************************************************
404 {-# NOINLINE unsafePerformIO #-}
405 unsafePerformIO :: IO a -> a
406 unsafePerformIO (IO m)
407 = case m realWorld# of
409 IOfail _ e -> error ("unsafePerformIO: I/O error: " ++ show e ++ "\n")
411 {-# NOINLINE unsafeInterleaveIO #-}
412 unsafeInterleaveIO :: IO a -> IO a
413 unsafeInterleaveIO (IO m) = IO ( \ s ->
419 {-# NOINLINE trace #-}
420 trace :: String -> a -> a
423 ((_ccall_ PreTraceHook sTDERR{-msg-}):: IO ()) >>
424 fputs sTDERR string >>
425 ((_ccall_ PostTraceHook sTDERR{-msg-}):: IO ()) >>
428 sTDERR = (``stderr'' :: Addr)