packages feed

KiCS-0.8.8: src/lib/Curry/Module/IO.hs.include

[ForType "Handle" Nothing
,ForFunction "stdin"
,ForFunction "stdout"
,ForFunction "stderr"
,ForFunction "prim_openFile"
,ForFunction "prim_hClose"
,ForFunction "prim_hFlush"
,ForFunction "prim_hIsEOF"
,ForFunction "prim_hSeek"
,ForFunction "prim_hWaitForInput"
,ForFunction "prim_hGetChar"
,ForFunction "prim_hPutChar"
,ForFunction "prim_hIsReadable"
,ForFunction "prim_hIsWritable"
]

import System.IO
import qualified System.IO as SI
import Control.Concurrent
import qualified Control.Exception as CE

-- somehow using an either type did not get the curry class for prim through.
data IOHandle = One Handle | Two Handle Handle deriving (Show,Eq)
type C_Handle = Prim IOHandle

inputHandle, outputHandle :: IOHandle -> Handle
inputHandle  (One h)   = h
inputHandle  (Two h _) = h
outputHandle (One h)   = h
outputHandle (Two _ h) = h


instance Read IOHandle where
  readsPrec = error "reading Handle"

instance Generate IOHandle where
  genFree    = error "free variable of type IO-Handle"
  maxArity _ = error "free variable of type IO-Handle"


instance ConvertCH C_IOMode SI.IOMode where
  toCurry SI.ReadMode = C_ReadMode
  toCurry SI.WriteMode = C_WriteMode
  toCurry SI.AppendMode = C_AppendMode

  fromCurry C_ReadMode = SI.ReadMode
  fromCurry C_WriteMode = SI.WriteMode
  fromCurry C_AppendMode = SI.AppendMode

instance ConvertCH C_SeekMode SI.SeekMode where
  toCurry SI.AbsoluteSeek = C_AbsoluteSeek
  toCurry SI.RelativeSeek = C_RelativeSeek
  toCurry SI.SeekFromEnd  = C_SeekFromEnd

  fromCurry C_AbsoluteSeek = SI.AbsoluteSeek
  fromCurry C_RelativeSeek = SI.RelativeSeek
  fromCurry C_SeekFromEnd  = SI.SeekFromEnd

stdin :: Result C_Handle
stdin _ = PrimValue (One SI.stdin)

stdout :: Result C_Handle
stdout _ = PrimValue (One SI.stdout)

stderr :: Result C_Handle
stderr _ = PrimValue (One SI.stderr)

prim_openFile :: List C_Char -> C_IOMode -> Result (C_IO C_Handle)
prim_openFile = ioFunc2 (\ s m -> do
  h <- SI.openFile s m
  Prelude.return (One h))

prim_hClose :: C_Handle -> Result (C_IO T0)
prim_hClose = ioFunc1 (\ eh -> case eh of
  One h     -> SI.hClose h
  Two h1 h2 -> SI.hClose h1 Prelude.>> SI.hClose h2)

prim_hFlush :: C_Handle -> Result (C_IO T0)
prim_hFlush = ioFunc1 (SI.hFlush . outputHandle)

prim_hIsEOF :: C_Handle -> Result (C_IO C_Bool)
prim_hIsEOF = ioFunc1 (SI.hIsEOF . inputHandle)

prim_hSeek :: C_Handle -> C_SeekMode -> C_Int -> Result (C_IO T0)
prim_hSeek = ioFunc3 (\ h -> SI.hSeek (inputHandle h))

prim_hWaitForInput ::  C_Handle -> C_Int -> Result (C_IO C_Bool)
prim_hWaitForInput = ioFunc2 (\ h -> myhWaitForInput (inputHandle h))

myhWaitForInput :: SI.Handle -> Int -> IO Bool
myhWaitForInput h i =
  if i Prelude.< 0 
  then SI.hIsEOF h Prelude.>>= Prelude.return . Prelude.not
  else SI.hWaitForInput h i 

selectHandle :: [IOHandle] -> Int -> IO Int
selectHandle handles t = do
  mvar <- newEmptyMVar
  threads <- mapM (\ (i,h) -> forkIO (waitOnHandle (inputHandle h) i t mvar)) 
                  (zip [0..] handles)
  inspectRes (length handles) mvar threads

inspectRes :: Int -> MVar (Maybe Int) -> [ThreadId] ->  IO Int
inspectRes 0 _    _       = Prelude.return (-1)
inspectRes n mvar threads = do
  res <- readMVar mvar
  case res of 
    Nothing -> inspectRes (n-1) mvar threads
    Just v  -> mapM_ killThread threads Prelude.>> Prelude.return v

waitOnHandle :: SI.Handle -> Int -> Int -> MVar (Maybe Int) -> IO ()
waitOnHandle h v t mvar = do
   	    ready <- myhWaitForInput h t
  	    putMVar mvar (if ready then Just v else Nothing)

prim_hWaitForInputs :: List C_Handle -> C_Int -> Result (C_IO C_Int)
prim_hWaitForInputs  = ioFunc2 selectHandle

prim_hGetChar :: C_Handle -> Result (C_IO C_Char)
prim_hGetChar = ioFunc1 (SI.hGetChar . inputHandle)

prim_hPutChar :: C_Handle -> C_Char -> Result (C_IO T0)
prim_hPutChar = ioFunc2 (SI.hPutChar . outputHandle)

prim_hIsReadable :: C_Handle -> Result (C_IO C_Bool)
prim_hIsReadable = ioFunc1 (SI.hIsReadable . inputHandle)

prim_hIsWritable :: C_Handle -> Result (C_IO C_Bool)
prim_hIsWritable = ioFunc1 (SI.hIsWritable . outputHandle)