1 % ------------------------------------------------------------------------------
2 % $Id: PrelIOBase.lhs,v 1.47 2002/01/29 17:12:53 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 #-}
12 module PrelIOBase where
17 import PrelNum -- To get fromInteger etc, needed because of -fno-implicit-prelude
18 import PrelMaybe ( Maybe(..) )
24 -- ---------------------------------------------------------------------------
28 The IO Monad is just an instance of the ST monad, where the state is
29 the real world. We use the exception mechanism (in PrelException) to
30 implement IO exceptions.
32 NOTE: The IO representation is deeply wired in to various parts of the
33 system. The following list may or may not be exhaustive:
35 Compiler - types of various primitives in PrimOp.lhs
37 RTS - forceIO (StgMiscClosures.hc)
38 - catchzh_fast, (un)?blockAsyncExceptionszh_fast, raisezh_fast
40 - raiseAsync (Schedule.c)
42 Prelude - PrelIOBase.lhs, and several other places including
45 Libraries - parts of hslibs/lang.
50 newtype IO a = IO (State# RealWorld -> (# State# RealWorld, a #))
52 unIO :: IO a -> (State# RealWorld -> (# State# RealWorld, a #))
55 instance Functor IO where
56 fmap f x = x >>= (return . f)
58 instance Monad IO where
62 m >> k = m >>= \ _ -> k
68 failIO :: String -> IO a
69 failIO s = ioError (userError s)
71 liftIO :: IO a -> State# RealWorld -> STret RealWorld a
72 liftIO (IO m) = \s -> case m s of (# s', r #) -> STret s' r
74 bindIO :: IO a -> (a -> IO b) -> IO b
75 bindIO (IO m) k = IO ( \ s ->
77 (# new_s, a #) -> unIO (k a) new_s
81 returnIO x = IO (\ s -> (# s, x #))
83 -- ---------------------------------------------------------------------------
84 -- Coercions between IO and ST
86 --stToIO :: (forall s. ST s a) -> IO a
87 stToIO :: ST RealWorld a -> IO a
90 ioToST :: IO a -> ST RealWorld a
91 ioToST (IO m) = (ST m)
93 -- ---------------------------------------------------------------------------
94 -- Unsafe IO operations
96 {-# NOINLINE unsafePerformIO #-}
97 unsafePerformIO :: IO a -> a
98 unsafePerformIO (IO m) = case m realWorld# of (# _, r #) -> r
100 {-# NOINLINE unsafeInterleaveIO #-}
101 unsafeInterleaveIO :: IO a -> IO a
102 unsafeInterleaveIO (IO m)
104 r = case m s of (# _, res #) -> res
108 -- ---------------------------------------------------------------------------
111 data MVar a = MVar (MVar# RealWorld a)
113 -- pull in Eq (Mvar a) too, to avoid PrelConc being an orphan-instance module
114 instance Eq (MVar a) where
115 (MVar mvar1#) == (MVar mvar2#) = sameMVar# mvar1# mvar2#
117 -- A Handle is represented by (a reference to) a record
118 -- containing the state of the I/O port/device. We record
119 -- the following pieces of info:
121 -- * type (read,write,closed etc.)
122 -- * the underlying file descriptor
124 -- * buffer, and spare buffers
125 -- * user-friendly name (usually the
126 -- FilePath used when IO.openFile was called)
128 -- Note: when a Handle is garbage collected, we want to flush its buffer
129 -- and close the OS file handle, so as to free up a (precious) resource.
132 = FileHandle -- A normal handle to a file
135 | DuplexHandle -- A handle to a read/write stream
136 !(MVar Handle__) -- The read side
137 !(MVar Handle__) -- The write side
140 -- * A 'FileHandle' is seekable. A 'DuplexHandle' may or may not be
143 instance Eq Handle where
144 (FileHandle h1) == (FileHandle h2) = h1 == h2
145 (DuplexHandle h1 _) == (DuplexHandle h2 _) = h1 == h2
148 type FD = Int -- XXX ToDo: should be CInt
152 haFD :: !FD, -- file descriptor
153 haType :: HandleType, -- type (read/write/append etc.)
154 haIsBin :: Bool, -- binary mode?
155 haIsStream :: Bool, -- is this a stream handle?
156 haBufferMode :: BufferMode, -- buffer contains read/write data?
157 haFilePath :: FilePath, -- file name, possibly
158 haBuffer :: !(IORef Buffer), -- the current buffer
159 haBuffers :: !(IORef BufferList), -- spare buffers
160 haOtherSide :: Maybe (MVar Handle__) -- ptr to the write side of a
164 -- ---------------------------------------------------------------------------
167 -- The buffer is represented by a mutable variable containing a
168 -- record, where the record contains the raw buffer and the start/end
169 -- points of the filled portion. We use a mutable variable so that
170 -- the common operation of writing (or reading) some data from (to)
171 -- the buffer doesn't need to modify, and hence copy, the handle
172 -- itself, it just updates the buffer.
174 -- There will be some allocation involved in a simple hPutChar in
175 -- order to create the new Buffer structure (below), but this is
176 -- relatively small, and this only has to be done once per write
179 -- The buffer contains its size - we could also get the size by
180 -- calling sizeOfMutableByteArray# on the raw buffer, but that tends
181 -- to be rounded up to the nearest Word.
183 type RawBuffer = MutableByteArray# RealWorld
185 -- INVARIANTS on a Buffer:
187 -- * A handle *always* has a buffer, even if it is only 1 character long
188 -- (an unbuffered handle needs a 1 character buffer in order to support
189 -- hLookAhead and hIsEOF).
191 -- * if r == w, then r == 0 && w == 0
192 -- * if state == WriteBuffer, then r == 0
193 -- * a write buffer is never full. If an operation
194 -- fills up the buffer, it will always flush it before
196 -- * a read buffer may be full as a result of hLookAhead. In normal
197 -- operation, a read buffer always has at least one character of space.
205 bufState :: BufferState
208 data BufferState = ReadBuffer | WriteBuffer deriving (Eq)
210 -- we keep a few spare buffers around in a handle to avoid allocating
211 -- a new one for each hPutStr. These buffers are *guaranteed* to be the
212 -- same size as the main buffer.
215 | BufferListCons RawBuffer BufferList
218 bufferIsWritable :: Buffer -> Bool
219 bufferIsWritable Buffer{ bufState=WriteBuffer } = True
220 bufferIsWritable _other = False
222 bufferEmpty :: Buffer -> Bool
223 bufferEmpty Buffer{ bufRPtr=r, bufWPtr=w } = r == w
225 -- only makes sense for a write buffer
226 bufferFull :: Buffer -> Bool
227 bufferFull b@Buffer{ bufWPtr=w } = w >= bufSize b
229 -- Internally, we classify handles as being one
240 isReadableHandleType ReadHandle = True
241 isReadableHandleType ReadWriteHandle = True
242 isReadableHandleType _ = False
244 isWritableHandleType AppendHandle = True
245 isWritableHandleType WriteHandle = True
246 isWritableHandleType ReadWriteHandle = True
247 isWritableHandleType _ = False
249 -- File names are specified using @FilePath@, a OS-dependent
250 -- string that (hopefully, I guess) maps to an accessible file/object.
252 type FilePath = String
254 -- ---------------------------------------------------------------------------
257 -- Three kinds of buffering are supported: line-buffering,
258 -- block-buffering or no-buffering. These modes have the following
259 -- effects. For output, items are written out from the internal
260 -- buffer according to the buffer mode:
262 -- * line-buffering the entire output buffer is written
263 -- out whenever a newline is output, the output buffer overflows,
264 -- a flush is issued, or the handle is closed.
266 -- * block-buffering the entire output buffer is written out whenever
267 -- it overflows, a flush is issued, or the handle
270 -- * no-buffering output is written immediately, and never stored
271 -- in the output buffer.
273 -- The output buffer is emptied as soon as it has been written out.
275 -- Similarly, input occurs according to the buffer mode for handle {\em hdl}.
277 -- * line-buffering when the input buffer for the handle is not empty,
278 -- the next item is obtained from the buffer;
279 -- otherwise, when the input buffer is empty,
280 -- characters up to and including the next newline
281 -- character are read into the buffer. No characters
282 -- are available until the newline character is
285 -- * block-buffering when the input buffer for the handle becomes empty,
286 -- the next block of data is read into this buffer.
288 -- * no-buffering the next input item is read and returned.
290 -- For most implementations, physical files will normally be block-buffered
291 -- and terminals will normally be line-buffered. (the IO interface provides
292 -- operations for changing the default buffering of a handle tho.)
295 = NoBuffering | LineBuffering | BlockBuffering (Maybe Int)
296 deriving (Eq, Ord, Read, Show)
298 -- ---------------------------------------------------------------------------
301 newtype IORef a = IORef (STRef RealWorld a) deriving Eq
303 newIORef :: a -> IO (IORef a)
304 newIORef v = stToIO (newSTRef v) >>= \ var -> return (IORef var)
306 readIORef :: IORef a -> IO a
307 readIORef (IORef var) = stToIO (readSTRef var)
309 writeIORef :: IORef a -> a -> IO ()
310 writeIORef (IORef var) v = stToIO (writeSTRef var v)
312 modifyIORef :: IORef a -> (a -> a) -> IO ()
313 modifyIORef ref f = readIORef ref >>= \x -> writeIORef ref (f x)
315 -- deprecated, use modifyIORef
316 updateIORef :: IORef a -> (a -> a) -> IO ()
317 updateIORef = modifyIORef
319 -- ---------------------------------------------------------------------------
320 -- Show instance for Handles
322 -- handle types are 'show'n when printing error msgs, so
323 -- we provide a more user-friendly Show instance for it
324 -- than the derived one.
326 instance Show HandleType where
329 ClosedHandle -> showString "closed"
330 SemiClosedHandle -> showString "semi-closed"
331 ReadHandle -> showString "readable"
332 WriteHandle -> showString "writable"
333 AppendHandle -> showString "writable (append)"
334 ReadWriteHandle -> showString "read-writable"
336 instance Show Handle where
337 showsPrec p (FileHandle h) = showHandle p h False
338 showsPrec p (DuplexHandle _ h) = showHandle p h True
340 showHandle p h duplex =
342 -- (Big) SIGH: unfolded defn of takeMVar to avoid
343 -- an (oh-so) unfortunate module loop with PrelConc.
344 hdl_ = unsafePerformIO (IO $ \ s# ->
345 case h of { MVar h# ->
346 case takeMVar# h# s# of { (# s2# , r #) ->
347 case putMVar# h# r s2# of { s3# ->
350 showType | duplex = showString "duplex (read-write)"
351 | otherwise = showsPrec p (haType hdl_)
354 showHdl (haType hdl_)
355 (showString "loc=" . showString (haFilePath hdl_) . showChar ',' .
356 showString "type=" . showType . showChar ',' .
357 showString "binary=" . showsPrec p (haIsBin hdl_) . showChar ',' .
358 showString "buffering=" . showBufMode (unsafePerformIO (readIORef (haBuffer hdl_))) (haBufferMode hdl_) . showString "}" )
361 showHdl :: HandleType -> ShowS -> ShowS
364 ClosedHandle -> showsPrec p ht . showString "}"
367 showBufMode :: Buffer -> BufferMode -> ShowS
368 showBufMode buf bmo =
370 NoBuffering -> showString "none"
371 LineBuffering -> showString "line"
372 BlockBuffering (Just n) -> showString "block " . showParen True (showsPrec p n)
373 BlockBuffering Nothing -> showString "block " . showParen True (showsPrec p def)
378 -- ------------------------------------------------------------------------
379 -- Exception datatype and operations
382 = IOException IOException -- IO exceptions
383 | ArithException ArithException -- Arithmetic exceptions
384 | ArrayException ArrayException -- Array-related exceptions
385 | ErrorCall String -- Calls to 'error'
386 | ExitException ExitCode -- Call to System.exitWith
387 | NoMethodError String -- A non-existent method was invoked
388 | PatternMatchFail String -- A pattern match / guard failure
389 | RecSelError String -- Selecting a non-existent field
390 | RecConError String -- Field missing in record construction
391 | RecUpdError String -- Record doesn't contain updated field
392 | AssertionFailed String -- Assertions
393 | DynException Dynamic -- Dynamic exceptions
394 | AsyncException AsyncException -- Externally generated errors
395 | BlockedOnDeadMVar -- Blocking on a dead MVar
396 | NonTermination -- Cyclic data dependency or other loop
397 | Deadlock -- no threads can run (raised in main thread)
415 = IndexOutOfBounds String -- out-of-range array access
416 | UndefinedElement String -- evaluating an undefined element
419 stackOverflow, heapOverflow :: Exception -- for the RTS
420 stackOverflow = AsyncException StackOverflow
421 heapOverflow = AsyncException HeapOverflow
423 instance Show ArithException where
424 showsPrec _ Overflow = showString "arithmetic overflow"
425 showsPrec _ Underflow = showString "arithmetic underflow"
426 showsPrec _ LossOfPrecision = showString "loss of precision"
427 showsPrec _ DivideByZero = showString "divide by zero"
428 showsPrec _ Denormal = showString "denormal"
430 instance Show AsyncException where
431 showsPrec _ StackOverflow = showString "stack overflow"
432 showsPrec _ HeapOverflow = showString "heap overflow"
433 showsPrec _ ThreadKilled = showString "thread killed"
435 instance Show ArrayException where
436 showsPrec _ (IndexOutOfBounds s)
437 = showString "array index out of range"
438 . (if not (null s) then showString ": " . showString s
440 showsPrec _ (UndefinedElement s)
441 = showString "undefined array element"
442 . (if not (null s) then showString ": " . showString s
445 instance Show Exception where
446 showsPrec _ (IOException err) = shows err
447 showsPrec _ (ArithException err) = shows err
448 showsPrec _ (ArrayException err) = shows err
449 showsPrec _ (ErrorCall err) = showString err
450 showsPrec _ (ExitException err) = showString "exit: " . shows err
451 showsPrec _ (NoMethodError err) = showString err
452 showsPrec _ (PatternMatchFail err) = showString err
453 showsPrec _ (RecSelError err) = showString err
454 showsPrec _ (RecConError err) = showString err
455 showsPrec _ (RecUpdError err) = showString err
456 showsPrec _ (AssertionFailed err) = showString err
457 showsPrec _ (DynException _err) = showString "unknown exception"
458 showsPrec _ (AsyncException e) = shows e
459 showsPrec _ (BlockedOnDeadMVar) = showString "thread blocked indefinitely"
460 showsPrec _ (NonTermination) = showString "<<loop>>"
461 showsPrec _ (Deadlock) = showString "<<deadlock>>"
462 showsPrec _ (UserError err) = showString err
464 instance Eq Exception where
465 IOException e1 == IOException e2 = e1 == e2
466 ArithException e1 == ArithException e2 = e1 == e2
467 ArrayException e1 == ArrayException e2 = e1 == e2
468 ErrorCall e1 == ErrorCall e2 = e1 == e2
469 ExitException e1 == ExitException e2 = e1 == e2
470 NoMethodError e1 == NoMethodError e2 = e1 == e2
471 PatternMatchFail e1 == PatternMatchFail e2 = e1 == e2
472 RecSelError e1 == RecSelError e2 = e1 == e2
473 RecConError e1 == RecConError e2 = e1 == e2
474 RecUpdError e1 == RecUpdError e2 = e1 == e2
475 AssertionFailed e1 == AssertionFailed e2 = e1 == e2
476 DynException _ == DynException _ = False -- incomparable
477 AsyncException e1 == AsyncException e2 = e1 == e2
478 BlockedOnDeadMVar == BlockedOnDeadMVar = True
479 NonTermination == NonTermination = True
480 Deadlock == Deadlock = True
481 UserError e1 == UserError e2 = e1 == e2
483 -- -----------------------------------------------------------------------------
486 -- The `ExitCode' type defines the exit codes that a program
487 -- can return. `ExitSuccess' indicates successful termination;
488 -- and `ExitFailure code' indicates program failure
489 -- with value `code'. The exact interpretation of `code'
490 -- is operating-system dependent. In particular, some values of
491 -- `code' may be prohibited (e.g. 0 on a POSIX-compliant system).
493 -- We need it here because it is used in ExitException in the
494 -- Exception datatype (above).
496 data ExitCode = ExitSuccess | ExitFailure Int
497 deriving (Eq, Ord, Read, Show)
499 -- --------------------------------------------------------------------------
502 throw :: Exception -> a
503 throw exception = raise# exception
505 ioError :: Exception -> IO a
506 ioError err = IO $ \s -> throw err s
508 ioException :: IOException -> IO a
509 ioException err = IO $ \s -> throw (IOException err) s
511 -- ---------------------------------------------------------------------------
514 -- A value @IOError@ encode errors occurred in the @IO@ monad.
515 -- An @IOError@ records a more specific error type, a descriptive
516 -- string and maybe the handle that was used when the error was
519 type IOError = Exception
523 (Maybe Handle) -- the handle used by the action flagging the
525 IOErrorType -- what it was.
527 String -- error type specific information.
528 (Maybe FilePath) -- filename the error is related to.
530 instance Eq IOException where
531 (IOError h1 e1 loc1 str1 fn1) == (IOError h2 e2 loc2 str2 fn2) =
532 e1==e2 && str1==str2 && h1==h2 && loc1==loc2 && fn1==fn2
535 = AlreadyExists | HardwareFault
536 | IllegalOperation | InappropriateType
537 | Interrupted | InvalidArgument
538 | NoSuchThing | OtherError
539 | PermissionDenied | ProtocolError
540 | ResourceBusy | ResourceExhausted
541 | ResourceVanished | SystemError
542 | TimeExpired | UnsatisfiedConstraints
543 | UnsupportedOperation
545 | DynIOError Dynamic -- cheap&cheerful extensible IO error type.
547 instance Eq IOErrorType where
550 DynIOError{} -> False -- from a strictness POV, compatible with a derived Eq inst?
551 _ -> getTag# x ==# getTag# y
553 instance Show IOErrorType where
557 AlreadyExists -> "already exists"
558 HardwareFault -> "hardware fault"
559 IllegalOperation -> "illegal operation"
560 InappropriateType -> "inappropriate type"
561 Interrupted -> "interrupted"
562 InvalidArgument -> "invalid argument"
563 NoSuchThing -> "does not exist"
564 OtherError -> "failed"
565 PermissionDenied -> "permission denied"
566 ProtocolError -> "protocol error"
567 ResourceBusy -> "resource busy"
568 ResourceExhausted -> "resource exhausted"
569 ResourceVanished -> "resource vanished"
570 SystemError -> "system error"
571 TimeExpired -> "timeout"
572 UnsatisfiedConstraints -> "unsatisified constraints" -- ultra-precise!
573 UnsupportedOperation -> "unsupported operation"
575 DynIOError{} -> "unknown IO error"
577 userError :: String -> IOError
578 userError str = UserError str
580 -- ---------------------------------------------------------------------------
581 -- Predicates on IOError
583 isAlreadyExistsError :: IOError -> Bool
584 isAlreadyExistsError (IOException (IOError _ AlreadyExists _ _ _)) = True
585 isAlreadyExistsError _ = False
587 isAlreadyInUseError :: IOError -> Bool
588 isAlreadyInUseError (IOException (IOError _ ResourceBusy _ _ _)) = True
589 isAlreadyInUseError _ = False
591 isFullError :: IOError -> Bool
592 isFullError (IOException (IOError _ ResourceExhausted _ _ _)) = True
593 isFullError _ = False
595 isEOFError :: IOError -> Bool
596 isEOFError (IOException (IOError _ EOF _ _ _)) = True
599 isIllegalOperation :: IOError -> Bool
600 isIllegalOperation (IOException (IOError _ IllegalOperation _ _ _)) = True
601 isIllegalOperation _ = False
603 isPermissionError :: IOError -> Bool
604 isPermissionError (IOException (IOError _ PermissionDenied _ _ _)) = True
605 isPermissionError _ = False
607 isDoesNotExistError :: IOError -> Bool
608 isDoesNotExistError (IOException (IOError _ NoSuchThing _ _ _)) = True
609 isDoesNotExistError _ = False
611 isUserError :: IOError -> Bool
612 isUserError (UserError _) = True
613 isUserError _ = False
615 -- ---------------------------------------------------------------------------
618 instance Show IOException where
619 showsPrec p (IOError hdl iot loc s fn) =
623 _ -> showString "\nAction: " . showString loc) .
626 Just h -> showString "\nHandle: " . showsPrec p h) .
629 _ -> showString "\nReason: " . showString s) .
632 Just name -> showString "\nFile: " . showString name)