Skip to content

Commit 37fca51

Browse files
committed
Add PulseCalculation
This ADT describes all possible functions of a pulse node.
1 parent d2dce41 commit 37fca51

File tree

6 files changed

+63
-43
lines changed

6 files changed

+63
-43
lines changed

reactive-banana/src/Reactive/Banana/Prim/Combinators.hs

Lines changed: 10 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import Reactive.Banana.Prim.Plumbing
1515
, readPulseP, readLatchP, readLatchFutureP, liftBuildP,
1616
)
1717
import qualified Reactive.Banana.Prim.Plumbing (pureL)
18-
import Reactive.Banana.Prim.Types (Latch, Future, Pulse, Build)
18+
import Reactive.Banana.Prim.Types (Latch, Future, Pulse, Build, PulseCalculation(..))
1919

2020
import Debug.Trace
2121
-- debug s = trace s
@@ -26,7 +26,7 @@ debug s = id
2626
------------------------------------------------------------------------------}
2727
mapP :: (a -> b) -> Pulse a -> Build (Pulse b)
2828
mapP f p1 = do
29-
p2 <- newPulse "mapP" $ {-# SCC mapP #-} fmap f <$> readPulseP p1
29+
p2 <- newPulse "mapP" (PulseMap f p1)
3030
p2 `dependOn` p1
3131
return p2
3232

@@ -36,45 +36,33 @@ mapP f p1 = do
3636
-- of a 'Latch' to a pulse.
3737
tagFuture :: Latch a -> Pulse b -> Build (Pulse (Future a))
3838
tagFuture x p1 = do
39-
p2 <- newPulse "tagFuture" $
40-
fmap . const <$> readLatchFutureP x <*> readPulseP p1
39+
p2 <- newPulse "tagFuture" $ PulseFuture x p1
4140
p2 `dependOn` p1
4241
return p2
4342

4443
filterJustP :: Pulse (Maybe a) -> Build (Pulse a)
4544
filterJustP p1 = do
46-
p2 <- newPulse "filterJustP" $ {-# SCC filterJustP #-} join <$> readPulseP p1
45+
p2 <- newPulse "filterJustP" $ PulseJoin p1
4746
p2 `dependOn` p1
4847
return p2
4948

5049
unsafeMapIOP :: (a -> IO b) -> Pulse a -> Build (Pulse b)
5150
unsafeMapIOP f p1 = do
52-
p2 <- newPulse "unsafeMapIOP" $
53-
{-# SCC unsafeMapIOP #-} eval =<< readPulseP p1
51+
p2 <- newPulse "unsafeMapIOP" $ PulseMapIO f p1
5452
p2 `dependOn` p1
5553
return p2
56-
where
57-
eval (Just x) = Just <$> liftIO (f x)
58-
eval Nothing = return Nothing
5954

6055
unionWithP :: (a -> a -> a) -> Pulse a -> Pulse a -> Build (Pulse a)
6156
unionWithP f px py = do
62-
p <- newPulse "unionWithP" $
63-
{-# SCC unionWithP #-} eval <$> readPulseP px <*> readPulseP py
57+
p <- newPulse "unionWithP" $ PulseUnionWith f px py
6458
p `dependOn` px
6559
p `dependOn` py
6660
return p
67-
where
68-
eval (Just x) (Just y) = Just (f x y)
69-
eval (Just x) Nothing = Just x
70-
eval Nothing (Just y) = Just y
71-
eval Nothing Nothing = Nothing
7261

7362
-- See note [LatchRecursion]
7463
applyP :: Latch (a -> b) -> Pulse a -> Build (Pulse b)
7564
applyP f x = do
76-
p <- newPulse "applyP" $
77-
{-# SCC applyP #-} fmap <$> readLatchP f <*> readPulseP x
65+
p <- newPulse "applyP" $ PulseApply f x
7866
p `dependOn` x
7967
return p
8068

@@ -113,30 +101,16 @@ switchL l pl = mdo
113101

114102
executeP :: Pulse (b -> Build a) -> b -> Build (Pulse a)
115103
executeP p1 b = do
116-
p2 <- newPulse "executeP" $ {-# SCC executeP #-} eval =<< readPulseP p1
104+
p2 <- newPulse "executeP" $ PulseExecute p1 b
117105
p2 `dependOn` p1
118106
return p2
119-
where
120-
eval (Just x) = Just <$> liftBuildP (x b)
121-
eval Nothing = return Nothing
122107

123108
switchP :: Pulse (Pulse a) -> Build (Pulse a)
124109
switchP pp = mdo
125110
never <- neverP
126111
lp <- stepperL never pp
127-
let
128-
-- switch to a new parent
129-
switch = do
130-
mnew <- readPulseP pp
131-
case mnew of
132-
Nothing -> return ()
133-
Just new -> liftBuildP $ p2 `changeParent` new
134-
return Nothing
135-
-- fetch value from old parent
136-
eval = readPulseP =<< readLatchP lp
137-
138-
p1 <- newPulse "switchP_in" switch :: Build (Pulse ())
112+
p1 <- newPulse "switchP_in" (PulseSwitch pp p2)
139113
p1 `dependOn` pp
140-
p2 <- newPulse "switchP_out" eval
114+
p2 <- newPulse "switchP_out" (PulseReadLatch lp)
141115
p2 `keepAlive` p1
142116
return p2

reactive-banana/src/Reactive/Banana/Prim/Compile.hs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ compile m state1 = do
2828
theAlwaysP <- case nAlwaysP state1 of
2929
Just x -> return x
3030
Nothing -> do
31-
(x,_,_) <- runBuildIO undefined $ newPulse "alwaysP" (return $ Just ())
31+
(x,_,_) <- runBuildIO undefined $ newPulse "alwaysP" (PulseAlways ())
3232
return x
3333

3434
(a, topology, os) <- runBuildIO (nTime state1, theAlwaysP) m

reactive-banana/src/Reactive/Banana/Prim/Evaluation.hs

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{-----------------------------------------------------------------------------
22
reactive-banana
33
------------------------------------------------------------------------------}
4-
{-# LANGUAGE RecordWildCards, BangPatterns #-}
4+
{-# LANGUAGE RecordWildCards, BangPatterns, GADTs #-}
55
module Reactive.Banana.Prim.Evaluation (
66
step
77
) where
@@ -78,7 +78,7 @@ evaluatePulses roots = wrapEvalP $ \r -> go r =<< insertNodes r roots Q.empty
7878
evaluateNode :: SomeNode -> EvalP [SomeNode]
7979
evaluateNode (P p) = {-# SCC evaluateNodeP #-} do
8080
Pulse{..} <- readRef p
81-
ma <- _evalP
81+
ma <- runPulseCalculation _evalP
8282
writePulseP _keyP ma
8383
case ma of
8484
Nothing -> return []
@@ -118,3 +118,32 @@ insertNodes (RWS.Tuple (time,_) _ _) = {-# SCC insertNodes #-} go
118118
go (node:xs) q = go xs (Q.insert ground node q)
119119
-- O and L nodes have only one parent, so
120120
-- we can insert them at an arbitrary level
121+
122+
runPulseCalculation :: PulseCalculation a -> EvalP (Maybe a)
123+
runPulseCalculation (PulseMap f p1) = fmap f <$> readPulseP p1
124+
runPulseCalculation PulseNever = return Nothing
125+
runPulseCalculation (PulseJoin p1) = join <$> readPulseP p1
126+
runPulseCalculation (PulseMapIO f p1) = eval =<< readPulseP p1
127+
where eval (Just x) = Just <$> liftIO (f x)
128+
eval Nothing = return Nothing
129+
runPulseCalculation (PulseUnionWith f px py) =
130+
eval <$> readPulseP px <*> readPulseP py
131+
where eval (Just x) (Just y) = Just (f x y)
132+
eval (Just x) Nothing = Just x
133+
eval Nothing (Just y) = Just y
134+
eval Nothing Nothing = Nothing
135+
runPulseCalculation (PulseApply f x) = fmap <$> readLatchP f <*> readPulseP x
136+
runPulseCalculation (PulseExecute p1 b) = eval =<< readPulseP p1
137+
where eval (Just x) = Just <$> liftBuildP (x b)
138+
eval Nothing = return Nothing
139+
runPulseCalculation (PulseSwitch pp p2) =
140+
do mnew <- readPulseP pp
141+
case mnew of
142+
Nothing -> return ()
143+
Just new -> liftBuildP $ p2 `changeParent` new
144+
return Nothing
145+
runPulseCalculation (PulseReadLatch lp) = readPulseP =<< readLatchP lp
146+
runPulseCalculation (PulseReadPulse p) = readPulseP p
147+
runPulseCalculation (PulseAlways x) = return $ Just x
148+
runPulseCalculation (PulseFuture x p1) =
149+
fmap . const <$> readLatchFutureP x <*> readPulseP p1

reactive-banana/src/Reactive/Banana/Prim/IO.hs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ newInput = mdo
3131
pulse <- liftIO $ newRef $ Pulse
3232
{ _keyP = key
3333
, _seenP = agesAgo
34-
, _evalP = readPulseP pulse -- get its own value
34+
, _evalP = PulseReadPulse pulse -- get its own value
3535
, _childrenP = []
3636
, _parentsP = []
3737
, _levelP = ground

reactive-banana/src/Reactive/Banana/Prim/Plumbing.hs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,10 @@ import Reactive.Banana.Prim.Util
2525
{-----------------------------------------------------------------------------
2626
Build primitive pulses and latches
2727
------------------------------------------------------------------------------}
28+
29+
2830
-- | Make 'Pulse' from evaluation function
29-
newPulse :: String -> EvalP (Maybe a) -> Build (Pulse a)
31+
newPulse :: String -> PulseCalculation a -> Build (Pulse a)
3032
newPulse name eval = liftIO $ do
3133
key <- Lazy.newKey
3234
newRef $ Pulse
@@ -56,7 +58,7 @@ neverP = liftIO $ do
5658
newRef $ Pulse
5759
{ _keyP = key
5860
, _seenP = agesAgo
59-
, _evalP = return Nothing
61+
, _evalP = PulseNever
6062
, _childrenP = []
6163
, _parentsP = []
6264
, _levelP = ground

reactive-banana/src/Reactive/Banana/Prim/Types.hs

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
------------------------------------------------------------------------------}
44
{-# LANGUAGE ExistentialQuantification, NamedFieldPuns #-}
55
{-# LANGUAGE TypeSynonymInstances, FlexibleInstances #-}
6+
{-# LANGUAGE GADTs #-}
67
module Reactive.Banana.Prim.Types where
78

89
import Control.Monad.Trans.RWSIO
@@ -86,13 +87,27 @@ type Pulse a = Ref (Pulse' a)
8687
data Pulse' a = Pulse
8788
{ _keyP :: Lazy.Key (Maybe a) -- Key to retrieve pulse from cache.
8889
, _seenP :: !Time -- See note [Timestamp].
89-
, _evalP :: EvalP (Maybe a) -- Calculate current value.
90+
, _evalP :: PulseCalculation a -- Calculate current value.
9091
, _childrenP :: [Weak SomeNode] -- Weak references to child nodes.
9192
, _parentsP :: [Weak SomeNode] -- Weak reference to parent nodes.
9293
, _levelP :: !Level -- Priority in evaluation order.
9394
, _nameP :: String -- Name for debugging.
9495
}
9596

97+
data PulseCalculation x where
98+
PulseMap :: (a -> x) -> Pulse a -> PulseCalculation x
99+
PulseFuture :: Latch x -> Pulse a -> PulseCalculation (Future x)
100+
PulseNever :: PulseCalculation x
101+
PulseJoin :: Pulse (Maybe x) -> PulseCalculation x
102+
PulseMapIO :: (a -> IO x) -> Pulse a -> PulseCalculation x
103+
PulseUnionWith :: (x -> x -> x) -> Pulse x -> Pulse x -> PulseCalculation x
104+
PulseApply :: Latch (a -> x) -> Pulse a -> PulseCalculation x
105+
PulseExecute :: Pulse (a -> Build x) -> a -> PulseCalculation x
106+
PulseSwitch :: Pulse (Pulse x) -> Pulse x -> PulseCalculation x
107+
PulseReadLatch :: Latch (Pulse x) -> PulseCalculation x
108+
PulseReadPulse :: Pulse x -> PulseCalculation x
109+
PulseAlways :: x -> PulseCalculation x
110+
96111
instance Show (Pulse a) where
97112
show p = _nameP (unsafePerformIO $ readRef p) ++ " " ++ show (hashWithSalt 0 p)
98113

0 commit comments

Comments
 (0)