module Feldspar.Run.Concurrent
  ( ThreadId
  , Chan, Closeable, Uncloseable
  , Transferable (..), BulkTransferable (..)
  , fork
  , forkWithId
  , asyncKillThread
  , killThread
  , waitThread
  , delayThread
  , closeChan
  , lastChanReadOK
  ) where



import Prelude hiding ((&&))
import Data.Proxy
import Data.TypedStruct

import qualified Language.Embedded.Concurrent as Imp
import Language.Embedded.Concurrent (ThreadId, Chan, Closeable, Uncloseable)

import Feldspar
import Feldspar.Representation
import Feldspar.Run.Representation



-- | Fork off a computation as a new thread.
fork :: Run () -> Run ThreadId
fork :: Run () -> Run ThreadId
fork = ProgramT
  RunCMD
  (Param2 Data PrimType')
  (Program CompCMD (Param2 Data PrimType'))
  ThreadId
-> Run ThreadId
forall a.
ProgramT
  RunCMD
  (Param2 Data PrimType')
  (Program CompCMD (Param2 Data PrimType'))
  a
-> Run a
Run (ProgramT
   RunCMD
   (Param2 Data PrimType')
   (Program CompCMD (Param2 Data PrimType'))
   ThreadId
 -> Run ThreadId)
-> (Run ()
    -> ProgramT
         RunCMD
         (Param2 Data PrimType')
         (Program CompCMD (Param2 Data PrimType'))
         ThreadId)
-> Run ()
-> Run ThreadId
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ProgramT
  RunCMD
  (Param2 Data PrimType')
  (Program CompCMD (Param2 Data PrimType'))
  ()
-> ProgramT
     RunCMD
     (Param2 Data PrimType')
     (Program CompCMD (Param2 Data PrimType'))
     ThreadId
forall k1 (instr :: (* -> *, (* -> *, (k1, *))) -> * -> *)
       (exp :: * -> *) (pred :: k1) (m :: * -> *).
(ThreadCMD :<: instr) =>
ProgramT instr (Param2 exp pred) m ()
-> ProgramT instr (Param2 exp pred) m ThreadId
Imp.fork (ProgramT
   RunCMD
   (Param2 Data PrimType')
   (Program CompCMD (Param2 Data PrimType'))
   ()
 -> ProgramT
      RunCMD
      (Param2 Data PrimType')
      (Program CompCMD (Param2 Data PrimType'))
      ThreadId)
-> (Run ()
    -> ProgramT
         RunCMD
         (Param2 Data PrimType')
         (Program CompCMD (Param2 Data PrimType'))
         ())
-> Run ()
-> ProgramT
     RunCMD
     (Param2 Data PrimType')
     (Program CompCMD (Param2 Data PrimType'))
     ThreadId
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Run ()
-> ProgramT
     RunCMD
     (Param2 Data PrimType')
     (Program CompCMD (Param2 Data PrimType'))
     ()
forall a.
Run a
-> ProgramT
     RunCMD
     (Param2 Data PrimType')
     (Program CompCMD (Param2 Data PrimType'))
     a
unRun

-- | Fork off a computation as a new thread, with access to its own thread ID.
forkWithId :: (ThreadId -> Run ()) -> Run ThreadId
forkWithId :: (ThreadId -> Run ()) -> Run ThreadId
forkWithId ThreadId -> Run ()
f = ProgramT
  RunCMD
  (Param2 Data PrimType')
  (Program CompCMD (Param2 Data PrimType'))
  ThreadId
-> Run ThreadId
forall a.
ProgramT
  RunCMD
  (Param2 Data PrimType')
  (Program CompCMD (Param2 Data PrimType'))
  a
-> Run a
Run (ProgramT
   RunCMD
   (Param2 Data PrimType')
   (Program CompCMD (Param2 Data PrimType'))
   ThreadId
 -> Run ThreadId)
-> ProgramT
     RunCMD
     (Param2 Data PrimType')
     (Program CompCMD (Param2 Data PrimType'))
     ThreadId
-> Run ThreadId
forall a b. (a -> b) -> a -> b
$ (ThreadId
 -> ProgramT
      RunCMD
      (Param2 Data PrimType')
      (Program CompCMD (Param2 Data PrimType'))
      ())
-> ProgramT
     RunCMD
     (Param2 Data PrimType')
     (Program CompCMD (Param2 Data PrimType'))
     ThreadId
forall k1 (instr :: (* -> *, (* -> *, (k1, *))) -> * -> *)
       (exp :: * -> *) (pred :: k1) (m :: * -> *).
(ThreadCMD :<: instr) =>
(ThreadId -> ProgramT instr (Param2 exp pred) m ())
-> ProgramT instr (Param2 exp pred) m ThreadId
Imp.forkWithId (Run ()
-> ProgramT
     RunCMD
     (Param2 Data PrimType')
     (Program CompCMD (Param2 Data PrimType'))
     ()
forall a.
Run a
-> ProgramT
     RunCMD
     (Param2 Data PrimType')
     (Program CompCMD (Param2 Data PrimType'))
     a
unRun (Run ()
 -> ProgramT
      RunCMD
      (Param2 Data PrimType')
      (Program CompCMD (Param2 Data PrimType'))
      ())
-> (ThreadId -> Run ())
-> ThreadId
-> ProgramT
     RunCMD
     (Param2 Data PrimType')
     (Program CompCMD (Param2 Data PrimType'))
     ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ThreadId -> Run ()
f)

-- | Forcibly terminate a thread, then continue execution immediately.
asyncKillThread :: ThreadId -> Run ()
asyncKillThread :: ThreadId -> Run ()
asyncKillThread = ProgramT
  RunCMD
  (Param2 Data PrimType')
  (Program CompCMD (Param2 Data PrimType'))
  ()
-> Run ()
forall a.
ProgramT
  RunCMD
  (Param2 Data PrimType')
  (Program CompCMD (Param2 Data PrimType'))
  a
-> Run a
Run (ProgramT
   RunCMD
   (Param2 Data PrimType')
   (Program CompCMD (Param2 Data PrimType'))
   ()
 -> Run ())
-> (ThreadId
    -> ProgramT
         RunCMD
         (Param2 Data PrimType')
         (Program CompCMD (Param2 Data PrimType'))
         ())
-> ThreadId
-> Run ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ThreadId
-> ProgramT
     RunCMD
     (Param2 Data PrimType')
     (Program CompCMD (Param2 Data PrimType'))
     ()
forall k2 (instr :: (* -> *, (* -> *, (k2, *))) -> * -> *)
       (exp :: * -> *) (pred :: k2) (m :: * -> *).
(ThreadCMD :<: instr) =>
ThreadId -> ProgramT instr (Param2 exp pred) m ()
Imp.asyncKillThread

-- | Forcibly terminate a thread. Blocks until the thread is actually dead.
killThread :: ThreadId -> Run ()
killThread :: ThreadId -> Run ()
killThread = ProgramT
  RunCMD
  (Param2 Data PrimType')
  (Program CompCMD (Param2 Data PrimType'))
  ()
-> Run ()
forall a.
ProgramT
  RunCMD
  (Param2 Data PrimType')
  (Program CompCMD (Param2 Data PrimType'))
  a
-> Run a
Run (ProgramT
   RunCMD
   (Param2 Data PrimType')
   (Program CompCMD (Param2 Data PrimType'))
   ()
 -> Run ())
-> (ThreadId
    -> ProgramT
         RunCMD
         (Param2 Data PrimType')
         (Program CompCMD (Param2 Data PrimType'))
         ())
-> ThreadId
-> Run ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ThreadId
-> ProgramT
     RunCMD
     (Param2 Data PrimType')
     (Program CompCMD (Param2 Data PrimType'))
     ()
forall k2 (instr :: (* -> *, (* -> *, (k2, *))) -> * -> *)
       (m :: * -> *) (exp :: * -> *) (pred :: k2).
(ThreadCMD :<: instr, Monad m) =>
ThreadId -> ProgramT instr (Param2 exp pred) m ()
Imp.killThread

-- | Wait for a thread to terminate.
waitThread :: ThreadId -> Run ()
waitThread :: ThreadId -> Run ()
waitThread = ProgramT
  RunCMD
  (Param2 Data PrimType')
  (Program CompCMD (Param2 Data PrimType'))
  ()
-> Run ()
forall a.
ProgramT
  RunCMD
  (Param2 Data PrimType')
  (Program CompCMD (Param2 Data PrimType'))
  a
-> Run a
Run (ProgramT
   RunCMD
   (Param2 Data PrimType')
   (Program CompCMD (Param2 Data PrimType'))
   ()
 -> Run ())
-> (ThreadId
    -> ProgramT
         RunCMD
         (Param2 Data PrimType')
         (Program CompCMD (Param2 Data PrimType'))
         ())
-> ThreadId
-> Run ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ThreadId
-> ProgramT
     RunCMD
     (Param2 Data PrimType')
     (Program CompCMD (Param2 Data PrimType'))
     ()
forall k2 (instr :: (* -> *, (* -> *, (k2, *))) -> * -> *)
       (exp :: * -> *) (pred :: k2) (m :: * -> *).
(ThreadCMD :<: instr) =>
ThreadId -> ProgramT instr (Param2 exp pred) m ()
Imp.waitThread

-- | Sleep for a given amount of microseconds. Implemented with `usleep`.
--   A C compiler might require a feature test macro to be defined,
--   otherwise it emits a warning about an implicitly declared function.
--   For more details, see: http://man7.org/linux/man-pages/man3/usleep.3.html
delayThread :: Integral i => Data i -> Run ()
delayThread :: Data i -> Run ()
delayThread = ProgramT
  RunCMD
  (Param2 Data PrimType')
  (Program CompCMD (Param2 Data PrimType'))
  ()
-> Run ()
forall a.
ProgramT
  RunCMD
  (Param2 Data PrimType')
  (Program CompCMD (Param2 Data PrimType'))
  a
-> Run a
Run (ProgramT
   RunCMD
   (Param2 Data PrimType')
   (Program CompCMD (Param2 Data PrimType'))
   ()
 -> Run ())
-> (Data i
    -> ProgramT
         RunCMD
         (Param2 Data PrimType')
         (Program CompCMD (Param2 Data PrimType'))
         ())
-> Data i
-> Run ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Data i
-> ProgramT
     RunCMD
     (Param2 Data PrimType')
     (Program CompCMD (Param2 Data PrimType'))
     ()
forall k2 i (instr :: (* -> *, (* -> *, (k2, *))) -> * -> *)
       (exp :: * -> *) (pred :: k2) (m :: * -> *).
(Integral i, ThreadCMD :<: instr) =>
exp i -> ProgramT instr (Param2 exp pred) m ()
Imp.delayThread


--------------------------------------------------------------------------------
-- * 'Transferable' classes
--------------------------------------------------------------------------------

class Transferable a
  where
    -- | Size specification of a channel. In most of the cases, it is a natural
    --   number representing how many elements could be stored at the same time
    --   in the channel.
    type SizeSpec a :: *

    -- | Maps a size specification to an internal channel size representation,
    --   that is a map from primitive types to quantities. The byte size of the
    --   channel will be calculated as the sum of multiplying the byte size of
    --   each type with its quantity.
    calcChanSize :: proxy a -> SizeSpec a -> Imp.ChanSize Data PrimType' Length

    -- | Create a new channel. Writing a reference type to a channel will copy
    --   contents into the channel, so modifying it post-write is completely
    --   safe.
    newChan :: SizeSpec a -> Run (Chan Uncloseable a)
    newChan = ProgramT
  RunCMD
  (Param2 Data PrimType')
  (Program CompCMD (Param2 Data PrimType'))
  (Chan Uncloseable a)
-> Run (Chan Uncloseable a)
forall a.
ProgramT
  RunCMD
  (Param2 Data PrimType')
  (Program CompCMD (Param2 Data PrimType'))
  a
-> Run a
Run (ProgramT
   RunCMD
   (Param2 Data PrimType')
   (Program CompCMD (Param2 Data PrimType'))
   (Chan Uncloseable a)
 -> Run (Chan Uncloseable a))
-> (SizeSpec a
    -> ProgramT
         RunCMD
         (Param2 Data PrimType')
         (Program CompCMD (Param2 Data PrimType'))
         (Chan Uncloseable a))
-> SizeSpec a
-> Run (Chan Uncloseable a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ChanSize Data PrimType' Length
-> ProgramT
     RunCMD
     (Param2 Data PrimType')
     (Program CompCMD (Param2 Data PrimType'))
     (Chan Uncloseable a)
forall k i
       (instr :: (* -> *, (* -> *, (* -> Constraint, *))) -> * -> *)
       (exp :: * -> *) (pred :: * -> Constraint) (m :: * -> *) (a :: k).
(Integral i, ChanCMD :<: instr) =>
ChanSize exp pred i
-> ProgramT instr (Param2 exp pred) m (Chan Uncloseable a)
Imp.newChan' (ChanSize Data PrimType' Length
 -> ProgramT
      RunCMD
      (Param2 Data PrimType')
      (Program CompCMD (Param2 Data PrimType'))
      (Chan Uncloseable a))
-> (SizeSpec a -> ChanSize Data PrimType' Length)
-> SizeSpec a
-> ProgramT
     RunCMD
     (Param2 Data PrimType')
     (Program CompCMD (Param2 Data PrimType'))
     (Chan Uncloseable a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Proxy a -> SizeSpec a -> ChanSize Data PrimType' Length
forall a (proxy :: * -> *).
Transferable a =>
proxy a -> SizeSpec a -> ChanSize Data PrimType' Length
calcChanSize (Proxy a
forall k (t :: k). Proxy t
Proxy :: Proxy a)

    newCloseableChan :: SizeSpec a -> Run (Chan Closeable a)
    newCloseableChan = ProgramT
  RunCMD
  (Param2 Data PrimType')
  (Program CompCMD (Param2 Data PrimType'))
  (Chan Closeable a)
-> Run (Chan Closeable a)
forall a.
ProgramT
  RunCMD
  (Param2 Data PrimType')
  (Program CompCMD (Param2 Data PrimType'))
  a
-> Run a
Run (ProgramT
   RunCMD
   (Param2 Data PrimType')
   (Program CompCMD (Param2 Data PrimType'))
   (Chan Closeable a)
 -> Run (Chan Closeable a))
-> (SizeSpec a
    -> ProgramT
         RunCMD
         (Param2 Data PrimType')
         (Program CompCMD (Param2 Data PrimType'))
         (Chan Closeable a))
-> SizeSpec a
-> Run (Chan Closeable a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ChanSize Data PrimType' Length
-> ProgramT
     RunCMD
     (Param2 Data PrimType')
     (Program CompCMD (Param2 Data PrimType'))
     (Chan Closeable a)
forall k i
       (instr :: (* -> *, (* -> *, (* -> Constraint, *))) -> * -> *)
       (exp :: * -> *) (pred :: * -> Constraint) (m :: * -> *) (a :: k).
(Integral i, ChanCMD :<: instr) =>
ChanSize exp pred i
-> ProgramT instr (Param2 exp pred) m (Chan Closeable a)
Imp.newCloseableChan' (ChanSize Data PrimType' Length
 -> ProgramT
      RunCMD
      (Param2 Data PrimType')
      (Program CompCMD (Param2 Data PrimType'))
      (Chan Closeable a))
-> (SizeSpec a -> ChanSize Data PrimType' Length)
-> SizeSpec a
-> ProgramT
     RunCMD
     (Param2 Data PrimType')
     (Program CompCMD (Param2 Data PrimType'))
     (Chan Closeable a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Proxy a -> SizeSpec a -> ChanSize Data PrimType' Length
forall a (proxy :: * -> *).
Transferable a =>
proxy a -> SizeSpec a -> ChanSize Data PrimType' Length
calcChanSize (Proxy a
forall k (t :: k). Proxy t
Proxy :: Proxy a)

    -- | Read an element from a channel. If channel is empty, blocks until there
    --   is an item available.
    --   If 'closeChan' has been called on the channel *and* if the channel is
    --   empty, @readChan@ returns an undefined value immediately.
    readChan :: Chan t a -> Run a
    readChan = Chan t a -> Run a
forall a t c. Transferable a => Chan t c -> Run a
untypedReadChan

    -- | Reads a value from any kind of channel. Instances should define this,
    --   but the user should never call it.
    untypedReadChan :: Chan t c -> Run a

    -- | Write a data element to a channel.
    --   If 'closeChan' has been called on the channel, all calls to @writeChan@
    --   become non-blocking no-ops and return @False@, otherwise returns @True@.
    --   If the channel is full, this function blocks until there's space in the
    --   queue.
    writeChan :: Chan t a -> a -> Run (Data Bool)
    writeChan = Chan t a -> a -> Run (Data Bool)
forall a t c. Transferable a => Chan t c -> a -> Run (Data Bool)
untypedWriteChan

    -- | Writes a value to any kind of channel. Instances should define this,
    --   but the user should never call it.
    untypedWriteChan :: Chan t c -> a -> Run (Data Bool)


class Transferable a => BulkTransferable a
  where
    type ContainerType a :: *

    -- | Read an arbitrary number of elements from a channel into an array.
    --   The semantics are the same as for 'readChan', where "channel is empty"
    --   is defined as "channel contains less data than requested".
    --   Returns @False@ without reading any data if the channel is closed.
    readChanBuf :: Chan t a
                -> Data Index -- ^ Offset in array to start writing
                -> Data Index -- ^ Elements to read
                -> (ContainerType a)
                -> Run (Data Bool)
    readChanBuf = Proxy a
-> Chan t a
-> Data Length
-> Data Length
-> ContainerType a
-> Run (Data Bool)
forall a (proxy :: * -> *) t c.
BulkTransferable a =>
proxy a
-> Chan t c
-> Data Length
-> Data Length
-> ContainerType a
-> Run (Data Bool)
untypedReadChanBuf (Proxy a
forall k (t :: k). Proxy t
Proxy :: Proxy a)

    -- | Read an arbitrary number of elements from any channel into an array.
    --   Instances should define this, but the user should never call it.
    untypedReadChanBuf :: proxy a
                       -> Chan t c
                       -> Data Index -- ^ Offset in array to start writing
                       -> Data Index -- ^ Elements to read
                       -> (ContainerType a)
                       -> Run (Data Bool)

    -- | Write an arbitrary number of elements from an array into an channel.
    --   The semantics are the same as for 'writeChan', where "channel is full"
    --   is defined as "channel has insufficient free space to store all written
    --   data".
    writeChanBuf :: Chan t a
                 -> Data Index -- ^ Offset in array to start reading
                 -> Data Index -- ^ Elements to write
                 -> (ContainerType a)
                 -> Run (Data Bool)
    writeChanBuf = Proxy a
-> Chan t a
-> Data Length
-> Data Length
-> ContainerType a
-> Run (Data Bool)
forall a (proxy :: * -> *) t c.
BulkTransferable a =>
proxy a
-> Chan t c
-> Data Length
-> Data Length
-> ContainerType a
-> Run (Data Bool)
untypedWriteChanBuf (Proxy a
forall k (t :: k). Proxy t
Proxy :: Proxy a)

    -- | Write an arbitrary number of elements from an array into any channel.
    --   Instances should define this, but the user should never call it.
    untypedWriteChanBuf :: proxy a
                        -> Chan t c
                        -> Data Index -- ^ Offset in array to start reading
                        -> Data Index -- ^ Elements to write
                        -> (ContainerType a)
                        -> Run (Data Bool)

-- | When 'readChan' was last called on the given channel, did the read
--   succeed?
--   Always returns @True@ unless 'closeChan' has been called on the channel.
--   Always returns @True@ if the channel has never been read.
lastChanReadOK :: Chan Closeable a -> Run (Data Bool)
lastChanReadOK :: Chan Closeable a -> Run (Data Bool)
lastChanReadOK = ProgramT
  RunCMD
  (Param2 Data PrimType')
  (Program CompCMD (Param2 Data PrimType'))
  (Data Bool)
-> Run (Data Bool)
forall a.
ProgramT
  RunCMD
  (Param2 Data PrimType')
  (Program CompCMD (Param2 Data PrimType'))
  a
-> Run a
Run (ProgramT
   RunCMD
   (Param2 Data PrimType')
   (Program CompCMD (Param2 Data PrimType'))
   (Data Bool)
 -> Run (Data Bool))
-> (Chan Closeable a
    -> ProgramT
         RunCMD
         (Param2 Data PrimType')
         (Program CompCMD (Param2 Data PrimType'))
         (Data Bool))
-> Chan Closeable a
-> Run (Data Bool)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Chan Closeable a
-> ProgramT
     RunCMD
     (Param2 Data PrimType')
     (Program CompCMD (Param2 Data PrimType'))
     (Data Bool)
forall k (exp :: * -> *)
       (instr :: (* -> *, (* -> *, (* -> Constraint, *))) -> * -> *)
       (m :: * -> *) (c :: k) (pred :: * -> Constraint).
(FreeExp exp, FreePred exp Bool, ChanCMD :<: instr, Monad m) =>
Chan Closeable c -> ProgramT instr (Param2 exp pred) m (exp Bool)
Imp.lastChanReadOK

-- | Close a channel. All subsequent write operations will be no-ops.
--   After the channel is drained, all subsequent read operations will be
--   no-ops as well.
closeChan :: Chan Closeable a -> Run ()
closeChan :: Chan Closeable a -> Run ()
closeChan = ProgramT
  RunCMD
  (Param2 Data PrimType')
  (Program CompCMD (Param2 Data PrimType'))
  ()
-> Run ()
forall a.
ProgramT
  RunCMD
  (Param2 Data PrimType')
  (Program CompCMD (Param2 Data PrimType'))
  a
-> Run a
Run (ProgramT
   RunCMD
   (Param2 Data PrimType')
   (Program CompCMD (Param2 Data PrimType'))
   ()
 -> Run ())
-> (Chan Closeable a
    -> ProgramT
         RunCMD
         (Param2 Data PrimType')
         (Program CompCMD (Param2 Data PrimType'))
         ())
-> Chan Closeable a
-> Run ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Chan Closeable a
-> ProgramT
     RunCMD
     (Param2 Data PrimType')
     (Program CompCMD (Param2 Data PrimType'))
     ()
forall k
       (instr :: (* -> *, (* -> *, (* -> Constraint, *))) -> * -> *)
       (c :: k) (exp :: * -> *) (pred :: * -> Constraint) (m :: * -> *).
(ChanCMD :<: instr) =>
Chan Closeable c -> ProgramT instr (Param2 exp pred) m ()
Imp.closeChan


--------------------------------------------------------------------------------
-- * 'Transferable' instances
--------------------------------------------------------------------------------

instance PrimType' a => Transferable (Data a)
  where
    type SizeSpec (Data a) = Data Length
    calcChanSize :: proxy (Data a)
-> SizeSpec (Data a) -> ChanSize Data PrimType' Length
calcChanSize proxy (Data a)
_ SizeSpec (Data a)
sz = Data Length
SizeSpec (Data a)
sz Data Length -> Proxy a -> ChanSize Data PrimType' Length
forall k (pred :: k -> Constraint) (a :: k) i (exp :: * -> *)
       (proxy :: k -> *).
(pred a, Integral i) =>
exp i -> proxy a -> ChanSize exp pred i
`Imp.timesSizeOf` (Proxy a
forall k (t :: k). Proxy t
Proxy :: Proxy a)
    untypedReadChan :: Chan t c -> Run (Data a)
untypedReadChan    = ProgramT
  RunCMD
  (Param2 Data PrimType')
  (Program CompCMD (Param2 Data PrimType'))
  (Data a)
-> Run (Data a)
forall a.
ProgramT
  RunCMD
  (Param2 Data PrimType')
  (Program CompCMD (Param2 Data PrimType'))
  a
-> Run a
Run (ProgramT
   RunCMD
   (Param2 Data PrimType')
   (Program CompCMD (Param2 Data PrimType'))
   (Data a)
 -> Run (Data a))
-> (Chan t c
    -> ProgramT
         RunCMD
         (Param2 Data PrimType')
         (Program CompCMD (Param2 Data PrimType'))
         (Data a))
-> Chan t c
-> Run (Data a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Chan t c
-> ProgramT
     RunCMD
     (Param2 Data PrimType')
     (Program CompCMD (Param2 Data PrimType'))
     (Data a)
forall k1 k2 a (pred :: * -> Constraint) (exp :: * -> *)
       (instr :: (* -> *, (* -> *, (* -> Constraint, *))) -> * -> *)
       (m :: * -> *) (t :: k1) (c :: k2).
(Typeable a, pred a, FreeExp exp, FreePred exp a,
 ChanCMD :<: instr, Monad m) =>
Chan t c -> ProgramT instr (Param2 exp pred) m (exp a)
Imp.readChan'
    untypedWriteChan :: Chan t c -> Data a -> Run (Data Bool)
untypedWriteChan Chan t c
c = ProgramT
  RunCMD
  (Param2 Data PrimType')
  (Program CompCMD (Param2 Data PrimType'))
  (Data Bool)
-> Run (Data Bool)
forall a.
ProgramT
  RunCMD
  (Param2 Data PrimType')
  (Program CompCMD (Param2 Data PrimType'))
  a
-> Run a
Run (ProgramT
   RunCMD
   (Param2 Data PrimType')
   (Program CompCMD (Param2 Data PrimType'))
   (Data Bool)
 -> Run (Data Bool))
-> (Data a
    -> ProgramT
         RunCMD
         (Param2 Data PrimType')
         (Program CompCMD (Param2 Data PrimType'))
         (Data Bool))
-> Data a
-> Run (Data Bool)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Chan t c
-> Data a
-> ProgramT
     RunCMD
     (Param2 Data PrimType')
     (Program CompCMD (Param2 Data PrimType'))
     (Data Bool)
forall k1 k2 a (pred :: * -> Constraint) (exp :: * -> *)
       (instr :: (* -> *, (* -> *, (* -> Constraint, *))) -> * -> *)
       (m :: * -> *) (t :: k1) (c :: k2).
(Typeable a, pred a, FreeExp exp, FreePred exp Bool,
 ChanCMD :<: instr, Monad m) =>
Chan t c -> exp a -> ProgramT instr (Param2 exp pred) m (exp Bool)
Imp.writeChan' Chan t c
c

instance PrimType' a => BulkTransferable (Data a)
  where
    type ContainerType (Data a) = DArr a
    untypedReadChanBuf :: proxy (Data a)
-> Chan t c
-> Data Length
-> Data Length
-> ContainerType (Data a)
-> Run (Data Bool)
untypedReadChanBuf  proxy (Data a)
_ Chan t c
c Data Length
off Data Length
len ContainerType (Data a)
arr = do
      [Data Bool]
r <- [Run (Data Bool)] -> Run [Data Bool]
forall (t :: * -> *) (m :: * -> *) a.
(Traversable t, Monad m) =>
t (m a) -> m (t a)
sequence ([Run (Data Bool)] -> Run [Data Bool])
-> [Run (Data Bool)] -> Run [Data Bool]
forall a b. (a -> b) -> a -> b
$ (forall y. PrimType' y => Arr Length y -> Run (Data Bool))
-> Struct PrimType' (Arr Length) a -> [Run (Data Bool)]
forall (pred :: * -> Constraint) (cont :: * -> *) b c.
(forall y. pred y => cont y -> c) -> Struct pred cont b -> [c]
listStruct (ProgramT
  RunCMD
  (Param2 Data PrimType')
  (Program CompCMD (Param2 Data PrimType'))
  (Data Bool)
-> Run (Data Bool)
forall a.
ProgramT
  RunCMD
  (Param2 Data PrimType')
  (Program CompCMD (Param2 Data PrimType'))
  a
-> Run a
Run (ProgramT
   RunCMD
   (Param2 Data PrimType')
   (Program CompCMD (Param2 Data PrimType'))
   (Data Bool)
 -> Run (Data Bool))
-> (Arr Length y
    -> ProgramT
         RunCMD
         (Param2 Data PrimType')
         (Program CompCMD (Param2 Data PrimType'))
         (Data Bool))
-> Arr Length y
-> Run (Data Bool)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Chan t c
-> Data Length
-> Data Length
-> Arr Length y
-> ProgramT
     RunCMD
     (Param2 Data PrimType')
     (Program CompCMD (Param2 Data PrimType'))
     (Data Bool)
forall k1 k2 a (pred :: * -> Constraint) i (exp :: * -> *)
       (instr :: (* -> *, (* -> *, (* -> Constraint, *))) -> * -> *)
       (m :: * -> *) (t :: k1) (c :: k2).
(Typeable a, pred a, pred i, Ix i, Integral i, FreeExp exp,
 FreePred exp Bool, ChanCMD :<: instr, Monad m) =>
Chan t c
-> exp i
-> exp i
-> Arr i a
-> ProgramT instr (Param2 exp pred) m (exp Bool)
Imp.readChanBuf' Chan t c
c Data Length
off Data Length
len) (Arr (Data a) -> Struct PrimType' (Arr Length) (Internal (Data a))
forall a. Arr a -> Struct PrimType' (Arr Length) (Internal a)
unArr Arr (Data a)
ContainerType (Data a)
arr)
      Data Bool -> Run (Data Bool)
forall (m :: * -> *) a. Monad m => a -> m a
return (Data Bool -> Run (Data Bool)) -> Data Bool -> Run (Data Bool)
forall a b. (a -> b) -> a -> b
$ (Data Bool -> Data Bool -> Data Bool) -> [Data Bool] -> Data Bool
forall (t :: * -> *) a. Foldable t => (a -> a -> a) -> t a -> a
foldl1 Data Bool -> Data Bool -> Data Bool
(&&) [Data Bool]
r
    untypedWriteChanBuf :: proxy (Data a)
-> Chan t c
-> Data Length
-> Data Length
-> ContainerType (Data a)
-> Run (Data Bool)
untypedWriteChanBuf proxy (Data a)
_ Chan t c
c Data Length
off Data Length
len ContainerType (Data a)
arr = do
      [Data Bool]
r <- [Run (Data Bool)] -> Run [Data Bool]
forall (t :: * -> *) (m :: * -> *) a.
(Traversable t, Monad m) =>
t (m a) -> m (t a)
sequence ([Run (Data Bool)] -> Run [Data Bool])
-> [Run (Data Bool)] -> Run [Data Bool]
forall a b. (a -> b) -> a -> b
$ (forall y. PrimType' y => Arr Length y -> Run (Data Bool))
-> Struct PrimType' (Arr Length) a -> [Run (Data Bool)]
forall (pred :: * -> Constraint) (cont :: * -> *) b c.
(forall y. pred y => cont y -> c) -> Struct pred cont b -> [c]
listStruct (ProgramT
  RunCMD
  (Param2 Data PrimType')
  (Program CompCMD (Param2 Data PrimType'))
  (Data Bool)
-> Run (Data Bool)
forall a.
ProgramT
  RunCMD
  (Param2 Data PrimType')
  (Program CompCMD (Param2 Data PrimType'))
  a
-> Run a
Run (ProgramT
   RunCMD
   (Param2 Data PrimType')
   (Program CompCMD (Param2 Data PrimType'))
   (Data Bool)
 -> Run (Data Bool))
-> (Arr Length y
    -> ProgramT
         RunCMD
         (Param2 Data PrimType')
         (Program CompCMD (Param2 Data PrimType'))
         (Data Bool))
-> Arr Length y
-> Run (Data Bool)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Chan t c
-> Data Length
-> Data Length
-> Arr Length y
-> ProgramT
     RunCMD
     (Param2 Data PrimType')
     (Program CompCMD (Param2 Data PrimType'))
     (Data Bool)
forall k1 k2 a (pred :: * -> Constraint) i (exp :: * -> *)
       (instr :: (* -> *, (* -> *, (* -> Constraint, *))) -> * -> *)
       (m :: * -> *) (t :: k1) (c :: k2).
(Typeable a, pred a, pred i, Ix i, Integral i, FreeExp exp,
 FreePred exp Bool, ChanCMD :<: instr, Monad m) =>
Chan t c
-> exp i
-> exp i
-> Arr i a
-> ProgramT instr (Param2 exp pred) m (exp Bool)
Imp.writeChanBuf' Chan t c
c Data Length
off Data Length
len) (Arr (Data a) -> Struct PrimType' (Arr Length) (Internal (Data a))
forall a. Arr a -> Struct PrimType' (Arr Length) (Internal a)
unArr Arr (Data a)
ContainerType (Data a)
arr)
      Data Bool -> Run (Data Bool)
forall (m :: * -> *) a. Monad m => a -> m a
return (Data Bool -> Run (Data Bool)) -> Data Bool -> Run (Data Bool)
forall a b. (a -> b) -> a -> b
$ (Data Bool -> Data Bool -> Data Bool) -> [Data Bool] -> Data Bool
forall (t :: * -> *) a. Foldable t => (a -> a -> a) -> t a -> a
foldl1 Data Bool -> Data Bool -> Data Bool
(&&) [Data Bool]
r

instance ( Transferable a, Transferable b
         , SizeSpec a ~ SizeSpec b
         ) => Transferable (a, b)
  where
    type SizeSpec (a, b) = SizeSpec a
    calcChanSize :: proxy (a, b) -> SizeSpec (a, b) -> ChanSize Data PrimType' Length
calcChanSize proxy (a, b)
_ SizeSpec (a, b)
sz =
      let asz :: ChanSize Data PrimType' Length
asz = Proxy a -> SizeSpec a -> ChanSize Data PrimType' Length
forall a (proxy :: * -> *).
Transferable a =>
proxy a -> SizeSpec a -> ChanSize Data PrimType' Length
calcChanSize (Proxy a
forall k (t :: k). Proxy t
Proxy :: Proxy a) SizeSpec a
SizeSpec (a, b)
sz
          bsz :: ChanSize Data PrimType' Length
bsz = Proxy b -> SizeSpec b -> ChanSize Data PrimType' Length
forall a (proxy :: * -> *).
Transferable a =>
proxy a -> SizeSpec a -> ChanSize Data PrimType' Length
calcChanSize (Proxy b
forall k (t :: k). Proxy t
Proxy :: Proxy b) SizeSpec b
SizeSpec (a, b)
sz
      in  ChanSize Data PrimType' Length
asz ChanSize Data PrimType' Length
-> ChanSize Data PrimType' Length -> ChanSize Data PrimType' Length
forall k i (exp :: * -> *) (pred :: k -> Constraint).
Integral i =>
ChanSize exp pred i -> ChanSize exp pred i -> ChanSize exp pred i
`Imp.plusSize` ChanSize Data PrimType' Length
bsz
    untypedReadChan :: Chan t c -> Run (a, b)
untypedReadChan Chan t c
ch = (,) (a -> b -> (a, b)) -> Run a -> Run (b -> (a, b))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Chan t c -> Run a
forall a t c. Transferable a => Chan t c -> Run a
untypedReadChan Chan t c
ch Run (b -> (a, b)) -> Run b -> Run (a, b)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Chan t c -> Run b
forall a t c. Transferable a => Chan t c -> Run a
untypedReadChan Chan t c
ch
    untypedWriteChan :: Chan t c -> (a, b) -> Run (Data Bool)
untypedWriteChan Chan t c
ch (a
a, b
b) = do
      Data Bool
sa <- Chan t c -> a -> Run (Data Bool)
forall a t c. Transferable a => Chan t c -> a -> Run (Data Bool)
untypedWriteChan Chan t c
ch a
a
      Data Bool -> Run (Data Bool) -> Run (Data Bool) -> Run (Data Bool)
forall a (m :: * -> *).
(Syntax a, MonadComp m) =>
Data Bool -> m a -> m a -> m a
ifE Data Bool
sa (Chan t c -> b -> Run (Data Bool)
forall a t c. Transferable a => Chan t c -> a -> Run (Data Bool)
untypedWriteChan Chan t c
ch b
b) (Data Bool -> Run (Data Bool)
forall (m :: * -> *) a. Monad m => a -> m a
return Data Bool
false)

instance ( Transferable a, Transferable b, Transferable c
         , SizeSpec a ~ SizeSpec b, SizeSpec b ~ SizeSpec c
         ) => Transferable (a, b, c)
  where
    type SizeSpec (a, b, c) = SizeSpec a
    calcChanSize :: proxy (a, b, c)
-> SizeSpec (a, b, c) -> ChanSize Data PrimType' Length
calcChanSize proxy (a, b, c)
_ SizeSpec (a, b, c)
sz =
      let asz :: ChanSize Data PrimType' Length
asz = Proxy a -> SizeSpec a -> ChanSize Data PrimType' Length
forall a (proxy :: * -> *).
Transferable a =>
proxy a -> SizeSpec a -> ChanSize Data PrimType' Length
calcChanSize (Proxy a
forall k (t :: k). Proxy t
Proxy :: Proxy a) SizeSpec a
SizeSpec (a, b, c)
sz
          bsz :: ChanSize Data PrimType' Length
bsz = Proxy b -> SizeSpec b -> ChanSize Data PrimType' Length
forall a (proxy :: * -> *).
Transferable a =>
proxy a -> SizeSpec a -> ChanSize Data PrimType' Length
calcChanSize (Proxy b
forall k (t :: k). Proxy t
Proxy :: Proxy b) SizeSpec b
SizeSpec (a, b, c)
sz
          csz :: ChanSize Data PrimType' Length
csz = Proxy c -> SizeSpec c -> ChanSize Data PrimType' Length
forall a (proxy :: * -> *).
Transferable a =>
proxy a -> SizeSpec a -> ChanSize Data PrimType' Length
calcChanSize (Proxy c
forall k (t :: k). Proxy t
Proxy :: Proxy c) SizeSpec c
SizeSpec (a, b, c)
sz
      in  ChanSize Data PrimType' Length
asz ChanSize Data PrimType' Length
-> ChanSize Data PrimType' Length -> ChanSize Data PrimType' Length
forall k i (exp :: * -> *) (pred :: k -> Constraint).
Integral i =>
ChanSize exp pred i -> ChanSize exp pred i -> ChanSize exp pred i
`Imp.plusSize` ChanSize Data PrimType' Length
bsz ChanSize Data PrimType' Length
-> ChanSize Data PrimType' Length -> ChanSize Data PrimType' Length
forall k i (exp :: * -> *) (pred :: k -> Constraint).
Integral i =>
ChanSize exp pred i -> ChanSize exp pred i -> ChanSize exp pred i
`Imp.plusSize` ChanSize Data PrimType' Length
csz
    untypedReadChan :: Chan t c -> Run (a, b, c)
untypedReadChan Chan t c
ch = (,,)
                     (a -> b -> c -> (a, b, c)) -> Run a -> Run (b -> c -> (a, b, c))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Chan t c -> Run a
forall a t c. Transferable a => Chan t c -> Run a
untypedReadChan Chan t c
ch
                     Run (b -> c -> (a, b, c)) -> Run b -> Run (c -> (a, b, c))
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Chan t c -> Run b
forall a t c. Transferable a => Chan t c -> Run a
untypedReadChan Chan t c
ch
                     Run (c -> (a, b, c)) -> Run c -> Run (a, b, c)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Chan t c -> Run c
forall a t c. Transferable a => Chan t c -> Run a
untypedReadChan Chan t c
ch
    untypedWriteChan :: Chan t c -> (a, b, c) -> Run (Data Bool)
untypedWriteChan Chan t c
ch (a
a, b
b, c
c) = do
      Data Bool
sa <- Chan t c -> a -> Run (Data Bool)
forall a t c. Transferable a => Chan t c -> a -> Run (Data Bool)
untypedWriteChan Chan t c
ch a
a
      Data Bool -> Run (Data Bool) -> Run (Data Bool) -> Run (Data Bool)
forall a (m :: * -> *).
(Syntax a, MonadComp m) =>
Data Bool -> m a -> m a -> m a
ifE Data Bool
sa
        (do Data Bool
sb <- Chan t c -> b -> Run (Data Bool)
forall a t c. Transferable a => Chan t c -> a -> Run (Data Bool)
untypedWriteChan Chan t c
ch b
b
            Data Bool -> Run (Data Bool) -> Run (Data Bool) -> Run (Data Bool)
forall a (m :: * -> *).
(Syntax a, MonadComp m) =>
Data Bool -> m a -> m a -> m a
ifE Data Bool
sb (Chan t c -> c -> Run (Data Bool)
forall a t c. Transferable a => Chan t c -> a -> Run (Data Bool)
untypedWriteChan Chan t c
ch c
c) (Data Bool -> Run (Data Bool)
forall (m :: * -> *) a. Monad m => a -> m a
return Data Bool
false))
        (Data Bool -> Run (Data Bool)
forall (m :: * -> *) a. Monad m => a -> m a
return Data Bool
false)

instance ( Transferable a, Transferable b, Transferable c, Transferable d
         , SizeSpec a ~ SizeSpec b, SizeSpec b ~ SizeSpec c, SizeSpec c ~ SizeSpec d
         ) => Transferable (a, b, c, d)
  where
    type SizeSpec (a, b, c, d) = SizeSpec a
    calcChanSize :: proxy (a, b, c, d)
-> SizeSpec (a, b, c, d) -> ChanSize Data PrimType' Length
calcChanSize proxy (a, b, c, d)
_ SizeSpec (a, b, c, d)
sz =
      let asz :: ChanSize Data PrimType' Length
asz = Proxy a -> SizeSpec a -> ChanSize Data PrimType' Length
forall a (proxy :: * -> *).
Transferable a =>
proxy a -> SizeSpec a -> ChanSize Data PrimType' Length
calcChanSize (Proxy a
forall k (t :: k). Proxy t
Proxy :: Proxy a) SizeSpec a
SizeSpec (a, b, c, d)
sz
          bsz :: ChanSize Data PrimType' Length
bsz = Proxy b -> SizeSpec b -> ChanSize Data PrimType' Length
forall a (proxy :: * -> *).
Transferable a =>
proxy a -> SizeSpec a -> ChanSize Data PrimType' Length
calcChanSize (Proxy b
forall k (t :: k). Proxy t
Proxy :: Proxy b) SizeSpec b
SizeSpec (a, b, c, d)
sz
          csz :: ChanSize Data PrimType' Length
csz = Proxy c -> SizeSpec c -> ChanSize Data PrimType' Length
forall a (proxy :: * -> *).
Transferable a =>
proxy a -> SizeSpec a -> ChanSize Data PrimType' Length
calcChanSize (Proxy c
forall k (t :: k). Proxy t
Proxy :: Proxy c) SizeSpec c
SizeSpec (a, b, c, d)
sz
          dsz :: ChanSize Data PrimType' Length
dsz = Proxy d -> SizeSpec d -> ChanSize Data PrimType' Length
forall a (proxy :: * -> *).
Transferable a =>
proxy a -> SizeSpec a -> ChanSize Data PrimType' Length
calcChanSize (Proxy d
forall k (t :: k). Proxy t
Proxy :: Proxy d) SizeSpec d
SizeSpec (a, b, c, d)
sz
      in  ChanSize Data PrimType' Length
asz ChanSize Data PrimType' Length
-> ChanSize Data PrimType' Length -> ChanSize Data PrimType' Length
forall k i (exp :: * -> *) (pred :: k -> Constraint).
Integral i =>
ChanSize exp pred i -> ChanSize exp pred i -> ChanSize exp pred i
`Imp.plusSize` ChanSize Data PrimType' Length
bsz ChanSize Data PrimType' Length
-> ChanSize Data PrimType' Length -> ChanSize Data PrimType' Length
forall k i (exp :: * -> *) (pred :: k -> Constraint).
Integral i =>
ChanSize exp pred i -> ChanSize exp pred i -> ChanSize exp pred i
`Imp.plusSize` ChanSize Data PrimType' Length
csz ChanSize Data PrimType' Length
-> ChanSize Data PrimType' Length -> ChanSize Data PrimType' Length
forall k i (exp :: * -> *) (pred :: k -> Constraint).
Integral i =>
ChanSize exp pred i -> ChanSize exp pred i -> ChanSize exp pred i
`Imp.plusSize` ChanSize Data PrimType' Length
dsz
    untypedReadChan :: Chan t c -> Run (a, b, c, d)
untypedReadChan Chan t c
ch = (,,,)
                     (a -> b -> c -> d -> (a, b, c, d))
-> Run a -> Run (b -> c -> d -> (a, b, c, d))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Chan t c -> Run a
forall a t c. Transferable a => Chan t c -> Run a
untypedReadChan Chan t c
ch
                     Run (b -> c -> d -> (a, b, c, d))
-> Run b -> Run (c -> d -> (a, b, c, d))
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Chan t c -> Run b
forall a t c. Transferable a => Chan t c -> Run a
untypedReadChan Chan t c
ch
                     Run (c -> d -> (a, b, c, d)) -> Run c -> Run (d -> (a, b, c, d))
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Chan t c -> Run c
forall a t c. Transferable a => Chan t c -> Run a
untypedReadChan Chan t c
ch
                     Run (d -> (a, b, c, d)) -> Run d -> Run (a, b, c, d)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Chan t c -> Run d
forall a t c. Transferable a => Chan t c -> Run a
untypedReadChan Chan t c
ch
    untypedWriteChan :: Chan t c -> (a, b, c, d) -> Run (Data Bool)
untypedWriteChan Chan t c
ch (a
a, b
b, c
c, d
d) = do
      Data Bool
sa <- Chan t c -> a -> Run (Data Bool)
forall a t c. Transferable a => Chan t c -> a -> Run (Data Bool)
untypedWriteChan Chan t c
ch a
a
      Data Bool -> Run (Data Bool) -> Run (Data Bool) -> Run (Data Bool)
forall a (m :: * -> *).
(Syntax a, MonadComp m) =>
Data Bool -> m a -> m a -> m a
ifE Data Bool
sa
        (do Data Bool
sb <- Chan t c -> b -> Run (Data Bool)
forall a t c. Transferable a => Chan t c -> a -> Run (Data Bool)
untypedWriteChan Chan t c
ch b
b
            Data Bool -> Run (Data Bool) -> Run (Data Bool) -> Run (Data Bool)
forall a (m :: * -> *).
(Syntax a, MonadComp m) =>
Data Bool -> m a -> m a -> m a
ifE Data Bool
sb
              (do Data Bool
sc <- Chan t c -> c -> Run (Data Bool)
forall a t c. Transferable a => Chan t c -> a -> Run (Data Bool)
untypedWriteChan Chan t c
ch c
c
                  Data Bool -> Run (Data Bool) -> Run (Data Bool) -> Run (Data Bool)
forall a (m :: * -> *).
(Syntax a, MonadComp m) =>
Data Bool -> m a -> m a -> m a
ifE Data Bool
sc
                    (Chan t c -> d -> Run (Data Bool)
forall a t c. Transferable a => Chan t c -> a -> Run (Data Bool)
untypedWriteChan Chan t c
ch d
d)
                    (Data Bool -> Run (Data Bool)
forall (m :: * -> *) a. Monad m => a -> m a
return Data Bool
false))
              (Data Bool -> Run (Data Bool)
forall (m :: * -> *) a. Monad m => a -> m a
return Data Bool
false))
        (Data Bool -> Run (Data Bool)
forall (m :: * -> *) a. Monad m => a -> m a
return Data Bool
false)