{-# LANGUAGE NoImplicitPrelude #-}
{-# LANGUAGE EmptyDataDecls #-}
{-# LANGUAGE FlexibleContexts #-}

module Data.Var
  (
  -- * Different types of variables
    Sig
  , newSig
  , Ref
  , newRef
  , Var
  , newVar

  -- * Generic operations
  , Settable
  , set
  , Gettable
  , get
  , modify
  , modifyWith
  , Subscribable
  , subscribe
  , withUnsubscriber

  -- * Specific operations
  , subscribeWithOld
  , subscribeChange
  , subscribeAndRead
  , subscribeChangeAndRead
  , subscribeExclusive
  , subscribeAndReadExclusive
  , mapVar
  , mergeVars
  , mergeVars'
  , tupleVars
  , tupleVars'
  , waitForN
  , waitFor
  , oneShot
  , holdSig

  ) where

import Data.Maybe
import FFI
import Prelude

-- | A subscribable signal.  Can have handlers subscribed to them, but doesn't
--   store a value.
data Sig a

-- | Make a new signal.
newSig :: Fay (Ptr (Sig a))
newSig :: Fay (Ptr (Sig a))
newSig = [Char] -> Fay (Ptr (Sig a))
forall s a. IsString s => s -> a
ffi [Char]
"new Fay$$Sig()"

-- | A mutable reference, with no subscribers.
data Ref a

-- | Make a new mutable reference.
newRef :: Ptr a -> Fay (Ptr (Ref a))
newRef :: Ptr a -> Fay (Ptr (Ref (Ptr a)))
newRef = [Char] -> Ptr a -> Fay (Ptr (Ref (Ptr a)))
forall s a. IsString s => s -> a
ffi [Char]
"new Fay$$Ref2(%1)"

-- | A reactive variable.  Stores a value, and can have handlers subscribed to
--   changes.
data Var a

-- | Make a new reactive variable.
newVar :: Ptr a -> Fay (Ptr (Var a))
newVar :: Ptr a -> Fay (Ptr (Var (Ptr a)))
newVar = [Char] -> Ptr a -> Fay (Ptr (Var (Ptr a)))
forall s a. IsString s => s -> a
ffi [Char]
"new Fay$$Var(%1)"


-- | All of the variable types can be set to a value.
class Settable v
instance Settable (Ref a)
instance Settable (Sig a)
instance Settable (Var a)

-- | Write to the value (if any), and call subscribers (if any).
set :: Settable (v a) => Ptr (v a) -> Ptr a -> Fay ()
set :: Ptr (v a) -> a -> Fay ()
set = [Char] -> Ptr (v a) -> a -> Fay ()
forall s a. IsString s => s -> a
ffi [Char]
"Fay$$setValue(Fay$$_(%1), %2, Fay$$_)"


-- | 'Ref' and 'Var' store their last set value.
class Gettable v
instance Gettable (Ref a)
instance Gettable (Var a)

-- | Get the value of a 'Ref' or 'Var'.
get :: Gettable (v a) => Ptr (v a) -> Fay (Ptr a)
get :: Ptr (v a) -> Fay a
get = [Char] -> Ptr (v a) -> Fay a
forall s a. IsString s => s -> a
ffi [Char]
"Fay$$_(%1).val"

-- | Modifies the current value with a pure function.
modify :: (Settable (v a), Gettable (v a)) => v a -> (a -> a) -> Fay ()
modify :: v a -> (a -> a) -> Fay ()
modify v a
v a -> a
f = v a -> Fay a
forall (v :: * -> *) a. Gettable (v a) => v a -> Fay a
get v a
v Fay a -> Ptr (a -> Fay ()) -> Fay ()
forall a b. Ptr (Fay a) -> Ptr (a -> Fay b) -> Fay b
>>= v a -> Ptr (a -> Fay ())
forall (v :: * -> *) a. Settable (v a) => v a -> a -> Fay ()
set v a
v Ptr (a -> Fay ()) -> (a -> a) -> Ptr (a -> Fay ())
forall t1 t t2. (t1 -> t) -> (t2 -> t1) -> t2 -> t
. a -> a
f

-- | Runs a 'Fay' action on the current value, and updates with the result.
modifyWith :: (Settable (v a), Gettable (v a)) => v a -> (a -> Fay a) -> Fay ()
modifyWith :: v a -> (a -> Fay a) -> Fay ()
modifyWith v a
v a -> Fay a
f = v a -> Fay a
forall (v :: * -> *) a. Gettable (v a) => v a -> Fay a
get v a
v Fay a -> (a -> Fay a) -> Fay a
forall a b. Ptr (Fay a) -> Ptr (a -> Fay b) -> Fay b
>>= a -> Fay a
f Fay a -> Ptr (a -> Fay ()) -> Fay ()
forall a b. Ptr (Fay a) -> Ptr (a -> Fay b) -> Fay b
>>= v a -> Ptr (a -> Fay ())
forall (v :: * -> *) a. Settable (v a) => v a -> a -> Fay ()
set v a
v

-- | 'Sig' and 'Var' have lists of subscribers that are notified when 'set' is
--   used.
class Settable v => Subscribable v
instance Subscribable (Sig a)
instance Subscribable (Var a)

-- | Subscribe to the value of a 'Sig' or 'Var'.
--
--   The result is an unsubscribe function.
subscribe :: Subscribable (v a) => Ptr (v a) -> Ptr (a -> Fay void) -> Fay (() -> Fay ())
subscribe :: Ptr (v a) -> Ptr (a -> Fay void) -> Fay (() -> Fay ())
subscribe = [Char] -> Ptr (v a) -> Ptr (a -> Fay void) -> Fay (() -> Fay ())
forall s a. IsString s => s -> a
ffi [Char]
"Fay$$subscribe(Fay$$_(%1), Fay$$_(%2))"

-- | Run the same subscribing action but provide an additional
-- unsubscribe parameter to the handler.
withUnsubscriber :: ((a -> Fay ()) -> Fay (() -> Fay ()))
                 -> (((() -> Fay ()) -> a -> Fay ()) -> Fay (() -> Fay ()))
withUnsubscriber :: ((a -> Fay ()) -> Fay (() -> Fay ()))
-> ((() -> Fay ()) -> a -> Fay ()) -> Fay (() -> Fay ())
withUnsubscriber (a -> Fay ()) -> Fay (() -> Fay ())
f = \(() -> Fay ()) -> a -> Fay ()
g -> do
  Ptr (Ref (Maybe (() -> Fay ())))
unsubscriber <- Maybe (() -> Fay ()) -> Fay (Ptr (Ref (Maybe (() -> Fay ()))))
forall a. Ptr a -> Fay (Ptr (Ref (Ptr a)))
newRef Maybe (() -> Fay ())
forall a. Maybe a
Nothing
  () -> Fay ()
unsubscribe <- (a -> Fay ()) -> Fay (() -> Fay ())
f ((a -> Fay ()) -> Fay (() -> Fay ()))
-> (a -> Fay ()) -> Fay (() -> Fay ())
forall t1 t. (t1 -> t) -> t1 -> t
$ \a
v -> do Maybe (() -> Fay ())
munsubscriber <- Ptr (Ref (Maybe (() -> Fay ()))) -> Fay (Maybe (() -> Fay ()))
forall (v :: * -> *) a. Gettable (v a) => v a -> Fay a
get Ptr (Ref (Maybe (() -> Fay ())))
unsubscriber
                              Maybe (() -> Fay ()) -> ((() -> Fay ()) -> Fay ()) -> Fay ()
forall a. Maybe a -> (a -> Fay ()) -> Fay ()
whenJust Maybe (() -> Fay ())
munsubscriber (((() -> Fay ()) -> Fay ()) -> Fay ())
-> ((() -> Fay ()) -> Fay ()) -> Fay ()
forall t1 t. (t1 -> t) -> t1 -> t
$ \() -> Fay ()
unsubscribe -> (() -> Fay ()) -> a -> Fay ()
g () -> Fay ()
unsubscribe a
v
  Ptr (Ref (Maybe (() -> Fay ()))) -> Maybe (() -> Fay ()) -> Fay ()
forall (v :: * -> *) a. Settable (v a) => v a -> a -> Fay ()
set Ptr (Ref (Maybe (() -> Fay ())))
unsubscriber ((() -> Fay ()) -> Maybe (() -> Fay ())
forall a. a -> Maybe a
Just () -> Fay ()
unsubscribe)
  (() -> Fay ()) -> Fay (() -> Fay ())
forall a. a -> Fay a
return () -> Fay ()
unsubscribe

-- | Subscribe to a 'Var', along with the previous value.
--
--   The result is an unsubscribe function.
subscribeWithOld :: Var a -> (a -> a -> Fay ()) -> Fay (() -> Fay ())
subscribeWithOld :: Var a -> (a -> a -> Fay ()) -> Fay (() -> Fay ())
subscribeWithOld Var a
v a -> a -> Fay ()
f = do
  Ptr (Ref a)
o <- Var a -> Fay a
forall (v :: * -> *) a. Gettable (v a) => v a -> Fay a
get Var a
v Fay a -> Ptr (a -> Fay (Ptr (Ref a))) -> Fay (Ptr (Ref a))
forall a b. Ptr (Fay a) -> Ptr (a -> Fay b) -> Fay b
>>= Ptr (a -> Fay (Ptr (Ref a)))
forall a. Ptr a -> Fay (Ptr (Ref (Ptr a)))
newRef
  Var a -> (a -> Fay ()) -> Fay (() -> Fay ())
forall (v :: * -> *) a void.
Subscribable (v a) =>
v a -> Ptr (a -> Fay void) -> Fay (() -> Fay ())
subscribe Var a
v ((a -> Fay ()) -> Fay (() -> Fay ()))
-> (a -> Fay ()) -> Fay (() -> Fay ())
forall t1 t. (t1 -> t) -> t1 -> t
$ \a
x' -> do
    a
x <- Ptr (Ref a) -> Fay a
forall (v :: * -> *) a. Gettable (v a) => v a -> Fay a
get Ptr (Ref a)
o
    Ptr (Ref a) -> a -> Fay ()
forall (v :: * -> *) a. Settable (v a) => v a -> a -> Fay ()
set Ptr (Ref a)
o a
x'
    a -> a -> Fay ()
f a
x a
x'

-- | Subscribe to a 'Var', but only call handler when it actually changes.
--
--   The result is an unsubscribe function.
subscribeChange :: Eq a => Var a -> (a -> Fay ()) -> Fay (() -> Fay ())
subscribeChange :: Var a -> (a -> Fay ()) -> Fay (() -> Fay ())
subscribeChange Var a
v a -> Fay ()
f = Var a -> (a -> a -> Fay ()) -> Fay (() -> Fay ())
forall a. Var a -> (a -> a -> Fay ()) -> Fay (() -> Fay ())
subscribeWithOld Var a
v ((a -> a -> Fay ()) -> Fay (() -> Fay ()))
-> (a -> a -> Fay ()) -> Fay (() -> Fay ())
forall t1 t. (t1 -> t) -> t1 -> t
$ \a
x a
x' -> Bool -> Fay () -> Fay ()
when (a
x a -> a -> Bool
forall a. Eq a => a -> a -> Bool
/= a
x') (Fay () -> Fay ()) -> Fay () -> Fay ()
forall t1 t. (t1 -> t) -> t1 -> t
$ a -> Fay ()
f a
x'

-- | Subscribe to a 'Var', and call the function on the current value.
--
--   The result is an unsubscribe function.
subscribeAndRead :: Var a -> (a -> Fay void) -> Fay (() -> Fay ())
subscribeAndRead :: Var a -> (a -> Fay void) -> Fay (() -> Fay ())
subscribeAndRead Var a
v a -> Fay void
f = do
  a
x <- Var a -> Fay a
forall (v :: * -> *) a. Gettable (v a) => v a -> Fay a
get Var a
v
  void
_ <- a -> Fay void
f a
x
  Var a -> (a -> Fay void) -> Fay (() -> Fay ())
forall (v :: * -> *) a void.
Subscribable (v a) =>
v a -> Ptr (a -> Fay void) -> Fay (() -> Fay ())
subscribe Var a
v a -> Fay void
f

-- | Subscribe to a 'Var', but only call handler when it actually changes, and
--   also initially on registration.
--
--   The result is an unsubscribe function.
subscribeChangeAndRead :: Eq a => Var a -> (a -> Fay ()) -> Fay (() -> Fay ())
subscribeChangeAndRead :: Var a -> (a -> Fay ()) -> Fay (() -> Fay ())
subscribeChangeAndRead Var a
v a -> Fay ()
f = do
  a
x <- Var a -> Fay a
forall (v :: * -> *) a. Gettable (v a) => v a -> Fay a
get Var a
v
  a -> Fay ()
f a
x
  Var a -> (a -> Fay ()) -> Fay (() -> Fay ())
forall a. Eq a => Var a -> (a -> Fay ()) -> Fay (() -> Fay ())
subscribeChange Var a
v a -> Fay ()
f


-- | Given a change handler, returns a function that can be used to set a
--   subscribable without invoking the handler.  This can be useful in
--   situations where the handler for a 'Var' causes an event which otherwise
--   ought to set the value of the 'Var'.  An example of this is interfacing
--   with HTML input field change events.
--
--   The 'snd' part of the result is an unsubscribe function.
subscribeExclusive :: Subscribable (v a) => v a -> (a -> Fay ()) -> Fay (a -> Fay (), () -> Fay ())
subscribeExclusive :: v a -> (a -> Fay ()) -> Fay (a -> Fay (), () -> Fay ())
subscribeExclusive v a
v a -> Fay ()
onChange = do
  Fay () -> Fay ()
bracket <- Fay (Fay () -> Fay ())
getBracket
  () -> Fay ()
unsubscribe <- v a -> (a -> Fay ()) -> Fay (() -> Fay ())
forall (v :: * -> *) a void.
Subscribable (v a) =>
v a -> Ptr (a -> Fay void) -> Fay (() -> Fay ())
subscribe v a
v ((a -> Fay ()) -> Fay (() -> Fay ()))
-> (a -> Fay ()) -> Fay (() -> Fay ())
forall t1 t. (t1 -> t) -> t1 -> t
$ Fay () -> Fay ()
bracket (Fay () -> Fay ()) -> (a -> Fay ()) -> a -> Fay ()
forall t1 t t2. (t1 -> t) -> (t2 -> t1) -> t2 -> t
. a -> Fay ()
onChange
  (a -> Fay (), () -> Fay ()) -> Fay (a -> Fay (), () -> Fay ())
forall a. a -> Fay a
return (\a
x -> Fay () -> Fay ()
bracket (Fay () -> Fay ()) -> Fay () -> Fay ()
forall t1 t. (t1 -> t) -> t1 -> t
$ v a -> a -> Fay ()
forall (v :: * -> *) a. Settable (v a) => v a -> a -> Fay ()
set v a
v a
x, () -> Fay ()
unsubscribe)

-- | Given a change handler, returns a function that can be used to set a var
--   without invoking the handler. The handler is called with the initial
--   value. This can be useful in situations where the handler for a 'Var'
--   causes an event which otherwise ought to set the value of the 'Var'.  An
--   example of this is interfacing with HTML input field change events.
--
--   The 'snd' part of the result is an unsubscribe function.
subscribeAndReadExclusive :: Var a -> (a -> Fay ()) -> Fay (a -> Fay (), () -> Fay ())
subscribeAndReadExclusive :: Var a -> (a -> Fay ()) -> Fay (a -> Fay (), () -> Fay ())
subscribeAndReadExclusive Var a
v a -> Fay ()
onChange = do
  Fay () -> Fay ()
bracket <- Fay (Fay () -> Fay ())
getBracket
  () -> Fay ()
unsubscribe <- Var a -> (a -> Fay ()) -> Fay (() -> Fay ())
forall a void. Var a -> (a -> Fay void) -> Fay (() -> Fay ())
subscribeAndRead Var a
v ((a -> Fay ()) -> Fay (() -> Fay ()))
-> (a -> Fay ()) -> Fay (() -> Fay ())
forall t1 t. (t1 -> t) -> t1 -> t
$ Fay () -> Fay ()
bracket (Fay () -> Fay ()) -> (a -> Fay ()) -> a -> Fay ()
forall t1 t t2. (t1 -> t) -> (t2 -> t1) -> t2 -> t
. a -> Fay ()
onChange
  (a -> Fay (), () -> Fay ()) -> Fay (a -> Fay (), () -> Fay ())
forall a. a -> Fay a
return (\a
x -> Fay () -> Fay ()
bracket (Fay () -> Fay ()) -> Fay () -> Fay ()
forall t1 t. (t1 -> t) -> t1 -> t
$ Var a -> a -> Fay ()
forall (v :: * -> *) a. Settable (v a) => v a -> a -> Fay ()
set Var a
v a
x, () -> Fay ()
unsubscribe)

-- Utility used for 'subscribeExclusive', 'subscribeAndReadExclusive', and
-- 'mergeVars'.
getBracket :: Fay (Fay () -> Fay ())
getBracket :: Fay (Fay () -> Fay ())
getBracket = do
  Ptr (Ref Bool)
rhandle <- Bool -> Fay (Ptr (Ref Bool))
forall a. Ptr a -> Fay (Ptr (Ref (Ptr a)))
newRef Bool
True
  (Fay () -> Fay ()) -> Fay (Fay () -> Fay ())
forall a. a -> Fay a
return ((Fay () -> Fay ()) -> Fay (Fay () -> Fay ()))
-> (Fay () -> Fay ()) -> Fay (Fay () -> Fay ())
forall t1 t. (t1 -> t) -> t1 -> t
$ \Fay ()
f -> do
    Bool
handle <- Ptr (Ref Bool) -> Fay Bool
forall (v :: * -> *) a. Gettable (v a) => v a -> Fay a
get Ptr (Ref Bool)
rhandle
    Bool -> Fay () -> Fay ()
when Bool
handle (Fay () -> Fay ()) -> Fay () -> Fay ()
forall t1 t. (t1 -> t) -> t1 -> t
$ do
      Ptr (Ref Bool) -> Bool -> Fay ()
forall (v :: * -> *) a. Settable (v a) => v a -> a -> Fay ()
set Ptr (Ref Bool)
rhandle Bool
False
      Fay ()
f
      Ptr (Ref Bool) -> Bool -> Fay ()
forall (v :: * -> *) a. Settable (v a) => v a -> a -> Fay ()
set Ptr (Ref Bool)
rhandle Bool
True

--TODO: mapVar variant that's bidirectional?
--TODO: return unsubscribe?

-- | Creates a 'Var' that updates whenever the source var is changed, applying
--   the provided function to compute the new value.
mapVar :: (a -> b) -> Var a -> Fay (Var b)
mapVar :: (a -> b) -> Var a -> Fay (Var b)
mapVar a -> b
f Var a
v = do
  a
x <- Var a -> Fay a
forall (v :: * -> *) a. Gettable (v a) => v a -> Fay a
get Var a
v
  Var b
r <- b -> Fay (Var b)
forall a. Ptr a -> Fay (Ptr (Var (Ptr a)))
newVar (a -> b
f a
x)
  () -> Fay ()
_ <- Var a -> Ptr (a -> Fay ()) -> Fay (() -> Fay ())
forall (v :: * -> *) a void.
Subscribable (v a) =>
v a -> Ptr (a -> Fay void) -> Fay (() -> Fay ())
subscribe Var a
v (Ptr (a -> Fay ()) -> Fay (() -> Fay ()))
-> Ptr (a -> Fay ()) -> Fay (() -> Fay ())
forall t1 t. (t1 -> t) -> t1 -> t
$ \a
x' -> Var b -> b -> Fay ()
forall (v :: * -> *) a. Settable (v a) => v a -> a -> Fay ()
set Var b
r (b -> Fay ()) -> b -> Fay ()
forall t1 t. (t1 -> t) -> t1 -> t
$ a -> b
f a
x'
  Var b -> Fay (Var b)
forall a. a -> Fay a
return Var b
r

-- | Creates a 'Var' that updates whenever one of its source vars are changed.
--   If the 2nd argument is a 'Just' value, then its used to set the source
--   vars when the variable is changed. Setting using a merged var is
--   sometimes preferred because both values are set before the subscribers
--   are called.
--
--   The 'snd' part of the result is an unsubscribe function.
mergeVars :: (a -> b -> c) -> Maybe (c -> (a, b)) -> Var a -> Var b
          -> Fay (Var c, Fay ())
mergeVars :: (a -> b -> c)
-> Maybe (c -> (a, b)) -> Var a -> Var b -> Fay (Var c, Fay ())
mergeVars a -> b -> c
f Maybe (c -> (a, b))
mg Var a
va Var b
vb = do
  Fay () -> Fay ()
bracket <- Fay (Fay () -> Fay ())
getBracket
  a
a0 <- Var a -> Fay a
forall (v :: * -> *) a. Gettable (v a) => v a -> Fay a
get Var a
va
  b
b0 <- Var b -> Fay b
forall (v :: * -> *) a. Gettable (v a) => v a -> Fay a
get Var b
vb
  Var c
vc <- c -> Fay (Var c)
forall a. Ptr a -> Fay (Ptr (Var (Ptr a)))
newVar (a -> b -> c
f a
a0 b
b0)
  () -> Fay ()
unsubscribeA <- Var a -> Ptr (a -> Fay ()) -> Fay (() -> Fay ())
forall (v :: * -> *) a void.
Subscribable (v a) =>
v a -> Ptr (a -> Fay void) -> Fay (() -> Fay ())
subscribe Var a
va (Ptr (a -> Fay ()) -> Fay (() -> Fay ()))
-> Ptr (a -> Fay ()) -> Fay (() -> Fay ())
forall t1 t. (t1 -> t) -> t1 -> t
$ \a
a -> Fay () -> Fay ()
bracket (Fay () -> Fay ()) -> Fay () -> Fay ()
forall t1 t. (t1 -> t) -> t1 -> t
$ do
    b
b <- Var b -> Fay b
forall (v :: * -> *) a. Gettable (v a) => v a -> Fay a
get Var b
vb
    Var c -> c -> Fay ()
forall (v :: * -> *) a. Settable (v a) => v a -> a -> Fay ()
set Var c
vc (a -> b -> c
f a
a b
b)
  () -> Fay ()
unsubscribeB <- Var b -> Ptr (b -> Fay ()) -> Fay (() -> Fay ())
forall (v :: * -> *) a void.
Subscribable (v a) =>
v a -> Ptr (a -> Fay void) -> Fay (() -> Fay ())
subscribe Var b
vb (Ptr (b -> Fay ()) -> Fay (() -> Fay ()))
-> Ptr (b -> Fay ()) -> Fay (() -> Fay ())
forall t1 t. (t1 -> t) -> t1 -> t
$ \b
b -> Fay () -> Fay ()
bracket (Fay () -> Fay ()) -> Fay () -> Fay ()
forall t1 t. (t1 -> t) -> t1 -> t
$ do
    a
a <- Var a -> Fay a
forall (v :: * -> *) a. Gettable (v a) => v a -> Fay a
get Var a
va
    Var c -> c -> Fay ()
forall (v :: * -> *) a. Settable (v a) => v a -> a -> Fay ()
set Var c
vc (a -> b -> c
f a
a b
b)
  Fay ()
unsubscribe <- case Maybe (c -> (a, b))
mg of
    Maybe (c -> (a, b))
Nothing -> Fay () -> Fay (Fay ())
forall a. a -> Fay a
return (Fay () -> Fay (Fay ())) -> Fay () -> Fay (Fay ())
forall t1 t. (t1 -> t) -> t1 -> t
$ () -> Fay ()
unsubscribeA () Fay () -> Fay () -> Fay ()
forall a b. Ptr (Fay a) -> Ptr (Fay b) -> Ptr (Fay b)
>> () -> Fay ()
unsubscribeB ()
    Just c -> (a, b)
g -> do
      () -> Fay ()
unsubscribeC <- Var c -> (c -> Fay ()) -> Fay (() -> Fay ())
forall (v :: * -> *) a void.
Subscribable (v a) =>
v a -> Ptr (a -> Fay void) -> Fay (() -> Fay ())
subscribe Var c
vc ((c -> Fay ()) -> Fay (() -> Fay ()))
-> (c -> Fay ()) -> Fay (() -> Fay ())
forall t1 t. (t1 -> t) -> t1 -> t
$ \c
c -> Fay () -> Fay ()
bracket (Fay () -> Fay ()) -> Fay () -> Fay ()
forall t1 t. (t1 -> t) -> t1 -> t
$ case c -> (a, b)
g c
c of
        (a
a, b
b) -> do
          -- Set variables before broadcast.
          Var a -> Ptr (a -> Fay ())
forall a. Ptr (Var a) -> a -> Fay ()
setInternal Var a
va a
a
          Var b -> Ptr (b -> Fay ())
forall a. Ptr (Var a) -> a -> Fay ()
setInternal Var b
vb b
b
          Var a -> Ptr (a -> Fay ())
forall a. Ptr (Var a) -> a -> Fay ()
broadcastInternal Var a
va a
a
          Var b -> Ptr (b -> Fay ())
forall a. Ptr (Var a) -> a -> Fay ()
broadcastInternal Var b
vb b
b
      Fay () -> Fay (Fay ())
forall a. a -> Fay a
return (Fay () -> Fay (Fay ())) -> Fay () -> Fay (Fay ())
forall t1 t. (t1 -> t) -> t1 -> t
$ () -> Fay ()
unsubscribeA () Fay () -> Fay () -> Fay ()
forall a b. Ptr (Fay a) -> Ptr (Fay b) -> Ptr (Fay b)
>> () -> Fay ()
unsubscribeB () Fay () -> Fay () -> Fay ()
forall a b. Ptr (Fay a) -> Ptr (Fay b) -> Ptr (Fay b)
>> () -> Fay ()
unsubscribeC ()
  (Var c, Fay ()) -> Fay (Var c, Fay ())
forall a. a -> Fay a
return (Var c
vc, Fay ()
unsubscribe)

setInternal :: Ptr (Var a) -> Ptr a -> Fay ()
setInternal :: Ptr (Var a) -> a -> Fay ()
setInternal = [Char] -> Ptr (Var a) -> a -> Fay ()
forall s a. IsString s => s -> a
ffi [Char]
"function() { Fay$$_(%1).val = %2; }()"

broadcastInternal :: Ptr (Var a) -> Ptr a -> Fay ()
broadcastInternal :: Ptr (Var a) -> a -> Fay ()
broadcastInternal = [Char] -> Ptr (Var a) -> a -> Fay ()
forall s a. IsString s => s -> a
ffi [Char]
"Fay$$broadcastInternal(Fay$$_(%1), %2, Fay$$_)"

-- | Like 'mergeVars', but discards the unsubscribe function.
mergeVars' :: (a -> b -> c) -> Maybe (c -> (a, b)) -> Var a -> Var b
           -> Fay (Var c)
mergeVars' :: (a -> b -> c)
-> Maybe (c -> (a, b)) -> Var a -> Var b -> Fay (Var c)
mergeVars' a -> b -> c
f Maybe (c -> (a, b))
mg Var a
va Var b
vb = do
  (Var c, Fay ())
result <- (a -> b -> c)
-> Maybe (c -> (a, b)) -> Var a -> Var b -> Fay (Var c, Fay ())
forall a b c.
(a -> b -> c)
-> Maybe (c -> (a, b)) -> Var a -> Var b -> Fay (Var c, Fay ())
mergeVars a -> b -> c
f Maybe (c -> (a, b))
mg Var a
va Var b
vb
  case (Var c, Fay ())
result of
    (Var c
v, Fay ()
_) -> Var c -> Fay (Var c)
forall a. a -> Fay a
return Var c
v

-- | Creates a 'Var' that updates whenever one of its source vars are changed.
--   It can also be used to set both source vars at once.
--
--   See 'mergeVars' for more information.  Note that when using nested tuples,
--   if you want all of the values to be set before broadcast, then they should
--   nest to the left.
tupleVars :: Var a -> Var b -> Fay (Var (a, b), Fay ())
tupleVars :: Var a -> Var b -> Fay (Var (a, b), Fay ())
tupleVars = (a -> b -> (a, b))
-> Maybe ((a, b) -> (a, b))
-> Var a
-> Var b
-> Fay (Var (a, b), Fay ())
forall a b c.
(a -> b -> c)
-> Maybe (c -> (a, b)) -> Var a -> Var b -> Fay (Var c, Fay ())
mergeVars (\a
x b
y -> (a
x, b
y)) (((a, b) -> (a, b)) -> Maybe ((a, b) -> (a, b))
forall a. a -> Maybe a
Just (a, b) -> (a, b)
forall a. a -> a
id)

-- | Like 'tupleVars', but discards the unsubscribe function.
tupleVars' :: Var a -> Var b -> Fay (Var (a, b))
tupleVars' :: Var a -> Var b -> Fay (Var (a, b))
tupleVars' Var a
va Var b
vb = do
  (Var (a, b), Fay ())
result <- Var a -> Var b -> Fay (Var (a, b), Fay ())
forall a b. Var a -> Var b -> Fay (Var (a, b), Fay ())
tupleVars Var a
va Var b
vb
  case (Var (a, b), Fay ())
result of
    (Var (a, b)
v, Fay ()
_) -> Var (a, b) -> Fay (Var (a, b))
forall a. a -> Fay a
return Var (a, b)
v

-- | Wait for n signals on the given signaller.
waitForN :: Int -> Fay (Fay void -> Fay (),Sig ())
waitForN :: Int -> Fay (Fay void -> Fay (), Sig ())
waitForN Int
n = do
  Sig ()
sig <- Fay (Sig ())
forall a. Fay (Ptr (Sig a))
newSig
  Ptr (Var Int)
count <- Int -> Fay (Ptr (Var Int))
forall a. Ptr a -> Fay (Ptr (Var (Ptr a)))
newVar (Int
0 :: Int)
  () -> Fay ()
_ <- Sig () -> (() -> Fay ()) -> Fay (() -> Fay ())
forall (v :: * -> *) a void.
Subscribable (v a) =>
v a -> Ptr (a -> Fay void) -> Fay (() -> Fay ())
subscribe Sig ()
sig (Fay () -> () -> Fay ()
forall a b. a -> b -> a
const (Ptr (Var Int) -> (Int -> Int) -> Fay ()
forall (v :: * -> *) a.
(Settable (v a), Gettable (v a)) =>
v a -> (a -> a) -> Fay ()
modify Ptr (Var Int)
count (Int -> Int -> Int
forall a. Num a => a -> a -> a
+Int
1)))
  (Fay void -> Fay (), Sig ()) -> Fay (Fay void -> Fay (), Sig ())
forall a. a -> Fay a
return (\Fay void
m -> Ptr (Var Int) -> (Int -> Fay ()) -> Fay (() -> Fay ())
forall a void. Var a -> (a -> Fay void) -> Fay (() -> Fay ())
subscribeAndRead Ptr (Var Int)
count (\Int
i -> Bool -> Fay () -> Fay ()
when (Int
i Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
n) (Fay void
m Fay void -> Fay () -> Fay ()
forall a b. Ptr (Fay a) -> Ptr (Fay b) -> Ptr (Fay b)
>> () -> Fay ()
forall a. a -> Fay a
return ())) Fay (() -> Fay ()) -> Fay () -> Fay ()
forall a b. Ptr (Fay a) -> Ptr (Fay b) -> Ptr (Fay b)
>> () -> Fay ()
forall a. a -> Fay a
return (),Sig ()
sig)

-- | Wait for the given predicate to be satisfied on the var and then
-- unsubscribe.
waitFor :: Var a -> (a -> Bool) -> (a -> Fay ()) -> Fay ()
waitFor :: Var a -> (a -> Bool) -> (a -> Fay ()) -> Fay ()
waitFor Var a
v a -> Bool
p a -> Fay ()
f = do
  () -> Fay ()
_ <- ((a -> Fay ()) -> Fay (() -> Fay ()))
-> ((() -> Fay ()) -> a -> Fay ()) -> Fay (() -> Fay ())
forall a.
((a -> Fay ()) -> Fay (() -> Fay ()))
-> ((() -> Fay ()) -> a -> Fay ()) -> Fay (() -> Fay ())
withUnsubscriber (Var a -> (a -> Fay ()) -> Fay (() -> Fay ())
forall a void. Var a -> (a -> Fay void) -> Fay (() -> Fay ())
subscribeAndRead Var a
v)
    (((() -> Fay ()) -> a -> Fay ()) -> Fay (() -> Fay ()))
-> ((() -> Fay ()) -> a -> Fay ()) -> Fay (() -> Fay ())
forall t1 t. (t1 -> t) -> t1 -> t
$ \() -> Fay ()
unsubscribe a
x -> Bool -> Fay () -> Fay ()
when (a -> Bool
p a
x) (Fay () -> Fay ()) -> Fay () -> Fay ()
forall t1 t. (t1 -> t) -> t1 -> t
$ () -> Fay ()
unsubscribe () Fay () -> Fay () -> Fay ()
forall a b. Ptr (Fay a) -> Ptr (Fay b) -> Ptr (Fay b)
>> a -> Fay ()
f a
x
  () -> Fay ()
forall a. a -> Fay a
return ()

-- | Make a one-shot variable subscription that immediately
-- unsubscribes after the event has triggered.
oneShot :: Subscribable (v a) => v a -> (a -> Fay ()) -> Fay ()
oneShot :: v a -> (a -> Fay ()) -> Fay ()
oneShot v a
v a -> Fay ()
f = do
  () -> Fay ()
_ <- ((a -> Fay ()) -> Fay (() -> Fay ()))
-> ((() -> Fay ()) -> a -> Fay ()) -> Fay (() -> Fay ())
forall a.
((a -> Fay ()) -> Fay (() -> Fay ()))
-> ((() -> Fay ()) -> a -> Fay ()) -> Fay (() -> Fay ())
withUnsubscriber (v a -> (a -> Fay ()) -> Fay (() -> Fay ())
forall (v :: * -> *) a void.
Subscribable (v a) =>
v a -> Ptr (a -> Fay void) -> Fay (() -> Fay ())
subscribe v a
v) (((() -> Fay ()) -> a -> Fay ()) -> Fay (() -> Fay ()))
-> ((() -> Fay ()) -> a -> Fay ()) -> Fay (() -> Fay ())
forall t1 t. (t1 -> t) -> t1 -> t
$ \() -> Fay ()
unsubscribe a
x -> () -> Fay ()
unsubscribe () Fay () -> Fay () -> Fay ()
forall a b. Ptr (Fay a) -> Ptr (Fay b) -> Ptr (Fay b)
>> a -> Fay ()
f a
x
  () -> Fay ()
forall a. a -> Fay a
return ()

-- | Turn a sig into a var, by storing the last reported value.
holdSig :: a -> Sig a -> Fay (Var a)
holdSig :: a -> Sig a -> Fay (Var a)
holdSig a
initial Sig a
sig = do
  Var a
v <- a -> Fay (Var a)
forall a. Ptr a -> Fay (Ptr (Var (Ptr a)))
newVar a
initial
  Fay (() -> Fay ()) -> Fay ()
forall a. Fay a -> Fay ()
void (Fay (() -> Fay ()) -> Fay ()) -> Fay (() -> Fay ()) -> Fay ()
forall t1 t. (t1 -> t) -> t1 -> t
$ Sig a -> Ptr (a -> Fay ()) -> Fay (() -> Fay ())
forall (v :: * -> *) a void.
Subscribable (v a) =>
v a -> Ptr (a -> Fay void) -> Fay (() -> Fay ())
subscribe Sig a
sig (Ptr (a -> Fay ()) -> Fay (() -> Fay ()))
-> Ptr (a -> Fay ()) -> Fay (() -> Fay ())
forall t1 t. (t1 -> t) -> t1 -> t
$ Var a -> Ptr (a -> Fay ())
forall (v :: * -> *) a. Settable (v a) => v a -> a -> Fay ()
set Var a
v
  Var a -> Fay (Var a)
forall a. a -> Fay a
return Var a
v