module Simulation.Aivika.Gate
(Gate,
newGate,
newGateOpened,
newGateClosed,
openGate,
closeGate,
invertGate,
gateOpened,
gateClosed,
awaitGateOpened,
awaitGateClosed,
gateChanged_) where
import Control.Monad
import Simulation.Aivika.Simulation
import Simulation.Aivika.Event
import Simulation.Aivika.Process
import Simulation.Aivika.Signal
import Simulation.Aivika.Ref
data Gate = Gate { Gate -> Ref Bool
gateRef :: Ref Bool }
newGate :: Bool -> Simulation Gate
newGate :: Bool -> Simulation Gate
newGate Bool
opened =
do Ref Bool
r <- Bool -> Simulation (Ref Bool)
forall a. a -> Simulation (Ref a)
newRef Bool
opened
Gate -> Simulation Gate
forall (m :: * -> *) a. Monad m => a -> m a
return Gate :: Ref Bool -> Gate
Gate { gateRef :: Ref Bool
gateRef = Ref Bool
r }
newGateOpened :: Simulation Gate
newGateOpened :: Simulation Gate
newGateOpened = Bool -> Simulation Gate
newGate Bool
True
newGateClosed :: Simulation Gate
newGateClosed :: Simulation Gate
newGateClosed = Bool -> Simulation Gate
newGate Bool
False
openGate :: Gate -> Event ()
openGate :: Gate -> Event ()
openGate Gate
gate =
Ref Bool -> Bool -> Event ()
forall a. Ref a -> a -> Event ()
writeRef (Gate -> Ref Bool
gateRef Gate
gate) Bool
True
closeGate :: Gate -> Event ()
closeGate :: Gate -> Event ()
closeGate Gate
gate =
Ref Bool -> Bool -> Event ()
forall a. Ref a -> a -> Event ()
writeRef (Gate -> Ref Bool
gateRef Gate
gate) Bool
False
invertGate :: Gate -> Event ()
invertGate :: Gate -> Event ()
invertGate Gate
gate =
Ref Bool -> (Bool -> Bool) -> Event ()
forall a. Ref a -> (a -> a) -> Event ()
modifyRef (Gate -> Ref Bool
gateRef Gate
gate) Bool -> Bool
not
gateOpened :: Gate -> Event Bool
gateOpened :: Gate -> Event Bool
gateOpened Gate
gate =
Ref Bool -> Event Bool
forall a. Ref a -> Event a
readRef (Gate -> Ref Bool
gateRef Gate
gate)
gateClosed :: Gate -> Event Bool
gateClosed :: Gate -> Event Bool
gateClosed Gate
gate =
(Bool -> Bool) -> Event Bool -> Event Bool
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Bool -> Bool
not (Event Bool -> Event Bool) -> Event Bool -> Event Bool
forall a b. (a -> b) -> a -> b
$ Ref Bool -> Event Bool
forall a. Ref a -> Event a
readRef (Gate -> Ref Bool
gateRef Gate
gate)
awaitGateOpened :: Gate -> Process ()
awaitGateOpened :: Gate -> Process ()
awaitGateOpened Gate
gate =
do Bool
f <- Event Bool -> Process Bool
forall (m :: * -> *) a. EventLift m => Event a -> m a
liftEvent (Event Bool -> Process Bool) -> Event Bool -> Process Bool
forall a b. (a -> b) -> a -> b
$ Ref Bool -> Event Bool
forall a. Ref a -> Event a
readRef (Gate -> Ref Bool
gateRef Gate
gate)
Bool -> Process () -> Process ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless Bool
f (Process () -> Process ()) -> Process () -> Process ()
forall a b. (a -> b) -> a -> b
$
do Signal () -> Process ()
forall a. Signal a -> Process a
processAwait (Signal () -> Process ()) -> Signal () -> Process ()
forall a b. (a -> b) -> a -> b
$ Ref Bool -> Signal ()
forall a. Ref a -> Signal ()
refChanged_ (Gate -> Ref Bool
gateRef Gate
gate)
Gate -> Process ()
awaitGateOpened Gate
gate
awaitGateClosed :: Gate -> Process ()
awaitGateClosed :: Gate -> Process ()
awaitGateClosed Gate
gate =
do Bool
f <- Event Bool -> Process Bool
forall (m :: * -> *) a. EventLift m => Event a -> m a
liftEvent (Event Bool -> Process Bool) -> Event Bool -> Process Bool
forall a b. (a -> b) -> a -> b
$ Ref Bool -> Event Bool
forall a. Ref a -> Event a
readRef (Gate -> Ref Bool
gateRef Gate
gate)
Bool -> Process () -> Process ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when Bool
f (Process () -> Process ()) -> Process () -> Process ()
forall a b. (a -> b) -> a -> b
$
do Signal () -> Process ()
forall a. Signal a -> Process a
processAwait (Signal () -> Process ()) -> Signal () -> Process ()
forall a b. (a -> b) -> a -> b
$ Ref Bool -> Signal ()
forall a. Ref a -> Signal ()
refChanged_ (Gate -> Ref Bool
gateRef Gate
gate)
Gate -> Process ()
awaitGateClosed Gate
gate
gateChanged_ :: Gate -> Signal ()
gateChanged_ :: Gate -> Signal ()
gateChanged_ Gate
gate =
Ref Bool -> Signal ()
forall a. Ref a -> Signal ()
refChanged_ (Gate -> Ref Bool
gateRef Gate
gate)