[project @ 2002-02-05 17:32:24 by simonmar]
[haskell-directory.git] / GHC / IOBase.lhs
index 7e77363..e7f5bd0 100644 (file)
@@ -1,5 +1,5 @@
 % ------------------------------------------------------------------------------
-% $Id: IOBase.lhs,v 1.1 2001/06/28 14:15:03 simonmar Exp $
+% $Id: IOBase.lhs,v 1.6 2002/02/05 17:32:26 simonmar Exp $
 % 
 % (c) The University of Glasgow, 1994-2001
 %
@@ -9,16 +9,14 @@
 
 \begin{code}
 {-# OPTIONS -fno-implicit-prelude #-}
-#include "config.h"
 
 module GHC.IOBase where
 
 import GHC.ST
 import GHC.STRef
-import GHC.Arr
 import GHC.Base
 import GHC.Num -- To get fromInteger etc, needed because of -fno-implicit-prelude
-import GHC.Maybe  ( Maybe(..) )
+import Data.Maybe  ( Maybe(..) )
 import GHC.Show
 import GHC.List
 import GHC.Read
@@ -152,13 +150,16 @@ type FD = Int -- XXX ToDo: should be CInt
 
 data Handle__
   = Handle__ {
-      haFD         :: !FD,
-      haType        :: HandleType,
-      haIsBin      :: Bool,
-      haBufferMode  :: BufferMode,
-      haFilePath    :: FilePath,
-      haBuffer     :: !(IORef Buffer),
-      haBuffers     :: !(IORef BufferList)
+      haFD         :: !FD,                  -- file descriptor
+      haType        :: HandleType,          -- type (read/write/append etc.)
+      haIsBin       :: Bool,                -- binary mode?
+      haIsStream    :: Bool,                -- is this a stream handle?
+      haBufferMode  :: BufferMode,          -- buffer contains read/write data?
+      haFilePath    :: FilePath,            -- file name, possibly
+      haBuffer     :: !(IORef Buffer),      -- the current buffer
+      haBuffers     :: !(IORef BufferList),  -- spare buffers
+      haOtherSide   :: Maybe (MVar Handle__) -- ptr to the write side of a 
+                                            -- duplex handle.
     }
 
 -- ---------------------------------------------------------------------------
@@ -236,11 +237,9 @@ data HandleType
  | WriteHandle
  | AppendHandle
  | ReadWriteHandle
- | ReadSideHandle  !(MVar Handle__)    -- read side of a duplex handle
 
 isReadableHandleType ReadHandle         = True
 isReadableHandleType ReadWriteHandle    = True
-isReadableHandleType (ReadSideHandle _) = True
 isReadableHandleType _                 = False
 
 isWritableHandleType AppendHandle    = True
@@ -327,13 +326,12 @@ instance Show HandleType where
       WriteHandle       -> showString "writable"
       AppendHandle      -> showString "writable (append)"
       ReadWriteHandle   -> showString "read-writable"
-      ReadSideHandle _  -> showString "read-writable (duplex)"
 
 instance Show Handle where 
-  showsPrec p (FileHandle   h)   = showHandle p h
-  showsPrec p (DuplexHandle h _) = showHandle p h
+  showsPrec p (FileHandle   h)   = showHandle p h False
+  showsPrec p (DuplexHandle _ h) = showHandle p h True
    
-showHandle p h =
+showHandle p h duplex =
     let
      -- (Big) SIGH: unfolded defn of takeMVar to avoid
      -- an (oh-so) unfortunate module loop with GHC.Conc.
@@ -342,14 +340,18 @@ showHandle p h =
             case takeMVar# h# s#   of { (# s2# , r #) -> 
             case putMVar# h# r s2# of { s3# ->
             (# s3#, r #) }}})
+
+     showType | duplex = showString "duplex (read-write)"
+             | otherwise = showsPrec p (haType hdl_)
     in
     showChar '{' . 
     showHdl (haType hdl_) 
            (showString "loc=" . showString (haFilePath hdl_) . showChar ',' .
-            showString "type=" . showsPrec p (haType hdl_) . showChar ',' .
+            showString "type=" . showType . showChar ',' .
             showString "binary=" . showsPrec p (haIsBin hdl_) . showChar ',' .
             showString "buffering=" . showBufMode (unsafePerformIO (readIORef (haBuffer hdl_))) (haBufferMode hdl_) . showString "}" )
    where
+
     showHdl :: HandleType -> ShowS -> ShowS
     showHdl ht cont = 
        case ht of
@@ -385,8 +387,8 @@ data Exception
   | DynException       Dynamic         -- Dynamic exceptions
   | AsyncException     AsyncException  -- Externally generated errors
   | BlockedOnDeadMVar                  -- Blocking on a dead MVar
+  | Deadlock                           -- no threads can run (raised in main thread)
   | NonTermination
-  | UserError          String
 
 data ArithException
   = Overflow
@@ -449,7 +451,25 @@ instance Show Exception where
   showsPrec _ (AsyncException e)        = shows e
   showsPrec _ (BlockedOnDeadMVar)       = showString "thread blocked indefinitely"
   showsPrec _ (NonTermination)           = showString "<<loop>>"
-  showsPrec _ (UserError err)            = showString err
+  showsPrec _ (Deadlock)                 = showString "<<deadlock>>"
+
+instance Eq Exception where
+  IOException e1      == IOException e2      = e1 == e2
+  ArithException e1   == ArithException e2   = e1 == e2
+  ArrayException e1   == ArrayException e2   = e1 == e2
+  ErrorCall e1        == ErrorCall e2       = e1 == e2
+  ExitException        e1    == ExitException e2    = e1 == e2
+  NoMethodError e1    == NoMethodError e2    = e1 == e2
+  PatternMatchFail e1 == PatternMatchFail e2 = e1 == e2
+  RecSelError e1      == RecSelError e2      = e1 == e2
+  RecConError e1      == RecConError e2      = e1 == e2
+  RecUpdError e1      == RecUpdError e2      = e1 == e2
+  AssertionFailed e1  == AssertionFailed e2  = e1 == e2
+  DynException _      == DynException _      = False -- incomparable
+  AsyncException e1   == AsyncException e2   = e1 == e2
+  BlockedOnDeadMVar   == BlockedOnDeadMVar   = True
+  NonTermination      == NonTermination      = True
+  Deadlock            == Deadlock            = True
 
 -- -----------------------------------------------------------------------------
 -- The ExitCode type
@@ -490,99 +510,76 @@ ioException err =  IO $ \s -> throw (IOException err) s
 type IOError = Exception
 
 data IOException
- = IOError
-     (Maybe Handle)   -- the handle used by the action flagging the
-                     --   the error.
-     IOErrorType      -- what it was.
-     String          -- location.
-     String           -- error type specific information.
-     (Maybe FilePath) -- filename the error is related to.
+ = IOError {
+     ioe_handle   :: Maybe Handle,   -- the handle used by the action flagging 
+                                    -- the error.
+     ioe_type     :: IOErrorType,    -- what it was.
+     ioe_location :: String,        -- location.
+     ioe_descr    :: String,         -- error type specific information.
+     ioe_filename :: Maybe FilePath  -- filename the error is related to.
+   }
 
 instance Eq IOException where
   (IOError h1 e1 loc1 str1 fn1) == (IOError h2 e2 loc2 str2 fn2) = 
     e1==e2 && str1==str2 && h1==h2 && loc1==loc2 && fn1==fn2
 
 data IOErrorType
-  = AlreadyExists        | HardwareFault
-  | IllegalOperation     | InappropriateType
-  | Interrupted          | InvalidArgument
-  | NoSuchThing          | OtherError
-  | PermissionDenied     | ProtocolError
-  | ResourceBusy         | ResourceExhausted
-  | ResourceVanished     | SystemError
-  | TimeExpired          | UnsatisfiedConstraints
-  | UnsupportedOperation
+  -- Haskell 98:
+  = AlreadyExists
+  | NoSuchThing
+  | ResourceBusy
+  | ResourceExhausted
   | EOF
-#if defined(cygwin32_TARGET_OS) || defined(mingw32_TARGET_OS)
-  | ComError Int           -- HRESULT
-#endif
-  deriving (Eq)
-
+  | IllegalOperation
+  | PermissionDenied
+  | UserError
+  -- GHC only:
+  | UnsatisfiedConstraints
+  | SystemError
+  | ProtocolError
+  | OtherError
+  | InvalidArgument
+  | InappropriateType
+  | HardwareFault
+  | UnsupportedOperation
+  | TimeExpired
+  | ResourceVanished
+  | Interrupted
+  | DynIOError Dynamic -- cheap&cheerful extensible IO error type.
+
+instance Eq IOErrorType where
+   x == y = 
+     case x of
+       DynIOError{} -> False -- from a strictness POV, compatible with a derived Eq inst?
+       _ -> getTag# x ==# getTag# y
 instance Show IOErrorType where
   showsPrec _ e =
     showString $
     case e of
       AlreadyExists    -> "already exists"
-      HardwareFault    -> "hardware fault"
+      NoSuchThing       -> "does not exist"
+      ResourceBusy      -> "resource busy"
+      ResourceExhausted -> "resource exhausted"
+      EOF              -> "end of file"
       IllegalOperation -> "illegal operation"
+      PermissionDenied  -> "permission denied"
+      UserError                -> "user error"
+      HardwareFault    -> "hardware fault"
       InappropriateType -> "inappropriate type"
       Interrupted       -> "interrupted"
       InvalidArgument   -> "invalid argument"
-      NoSuchThing       -> "does not exist"
       OtherError        -> "failed"
-      PermissionDenied  -> "permission denied"
       ProtocolError     -> "protocol error"
-      ResourceBusy      -> "resource busy"
-      ResourceExhausted -> "resource exhausted"
       ResourceVanished  -> "resource vanished"
       SystemError      -> "system error"
       TimeExpired       -> "timeout"
       UnsatisfiedConstraints -> "unsatisified constraints" -- ultra-precise!
       UnsupportedOperation -> "unsupported operation"
-      EOF              -> "end of file"
-#if defined(cygwin32_TARGET_OS) || defined(mingw32_TARGET_OS)
-      ComError _       -> "COM error"
-#endif
-
-
+      DynIOError{}      -> "unknown IO error"
 
 userError       :: String  -> IOError
-userError str  =  UserError str
-
--- ---------------------------------------------------------------------------
--- Predicates on IOError
-
-isAlreadyExistsError :: IOError -> Bool
-isAlreadyExistsError (IOException (IOError _ AlreadyExists _ _ _)) = True
-isAlreadyExistsError _                                             = False
-
-isAlreadyInUseError :: IOError -> Bool
-isAlreadyInUseError (IOException (IOError _ ResourceBusy _ _ _)) = True
-isAlreadyInUseError _                                            = False
-
-isFullError :: IOError -> Bool
-isFullError (IOException (IOError _ ResourceExhausted _ _ _)) = True
-isFullError _                                                 = False
-
-isEOFError :: IOError -> Bool
-isEOFError (IOException (IOError _ EOF _ _ _)) = True
-isEOFError _                                   = False
-
-isIllegalOperation :: IOError -> Bool
-isIllegalOperation (IOException (IOError _ IllegalOperation _ _ _)) = True
-isIllegalOperation _                                                = False
-
-isPermissionError :: IOError -> Bool
-isPermissionError (IOException (IOError _ PermissionDenied _ _ _)) = True
-isPermissionError _                                                = False
-
-isDoesNotExistError :: IOError -> Bool
-isDoesNotExistError (IOException (IOError _ NoSuchThing _ _ _)) = True
-isDoesNotExistError _                                           = False
-
-isUserError :: IOError -> Bool
-isUserError (UserError _) = True
-isUserError _             = False
+userError str  =  IOException (IOError Nothing UserError "" str Nothing)
 
 -- ---------------------------------------------------------------------------
 -- Showing IOErrors