@@ -1,33 +1,66 @@
1{-# LANGUAGE GADTs #-}
1{-# LANGUAGE GADTs #-}
2+{-# LANGUAGE LambdaCase #-}
2module Test.Run where
3module Test.Run where
4import Control.Monad
5import Control.Monad
5import Control.Monad.Ref
6import Control.Monad.Ref
6import Data.Dependent.Sum
7import Data.Dependent.Sum
7import Data.Functor.Identity
8import Data.Functor.Identity
9import Reflex
11import Reflex
10import Reflex.Host.Class
12import Reflex.Host.Class
14+data AppIn t b e = AppIn
15+ { _appIn_behavior :: Behavior t b
16+ , _appIn_event :: Event t e
19+data AppOut t b e = AppOut
20+ { _appOut_behavior :: Behavior t b
21+ , _appOut_event :: Event t e
12−runApp :: (Show a, t ~ SpiderTimeline Global, m ~ SpiderHost Global)
24+runApp :: (t ~ SpiderTimeline Global, m ~ SpiderHost Global)
13− => (Event t () -> PerformEventT t m (Maybe (Ref m (Maybe (EventTrigger t ()))), Event t a))
25+ => (AppIn t bIn eIn -> PerformEventT t m (AppOut t bOut eOut))
27+ -> [Maybe (These bIn eIn)]
14− -> IO (Maybe a, Maybe (a, a))
28+ -> IO [[(bOut, Maybe eOut)]]
15−runApp x = runSpiderHost $ do
29+runApp app b0 input = runSpiderHost $ do
16− (pulseE, pulseTriggerRef) <- newEventWithTriggerRef
30+ (appInHoldE, pulseHoldTriggerRef) <- newEventWithTriggerRef
31+ (appInE, pulseEventTriggerRef) <- newEventWithTriggerRef
32+ appInB <- hold b0 appInHoldE
17− ((mactuateRef, e), FireCommand fire) <- hostPerformEventT $ x pulseE
33+ (out, FireCommand fire) <- hostPerformEventT $ app $ AppIn
34+ { _appIn_event = appInE
35+ , _appIn_behavior = appInB
18− hnd <- subscribeEvent e
37+ hnd <- subscribeEvent (_appOut_event out)
19− out1 <- fireEventRefAndRead pulseTriggerRef () hnd
38+ mpulseB <- readRef pulseHoldTriggerRef
20− out2 <- fmap join $ forM mactuateRef $ \actuateRef -> do
39+ mpulseE <- readRef pulseEventTriggerRef
21− let readPhase = do
40+ let readPhase = do
41+ b <- sample (_appOut_behavior out)
22− mGetValue <- readEvent hnd
42+ frames <- sequence =<< readEvent hnd
23− case mGetValue of
43+ return (b, frames)
24− Nothing -> return Nothing
44+ forM input $ \case
25− Just getValue -> fmap Just getValue
45+ Nothing ->
26− mactuate <- readRef actuateRef
46+ fire [] $ readPhase
27− mpulse <- readRef pulseTriggerRef
47+ Just i -> case i of
28− forM ((,) <$> mactuate <*> mpulse) $ \(actuate, pulse) -> do
48+ This b' -> case mpulseB of
29− _ <- fire [actuate :=> Identity ()] $ return ()
49+ Nothing -> error "tried to fire in-behavior but ref was empty"
30− [Just a] <- fire [pulse :=> Identity ()] $ readPhase
50+ Just pulseB -> fire [ pulseB :=> Identity b' ] $ readPhase
31− [Just b, Nothing] <- fire [actuate :=> Identity (), pulse :=> Identity ()] $ readPhase
51+ That e' -> case mpulseE of
32− return (a,b)
52+ Nothing -> error "tried to fire in-event but ref was empty"
33− return (out1, out2)
53+ Just pulseE -> fire [ pulseE :=> Identity e' ] $ readPhase
54+ These b' e' -> case mpulseB of
55+ Nothing -> error "tried to fire in-behavior but ref was empty"
56+ Just pulseB -> case mpulseE of
57+ Nothing -> error "tried to fire in-event but ref was empty"
58+ Just pulseE -> fire [ pulseB :=> Identity b', pulseE :=> Identity e' ] $ readPhase
60+runApp' :: (t ~ SpiderTimeline Global, m ~ SpiderHost Global)
61+ => (Event t eIn -> PerformEventT t m (Event t eOut))
64+runApp' app input = do
65+ let app' = fmap (AppOut (pure ())) . app
66+ map (map snd) <$> runApp (app' . _appIn_event) () (map (fmap That) input)