1 % ------------------------------------------------------------------------------
2 % $Id: PrelIOBase.lhs,v 1.31 2001/01/11 07:04:16 qrczak Exp $
4 % (c) The University of Glasgow, 1994-2000
7 \section[PrelIOBase]{Module @PrelIOBase@}
9 Definitions for the @IO@ monad and its friends. Everything is exported
10 concretely; the @IO@ module itself exports abstractly.
13 {-# OPTIONS -fno-implicit-prelude -#include "cbits/stgio.h" #-}
15 #include "cbits/stgerror.h"
17 #ifndef __HUGS__ /* Hugs just includes this in PreludeBuiltin so no header needed */
18 module PrelIOBase where
20 import {-# SOURCE #-} PrelErr ( error )
24 import PrelNum ( fromInteger ) -- Integer literals
25 import PrelMaybe ( Maybe(..) )
26 import PrelAddr ( Addr(..), nullAddr )
30 import PrelPack ( unpackCString )
32 #if !defined(__CONCURRENT_HASKELL__)
33 import PrelArr ( MutableVar, readVar )
38 #define __CONCURRENT_HASKELL__
40 #define unpackCString primUnpackString
43 #ifndef __PARALLEL_HASKELL__
44 #define FILE_OBJECT ForeignObj
46 #define FILE_OBJECT Addr
50 %*********************************************************
52 \subsection{The @IO@ monad}
54 %*********************************************************
56 The IO Monad is just an instance of the ST monad, where the state is
57 the real world. We use the exception mechanism (in PrelException) to
58 implement IO exceptions.
60 NOTE: The IO representation is deeply wired in to various parts of the
61 system. The following list may or may not be exhaustive:
63 Compiler - types of various primitives in PrimOp.lhs
65 RTS - forceIO (StgMiscClosures.hc)
66 - catchzh_fast, (un)?blockAsyncExceptionszh_fast, raisezh_fast
68 - raiseAsync (Schedule.c)
70 Prelude - PrelIOBase.lhs, and several other places including
73 Libraries - parts of hslibs/lang.
79 newtype IO a = IO (State# RealWorld -> (# State# RealWorld, a #))
81 unIO :: IO a -> (State# RealWorld -> (# State# RealWorld, a #))
84 instance Functor IO where
85 fmap f x = x >>= (return . f)
87 instance Monad IO where
91 m >> k = m >>= \ _ -> k
95 fail s = ioError (userError s)
97 liftIO :: IO a -> State# RealWorld -> STret RealWorld a
98 liftIO (IO m) = \s -> case m s of (# s', r #) -> STret s' r
100 bindIO :: IO a -> (a -> IO b) -> IO b
101 bindIO (IO m) k = IO ( \ s ->
103 (# new_s, a #) -> unIO (k a) new_s
106 returnIO :: a -> IO a
107 returnIO x = IO (\ s -> (# s, x #))
111 %*********************************************************
113 \subsection{Coercions to @ST@}
115 %*********************************************************
119 /* Hugs doesn't distinguish these types so no coercion required) */
121 stToIO :: ST RealWorld a -> IO a
122 stToIO (ST m) = (IO m)
124 ioToST :: IO a -> ST RealWorld a
125 ioToST (IO m) = (ST m)
129 %*********************************************************
131 \subsection{Unsafe @IO@ operations}
133 %*********************************************************
137 {-# NOINLINE unsafePerformIO #-}
138 unsafePerformIO :: IO a -> a
139 unsafePerformIO (IO m) = case m realWorld# of (# _, r #) -> r
141 unsafeInterleaveIO :: IO a -> IO a
142 unsafeInterleaveIO = stToIO . unsafeInterleaveST . ioToST
146 %*********************************************************
148 \subsection{Types @Handle@, @Handle__@}
150 %*********************************************************
152 The type for @Handle@ is defined rather than in @IOHandle@
153 module, as the @IOError@ type uses it..all operations over
154 a handles reside in @IOHandle@.
160 Sigh, the MVar ops in ConcBase depend on IO, the IO
161 representation here depend on MVars for handles (when
162 compiling in a concurrent way). Break the cycle by having
163 the definition of MVars go here:
166 data MVar a = MVar (MVar# RealWorld a)
168 -- pull in Eq (Mvar a) too, to avoid PrelConc being an orphan-instance module
169 instance Eq (MVar a) where
170 (MVar mvar1#) == (MVar mvar2#) = sameMVar# mvar1# mvar2#
173 Double sigh - ForeignObj is needed here too to break a cycle.
175 data ForeignObj = ForeignObj ForeignObj# -- another one
176 instance CCallable ForeignObj
178 eqForeignObj :: ForeignObj -> ForeignObj -> Bool
180 = unsafePerformIO (primEqForeignObj mp1 mp2) /= (0::Int)
182 foreign import "eqForeignObj" unsafe primEqForeignObj :: ForeignObj -> ForeignObj -> IO Int
184 instance Eq ForeignObj where
185 p == q = eqForeignObj p q
186 p /= q = not (eqForeignObj p q)
187 #endif /* ndef __HUGS__ */
189 #if defined(__CONCURRENT_HASKELL__)
190 newtype Handle = Handle (MVar Handle__)
192 newtype Handle = Handle (MutableVar RealWorld Handle__)
195 instance Eq Handle where
196 (Handle h1) == (Handle h2) = h1 == h2
199 A Handle is represented by (a reference to) a record
200 containing the state of the I/O port/device. We record
201 the following pieces of info:
203 * type (read,write,closed etc.)
204 * pointer to the external file object.
206 * user-friendly name (usually the
207 FilePath used when IO.openFile was called)
209 Note: when a Handle is garbage collected, we want to flush its buffer
210 and close the OS file handle, so as to free up a (precious) resource.
214 haFO__ :: FILE_OBJECT,
215 haType__ :: Handle__Type,
216 haBufferMode__ :: BufferMode,
217 haFilePath__ :: FilePath,
218 haBuffers__ :: [Addr]
222 Internally, we classify handles as being one
234 -- File names are specified using @FilePath@, a OS-dependent
235 -- string that (hopefully, I guess) maps to an accessible file/object.
237 type FilePath = String
240 %*********************************************************
242 \subsection[Show-Handle]{Show instance for Handles}
244 %*********************************************************
247 -- handle types are 'show'ed when printing error msgs, so
248 -- we provide a more user-friendly Show instance for it
249 -- than the derived one.
250 instance Show Handle__Type where
253 ClosedHandle -> showString "closed"
254 SemiClosedHandle -> showString "semi-closed"
255 ReadHandle -> showString "readable"
256 WriteHandle -> showString "writeable"
257 AppendHandle -> showString "writeable (append)"
258 ReadWriteHandle -> showString "read-writeable"
260 instance Show Handle where
261 showsPrec p (Handle h) =
263 #if defined(__CONCURRENT_HASKELL__)
265 hdl_ = unsafePerformIO (primTakeMVar h)
267 -- (Big) SIGH: unfolded defn of takeMVar to avoid
268 -- an (oh-so) unfortunate module loop with PrelConc.
269 hdl_ = unsafePerformIO (IO $ \ s# ->
270 case h of { MVar h# ->
271 case takeMVar# h# s# of { (# s2# , r #) ->
275 hdl_ = unsafePerformIO (stToIO (readVar h))
279 showHdl (haType__ hdl_)
280 (showString "loc=" . showString (haFilePath__ hdl_) . showChar ',' .
281 showString "type=" . showsPrec p (haType__ hdl_) . showChar ',' .
282 showString "buffering=" . showBufMode (haFO__ hdl_) (haBufferMode__ hdl_) . showString "}\n" )
284 showHdl :: Handle__Type -> ShowS -> ShowS
287 ClosedHandle -> showsPrec p ht . showString "}\n"
290 showBufMode :: FILE_OBJECT -> BufferMode -> ShowS
293 NoBuffering -> showString "none"
294 LineBuffering -> showString "line"
295 BlockBuffering (Just n) -> showString "block " . showParen True (showsPrec p n)
296 BlockBuffering Nothing -> showString "block " . showParen True (showsPrec p def)
299 def = unsafePerformIO (getBufSize fo)
302 %*********************************************************
304 \subsection[BufferMode]{Buffering modes}
306 %*********************************************************
308 Three kinds of buffering are supported: line-buffering,
309 block-buffering or no-buffering. These modes have the following
310 effects. For output, items are written out from the internal
311 buffer according to the buffer mode:
314 \item[line-buffering] the entire output buffer is written
315 out whenever a newline is output, the output buffer overflows,
316 a flush is issued, or the handle is closed.
318 \item[block-buffering] the entire output buffer is written out whenever
319 it overflows, a flush is issued, or the handle
322 \item[no-buffering] output is written immediately, and never stored
323 in the output buffer.
326 The output buffer is emptied as soon as it has been written out.
328 Similarly, input occurs according to the buffer mode for handle {\em hdl}.
330 \item[line-buffering] when the input buffer for {\em hdl} is not empty,
331 the next item is obtained from the buffer;
332 otherwise, when the input buffer is empty,
333 characters up to and including the next newline
334 character are read into the buffer. No characters
335 are available until the newline character is
337 \item[block-buffering] when the input buffer for {\em hdl} becomes empty,
338 the next block of data is read into this buffer.
339 \item[no-buffering] the next input item is read and returned.
342 For most implementations, physical files will normally be block-buffered
343 and terminals will normally be line-buffered. (the IO interface provides
344 operations for changing the default buffering of a handle tho.)
348 = NoBuffering | LineBuffering | BlockBuffering (Maybe Int)
349 deriving (Eq, Ord, Show)
350 {- Read instance defined in IO. -}
354 Foreign import declarations to helper routines:
357 foreign import "libHS_cbits" "getErrStr__" unsafe getErrStr__ :: IO Addr
358 foreign import "libHS_cbits" "getErrNo__" unsafe getErrNo__ :: IO Int
359 foreign import "libHS_cbits" "getErrType__" unsafe getErrType__ :: IO Int
361 malloc :: Int -> IO Addr
365 then ioException (IOError Nothing ResourceExhausted
366 "malloc" "out of memory" Nothing)
369 foreign import "malloc" unsafe _malloc :: Int -> IO Addr
371 foreign import "libHS_cbits" "getBufSize" unsafe
372 getBufSize :: FILE_OBJECT -> IO Int
373 foreign import "libHS_cbits" "setBuf" unsafe
374 setBuf :: FILE_OBJECT -> Addr -> Int -> IO ()
378 %*********************************************************
380 \subsection{Exception datatype and operations}
382 %*********************************************************
386 = IOException IOException -- IO exceptions
387 | ArithException ArithException -- Arithmetic exceptions
388 | ArrayException ArrayException -- Array-related exceptions
389 | ErrorCall String -- Calls to 'error'
390 | NoMethodError String -- A non-existent method was invoked
391 | PatternMatchFail String -- A pattern match / guard failure
392 | RecSelError String -- Selecting a non-existent field
393 | RecConError String -- Field missing in record construction
394 | RecUpdError String -- Record doesn't contain updated field
395 | AssertionFailed String -- Assertions
396 | DynException Dynamic -- Dynamic exceptions
397 | AsyncException AsyncException -- Externally generated errors
398 | PutFullMVar -- Put on a full MVar
399 | BlockedOnDeadMVar -- Blocking on a dead MVar
418 = IndexOutOfBounds String -- out-of-range array access
419 | UndefinedElement String -- evaluating an undefined element
422 stackOverflow, heapOverflow :: Exception -- for the RTS
423 stackOverflow = AsyncException StackOverflow
424 heapOverflow = AsyncException HeapOverflow
426 instance Show ArithException where
427 showsPrec _ Overflow = showString "arithmetic overflow"
428 showsPrec _ Underflow = showString "arithmetic underflow"
429 showsPrec _ LossOfPrecision = showString "loss of precision"
430 showsPrec _ DivideByZero = showString "divide by zero"
431 showsPrec _ Denormal = showString "denormal"
433 instance Show AsyncException where
434 showsPrec _ StackOverflow = showString "stack overflow"
435 showsPrec _ HeapOverflow = showString "heap overflow"
436 showsPrec _ ThreadKilled = showString "thread killed"
438 instance Show ArrayException where
439 showsPrec _ (IndexOutOfBounds s)
440 = showString "array index out of range"
441 . (if not (null s) then showString ": " . showString s
443 showsPrec _ (UndefinedElement s)
444 = showString "undefined array element"
445 . (if not (null s) then showString ": " . showString s
448 instance Show Exception where
449 showsPrec _ (IOException err) = shows err
450 showsPrec _ (ArithException err) = shows err
451 showsPrec _ (ArrayException err) = shows err
452 showsPrec _ (ErrorCall err) = showString err
453 showsPrec _ (NoMethodError err) = showString err
454 showsPrec _ (PatternMatchFail err) = showString err
455 showsPrec _ (RecSelError err) = showString err
456 showsPrec _ (RecConError err) = showString err
457 showsPrec _ (RecUpdError err) = showString err
458 showsPrec _ (AssertionFailed err) = showString err
459 showsPrec _ (DynException _err) = showString "unknown exception"
460 showsPrec _ (AsyncException e) = shows e
461 showsPrec _ (PutFullMVar) = showString "putMVar: full MVar"
462 showsPrec _ (BlockedOnDeadMVar) = showString "thread blocked indefinitely"
463 showsPrec _ (NonTermination) = showString "<<loop>>"
464 showsPrec _ (UserError err) = showString err
467 %*********************************************************
469 \subsection{Primitive throw}
471 %*********************************************************
474 throw :: Exception -> a
475 throw exception = raise# exception
477 ioError :: Exception -> IO a
478 ioError err = IO $ \s -> throw err s
480 ioException :: IOException -> IO a
481 ioException err = IO $ \s -> throw (IOException err) s
484 %*********************************************************
486 \subsection{Type @IOError@}
488 %*********************************************************
490 A value @IOError@ encode errors occurred in the @IO@ monad.
491 An @IOError@ records a more specific error type, a descriptive
492 string and maybe the handle that was used when the error was
496 type IOError = Exception
500 (Maybe Handle) -- the handle used by the action flagging the
502 IOErrorType -- what it was.
504 String -- error type specific information.
505 (Maybe FilePath) -- filename the error is related to.
507 instance Eq IOException where
508 (IOError h1 e1 loc1 str1 fn1) == (IOError h2 e2 loc2 str2 fn2) =
509 e1==e2 && str1==str2 && h1==h2 && loc1==loc2 && fn1==fn2
512 = AlreadyExists | HardwareFault
513 | IllegalOperation | InappropriateType
514 | Interrupted | InvalidArgument
515 | NoSuchThing | OtherError
516 | PermissionDenied | ProtocolError
517 | ResourceBusy | ResourceExhausted
518 | ResourceVanished | SystemError
519 | TimeExpired | UnsatisfiedConstraints
520 | UnsupportedOperation
522 #if defined(cygwin32_TARGET_OS) || defined(mingw32_TARGET_OS)
523 | ComError Int -- HRESULT
527 instance Show IOErrorType where
531 AlreadyExists -> "already exists"
532 HardwareFault -> "hardware fault"
533 IllegalOperation -> "illegal operation"
534 InappropriateType -> "inappropriate type"
535 Interrupted -> "interrupted"
536 InvalidArgument -> "invalid argument"
537 NoSuchThing -> "does not exist"
538 OtherError -> "failed"
539 PermissionDenied -> "permission denied"
540 ProtocolError -> "protocol error"
541 ResourceBusy -> "resource busy"
542 ResourceExhausted -> "resource exhausted"
543 ResourceVanished -> "resource vanished"
544 SystemError -> "system error"
545 TimeExpired -> "timeout"
546 UnsatisfiedConstraints -> "unsatisified constraints" -- ultra-precise!
547 UnsupportedOperation -> "unsupported operation"
549 #if defined(cygwin32_TARGET_OS) || defined(mingw32_TARGET_OS)
550 ComError _ -> "COM error"
555 userError :: String -> IOError
556 userError str = UserError str
559 Predicates on IOError; little effort made on these so far...
563 isAlreadyExistsError :: IOError -> Bool
564 isAlreadyExistsError (IOException (IOError _ AlreadyExists _ _ _)) = True
565 isAlreadyExistsError _ = False
567 isAlreadyInUseError :: IOError -> Bool
568 isAlreadyInUseError (IOException (IOError _ ResourceBusy _ _ _)) = True
569 isAlreadyInUseError _ = False
571 isFullError :: IOError -> Bool
572 isFullError (IOException (IOError _ ResourceExhausted _ _ _)) = True
573 isFullError _ = False
575 isEOFError :: IOError -> Bool
576 isEOFError (IOException (IOError _ EOF _ _ _)) = True
579 isIllegalOperation :: IOError -> Bool
580 isIllegalOperation (IOException (IOError _ IllegalOperation _ _ _)) = True
581 isIllegalOperation _ = False
583 isPermissionError :: IOError -> Bool
584 isPermissionError (IOException (IOError _ PermissionDenied _ _ _)) = True
585 isPermissionError _ = False
587 isDoesNotExistError :: IOError -> Bool
588 isDoesNotExistError (IOException (IOError _ NoSuchThing _ _ _)) = True
589 isDoesNotExistError _ = False
591 isUserError :: IOError -> Bool
592 isUserError (UserError _) = True
593 isUserError _ = False
600 -- For now we give a fairly uninformative error message which just happens to
601 -- be like the ones that Hugs used to give.
602 instance Show IOException where
603 showsPrec p (IOError _ _ _ s _) = showString s . showChar '\n'
605 instance Show IOException where
606 showsPrec p (IOError hdl iot loc s fn) =
610 _ -> showString "\nAction: " . showString loc) .
614 _ -> showString "\nReason: " . showString s) .
617 Just name -> showString "\nFile: " . showString name)
622 Just h -> showString "\nHandle: " . showsPrec p h
627 The @String@ part of an @IOError@ is platform-dependent. However, to
628 provide a uniform mechanism for distinguishing among errors within
629 these broad categories, each platform-specific standard shall specify
630 the exact strings to be used for particular errors. For errors not
631 explicitly mentioned in the standard, any descriptive string may be
635 constructErrorAndFail :: String -> IO a
636 constructErrorAndFail call_site
637 = constructError call_site >>= \ io_error ->
638 ioError (IOException io_error)
640 constructErrorAndFailWithInfo :: String -> String -> IO a
641 constructErrorAndFailWithInfo call_site fn
642 = constructErrorMsg call_site (Just fn) >>= \ io_error ->
643 ioError (IOException io_error)
647 This doesn't seem to be documented/spelled out anywhere,
650 The implementation of the IO prelude uses various C stubs
651 to do the actual interaction with the OS. The bandwidth
652 \tr{C<->Haskell} is somewhat limited, so the general strategy
653 for flaggging any errors (apart from possibly using the
654 return code of the external call), is to set the @ghc_errtype@
655 to a value that is one of the \tr{#define}s in @includes/error.h@.
656 @ghc_errstr@ holds a character string providing error-specific
657 information. Error constructing functions will then reach out
658 and grab these values when generating
661 constructError :: String -> IO IOException
662 constructError call_site = constructErrorMsg call_site Nothing
664 constructErrorMsg :: String -> Maybe String -> IO IOException
665 constructErrorMsg call_site fn =
666 getErrType__ >>= \ errtype ->
667 getErrStr__ >>= \ str ->
670 case (errtype::Int) of
671 ERR_ALREADYEXISTS -> AlreadyExists
672 ERR_HARDWAREFAULT -> HardwareFault
673 ERR_ILLEGALOPERATION -> IllegalOperation
674 ERR_INAPPROPRIATETYPE -> InappropriateType
675 ERR_INTERRUPTED -> Interrupted
676 ERR_INVALIDARGUMENT -> InvalidArgument
677 ERR_NOSUCHTHING -> NoSuchThing
678 ERR_OTHERERROR -> OtherError
679 ERR_PERMISSIONDENIED -> PermissionDenied
680 ERR_PROTOCOLERROR -> ProtocolError
681 ERR_RESOURCEBUSY -> ResourceBusy
682 ERR_RESOURCEEXHAUSTED -> ResourceExhausted
683 ERR_RESOURCEVANISHED -> ResourceVanished
684 ERR_SYSTEMERROR -> SystemError
685 ERR_TIMEEXPIRED -> TimeExpired
686 ERR_UNSATISFIEDCONSTRAINTS -> UnsatisfiedConstraints
687 ERR_UNSUPPORTEDOPERATION -> UnsupportedOperation
694 OtherError -> "(error code: " ++ show errtype ++ ")"
697 return (IOError Nothing iot call_site msg fn)