1 % ------------------------------------------------------------------------------
2 % $Id: PrelIOBase.lhs,v 1.38 2001/05/18 16:54:05 simonmar Exp $
4 % (c) The University of Glasgow, 1994-2001
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
19 import PrelNum -- To get fromInteger etc, needed because of -fno-implicit-prelude
20 import PrelMaybe ( Maybe(..) )
25 -- ---------------------------------------------------------------------------
29 The IO Monad is just an instance of the ST monad, where the state is
30 the real world. We use the exception mechanism (in PrelException) to
31 implement IO exceptions.
33 NOTE: The IO representation is deeply wired in to various parts of the
34 system. The following list may or may not be exhaustive:
36 Compiler - types of various primitives in PrimOp.lhs
38 RTS - forceIO (StgMiscClosures.hc)
39 - catchzh_fast, (un)?blockAsyncExceptionszh_fast, raisezh_fast
41 - raiseAsync (Schedule.c)
43 Prelude - PrelIOBase.lhs, and several other places including
46 Libraries - parts of hslibs/lang.
51 newtype IO a = IO (State# RealWorld -> (# State# RealWorld, a #))
53 unIO :: IO a -> (State# RealWorld -> (# State# RealWorld, a #))
56 instance Functor IO where
57 fmap f x = x >>= (return . f)
59 instance Monad IO where
63 m >> k = m >>= \ _ -> k
69 failIO :: String -> IO a
70 failIO s = ioError (userError s)
72 liftIO :: IO a -> State# RealWorld -> STret RealWorld a
73 liftIO (IO m) = \s -> case m s of (# s', r #) -> STret s' r
75 bindIO :: IO a -> (a -> IO b) -> IO b
76 bindIO (IO m) k = IO ( \ s ->
78 (# new_s, a #) -> unIO (k a) new_s
82 returnIO x = IO (\ s -> (# s, x #))
84 -- ---------------------------------------------------------------------------
85 -- Coercions between IO and ST
87 --stToIO :: (forall s. ST s a) -> IO a
88 stToIO :: ST RealWorld a -> IO a
91 ioToST :: IO a -> ST RealWorld a
92 ioToST (IO m) = (ST m)
94 -- ---------------------------------------------------------------------------
95 -- Unsafe IO operations
97 {-# NOINLINE unsafePerformIO #-}
98 unsafePerformIO :: IO a -> a
99 unsafePerformIO (IO m) = case m realWorld# of (# _, r #) -> r
101 {-# NOINLINE unsafeInterleaveIO #-}
102 unsafeInterleaveIO :: IO a -> IO a
103 unsafeInterleaveIO (IO m)
105 r = case m s of (# _, res #) -> res
109 -- ---------------------------------------------------------------------------
112 data MVar a = MVar (MVar# RealWorld a)
114 -- pull in Eq (Mvar a) too, to avoid PrelConc being an orphan-instance module
115 instance Eq (MVar a) where
116 (MVar mvar1#) == (MVar mvar2#) = sameMVar# mvar1# mvar2#
118 -- A Handle is represented by (a reference to) a record
119 -- containing the state of the I/O port/device. We record
120 -- the following pieces of info:
122 -- * type (read,write,closed etc.)
123 -- * the underlying file descriptor
125 -- * buffer, and spare buffers
126 -- * user-friendly name (usually the
127 -- FilePath used when IO.openFile was called)
129 -- Note: when a Handle is garbage collected, we want to flush its buffer
130 -- and close the OS file handle, so as to free up a (precious) resource.
133 = FileHandle -- A normal handle to a file
136 | DuplexHandle -- A handle to a read/write stream
137 !(MVar Handle__) -- The read side
138 !(MVar Handle__) -- The write side
141 -- * A 'FileHandle' is seekable. A 'DuplexHandle' may or may not be
144 instance Eq Handle where
145 (FileHandle h1) == (FileHandle h2) = h1 == h2
146 (DuplexHandle h1 _) == (DuplexHandle h2 _) = h1 == h2
149 type FD = Int -- XXX ToDo: should be CInt
154 haType :: HandleType,
155 haBufferMode :: BufferMode,
156 haFilePath :: FilePath,
157 haBuffer :: !(IORef Buffer),
158 haBuffers :: !(IORef BufferList)
161 -- ---------------------------------------------------------------------------
164 -- The buffer is represented by a mutable variable containing a
165 -- record, where the record contains the raw buffer and the start/end
166 -- points of the filled portion. We use a mutable variable so that
167 -- the common operation of writing (or reading) some data from (to)
168 -- the buffer doesn't need to modify, and hence copy, the handle
169 -- itself, it just updates the buffer.
171 -- There will be some allocation involved in a simple hPutChar in
172 -- order to create the new Buffer structure (below), but this is
173 -- relatively small, and this only has to be done once per write
176 -- The buffer contains its size - we could also get the size by
177 -- calling sizeOfMutableByteArray# on the raw buffer, but that tends
178 -- to be rounded up to the nearest Word.
180 type RawBuffer = MutableByteArray# RealWorld
182 -- INVARIANTS on a Buffer:
184 -- * A handle *always* has a buffer, even if it is only 1 character long
185 -- (an unbuffered handle needs a 1 character buffer in order to support
186 -- hLookAhead and hIsEOF).
188 -- * if r == w, then r == 0 && w == 0
189 -- * if state == WriteBuffer, then r == 0
190 -- * a write buffer is never full. If an operation
191 -- fills up the buffer, it will always flush it before
193 -- * a read buffer may be full as a result of hLookAhead. In normal
194 -- operation, a read buffer always has at least one character of space.
202 bufState :: BufferState
205 data BufferState = ReadBuffer | WriteBuffer deriving (Eq)
207 -- we keep a few spare buffers around in a handle to avoid allocating
208 -- a new one for each hPutStr. These buffers are *guaranteed* to be the
209 -- same size as the main buffer.
212 | BufferListCons RawBuffer BufferList
215 bufferIsWritable :: Buffer -> Bool
216 bufferIsWritable Buffer{ bufState=WriteBuffer } = True
217 bufferIsWritable _other = False
219 bufferEmpty :: Buffer -> Bool
220 bufferEmpty Buffer{ bufRPtr=r, bufWPtr=w } | r == w = True
221 bufferEmpty _other = False
223 -- only makes sense for a write buffer
224 bufferFull :: Buffer -> Bool
225 bufferFull b@Buffer{ bufWPtr=w } = w >= bufSize b
227 -- Internally, we classify handles as being one
237 | ReadSideHandle !(MVar Handle__) -- read side of a duplex handle
239 -- File names are specified using @FilePath@, a OS-dependent
240 -- string that (hopefully, I guess) maps to an accessible file/object.
242 type FilePath = String
244 -- ---------------------------------------------------------------------------
247 -- Three kinds of buffering are supported: line-buffering,
248 -- block-buffering or no-buffering. These modes have the following
249 -- effects. For output, items are written out from the internal
250 -- buffer according to the buffer mode:
252 -- * line-buffering the entire output buffer is written
253 -- out whenever a newline is output, the output buffer overflows,
254 -- a flush is issued, or the handle is closed.
256 -- * block-buffering the entire output buffer is written out whenever
257 -- it overflows, a flush is issued, or the handle
260 -- * no-buffering output is written immediately, and never stored
261 -- in the output buffer.
263 -- The output buffer is emptied as soon as it has been written out.
265 -- Similarly, input occurs according to the buffer mode for handle {\em hdl}.
267 -- * line-buffering when the input buffer for the handle is not empty,
268 -- the next item is obtained from the buffer;
269 -- otherwise, when the input buffer is empty,
270 -- characters up to and including the next newline
271 -- character are read into the buffer. No characters
272 -- are available until the newline character is
275 -- * block-buffering when the input buffer for the handle becomes empty,
276 -- the next block of data is read into this buffer.
278 -- * no-buffering the next input item is read and returned.
280 -- For most implementations, physical files will normally be block-buffered
281 -- and terminals will normally be line-buffered. (the IO interface provides
282 -- operations for changing the default buffering of a handle tho.)
285 = NoBuffering | LineBuffering | BlockBuffering (Maybe Int)
286 deriving (Eq, Ord, Show)
287 {- Read instance defined in IO. -}
289 -- ---------------------------------------------------------------------------
292 newtype IORef a = IORef (STRef RealWorld a) deriving Eq
294 newIORef :: a -> IO (IORef a)
295 newIORef v = stToIO (newSTRef v) >>= \ var -> return (IORef var)
297 readIORef :: IORef a -> IO a
298 readIORef (IORef var) = stToIO (readSTRef var)
300 writeIORef :: IORef a -> a -> IO ()
301 writeIORef (IORef var) v = stToIO (writeSTRef var v)
303 modifyIORef :: IORef a -> (a -> a) -> IO ()
304 modifyIORef ref f = readIORef ref >>= \x -> writeIORef ref (f x)
306 -- deprecated, use modifyIORef
307 updateIORef :: IORef a -> (a -> a) -> IO ()
308 updateIORef = modifyIORef
310 -- ---------------------------------------------------------------------------
311 -- Show instance for Handles
313 -- handle types are 'show'n when printing error msgs, so
314 -- we provide a more user-friendly Show instance for it
315 -- than the derived one.
317 instance Show HandleType where
320 ClosedHandle -> showString "closed"
321 SemiClosedHandle -> showString "semi-closed"
322 ReadHandle -> showString "readable"
323 WriteHandle -> showString "writable"
324 AppendHandle -> showString "writable (append)"
325 ReadWriteHandle -> showString "read-writable"
326 ReadSideHandle _ -> showString "read-writable (duplex)"
328 instance Show Handle where
329 showsPrec p (FileHandle h) = showHandle p h
330 showsPrec p (DuplexHandle h _) = showHandle p h
334 -- (Big) SIGH: unfolded defn of takeMVar to avoid
335 -- an (oh-so) unfortunate module loop with PrelConc.
336 hdl_ = unsafePerformIO (IO $ \ s# ->
337 case h of { MVar h# ->
338 case takeMVar# h# s# of { (# s2# , r #) ->
339 case putMVar# h# r s2# of { s3# ->
343 showHdl (haType hdl_)
344 (showString "loc=" . showString (haFilePath hdl_) . showChar ',' .
345 showString "type=" . showsPrec p (haType hdl_) . showChar ',' .
346 showString "buffering=" . showBufMode (unsafePerformIO (readIORef (haBuffer hdl_))) (haBufferMode hdl_) . showString "}" )
348 showHdl :: HandleType -> ShowS -> ShowS
351 ClosedHandle -> showsPrec p ht . showString "}"
354 showBufMode :: Buffer -> BufferMode -> ShowS
355 showBufMode buf bmo =
357 NoBuffering -> showString "none"
358 LineBuffering -> showString "line"
359 BlockBuffering (Just n) -> showString "block " . showParen True (showsPrec p n)
360 BlockBuffering Nothing -> showString "block " . showParen True (showsPrec p def)
365 -- ------------------------------------------------------------------------
366 -- Exception datatype and operations
369 = IOException IOException -- IO exceptions
370 | ArithException ArithException -- Arithmetic exceptions
371 | ArrayException ArrayException -- Array-related exceptions
372 | ErrorCall String -- Calls to 'error'
373 | NoMethodError String -- A non-existent method was invoked
374 | PatternMatchFail String -- A pattern match / guard failure
375 | RecSelError String -- Selecting a non-existent field
376 | RecConError String -- Field missing in record construction
377 | RecUpdError String -- Record doesn't contain updated field
378 | AssertionFailed String -- Assertions
379 | DynException Dynamic -- Dynamic exceptions
380 | AsyncException AsyncException -- Externally generated errors
381 | BlockedOnDeadMVar -- Blocking on a dead MVar
400 = IndexOutOfBounds String -- out-of-range array access
401 | UndefinedElement String -- evaluating an undefined element
404 stackOverflow, heapOverflow :: Exception -- for the RTS
405 stackOverflow = AsyncException StackOverflow
406 heapOverflow = AsyncException HeapOverflow
408 instance Show ArithException where
409 showsPrec _ Overflow = showString "arithmetic overflow"
410 showsPrec _ Underflow = showString "arithmetic underflow"
411 showsPrec _ LossOfPrecision = showString "loss of precision"
412 showsPrec _ DivideByZero = showString "divide by zero"
413 showsPrec _ Denormal = showString "denormal"
415 instance Show AsyncException where
416 showsPrec _ StackOverflow = showString "stack overflow"
417 showsPrec _ HeapOverflow = showString "heap overflow"
418 showsPrec _ ThreadKilled = showString "thread killed"
420 instance Show ArrayException where
421 showsPrec _ (IndexOutOfBounds s)
422 = showString "array index out of range"
423 . (if not (null s) then showString ": " . showString s
425 showsPrec _ (UndefinedElement s)
426 = showString "undefined array element"
427 . (if not (null s) then showString ": " . showString s
430 instance Show Exception where
431 showsPrec _ (IOException err) = shows err
432 showsPrec _ (ArithException err) = shows err
433 showsPrec _ (ArrayException err) = shows err
434 showsPrec _ (ErrorCall err) = showString err
435 showsPrec _ (NoMethodError err) = showString err
436 showsPrec _ (PatternMatchFail err) = showString err
437 showsPrec _ (RecSelError err) = showString err
438 showsPrec _ (RecConError err) = showString err
439 showsPrec _ (RecUpdError err) = showString err
440 showsPrec _ (AssertionFailed err) = showString err
441 showsPrec _ (DynException _err) = showString "unknown exception"
442 showsPrec _ (AsyncException e) = shows e
443 showsPrec _ (BlockedOnDeadMVar) = showString "thread blocked indefinitely"
444 showsPrec _ (NonTermination) = showString "<<loop>>"
445 showsPrec _ (UserError err) = showString err
447 -- --------------------------------------------------------------------------
450 throw :: Exception -> a
451 throw exception = raise# exception
453 ioError :: Exception -> IO a
454 ioError err = IO $ \s -> throw err s
456 ioException :: IOException -> IO a
457 ioException err = IO $ \s -> throw (IOException err) s
459 -- ---------------------------------------------------------------------------
462 -- A value @IOError@ encode errors occurred in the @IO@ monad.
463 -- An @IOError@ records a more specific error type, a descriptive
464 -- string and maybe the handle that was used when the error was
467 type IOError = Exception
471 (Maybe Handle) -- the handle used by the action flagging the
473 IOErrorType -- what it was.
475 String -- error type specific information.
476 (Maybe FilePath) -- filename the error is related to.
478 instance Eq IOException where
479 (IOError h1 e1 loc1 str1 fn1) == (IOError h2 e2 loc2 str2 fn2) =
480 e1==e2 && str1==str2 && h1==h2 && loc1==loc2 && fn1==fn2
483 = AlreadyExists | HardwareFault
484 | IllegalOperation | InappropriateType
485 | Interrupted | InvalidArgument
486 | NoSuchThing | OtherError
487 | PermissionDenied | ProtocolError
488 | ResourceBusy | ResourceExhausted
489 | ResourceVanished | SystemError
490 | TimeExpired | UnsatisfiedConstraints
491 | UnsupportedOperation
493 #if defined(cygwin32_TARGET_OS) || defined(mingw32_TARGET_OS)
494 | ComError Int -- HRESULT
498 instance Show IOErrorType where
502 AlreadyExists -> "already exists"
503 HardwareFault -> "hardware fault"
504 IllegalOperation -> "illegal operation"
505 InappropriateType -> "inappropriate type"
506 Interrupted -> "interrupted"
507 InvalidArgument -> "invalid argument"
508 NoSuchThing -> "does not exist"
509 OtherError -> "failed"
510 PermissionDenied -> "permission denied"
511 ProtocolError -> "protocol error"
512 ResourceBusy -> "resource busy"
513 ResourceExhausted -> "resource exhausted"
514 ResourceVanished -> "resource vanished"
515 SystemError -> "system error"
516 TimeExpired -> "timeout"
517 UnsatisfiedConstraints -> "unsatisified constraints" -- ultra-precise!
518 UnsupportedOperation -> "unsupported operation"
520 #if defined(cygwin32_TARGET_OS) || defined(mingw32_TARGET_OS)
521 ComError _ -> "COM error"
526 userError :: String -> IOError
527 userError str = UserError str
529 -- ---------------------------------------------------------------------------
530 -- Predicates on IOError
532 isAlreadyExistsError :: IOError -> Bool
533 isAlreadyExistsError (IOException (IOError _ AlreadyExists _ _ _)) = True
534 isAlreadyExistsError _ = False
536 isAlreadyInUseError :: IOError -> Bool
537 isAlreadyInUseError (IOException (IOError _ ResourceBusy _ _ _)) = True
538 isAlreadyInUseError _ = False
540 isFullError :: IOError -> Bool
541 isFullError (IOException (IOError _ ResourceExhausted _ _ _)) = True
542 isFullError _ = False
544 isEOFError :: IOError -> Bool
545 isEOFError (IOException (IOError _ EOF _ _ _)) = True
548 isIllegalOperation :: IOError -> Bool
549 isIllegalOperation (IOException (IOError _ IllegalOperation _ _ _)) = True
550 isIllegalOperation _ = False
552 isPermissionError :: IOError -> Bool
553 isPermissionError (IOException (IOError _ PermissionDenied _ _ _)) = True
554 isPermissionError _ = False
556 isDoesNotExistError :: IOError -> Bool
557 isDoesNotExistError (IOException (IOError _ NoSuchThing _ _ _)) = True
558 isDoesNotExistError _ = False
560 isUserError :: IOError -> Bool
561 isUserError (UserError _) = True
562 isUserError _ = False
564 -- ---------------------------------------------------------------------------
567 instance Show IOException where
568 showsPrec p (IOError hdl iot loc s fn) =
572 _ -> showString "\nAction: " . showString loc) .
575 Just h -> showString "\nHandle: " . showsPrec p h) .
578 _ -> showString "\nReason: " . showString s) .
581 Just name -> showString "\nFile: " . showString name)