@@ -9,7 +9,6 @@
9{-# LANGUAGE GADTs #-}
9{-# LANGUAGE GADTs #-}
10{-# LANGUAGE GeneralizedNewtypeDeriving #-}
10{-# LANGUAGE GeneralizedNewtypeDeriving #-}
11{-# LANGUAGE LambdaCase #-}
11{-# LANGUAGE LambdaCase #-}
12−{-# LANGUAGE MultiParamTypeClasses #-}
13{-# LANGUAGE MultiWayIf #-}
12{-# LANGUAGE MultiWayIf #-}
14{-# LANGUAGE RankNTypes #-}
13{-# LANGUAGE RankNTypes #-}
15{-# LANGUAGE RoleAnnotations #-}
14{-# LANGUAGE RoleAnnotations #-}
@@ -17,9 +16,15 @@
17{-# LANGUAGE TypeFamilies #-}
16{-# LANGUAGE TypeFamilies #-}
18{-# LANGUAGE TypeOperators #-}
17{-# LANGUAGE TypeOperators #-}
19{-# LANGUAGE UndecidableInstances #-}
18{-# LANGUAGE UndecidableInstances #-}
19+{-# LANGUAGE PolyKinds #-}
20+{-# LANGUAGE DeriveFunctor #-}
21+{-# LANGUAGE StandaloneDeriving #-}
22+{-# LANGUAGE InstanceSigs #-}
20#ifdef USE_REFLEX_OPTIMIZER
24#ifdef USE_REFLEX_OPTIMIZER
21{-# OPTIONS_GHC -fplugin=Reflex.Optimizer #-}
25{-# OPTIONS_GHC -fplugin=Reflex.Optimizer #-}
27+{-# OPTIONS_GHC -Wunused-binds #-}
23-- | This module is the implementation of the 'Spider' 'Reflex' engine. It uses
28-- | This module is the implementation of the 'Spider' 'Reflex' engine. It uses
24-- a graph traversal algorithm to propagate 'Event's and 'Behavior's.
29-- a graph traversal algorithm to propagate 'Event's and 'Behavior's.
25module Reflex.Spider.Internal (module Reflex.Spider.Internal) where
30module Reflex.Spider.Internal (module Reflex.Spider.Internal) where
@@ -33,7 +38,10 @@ import Control.Monad hiding (forM, forM_, mapM, mapM_)
33import Control.Monad.Exception
38import Control.Monad.Exception
34import Control.Monad.Identity hiding (forM, forM_, mapM, mapM_)
39import Control.Monad.Identity hiding (forM, forM_, mapM, mapM_)
35import Control.Monad.Primitive
40import Control.Monad.Primitive
36−import Control.Monad.Reader hiding (forM, forM_, mapM, mapM_)
41+--import Control.Monad.Reader hiding (forM, forM_, mapM, mapM_)
42+import Control.Monad.Reader.Class
43+import Control.Monad.IO.Class
44+import Control.Monad.ReaderIO
37import Control.Monad.Ref
45import Control.Monad.Ref
38import Data.Align
46import Data.Align
39import Data.Coerce
47import Data.Coerce
@@ -49,6 +57,7 @@ import Data.GADT.Compare
49import Data.IntMap.Strict (IntMap)
57import Data.IntMap.Strict (IntMap)
50import qualified Data.IntMap.Strict as IntMap
58import qualified Data.IntMap.Strict as IntMap
51import Data.IORef
59import Data.IORef
60+import Data.Kind (Type)
52import Data.Maybe hiding (mapMaybe)
61import Data.Maybe hiding (mapMaybe)
53import Data.Monoid ((<>))
62import Data.Monoid ((<>))
54import Data.Proxy
63import Data.Proxy
@@ -63,6 +72,15 @@ import System.IO.Unsafe
63import System.Mem.Weak
72import System.Mem.Weak
64import Unsafe.Coerce
73import Unsafe.Coerce
75+#ifdef MIN_VERSION_semialign
76+#if MIN_VERSION_these(0,8,0)
77+import Data.These.Combinators (justThese)
79+#if MIN_VERSION_semialign(1,1,0)
80+import Data.Zip (Zip (..))
66#ifdef DEBUG_CYCLES
84#ifdef DEBUG_CYCLES
67import Control.Monad.State hiding (forM, forM_, mapM, mapM_, sequence)
85import Control.Monad.State hiding (forM, forM_, mapM, mapM_, sequence)
68import Data.List.NonEmpty (NonEmpty (..), nonEmpty)
86import Data.List.NonEmpty (NonEmpty (..), nonEmpty)
@@ -74,9 +92,9 @@ import Data.Tree (Forest, Tree (..), drawForest)
74import Data.FastWeakBag (FastWeakBag)
92import Data.FastWeakBag (FastWeakBag)
75import qualified Data.FastWeakBag as FastWeakBag
93import qualified Data.FastWeakBag as FastWeakBag
76import Data.Reflection
94import Data.Reflection
77−import Data.Some (Some)
95+import Data.Some (Some(Some))
78−import qualified Data.Some as Some
79import Data.Type.Coercion
96import Data.Type.Coercion
97+import Data.Profunctor.Unsafe ((#.), (.#))
80import Data.WeakBag (WeakBag, WeakBagTicket, _weakBag_children)
98import Data.WeakBag (WeakBag, WeakBagTicket, _weakBag_children)
81import qualified Data.WeakBag as WeakBag
99import qualified Data.WeakBag as WeakBag
82import qualified Reflex.Class
100import qualified Reflex.Class
@@ -85,6 +103,7 @@ import qualified Reflex.Host.Class
85import Reflex.NotReady.Class
103import Reflex.NotReady.Class
86import Reflex.Patch
104import Reflex.Patch
87import qualified Reflex.Patch.DMapWithMove as PatchDMapWithMove
105import qualified Reflex.Patch.DMapWithMove as PatchDMapWithMove
106+import Reflex.PerformEvent.Base (PerformEventT)
89#ifdef DEBUG_TRACE_EVENTS
108#ifdef DEBUG_TRACE_EVENTS
90import qualified Data.ByteString.Char8 as BS8
109import qualified Data.ByteString.Char8 as BS8
@@ -193,12 +212,6 @@ nextNodeIdRef = unsafePerformIO $ newIORef 1
194newNodeId :: IO Int
213newNodeId :: IO Int
195newNodeId = atomicModifyIORef' nextNodeIdRef $ \n -> (succ n, n)
214newNodeId = atomicModifyIORef' nextNodeIdRef $ \n -> (succ n, n)
197−{-# NOINLINE unsafeNodeId #-}
198−unsafeNodeId :: a -> Int
199−unsafeNodeId a = unsafePerformIO $ do
204--------------------------------------------------------------------------------
217--------------------------------------------------------------------------------
@@ -302,9 +315,10 @@ cacheEvent e =
318+ unsafePerformIO $ do
305− let mSubscribedRef :: IORef (FastWeak (CacheSubscribed x a))
319+ mSubscribedRef :: IORef (FastWeak (CacheSubscribed x a))
306− !mSubscribedRef = unsafeNewIORef e emptyFastWeak
320+ <- newIORef emptyFastWeak
307− in \sub -> {-# SCC "cacheEvent" #-} do
321+ pure $ \sub -> {-# SCC "cacheEvent" #-} do
308#ifdef DEBUG_TRACE_EVENTS
322#ifdef DEBUG_TRACE_EVENTS
309 unless (BS8.null callSite) $ liftIO $ BS8.hPutStrLn stderr callSite
323 unless (BS8.null callSite) $ liftIO $ BS8.hPutStrLn stderr callSite
@@ -319,9 +333,9 @@ cacheEvent e =
319 scheduleClear occRef
333 scheduleClear occRef
320 propagateFast a subscribers
334 propagateFast a subscribers
321 , subscriberInvalidateHeight = \old -> do
335 , subscriberInvalidateHeight = \old -> do
322− FastWeakBag.traverse subscribers $ invalidateSubscriberHeight old
336+ FastWeakBag.traverse_ subscribers $ invalidateSubscriberHeight old
323 , subscriberRecalculateHeight = \new -> do
337 , subscriberRecalculateHeight = \new -> do
324− FastWeakBag.traverse subscribers $ recalculateSubscriberHeight new
338+ FastWeakBag.traverse_ subscribers $ recalculateSubscriberHeight new
326 when (isJust occ) $ do
340 when (isJust occ) $ do
327 liftIO $ writeIORef occRef occ -- Set the initial value of occRef; we don't need to do this if occ is Nothing
341 liftIO $ writeIORef occRef occ -- Set the initial value of occRef; we don't need to do this if occ is Nothing
@@ -370,7 +384,7 @@ eventRoot !k !r = Event $ wrap eventSubscribedRoot $ liftIO . getRootSubscribed
370eventNever :: Event x a
384eventNever :: Event x a
371eventNever = Event $ \_ -> return (EventSubscription (return ()) eventSubscribedNever, Nothing)
385eventNever = Event $ \_ -> return (EventSubscription (return ()) eventSubscribedNever, Nothing)
373−eventFan :: (GCompare k, HasSpiderTimeline x) => k a -> Fan x k -> Event x a
387+eventFan :: (GCompare k, HasSpiderTimeline x) => k a -> Fan x k v -> Event x (v a)
374eventFan !k !f = Event $ wrap eventSubscribedFan $ getFanSubscribed k f
388eventFan !k !f = Event $ wrap eventSubscribedFan $ getFanSubscribed k f
376eventSwitch :: HasSpiderTimeline x => Switch x a -> Event x a
390eventSwitch :: HasSpiderTimeline x => Switch x a -> Event x a
@@ -422,14 +436,14 @@ newSubscriberHold h = return $ Subscriber
422 , subscriberRecalculateHeight = \_ -> return ()
436 , subscriberRecalculateHeight = \_ -> return ()
425−newSubscriberFan :: forall x k. (HasSpiderTimeline x, GCompare k) => FanSubscribed x k -> IO (Subscriber x (DMap k Identity))
439+newSubscriberFan :: forall x k v. (HasSpiderTimeline x, GCompare k) => FanSubscribed x k v -> IO (Subscriber x (DMap k v))
426newSubscriberFan subscribed = return $ Subscriber
440newSubscriberFan subscribed = return $ Subscriber
427 { subscriberPropagate = \a -> {-# SCC "traverseFan" #-} do
441 { subscriberPropagate = \a -> {-# SCC "traverseFan" #-} do
428 subs <- liftIO $ readIORef $ fanSubscribedSubscribers subscribed
442 subs <- liftIO $ readIORef $ fanSubscribedSubscribers subscribed
429 tracePropagate (Proxy :: Proxy x) $ "SubscriberFan" <> showNodeId subscribed <> ": " ++ show (DMap.size subs) ++ " keys subscribed, " ++ show (DMap.size a) ++ " keys firing"
443 tracePropagate (Proxy :: Proxy x) $ "SubscriberFan" <> showNodeId subscribed <> ": " ++ show (DMap.size subs) ++ " keys subscribed, " ++ show (DMap.size a) ++ " keys firing"
430 liftIO $ writeIORef (fanSubscribedOccurrence subscribed) $ Just a
444 liftIO $ writeIORef (fanSubscribedOccurrence subscribed) $ Just a
431 scheduleClear $ fanSubscribedOccurrence subscribed
445 scheduleClear $ fanSubscribedOccurrence subscribed
432− let f _ (Pair (Identity v) subsubs) = do
446+ let f _ (Pair v subsubs) = do
433 propagate v $ _fanSubscribedChildren_list subsubs
447 propagate v $ _fanSubscribedChildren_list subsubs
434 return $ Constant ()
448 return $ Constant ()
435 _ <- DMap.traverseWithKey f $ DMap.intersectionWithKey (\_ -> Pair) a subs --TODO: Would be nice to have DMap.traverse_
449 _ <- DMap.traverseWithKey f $ DMap.intersectionWithKey (\_ -> Pair) a subs --TODO: Would be nice to have DMap.traverse_
@@ -437,12 +451,12 @@ newSubscriberFan subscribed = return $ Subscriber
437 , subscriberInvalidateHeight = \old -> do
451 , subscriberInvalidateHeight = \old -> do
438 when debugInvalidateHeight $ putStrLn $ "invalidateSubscriberHeight: SubscriberFan" <> showNodeId subscribed
452 when debugInvalidateHeight $ putStrLn $ "invalidateSubscriberHeight: SubscriberFan" <> showNodeId subscribed
439 subscribers <- readIORef $ fanSubscribedSubscribers subscribed
453 subscribers <- readIORef $ fanSubscribedSubscribers subscribed
440− forM_ (DMap.toList subscribers) $ \(_ :=> v) -> WeakBag.traverse (_fanSubscribedChildren_list v) $ invalidateSubscriberHeight old
454+ forM_ (DMap.toList subscribers) $ \(_ :=> v) -> WeakBag.traverse_ (_fanSubscribedChildren_list v) $ invalidateSubscriberHeight old
441 when debugInvalidateHeight $ putStrLn $ "invalidateSubscriberHeight: SubscriberFan" <> showNodeId subscribed <> " done"
455 when debugInvalidateHeight $ putStrLn $ "invalidateSubscriberHeight: SubscriberFan" <> showNodeId subscribed <> " done"
442 , subscriberRecalculateHeight = \new -> do
456 , subscriberRecalculateHeight = \new -> do
443 when debugInvalidateHeight $ putStrLn $ "recalculateSubscriberHeight: SubscriberFan" <> showNodeId subscribed
457 when debugInvalidateHeight $ putStrLn $ "recalculateSubscriberHeight: SubscriberFan" <> showNodeId subscribed
444 subscribers <- readIORef $ fanSubscribedSubscribers subscribed
458 subscribers <- readIORef $ fanSubscribedSubscribers subscribed
445− forM_ (DMap.toList subscribers) $ \(_ :=> v) -> WeakBag.traverse (_fanSubscribedChildren_list v) $ recalculateSubscriberHeight new
459+ forM_ (DMap.toList subscribers) $ \(_ :=> v) -> WeakBag.traverse_ (_fanSubscribedChildren_list v) $ recalculateSubscriberHeight new
446 when debugInvalidateHeight $ putStrLn $ "recalculateSubscriberHeight: SubscriberFan" <> showNodeId subscribed <> " done"
460 when debugInvalidateHeight $ putStrLn $ "recalculateSubscriberHeight: SubscriberFan" <> showNodeId subscribed <> " done"
@@ -458,7 +472,7 @@ newSubscriberSwitch subscribed = return $ Subscriber
458 oldHeight <- readIORef $ switchSubscribedHeight subscribed
472 oldHeight <- readIORef $ switchSubscribedHeight subscribed
459 when (oldHeight /= invalidHeight) $ do
473 when (oldHeight /= invalidHeight) $ do
460 writeIORef (switchSubscribedHeight subscribed) $! invalidHeight
474 writeIORef (switchSubscribedHeight subscribed) $! invalidHeight
461− WeakBag.traverse (switchSubscribedSubscribers subscribed) $ invalidateSubscriberHeight oldHeight
475+ WeakBag.traverse_ (switchSubscribedSubscribers subscribed) $ invalidateSubscriberHeight oldHeight
462 when debugInvalidateHeight $ putStrLn $ "invalidateSubscriberHeight: SubscriberSwitch" <> showNodeId subscribed <> " done"
476 when debugInvalidateHeight $ putStrLn $ "invalidateSubscriberHeight: SubscriberSwitch" <> showNodeId subscribed <> " done"
463 , subscriberRecalculateHeight = \new -> do
477 , subscriberRecalculateHeight = \new -> do
464 when debugInvalidateHeight $ putStrLn $ "recalculateSubscriberHeight: SubscriberSwitch" <> showNodeId subscribed
478 when debugInvalidateHeight $ putStrLn $ "recalculateSubscriberHeight: SubscriberSwitch" <> showNodeId subscribed
@@ -481,8 +495,8 @@ newSubscriberCoincidenceOuter subscribed = return $ Subscriber
481 Nothing -> do
495 Nothing -> do
482 when (innerHeight > outerHeight) $ liftIO $ do -- If the event fires, it will fire at a later height
496 when (innerHeight > outerHeight) $ liftIO $ do -- If the event fires, it will fire at a later height
483 writeIORef (coincidenceSubscribedHeight subscribed) $! innerHeight
497 writeIORef (coincidenceSubscribedHeight subscribed) $! innerHeight
484− WeakBag.traverse (coincidenceSubscribedSubscribers subscribed) $ invalidateSubscriberHeight outerHeight
498+ WeakBag.traverse_ (coincidenceSubscribedSubscribers subscribed) $ invalidateSubscriberHeight outerHeight
485− WeakBag.traverse (coincidenceSubscribedSubscribers subscribed) $ recalculateSubscriberHeight innerHeight
499+ WeakBag.traverse_ (coincidenceSubscribedSubscribers subscribed) $ recalculateSubscriberHeight innerHeight
486 Just o -> do -- Since it's already firing, no need to adjust height
500 Just o -> do -- Since it's already firing, no need to adjust height
487 liftIO $ writeIORef (coincidenceSubscribedOccurrence subscribed) occ
501 liftIO $ writeIORef (coincidenceSubscribedOccurrence subscribed) occ
488 scheduleClear $ coincidenceSubscribedOccurrence subscribed
502 scheduleClear $ coincidenceSubscribedOccurrence subscribed
@@ -529,14 +543,14 @@ propagate :: a -> WeakBag (Subscriber x a) -> EventM x ()
529propagate a subscribers = withIncreasedDepth $ do
543propagate a subscribers = withIncreasedDepth $ do
530 -- Note: in the following traversal, we do not visit nodes that are added to the list during our traversal; they are new events, which will necessarily have full information already, so there is no need to traverse them
544 -- Note: in the following traversal, we do not visit nodes that are added to the list during our traversal; they are new events, which will necessarily have full information already, so there is no need to traverse them
531 --TODO: Should we check if nodes already have their values before propagating? Maybe we're re-doing work
545 --TODO: Should we check if nodes already have their values before propagating? Maybe we're re-doing work
532− WeakBag.traverse subscribers $ \s -> subscriberPropagate s a
546+ WeakBag.traverse_ subscribers $ \s -> subscriberPropagate s a
534-- | Propagate everything at the current height
548-- | Propagate everything at the current height
535propagateFast :: a -> FastWeakBag (Subscriber x a) -> EventM x ()
549propagateFast :: a -> FastWeakBag (Subscriber x a) -> EventM x ()
536propagateFast a subscribers = withIncreasedDepth $ do
550propagateFast a subscribers = withIncreasedDepth $ do
537 -- Note: in the following traversal, we do not visit nodes that are added to the list during our traversal; they are new events, which will necessarily have full information already, so there is no need to traverse them
551 -- Note: in the following traversal, we do not visit nodes that are added to the list during our traversal; they are new events, which will necessarily have full information already, so there is no need to traverse them
538 --TODO: Should we check if nodes already have their values before propagating? Maybe we're re-doing work
552 --TODO: Should we check if nodes already have their values before propagating? Maybe we're re-doing work
539− FastWeakBag.traverse subscribers $ \s -> subscriberPropagate s a
553+ FastWeakBag.traverse_ subscribers $ \s -> subscriberPropagate s a
541--------------------------------------------------------------------------------
555--------------------------------------------------------------------------------
542-- EventSubscribed
556-- EventSubscribed
@@ -545,6 +559,11 @@ propagateFast a subscribers = withIncreasedDepth $ do
545toAny :: a -> Any
559toAny :: a -> Any
546toAny = unsafeCoerce
560toAny = unsafeCoerce
562+-- Why do we use Any here, instead of just giving eventSubscribedRetained an
563+-- existential type? Sadly, GHC does not currently know how to unbox types
564+-- with existentially quantified fields. So instead we just coerce values
565+-- to type Any on the way in. Since we never coerce them back, this is
548data EventSubscribed x = EventSubscribed
567data EventSubscribed x = EventSubscribed
549 { eventSubscribedHeightRef :: {-# UNPACK #-} !(IORef Height)
568 { eventSubscribedHeightRef :: {-# UNPACK #-} !(IORef Height)
550 , eventSubscribedRetained :: {-# NOUNPACK #-} !Any
569 , eventSubscribedRetained :: {-# NOUNPACK #-} !Any
@@ -577,12 +596,12 @@ eventSubscribedNever = EventSubscribed
580−eventSubscribedFan :: FanSubscribed x k -> EventSubscribed x
599+eventSubscribedFan :: FanSubscribed x k v -> EventSubscribed x
581eventSubscribedFan !subscribed = EventSubscribed
600eventSubscribedFan !subscribed = EventSubscribed
582 { eventSubscribedHeightRef = eventSubscribedHeightRef $ _eventSubscription_subscribed $ fanSubscribedParent subscribed
601 { eventSubscribedHeightRef = eventSubscribedHeightRef $ _eventSubscription_subscribed $ fanSubscribedParent subscribed
583 , eventSubscribedRetained = toAny subscribed
602 , eventSubscribedRetained = toAny subscribed
584#ifdef DEBUG_CYCLES
603#ifdef DEBUG_CYCLES
585− , eventSubscribedGetParents = return [Some.This $ _eventSubscription_subscribed $ fanSubscribedParent subscribed]
604+ , eventSubscribedGetParents = return [Some $ _eventSubscription_subscribed $ fanSubscribedParent subscribed]
586 , eventSubscribedHasOwnHeightRef = False
605 , eventSubscribedHasOwnHeightRef = False
587 , eventSubscribedWhoCreated = whoCreatedIORef $ fanSubscribedCachedSubscribed subscribed
606 , eventSubscribedWhoCreated = whoCreatedIORef $ fanSubscribedCachedSubscribed subscribed
@@ -595,7 +614,7 @@ eventSubscribedSwitch !subscribed = EventSubscribed
595#ifdef DEBUG_CYCLES
614#ifdef DEBUG_CYCLES
596 , eventSubscribedGetParents = do
615 , eventSubscribedGetParents = do
597 s <- readIORef $ switchSubscribedCurrentParent subscribed
616 s <- readIORef $ switchSubscribedCurrentParent subscribed
598− return [Some.This $ _eventSubscription_subscribed s]
617+ return [Some $ _eventSubscription_subscribed s]
599 , eventSubscribedHasOwnHeightRef = True
618 , eventSubscribedHasOwnHeightRef = True
600 , eventSubscribedWhoCreated = whoCreatedIORef $ switchSubscribedCachedSubscribed subscribed
619 , eventSubscribedWhoCreated = whoCreatedIORef $ switchSubscribedCachedSubscribed subscribed
@@ -608,8 +627,8 @@ eventSubscribedCoincidence !subscribed = EventSubscribed
608#ifdef DEBUG_CYCLES
627#ifdef DEBUG_CYCLES
609 , eventSubscribedGetParents = do
628 , eventSubscribedGetParents = do
610 innerSubscription <- readIORef $ coincidenceSubscribedInnerParent subscribed
629 innerSubscription <- readIORef $ coincidenceSubscribedInnerParent subscribed
611− let outerParent = Some.This $ _eventSubscription_subscribed $ coincidenceSubscribedOuterParent subscribed
630+ let outerParent = Some $ _eventSubscription_subscribed $ coincidenceSubscribedOuterParent subscribed
612− innerParents = maybeToList $ fmap Some.This innerSubscription
631+ innerParents = maybeToList $ fmap Some innerSubscription
613 return $ outerParent : innerParents
632 return $ outerParent : innerParents
614 , eventSubscribedHasOwnHeightRef = True
633 , eventSubscribedHasOwnHeightRef = True
615 , eventSubscribedWhoCreated = whoCreatedIORef $ coincidenceSubscribedCachedSubscribed subscribed
634 , eventSubscribedWhoCreated = whoCreatedIORef $ coincidenceSubscribedCachedSubscribed subscribed
@@ -625,13 +644,13 @@ whoCreatedEventSubscribed = eventSubscribedWhoCreated
626walkInvalidHeightParents :: EventSubscribed x -> IO [Some (EventSubscribed x)]
645walkInvalidHeightParents :: EventSubscribed x -> IO [Some (EventSubscribed x)]
627walkInvalidHeightParents s0 = do
646walkInvalidHeightParents s0 = do
628− subscribers <- flip execStateT mempty $ ($ Some.This s0) $ fix $ \loop (Some.This s) -> do
647+ subscribers <- flip execStateT mempty $ ($ Some s0) $ fix $ \loop (Some s) -> do
629 h <- liftIO $ readIORef $ eventSubscribedHeightRef s
648 h <- liftIO $ readIORef $ eventSubscribedHeightRef s
630 when (h == invalidHeight) $ do
649 when (h == invalidHeight) $ do
631 when (eventSubscribedHasOwnHeightRef s) $ liftIO $ writeIORef (eventSubscribedHeightRef s) $! invalidHeightBeingTraversed
650 when (eventSubscribedHasOwnHeightRef s) $ liftIO $ writeIORef (eventSubscribedHeightRef s) $! invalidHeightBeingTraversed
632− modify (Some.This s :)
651+ modify (Some s :)
633 mapM_ loop =<< liftIO (eventSubscribedGetParents s)
652 mapM_ loop =<< liftIO (eventSubscribedGetParents s)
634− forM_ subscribers $ \(Some.This s) -> writeIORef (eventSubscribedHeightRef s) $! invalidHeight
653+ forM_ subscribers $ \(Some s) -> writeIORef (eventSubscribedHeightRef s) $! invalidHeight
635 return subscribers
654 return subscribers
@@ -659,7 +678,7 @@ behaviorPull !p = Behavior $ do
659 val <- liftIO $ readIORef $ pullValue p
678 val <- liftIO $ readIORef $ pullValue p
660 case val of
679 case val of
661 Just subscribed -> do
680 Just subscribed -> do
662− askParentsRef >>= mapM_ (\r -> liftIO $ modifyIORef' r (SomeBehaviorSubscribed (Some.This (BehaviorSubscribedPull subscribed)) :))
681+ askParentsRef >>= mapM_ (\r -> liftIO $ modifyIORef' r (SomeBehaviorSubscribed (Some (BehaviorSubscribedPull subscribed)) :))
663 askInvalidator >>= mapM_ (\wi -> liftIO $ modifyIORef' (pullSubscribedInvalidators subscribed) (wi:))
682 askInvalidator >>= mapM_ (\wi -> liftIO $ modifyIORef' (pullSubscribedInvalidators subscribed) (wi:))
664 liftIO $ touch $ pullSubscribedOwnInvalidator subscribed
683 liftIO $ touch $ pullSubscribedOwnInvalidator subscribed
665 return $ pullSubscribedValue subscribed
684 return $ pullSubscribedValue subscribed
@@ -668,7 +687,7 @@ behaviorPull !p = Behavior $ do
668 wi <- liftIO $ mkWeakPtrWithDebug i "InvalidatorPull"
687 wi <- liftIO $ mkWeakPtrWithDebug i "InvalidatorPull"
669 parentsRef <- liftIO $ newIORef []
688 parentsRef <- liftIO $ newIORef []
670 holdInits <- askBehaviorHoldInits
689 holdInits <- askBehaviorHoldInits
671− a <- liftIO $ runReaderT (unBehaviorM $ pullCompute p) (Just (wi, parentsRef), holdInits)
690+ a <- liftIO $ runReaderIO (unBehaviorM $ pullCompute p) (Just (wi, parentsRef), holdInits)
672 invsRef <- liftIO . newIORef . maybeToList =<< askInvalidator
691 invsRef <- liftIO . newIORef . maybeToList =<< askInvalidator
673 parents <- liftIO $ readIORef parentsRef
692 parents <- liftIO $ readIORef parentsRef
674 let subscribed = PullSubscribed
693 let subscribed = PullSubscribed
@@ -678,7 +697,7 @@ behaviorPull !p = Behavior $ do
678 , pullSubscribedParents = parents
697 , pullSubscribedParents = parents
680 liftIO $ writeIORef (pullValue p) $ Just subscribed
699 liftIO $ writeIORef (pullValue p) $ Just subscribed
681− askParentsRef >>= mapM_ (\r -> liftIO $ modifyIORef' r (SomeBehaviorSubscribed (Some.This (BehaviorSubscribedPull subscribed)) :))
700+ askParentsRef >>= mapM_ (\r -> liftIO $ modifyIORef' r (SomeBehaviorSubscribed (Some (BehaviorSubscribedPull subscribed)) :))
684behaviorDyn :: Patch p => Dyn x p -> Behavior x (PatchTarget p)
703behaviorDyn :: Patch p => Dyn x p -> Behavior x (PatchTarget p)
@@ -689,7 +708,7 @@ readHoldTracked :: Hold x p -> BehaviorM x (PatchTarget p)
689readHoldTracked h = do
708readHoldTracked h = do
690 result <- liftIO $ readIORef $ holdValue h
709 result <- liftIO $ readIORef $ holdValue h
691 askInvalidator >>= mapM_ (\wi -> liftIO $ modifyIORef' (holdInvalidators h) (wi:))
710 askInvalidator >>= mapM_ (\wi -> liftIO $ modifyIORef' (holdInvalidators h) (wi:))
692− askParentsRef >>= mapM_ (\r -> liftIO $ modifyIORef' r (SomeBehaviorSubscribed (Some.This (BehaviorSubscribedHold h)) :))
711+ askParentsRef >>= mapM_ (\r -> liftIO $ modifyIORef' r (SomeBehaviorSubscribed (Some (BehaviorSubscribedHold h)) :))
693 liftIO $ touch h -- Otherwise, if this gets inlined enough, the hold's parent reference may get collected
712 liftIO $ touch h -- Otherwise, if this gets inlined enough, the hold's parent reference may get collected
694 return result
713 return result
@@ -703,42 +722,46 @@ readBehaviorUntracked b = do
703-- Dynamic
722-- Dynamic
704--------------------------------------------------------------------------------
723--------------------------------------------------------------------------------
725+type DynamicS x p = Dynamic x (PatchTarget p) p
706−data Dynamic x p = Dynamic
727+data Dynamic x target p = Dynamic
707− { dynamicCurrent :: !(Behavior x (PatchTarget p))
728+ { dynamicCurrent :: !(Behavior x target)
708 , dynamicUpdated :: Event x p -- This must be lazy; see the comment on holdEvent --TODO: Would this let us eliminate `Dyn`?
729 , dynamicUpdated :: Event x p -- This must be lazy; see the comment on holdEvent --TODO: Would this let us eliminate `Dyn`?
732+deriving instance (HasSpiderTimeline x) => Functor (Dynamic x target)
711−dynamicHold :: Hold x p -> Dynamic x p
737+dynamicHold :: Hold x p -> DynamicS x p
712dynamicHold !h = Dynamic
738dynamicHold !h = Dynamic
713 { dynamicCurrent = behaviorHold h
739 { dynamicCurrent = behaviorHold h
714 , dynamicUpdated = eventHold h
740 , dynamicUpdated = eventHold h
717−dynamicHoldIdentity :: Hold x (Identity a) -> Dynamic x (Identity a)
743+dynamicHoldIdentity :: Hold x (Identity a) -> DynamicS x (Identity a)
718dynamicHoldIdentity = dynamicHold
744dynamicHoldIdentity = dynamicHold
720−dynamicConst :: PatchTarget p -> Dynamic x p
746+dynamicConst :: PatchTarget p -> DynamicS x p
721dynamicConst !a = Dynamic
747dynamicConst !a = Dynamic
722 { dynamicCurrent = behaviorConst a
748 { dynamicCurrent = behaviorConst a
723 , dynamicUpdated = eventNever
749 , dynamicUpdated = eventNever
726−dynamicDyn :: (HasSpiderTimeline x, Patch p) => Dyn x p -> Dynamic x p
752+dynamicDyn :: (HasSpiderTimeline x, Patch p) => Dyn x p -> DynamicS x p
727dynamicDyn !d = Dynamic
753dynamicDyn !d = Dynamic
728 { dynamicCurrent = behaviorDyn d
754 { dynamicCurrent = behaviorDyn d
729 , dynamicUpdated = eventDyn d
755 , dynamicUpdated = eventDyn d
732−dynamicDynIdentity :: HasSpiderTimeline x => Dyn x (Identity a) -> Dynamic x (Identity a)
758+dynamicDynIdentity :: HasSpiderTimeline x => Dyn x (Identity a) -> DynamicS x (Identity a)
733dynamicDynIdentity = dynamicDyn
759dynamicDynIdentity = dynamicDyn
735--------------------------------------------------------------------------------
761--------------------------------------------------------------------------------
736-- Combinators
762-- Combinators
737--------------------------------------------------------------------------------
763--------------------------------------------------------------------------------
739−--TODO: Figure out why certain things are not 'representational', then make them
740−--representational so we can use coerce
742--type role Hold representational
765--type role Hold representational
743data Hold x p
766data Hold x p
744 = Hold { holdValue :: !(IORef (PatchTarget p))
767 = Hold { holdValue :: !(IORef (PatchTarget p))
@@ -759,20 +782,25 @@ globalSpiderTimelineEnv = unsafePerformIO unsafeNewSpiderTimelineEnv
760-- | Stores all global data relevant to a particular Spider timeline; only one
783-- | Stores all global data relevant to a particular Spider timeline; only one
761-- value should exist for each type @x@
784-- value should exist for each type @x@
785+newtype SpiderTimelineEnv x = STE {unSTE :: SpiderTimelineEnv' x}
786+-- We implement SpiderTimelineEnv with a newtype wrapper so
787+-- we can get the coercions we want safely.
788+type role SpiderTimelineEnv nominal
762−data SpiderTimelineEnv x = SpiderTimelineEnv
790+data SpiderTimelineEnv' x = SpiderTimelineEnv
763 { _spiderTimeline_lock :: {-# UNPACK #-} !(MVar ())
791 { _spiderTimeline_lock :: {-# UNPACK #-} !(MVar ())
764 , _spiderTimeline_eventEnv :: {-# UNPACK #-} !(EventEnv x)
792 , _spiderTimeline_eventEnv :: {-# UNPACK #-} !(EventEnv x)
765#ifdef DEBUG
793#ifdef DEBUG
766 , _spiderTimeline_depth :: {-# UNPACK #-} !(IORef Int)
794 , _spiderTimeline_depth :: {-# UNPACK #-} !(IORef Int)
769−type role SpiderTimelineEnv nominal
797+type role SpiderTimelineEnv' phantom
771instance Eq (SpiderTimelineEnv x) where
799instance Eq (SpiderTimelineEnv x) where
772 _ == _ = True -- Since only one exists of each type
800 _ == _ = True -- Since only one exists of each type
774instance GEq SpiderTimelineEnv where
802instance GEq SpiderTimelineEnv where
775− a `geq` b = if _spiderTimeline_lock a == _spiderTimeline_lock b
803+ a `geq` b = if _spiderTimeline_lock (unSTE a) == _spiderTimeline_lock (unSTE b)
776 then Just $ unsafeCoerce Refl -- This unsafeCoerce is safe because the same SpiderTimelineEnv can't have two different 'x' arguments
804 then Just $ unsafeCoerce Refl -- This unsafeCoerce is safe because the same SpiderTimelineEnv can't have two different 'x' arguments
777 else Nothing
805 else Nothing
@@ -795,7 +823,7 @@ runEventM :: EventM x a -> IO a
795runEventM = unEventM
823runEventM = unEventM
797asksEventEnv :: forall x a. HasSpiderTimeline x => (EventEnv x -> a) -> EventM x a
825asksEventEnv :: forall x a. HasSpiderTimeline x => (EventEnv x -> a) -> EventM x a
798−asksEventEnv f = return $ f $ _spiderTimeline_eventEnv (spiderTimeline :: SpiderTimelineEnv x)
826+asksEventEnv f = return $ f $ _spiderTimeline_eventEnv (unSTE (spiderTimeline :: SpiderTimelineEnv x))
800class MonadIO m => Defer a m where
828class MonadIO m => Defer a m where
801 getDeferralQueue :: m (IORef [a])
829 getDeferralQueue :: m (IORef [a])
@@ -862,7 +890,7 @@ instance HasSpiderTimeline x => Defer (Some Clear) (EventM x) where
863{-# INLINE scheduleClear #-}
891{-# INLINE scheduleClear #-}
864scheduleClear :: Defer (Some Clear) m => IORef (Maybe a) -> m ()
892scheduleClear :: Defer (Some Clear) m => IORef (Maybe a) -> m ()
865−scheduleClear r = defer $ Some.This $ Clear r
893+scheduleClear r = defer $ Some $ Clear r
867instance HasSpiderTimeline x => Defer (Some IntClear) (EventM x) where
895instance HasSpiderTimeline x => Defer (Some IntClear) (EventM x) where
868 {-# INLINE getDeferralQueue #-}
896 {-# INLINE getDeferralQueue #-}
@@ -870,7 +898,7 @@ instance HasSpiderTimeline x => Defer (Some IntClear) (EventM x) where
871{-# INLINE scheduleIntClear #-}
899{-# INLINE scheduleIntClear #-}
872scheduleIntClear :: Defer (Some IntClear) m => IORef (IntMap a) -> m ()
900scheduleIntClear :: Defer (Some IntClear) m => IORef (IntMap a) -> m ()
873−scheduleIntClear r = defer $ Some.This $ IntClear r
901+scheduleIntClear r = defer $ Some $ IntClear r
875instance HasSpiderTimeline x => Defer (Some RootClear) (EventM x) where
903instance HasSpiderTimeline x => Defer (Some RootClear) (EventM x) where
876 {-# INLINE getDeferralQueue #-}
904 {-# INLINE getDeferralQueue #-}
@@ -878,7 +906,7 @@ instance HasSpiderTimeline x => Defer (Some RootClear) (EventM x) where
879{-# INLINE scheduleRootClear #-}
907{-# INLINE scheduleRootClear #-}
880scheduleRootClear :: Defer (Some RootClear) m => IORef (DMap k Identity) -> m ()
908scheduleRootClear :: Defer (Some RootClear) m => IORef (DMap k Identity) -> m ()
881−scheduleRootClear r = defer $ Some.This $ RootClear r
909+scheduleRootClear r = defer $ Some $ RootClear r
883instance HasSpiderTimeline x => Defer (SomeResetCoincidence x) (EventM x) where
911instance HasSpiderTimeline x => Defer (SomeResetCoincidence x) (EventM x) where
884 {-# INLINE getDeferralQueue #-}
912 {-# INLINE getDeferralQueue #-}
@@ -933,9 +961,9 @@ getHoldEventSubscription h = do
934type BehaviorEnv x = (Maybe (Weak (Invalidator x), IORef [SomeBehaviorSubscribed x]), IORef [SomeHoldInit x])
962type BehaviorEnv x = (Maybe (Weak (Invalidator x), IORef [SomeBehaviorSubscribed x]), IORef [SomeHoldInit x])
936−--type role BehaviorM representational
937-- BehaviorM can sample behaviors
964-- BehaviorM can sample behaviors
938−newtype BehaviorM x a = BehaviorM { unBehaviorM :: ReaderT (BehaviorEnv x) IO a } deriving (Functor, Applicative, MonadIO, MonadFix)
965+newtype BehaviorM x a = BehaviorM { unBehaviorM :: ReaderIO (BehaviorEnv x) a }
966+ deriving (Functor, Applicative, MonadIO, MonadFix, MonadReader (BehaviorEnv x))
940instance Monad (BehaviorM x) where
968instance Monad (BehaviorM x) where
941 {-# INLINE (>>=) #-}
969 {-# INLINE (>>=) #-}
@@ -986,7 +1014,7 @@ data RootSubscribed x a = forall k. GCompare k => RootSubscribed
989−data Root x (k :: * -> *)
1017+data Root x k
990 = Root { rootOccurrence :: !(IORef (DMap k Identity)) -- The currently-firing occurrence of this event
1018 = Root { rootOccurrence :: !(IORef (DMap k Identity)) -- The currently-firing occurrence of this event
991 , rootSubscribed :: !(IORef (DMap k (RootSubscribed x)))
1019 , rootSubscribed :: !(IORef (DMap k (RootSubscribed x)))
992 , rootInit :: !(forall a. k a -> RootTrigger x a -> IO (IO ()))
1020 , rootInit :: !(forall a. k a -> RootTrigger x a -> IO (IO ()))
@@ -1056,25 +1084,25 @@ heightBagVerify b@(HeightBag s c) = if
1056heightBagVerify = id
1084heightBagVerify = id
1059−data FanSubscribedChildren (x :: *) k a = FanSubscribedChildren
1087+data FanSubscribedChildren x k v a = FanSubscribedChildren
1060− { _fanSubscribedChildren_list :: !(WeakBag (Subscriber x a))
1088+ { _fanSubscribedChildren_list :: !(WeakBag (Subscriber x (v a)))
1061− , _fanSubscribedChildren_self :: {-# NOUNPACK #-} !(k a, FanSubscribed x k)
1089+ , _fanSubscribedChildren_self :: {-# NOUNPACK #-} !(k a, FanSubscribed x k v)
1062− , _fanSubscribedChildren_weakSelf :: !(IORef (Weak (k a, FanSubscribed x k)))
1090+ , _fanSubscribedChildren_weakSelf :: !(IORef (Weak (k a, FanSubscribed x k v)))
1065−data FanSubscribed (x :: *) k
1093+data FanSubscribed x k v
1066− = FanSubscribed { fanSubscribedCachedSubscribed :: !(IORef (Maybe (FanSubscribed x k)))
1094+ = FanSubscribed { fanSubscribedCachedSubscribed :: !(IORef (Maybe (FanSubscribed x k v)))
1067− , fanSubscribedOccurrence :: !(IORef (Maybe (DMap k Identity)))
1095+ , fanSubscribedOccurrence :: !(IORef (Maybe (DMap k v)))
1068− , fanSubscribedSubscribers :: !(IORef (DMap k (FanSubscribedChildren x k))) -- This DMap should never be empty
1096+ , fanSubscribedSubscribers :: !(IORef (DMap k (FanSubscribedChildren x k v))) -- This DMap should never be empty
1069 , fanSubscribedParent :: !(EventSubscription x)
1097 , fanSubscribedParent :: !(EventSubscription x)
1070#ifdef DEBUG_NODEIDS
1098#ifdef DEBUG_NODEIDS
1071 , fanSubscribedNodeId :: Int
1099 , fanSubscribedNodeId :: Int
1075−data Fan x k
1103+data Fan x k v
1076− = Fan { fanParent :: !(Event x (DMap k Identity))
1104+ = Fan { fanParent :: !(Event x (DMap k v))
1077− , fanSubscribed :: !(IORef (Maybe (FanSubscribed x k)))
1105+ , fanSubscribed :: !(IORef (Maybe (FanSubscribed x k v)))
1080data SwitchSubscribed x a
1108data SwitchSubscribed x a
@@ -1136,19 +1164,27 @@ instance HasSpiderTimeline x => Align (Event x) where
1136#if MIN_VERSION_these(0, 8, 0)
1164#if MIN_VERSION_these(0, 8, 0)
1137instance HasSpiderTimeline x => Semialign (Event x) where
1165instance HasSpiderTimeline x => Semialign (Event x) where
1167+ align ea eb = mapMaybe dmapToThese $ mergeG coerce $ dynamicConst $
1139− align ea eb = mapMaybe dmapToThese $ merge $ dynamicConst $ DMap.fromDistinctAscList [LeftTag :=> ea, RightTag :=> eb]
1168+ DMap.fromDistinctAscList [LeftTag :=> ea, RightTag :=> eb]
1170+#ifdef MIN_VERSION_semialign
1171+#if MIN_VERSION_semialign(1,1,0)
1172+instance HasSpiderTimeline x => Zip (Event x) where
1174+ zip x y = mapMaybe justThese $ align x y
1141data DynType x p = UnsafeDyn !(BehaviorM x (PatchTarget p), Event x p)
1177data DynType x p = UnsafeDyn !(BehaviorM x (PatchTarget p), Event x p)
1142 | BuildDyn !(EventM x (PatchTarget p), Event x p)
1178 | BuildDyn !(EventM x (PatchTarget p), Event x p)
1143 | HoldDyn !(Hold x p)
1179 | HoldDyn !(Hold x p)
1145−newtype Dyn x p = Dyn { unDyn :: IORef (DynType x p) }
1181+newtype Dyn (x :: Type) p = Dyn { unDyn :: IORef (DynType x p) }
1147−newMapDyn :: HasSpiderTimeline x => (a -> b) -> Dynamic x (Identity a) -> Dynamic x (Identity b)
1183+newMapDyn :: HasSpiderTimeline x => (a -> b) -> DynamicS x (Identity a) -> DynamicS x (Identity b)
1148newMapDyn f d = dynamicDynIdentity $ unsafeBuildDynamic (fmap f $ readBehaviorTracked $ dynamicCurrent d) (Identity . f . runIdentity <$> dynamicUpdated d)
1184newMapDyn f d = dynamicDynIdentity $ unsafeBuildDynamic (fmap f $ readBehaviorTracked $ dynamicCurrent d) (Identity . f . runIdentity <$> dynamicUpdated d)
1150--TODO: Avoid the duplication between this and R.zipDynWith
1186--TODO: Avoid the duplication between this and R.zipDynWith
1151−zipDynWith :: HasSpiderTimeline x => (a -> b -> c) -> Dynamic x (Identity a) -> Dynamic x (Identity b) -> Dynamic x (Identity c)
1187+zipDynWith :: HasSpiderTimeline x => (a -> b -> c) -> DynamicS x (Identity a) -> DynamicS x (Identity b) -> DynamicS x (Identity c)
1152zipDynWith f da db =
1188zipDynWith f da db =
1153 let eab = align (dynamicUpdated da) (dynamicUpdated db)
1189 let eab = align (dynamicUpdated da) (dynamicUpdated db)
1154 ec = flip push eab $ \o -> do
1190 ec = flip push eab $ \o -> do
@@ -1171,18 +1207,12 @@ buildDynamic readV0 v' = do
1171 return d
1207 return d
1173unsafeBuildDynamic :: BehaviorM x (PatchTarget p) -> Event x p -> Dyn x p
1209unsafeBuildDynamic :: BehaviorM x (PatchTarget p) -> Event x p -> Dyn x p
1174−unsafeBuildDynamic readV0 v' = Dyn $ unsafeNewIORef x $ UnsafeDyn x
1210+unsafeBuildDynamic readV0 v' =
1175− where x = (readV0, v')
1211+ Dyn $ unsafePerformIO $ newIORef $ UnsafeDyn (readV0, v')
1177-- ResultM can read behaviors and events
1213-- ResultM can read behaviors and events
1178type ResultM = EventM
1214type ResultM = EventM
1180−{-# NOINLINE unsafeNewIORef #-}
1181−unsafeNewIORef :: a -> b -> IORef b
1182−unsafeNewIORef a b = unsafePerformIO $ do
1186instance HasSpiderTimeline x => Functor (Event x) where
1216instance HasSpiderTimeline x => Functor (Event x) where
1187 fmap f = push $ return . Just . f
1217 fmap f = push $ return . Just . f
@@ -1195,33 +1225,42 @@ push f e = cacheEvent (pushCheap f e)
1196{-# INLINABLE pull #-}
1226{-# INLINABLE pull #-}
1197pull :: BehaviorM x a -> Behavior x a
1227pull :: BehaviorM x a -> Behavior x a
1198−pull a = behaviorPull $ Pull
1228+pull a = unsafePerformIO $ do
1199− { pullCompute = a
1229+ ref <- newIORef Nothing
1200− , pullValue = unsafeNewIORef a Nothing
1201#ifdef DEBUG_NODEIDS
1230#ifdef DEBUG_NODEIDS
1202− , pullNodeId = unsafeNodeId a
1231+ nid <- newNodeId
1233+ pure $ behaviorPull $ Pull
1236+#ifdef DEBUG_NODEIDS
1206{-# INLINABLE switch #-}
1241{-# INLINABLE switch #-}
1207switch :: HasSpiderTimeline x => Behavior x (Event x a) -> Event x a
1242switch :: HasSpiderTimeline x => Behavior x (Event x a) -> Event x a
1243+switch a = unsafePerformIO $ do
1244+ ref <- newIORef Nothing
1208−switch a = eventSwitch $ Switch
1245+ pure $ eventSwitch $ Switch
1209− { switchParent = a
1246+ { switchParent = a
1210− , switchSubscribed = unsafeNewIORef a Nothing
1247+ , switchSubscribed = ref
1213coincidence :: HasSpiderTimeline x => Event x (Event x a) -> Event x a
1250coincidence :: HasSpiderTimeline x => Event x (Event x a) -> Event x a
1251+coincidence a = unsafePerformIO $ do
1252+ ref <- newIORef Nothing
1214−coincidence a = eventCoincidence $ Coincidence
1253+ pure $ eventCoincidence $ Coincidence
1215− { coincidenceParent = a
1254+ { coincidenceParent = a
1216− , coincidenceSubscribed = unsafeNewIORef a Nothing
1255+ , coincidenceSubscribed = ref
1219-- Propagate the given event occurrence; before cleaning up, run the given action, which may read the state of events and behaviors
1258-- Propagate the given event occurrence; before cleaning up, run the given action, which may read the state of events and behaviors
1220run :: forall x b. HasSpiderTimeline x => [DSum (RootTrigger x) Identity] -> ResultM x b -> SpiderHost x b
1259run :: forall x b. HasSpiderTimeline x => [DSum (RootTrigger x) Identity] -> ResultM x b -> SpiderHost x b
1221run roots after = do
1260run roots after = do
1222 tracePropagate (Proxy :: Proxy x) $ "Running an event frame with " <> show (length roots) <> " events"
1261 tracePropagate (Proxy :: Proxy x) $ "Running an event frame with " <> show (length roots) <> " events"
1223 let t = spiderTimeline :: SpiderTimelineEnv x
1262 let t = spiderTimeline :: SpiderTimelineEnv x
1224− result <- SpiderHost $ withMVar (_spiderTimeline_lock t) $ \_ -> unSpiderHost $ runFrame $ do
1263+ result <- SpiderHost $ withMVar (_spiderTimeline_lock (unSTE t)) $ \_ -> unSpiderHost $ runFrame $ do
1225 rootsToPropagate <- forM roots $ \r@(RootTrigger (_, occRef, k) :=> a) -> do
1264 rootsToPropagate <- forM roots $ \r@(RootTrigger (_, occRef, k) :=> a) -> do
1226 occBefore <- liftIO $ do
1265 occBefore <- liftIO $ do
1227 occBefore <- readIORef occRef
1266 occBefore <- readIORef occRef
@@ -1285,9 +1324,9 @@ type WeakList a = [Weak a]
1285withIncreasedDepth :: CanTrace x m => m a -> m a
1324withIncreasedDepth :: CanTrace x m => m a -> m a
1286withIncreasedDepth a = do
1325withIncreasedDepth a = do
1287 spiderTimeline <- askSpiderTimelineEnv
1326 spiderTimeline <- askSpiderTimelineEnv
1288− liftIO $ modifyIORef' (_spiderTimeline_depth spiderTimeline) succ
1327+ liftIO $ modifyIORef' (_spiderTimeline_depth (unSTE spiderTimeline)) succ
1289 result <- a
1328 result <- a
1290− liftIO $ modifyIORef' (_spiderTimeline_depth spiderTimeline) pred
1329+ liftIO $ modifyIORef' (_spiderTimeline_depth (unSTE spiderTimeline)) pred
1291 return result
1330 return result
1293withIncreasedDepth :: m a -> m a
1332withIncreasedDepth :: m a -> m a
@@ -1314,7 +1353,7 @@ traceMWhen _ b getMessage = when b $ do
1314 message <- getMessage
1353 message <- getMessage
1315#ifdef DEBUG
1354#ifdef DEBUG
1316 spiderTimeline <- askSpiderTimelineEnv
1355 spiderTimeline <- askSpiderTimelineEnv
1317− d <- liftIO $ readIORef $ _spiderTimeline_depth spiderTimeline
1356+ d <- liftIO $ readIORef $ _spiderTimeline_depth $ unSTE spiderTimeline
1319 let d = 0
1358 let d = 0
@@ -1355,25 +1394,25 @@ propagateSubscriberHold h a = do
1355data SomeResetCoincidence x = forall a. SomeResetCoincidence !(EventSubscription x) !(Maybe (CoincidenceSubscribed x a)) -- The CoincidenceSubscriber will be present only if heights need to be reset
1394data SomeResetCoincidence x = forall a. SomeResetCoincidence !(EventSubscription x) !(Maybe (CoincidenceSubscribed x a)) -- The CoincidenceSubscriber will be present only if heights need to be reset
1357runBehaviorM :: BehaviorM x a -> Maybe (Weak (Invalidator x), IORef [SomeBehaviorSubscribed x]) -> IORef [SomeHoldInit x] -> IO a
1396runBehaviorM :: BehaviorM x a -> Maybe (Weak (Invalidator x), IORef [SomeBehaviorSubscribed x]) -> IORef [SomeHoldInit x] -> IO a
1358−runBehaviorM a mwi holdInits = runReaderT (unBehaviorM a) (mwi, holdInits)
1397+runBehaviorM a mwi holdInits = runReaderIO (unBehaviorM a) (mwi, holdInits)
1360askInvalidator :: BehaviorM x (Maybe (Weak (Invalidator x)))
1399askInvalidator :: BehaviorM x (Maybe (Weak (Invalidator x)))
1361askInvalidator = do
1400askInvalidator = do
1362− (!m, _) <- BehaviorM ask
1401+ (!m, _) <- ask
1363 case m of
1402 case m of
1364 Nothing -> return Nothing
1403 Nothing -> return Nothing
1365 Just (!wi, _) -> return $ Just wi
1404 Just (!wi, _) -> return $ Just wi
1367askParentsRef :: BehaviorM x (Maybe (IORef [SomeBehaviorSubscribed x]))
1406askParentsRef :: BehaviorM x (Maybe (IORef [SomeBehaviorSubscribed x]))
1368askParentsRef = do
1407askParentsRef = do
1369− (!m, _) <- BehaviorM ask
1408+ (!m, _) <- ask
1370 case m of
1409 case m of
1371 Nothing -> return Nothing
1410 Nothing -> return Nothing
1372 Just (_, !p) -> return $ Just p
1411 Just (_, !p) -> return $ Just p
1374askBehaviorHoldInits :: BehaviorM x (IORef [SomeHoldInit x])
1413askBehaviorHoldInits :: BehaviorM x (IORef [SomeHoldInit x])
1375askBehaviorHoldInits = do
1414askBehaviorHoldInits = do
1376− (_, !his) <- BehaviorM ask
1415+ (_, !his) <- ask
1377 return his
1416 return his
1379{-# INLINE getDynHold #-}
1418{-# INLINE getDynHold #-}
@@ -1418,6 +1457,9 @@ getRootSubscribed k r sub = do
1418 when debugPropagate $ putStrLn $ "getRootSubscribed: calling rootInit"
1457 when debugPropagate $ putStrLn $ "getRootSubscribed: calling rootInit"
1419 uninit <- rootInit r k $ RootTrigger (subs, rootOccurrence r, k)
1458 uninit <- rootInit r k $ RootTrigger (subs, rootOccurrence r, k)
1420 writeIORef uninitRef $! uninit
1459 writeIORef uninitRef $! uninit
1460+#ifdef DEBUG_NODEIDS
1421 let !subscribed = RootSubscribed
1463 let !subscribed = RootSubscribed
1422 { rootSubscribedKey = k
1464 { rootSubscribedKey = k
1423 , rootSubscribedCachedSubscribed = cached
1465 , rootSubscribedCachedSubscribed = cached
@@ -1426,7 +1468,7 @@ getRootSubscribed k r sub = do
1426 , rootSubscribedUninit = uninit
1468 , rootSubscribedUninit = uninit
1427 , rootSubscribedWeakSelf = weakSelf
1469 , rootSubscribedWeakSelf = weakSelf
1428#ifdef DEBUG_NODEIDS
1470#ifdef DEBUG_NODEIDS
1429− , rootSubscribedNodeId = unsafeNodeId (k, r, subs)
1471+ , rootSubscribedNodeId = nid
1432 -- If we die at the same moment that all our children die, they will
1474 -- If we die at the same moment that all our children die, they will
@@ -1475,16 +1517,10 @@ newFanInt = do
1475 , _fanInt_occRef = occRef
1517 , _fanInt_occRef = occRef
1478−{-# NOINLINE unsafeNewFanInt #-}
1479−unsafeNewFanInt :: b -> FanInt x a
1480−unsafeNewFanInt b = unsafePerformIO $ do
1484fanInt :: HasSpiderTimeline x => Event x (IntMap a) -> EventSelectorInt x a
1520fanInt :: HasSpiderTimeline x => Event x (IntMap a) -> EventSelectorInt x a
1485−fanInt p =
1521+fanInt p = unsafePerformIO $ do
1486− let self = unsafeNewFanInt p
1522+ self <- newFanInt
1487− in EventSelectorInt $ \k -> Event $ \sub -> do
1523+ pure $ EventSelectorInt $ \k -> Event $ \sub -> do
1488 isEmpty <- liftIO $ FastMutableIntMap.isEmpty (_fanInt_subscribers self)
1524 isEmpty <- liftIO $ FastMutableIntMap.isEmpty (_fanInt_subscribers self)
1489 when isEmpty $ do -- This is the first subscriber, so we need to subscribe to our input
1525 when isEmpty $ do -- This is the first subscriber, so we need to subscribe to our input
1490 (subscription, parentOcc) <- subscribeAndRead p $ Subscriber
1526 (subscription, parentOcc) <- subscribeAndRead p $ Subscriber
@@ -1492,15 +1528,15 @@ fanInt p =
1492 liftIO $ writeIORef (_fanInt_occRef self) m
1528 liftIO $ writeIORef (_fanInt_occRef self) m
1493 scheduleIntClear $ _fanInt_occRef self
1529 scheduleIntClear $ _fanInt_occRef self
1494 FastMutableIntMap.forIntersectionWithImmutable_ (_fanInt_subscribers self) m $ \b v -> do --TODO: Do we need to know that no subscribers are being added as we traverse?
1530 FastMutableIntMap.forIntersectionWithImmutable_ (_fanInt_subscribers self) m $ \b v -> do --TODO: Do we need to know that no subscribers are being added as we traverse?
1495− FastWeakBag.traverse b $ \s -> do
1531+ FastWeakBag.traverse_ b $ \s -> do
1496 subscriberPropagate s v
1532 subscriberPropagate s v
1497 , subscriberInvalidateHeight = \old -> do
1533 , subscriberInvalidateHeight = \old -> do
1498 FastMutableIntMap.for_ (_fanInt_subscribers self) $ \b -> do
1534 FastMutableIntMap.for_ (_fanInt_subscribers self) $ \b -> do
1499− FastWeakBag.traverse b $ \s -> do
1535+ FastWeakBag.traverse_ b $ \s -> do
1500 subscriberInvalidateHeight s old
1536 subscriberInvalidateHeight s old
1501 , subscriberRecalculateHeight = \new -> do
1537 , subscriberRecalculateHeight = \new -> do
1502 FastMutableIntMap.for_ (_fanInt_subscribers self) $ \b -> do
1538 FastMutableIntMap.for_ (_fanInt_subscribers self) $ \b -> do
1503− FastWeakBag.traverse b $ \s -> do
1539+ FastWeakBag.traverse_ b $ \s -> do
1504 subscriberRecalculateHeight s new
1540 subscriberRecalculateHeight s new
1506 liftIO $ do
1542 liftIO $ do
@@ -1520,7 +1556,7 @@ fanInt p =
1520 return (EventSubscription (FastWeakBag.remove t) $! EventSubscribed heightRef $! toAny (_fanInt_subscriptionRef self, t), IntMap.lookup k currentOcc)
1556 return (EventSubscription (FastWeakBag.remove t) $! EventSubscribed heightRef $! toAny (_fanInt_subscriptionRef self, t), IntMap.lookup k currentOcc)
1522{-# INLINABLE getFanSubscribed #-}
1558{-# INLINABLE getFanSubscribed #-}
1523−getFanSubscribed :: (HasSpiderTimeline x, GCompare k) => k a -> Fan x k -> Subscriber x a -> EventM x (WeakBagTicket, FanSubscribed x k, Maybe a)
1559+getFanSubscribed :: (HasSpiderTimeline x, GCompare k) => k a -> Fan x k v -> Subscriber x (v a) -> EventM x (WeakBagTicket, FanSubscribed x k v, Maybe (v a))
1524getFanSubscribed k f sub = do
1560getFanSubscribed k f sub = do
1525 mSubscribed <- liftIO $ readIORef $ fanSubscribed f
1561 mSubscribed <- liftIO $ readIORef $ fanSubscribed f
1526 case mSubscribed of
1562 case mSubscribed of
@@ -1538,13 +1574,16 @@ getFanSubscribed k f sub = do
1538 subscribersRef <- liftIO $ newIORef $ error "getFanSubscribed: subscribersRef not yet initialized"
1574 subscribersRef <- liftIO $ newIORef $ error "getFanSubscribed: subscribersRef not yet initialized"
1539 occRef <- liftIO $ newIORef parentOcc
1575 occRef <- liftIO $ newIORef parentOcc
1540 when (isJust parentOcc) $ scheduleClear occRef
1576 when (isJust parentOcc) $ scheduleClear occRef
1577+#ifdef DEBUG_NODEIDS
1578+ nid <- liftIO newNodeId
1541 let subscribed = FanSubscribed
1580 let subscribed = FanSubscribed
1542 { fanSubscribedCachedSubscribed = fanSubscribed f
1581 { fanSubscribedCachedSubscribed = fanSubscribed f
1543 , fanSubscribedOccurrence = occRef
1582 , fanSubscribedOccurrence = occRef
1544 , fanSubscribedParent = subscription
1583 , fanSubscribedParent = subscription
1545 , fanSubscribedSubscribers = subscribersRef
1584 , fanSubscribedSubscribers = subscribersRef
1546#ifdef DEBUG_NODEIDS
1585#ifdef DEBUG_NODEIDS
1547− , fanSubscribedNodeId = unsafeNodeId f
1586+ , fanSubscribedNodeId = nid
1550 let !self = (k, subscribed)
1589 let !self = (k, subscribed)
@@ -1554,7 +1593,7 @@ getFanSubscribed k f sub = do
1554 liftIO $ writeIORef (fanSubscribed f) $ Just subscribed
1593 liftIO $ writeIORef (fanSubscribed f) $ Just subscribed
1555 return (slnForSub, subscribed, coerce $ DMap.lookup k =<< parentOcc)
1594 return (slnForSub, subscribed, coerce $ DMap.lookup k =<< parentOcc)
1557−cleanupFanSubscribed :: GCompare k => (k a, FanSubscribed x k) -> IO ()
1596+cleanupFanSubscribed :: GCompare k => (k a, FanSubscribed x k v) -> IO ()
1558cleanupFanSubscribed (k, subscribed) = do
1597cleanupFanSubscribed (k, subscribed) = do
1559 subscribers <- readIORef $ fanSubscribedSubscribers subscribed
1598 subscribers <- readIORef $ fanSubscribedSubscribers subscribed
1560 let reducedSubscribers = DMap.delete k subscribers
1599 let reducedSubscribers = DMap.delete k subscribers
@@ -1566,7 +1605,7 @@ cleanupFanSubscribed (k, subscribed) = do
1566 else writeIORef (fanSubscribedSubscribers subscribed) $! reducedSubscribers
1605 else writeIORef (fanSubscribedSubscribers subscribed) $! reducedSubscribers
1568{-# INLINE subscribeFanSubscribed #-}
1607{-# INLINE subscribeFanSubscribed #-}
1569−subscribeFanSubscribed :: GCompare k => k a -> FanSubscribed x k -> Subscriber x a -> IO WeakBagTicket
1608+subscribeFanSubscribed :: GCompare k => k a -> FanSubscribed x k v -> Subscriber x (v a) -> IO WeakBagTicket
1570subscribeFanSubscribed k subscribed sub = do
1609subscribeFanSubscribed k subscribed sub = do
1571 subscribers <- readIORef $ fanSubscribedSubscribers subscribed
1610 subscribers <- readIORef $ fanSubscribedSubscribers subscribed
1572 case DMap.lookup k subscribers of
1611 case DMap.lookup k subscribers of
@@ -1604,6 +1643,9 @@ getSwitchSubscribed s sub = do
1604 when (isJust parentOcc) $ scheduleClear occRef
1643 when (isJust parentOcc) $ scheduleClear occRef
1605 weakSelf <- liftIO $ newIORef $ error "getSwitchSubscribed: weakSelf not yet initialized"
1644 weakSelf <- liftIO $ newIORef $ error "getSwitchSubscribed: weakSelf not yet initialized"
1606 (subs, slnForSub) <- liftIO $ WeakBag.singleton sub weakSelf cleanupSwitchSubscribed
1645 (subs, slnForSub) <- liftIO $ WeakBag.singleton sub weakSelf cleanupSwitchSubscribed
1646+#ifdef DEBUG_NODEIDS
1647+ nid <- liftIO newNodeId
1607 let !subscribed = SwitchSubscribed
1649 let !subscribed = SwitchSubscribed
1608 { switchSubscribedCachedSubscribed = switchSubscribed s
1650 { switchSubscribedCachedSubscribed = switchSubscribed s
1609 , switchSubscribedOccurrence = occRef
1651 , switchSubscribedOccurrence = occRef
@@ -1616,7 +1658,7 @@ getSwitchSubscribed s sub = do
1616 , switchSubscribedCurrentParent = subscriptionRef
1658 , switchSubscribedCurrentParent = subscriptionRef
1617 , switchSubscribedWeakSelf = weakSelf
1659 , switchSubscribedWeakSelf = weakSelf
1618#ifdef DEBUG_NODEIDS
1660#ifdef DEBUG_NODEIDS
1619− , switchSubscribedNodeId = unsafeNodeId s
1661+ , switchSubscribedNodeId = nid
1622 liftIO $ writeIORef weakSelf =<< evaluate =<< mkWeakPtrWithDebug subscribed "switchSubscribedWeakSelf"
1664 liftIO $ writeIORef weakSelf =<< evaluate =<< mkWeakPtrWithDebug subscribed "switchSubscribedWeakSelf"
@@ -1661,6 +1703,9 @@ getCoincidenceSubscribed c sub = do
1661 scheduleClear innerSubdRef
1703 scheduleClear innerSubdRef
1662 weakSelf <- liftIO $ newIORef $ error "getCoincidenceSubscribed: weakSelf not yet implemented"
1704 weakSelf <- liftIO $ newIORef $ error "getCoincidenceSubscribed: weakSelf not yet implemented"
1663 (subs, slnForSub) <- liftIO $ WeakBag.singleton sub weakSelf cleanupCoincidenceSubscribed
1705 (subs, slnForSub) <- liftIO $ WeakBag.singleton sub weakSelf cleanupCoincidenceSubscribed
1706+#ifdef DEBUG_NODEIDS
1707+ nid <- liftIO newNodeId
1664 let subscribed = CoincidenceSubscribed
1709 let subscribed = CoincidenceSubscribed
1665 { coincidenceSubscribedCachedSubscribed = coincidenceSubscribed c
1710 { coincidenceSubscribedCachedSubscribed = coincidenceSubscribed c
1666 , coincidenceSubscribedOccurrence = occRef
1711 , coincidenceSubscribedOccurrence = occRef
@@ -1671,7 +1716,7 @@ getCoincidenceSubscribed c sub = do
1671 , coincidenceSubscribedInnerParent = innerSubdRef
1716 , coincidenceSubscribedInnerParent = innerSubdRef
1672 , coincidenceSubscribedWeakSelf = weakSelf
1717 , coincidenceSubscribedWeakSelf = weakSelf
1673#ifdef DEBUG_NODEIDS
1718#ifdef DEBUG_NODEIDS
1674− , coincidenceSubscribedNodeId = unsafeNodeId c
1719+ , coincidenceSubscribedNodeId = nid
1677 liftIO $ writeIORef weakSelf =<< evaluate =<< mkWeakPtrWithDebug subscribed "CoincidenceSubscribed"
1722 liftIO $ writeIORef weakSelf =<< evaluate =<< mkWeakPtrWithDebug subscribed "CoincidenceSubscribed"
@@ -1688,26 +1733,34 @@ cleanupCoincidenceSubscribed subscribed = do
1688subscribeCoincidenceSubscribed :: CoincidenceSubscribed x a -> Subscriber x a -> IO WeakBagTicket
1733subscribeCoincidenceSubscribed :: CoincidenceSubscribed x a -> Subscriber x a -> IO WeakBagTicket
1689subscribeCoincidenceSubscribed subscribed sub = WeakBag.insert sub (coincidenceSubscribedSubscribers subscribed) (coincidenceSubscribedWeakSelf subscribed) cleanupCoincidenceSubscribed
1734subscribeCoincidenceSubscribed subscribed sub = WeakBag.insert sub (coincidenceSubscribedSubscribers subscribed) (coincidenceSubscribedWeakSelf subscribed) cleanupCoincidenceSubscribed
1691−{-# INLINE merge #-}
1736+{-# INLINE mergeG #-}
1692−merge :: forall k x. (HasSpiderTimeline x, GCompare k) => Dynamic x (PatchDMap k (Event x)) -> Event x (DMap k Identity)
1737+mergeG :: forall k q x v. (HasSpiderTimeline x, GCompare k)
1738+ => (forall a. q a -> Event x (v a))
1739+ -> DynamicS x (PatchDMap k q) -> Event x (DMap k v)
1693−merge d = cacheEvent (mergeCheap d)
1740+mergeG nt d = cacheEvent (mergeCheap nt d)
1695{-# INLINE mergeWithMove #-}
1742{-# INLINE mergeWithMove #-}
1696−mergeWithMove :: forall k x. (HasSpiderTimeline x, GCompare k) => Dynamic x (PatchDMapWithMove k (Event x)) -> Event x (DMap k Identity)
1743+mergeWithMove :: forall k v q x. (HasSpiderTimeline x, GCompare k)
1744+ => (forall a. q a -> Event x (v a))
1745+ -> DynamicS x (PatchDMapWithMove k q) -> Event x (DMap k v)
1697−mergeWithMove d = cacheEvent (mergeCheapWithMove d)
1746+mergeWithMove nt d = cacheEvent (mergeCheapWithMove nt d)
1699{-# INLINE [1] mergeCheap #-}
1748{-# INLINE [1] mergeCheap #-}
1700−mergeCheap :: forall k x. (HasSpiderTimeline x, GCompare k) => Dynamic x (PatchDMap k (Event x)) -> Event x (DMap k Identity)
1750+ :: forall k x q v. (HasSpiderTimeline x, GCompare k)
1751+ => (forall a. q a -> Event x (v a))
1752+ -> DynamicS x (PatchDMap k q)
1753+ -> Event x (DMap k v)
1701−mergeCheap = mergeCheap' getInitialSubscribers updateMe destroy
1754+mergeCheap nt = mergeGCheap' getInitialSubscribers updateMe destroy
1703− updateMe :: MergeUpdateFunc k x (PatchDMap k (Event x)) (MergeSubscribedParent x)
1756+ updateMe :: MergeUpdateFunc k v x (PatchDMap k q) (MergeSubscribedParent x)
1704 updateMe subscriber heightBagRef oldParents (PatchDMap p) = do
1757 updateMe subscriber heightBagRef oldParents (PatchDMap p) = do
1705 let f (subscriptionsToKill, ps) (k :=> ComposeMaybe me) = do
1758 let f (subscriptionsToKill, ps) (k :=> ComposeMaybe me) = do
1706 (mOldSubd, newPs) <- case me of
1759 (mOldSubd, newPs) <- case me of
1707 Nothing -> return $ DMap.updateLookupWithKey (\_ _ -> Nothing) k ps
1760 Nothing -> return $ DMap.updateLookupWithKey (\_ _ -> Nothing) k ps
1708 Just e -> do
1761 Just e -> do
1709 let s = subscriber $ return k
1762 let s = subscriber $ return k
1710− subscription@(EventSubscription _ subd) <- subscribe e s
1763+ subscription@(EventSubscription _ subd) <- subscribe (nt e) s
1711 newParentHeight <- liftIO $ getEventSubscribedHeight subd
1764 newParentHeight <- liftIO $ getEventSubscribedHeight subd
1712 let newParent = MergeSubscribedParent subscription
1765 let newParent = MergeSubscribedParent subscription
1713 liftIO $ modifyIORef' heightBagRef $ heightBagAdd newParentHeight
1766 liftIO $ modifyIORef' heightBagRef $ heightBagAdd newParentHeight
@@ -1717,28 +1770,33 @@ mergeCheap = mergeCheap' getInitialSubscribers updateMe destroy
1717 liftIO $ modifyIORef heightBagRef $ heightBagRemove oldHeight
1770 liftIO $ modifyIORef heightBagRef $ heightBagRemove oldHeight
1718 return (maybeToList (unMergeSubscribedParent <$> mOldSubd) ++ subscriptionsToKill, newPs)
1771 return (maybeToList (unMergeSubscribedParent <$> mOldSubd) ++ subscriptionsToKill, newPs)
1719 foldM f ([], oldParents) $ DMap.toList p
1772 foldM f ([], oldParents) $ DMap.toList p
1720− getInitialSubscribers :: MergeInitFunc k x (MergeSubscribedParent x)
1774+ getInitialSubscribers :: MergeInitFunc k v q x (MergeSubscribedParent x)
1721 getInitialSubscribers initialParents subscriber = do
1775 getInitialSubscribers initialParents subscriber = do
1722 subscribers <- forM (DMap.toList initialParents) $ \(k :=> e) -> do
1776 subscribers <- forM (DMap.toList initialParents) $ \(k :=> e) -> do
1723 let s = subscriber $ return k
1777 let s = subscriber $ return k
1724− (subscription@(EventSubscription _ parentSubd), parentOcc) <- subscribeAndRead e s
1778+ (subscription@(EventSubscription _ parentSubd), parentOcc) <- subscribeAndRead (nt e) s
1725 height <- liftIO $ getEventSubscribedHeight parentSubd
1779 height <- liftIO $ getEventSubscribedHeight parentSubd
1726− return (fmap (\x -> k :=> Identity x) parentOcc, height, k :=> MergeSubscribedParent subscription)
1780+ return (fmap (k :=>) parentOcc, height, k :=> MergeSubscribedParent subscription)
1727 return ( DMap.fromDistinctAscList $ mapMaybe (\(x, _, _) -> x) subscribers
1781 return ( DMap.fromDistinctAscList $ mapMaybe (\(x, _, _) -> x) subscribers
1728 , fmap (\(_, h, _) -> h) subscribers --TODO: Assert that there's no invalidHeight in here
1782 , fmap (\(_, h, _) -> h) subscribers --TODO: Assert that there's no invalidHeight in here
1729 , DMap.fromDistinctAscList $ map (\(_, _, x) -> x) subscribers
1783 , DMap.fromDistinctAscList $ map (\(_, _, x) -> x) subscribers
1731 destroy :: MergeDestroyFunc k (MergeSubscribedParent x)
1786 destroy :: MergeDestroyFunc k (MergeSubscribedParent x)
1732 destroy s = forM_ (DMap.toList s) $ \(_ :=> MergeSubscribedParent sub) -> unsubscribe sub
1787 destroy s = forM_ (DMap.toList s) $ \(_ :=> MergeSubscribedParent sub) -> unsubscribe sub
1734{-# INLINE [1] mergeCheapWithMove #-}
1789{-# INLINE [1] mergeCheapWithMove #-}
1735−mergeCheapWithMove :: forall k x. (HasSpiderTimeline x, GCompare k) => Dynamic x (PatchDMapWithMove k (Event x)) -> Event x (DMap k Identity)
1790+mergeCheapWithMove :: forall k x v q. (HasSpiderTimeline x, GCompare k)
1791+ => (forall a. q a -> Event x (v a))
1792+ -> DynamicS x (PatchDMapWithMove k q)
1793+ -> Event x (DMap k v)
1736−mergeCheapWithMove = mergeCheap' getInitialSubscribers updateMe destroy
1794+mergeCheapWithMove nt = mergeGCheap' getInitialSubscribers updateMe destroy
1738− updateMe :: MergeUpdateFunc k x (PatchDMapWithMove k (Event x)) (MergeSubscribedParentWithMove x k)
1796+ updateMe :: MergeUpdateFunc k v x (PatchDMapWithMove k q) (MergeSubscribedParentWithMove x k)
1739 updateMe subscriber heightBagRef oldParents p = do
1797 updateMe subscriber heightBagRef oldParents p = do
1740 -- Prepare new parents for insertion
1798 -- Prepare new parents for insertion
1741− let subscribeParent :: forall a. k a -> Event x a -> EventM x (MergeSubscribedParentWithMove x k a)
1799+ let subscribeParent :: forall a. k a -> Event x (v a) -> EventM x (MergeSubscribedParentWithMove x k a)
1742 subscribeParent k e = do
1800 subscribeParent k e = do
1743 keyRef <- liftIO $ newIORef k
1801 keyRef <- liftIO $ newIORef k
1744 let s = subscriber $ liftIO $ readIORef keyRef
1802 let s = subscriber $ liftIO $ readIORef keyRef
@@ -1747,9 +1805,9 @@ mergeCheapWithMove = mergeCheap' getInitialSubscribers updateMe destroy
1747 newParentHeight <- getEventSubscribedHeight subd
1805 newParentHeight <- getEventSubscribedHeight subd
1748 modifyIORef' heightBagRef $ heightBagAdd newParentHeight
1806 modifyIORef' heightBagRef $ heightBagAdd newParentHeight
1749 return $ MergeSubscribedParentWithMove subscription keyRef
1807 return $ MergeSubscribedParentWithMove subscription keyRef
1750− p' <- PatchDMapWithMove.traversePatchDMapWithMoveWithKey subscribeParent p
1808+ p' <- PatchDMapWithMove.traversePatchDMapWithMoveWithKey (\k q -> subscribeParent k (nt q)) p
1751 -- Collect old parents for deletion and update the keys of moved parents
1809 -- Collect old parents for deletion and update the keys of moved parents
1752− let moveOrDelete :: forall a. k a -> PatchDMapWithMove.NodeInfo k (Event x) a -> MergeSubscribedParentWithMove x k a -> Constant (EventM x (Maybe (EventSubscription x))) a
1810+ let moveOrDelete :: forall a. k a -> PatchDMapWithMove.NodeInfo k q a -> MergeSubscribedParentWithMove x k a -> Constant (EventM x (Maybe (EventSubscription x))) a
1753 moveOrDelete _ ni parent = Constant $ case getComposeMaybe $ PatchDMapWithMove._nodeInfo_to ni of
1811 moveOrDelete _ ni parent = Constant $ case getComposeMaybe $ PatchDMapWithMove._nodeInfo_to ni of
1754 Nothing -> do
1812 Nothing -> do
1755 oldHeight <- liftIO $ getEventSubscribedHeight $ _eventSubscription_subscribed $ _mergeSubscribedParentWithMove_subscription parent
1813 oldHeight <- liftIO $ getEventSubscribedHeight $ _eventSubscription_subscribed $ _mergeSubscribedParentWithMove_subscription parent
@@ -1760,46 +1818,47 @@ mergeCheapWithMove = mergeCheap' getInitialSubscribers updateMe destroy
1760 return Nothing
1818 return Nothing
1761 toDelete <- fmap catMaybes $ mapM (\(_ :=> v) -> getConstant v) $ DMap.toList $ DMap.intersectionWithKey moveOrDelete (unPatchDMapWithMove p) oldParents
1819 toDelete <- fmap catMaybes $ mapM (\(_ :=> v) -> getConstant v) $ DMap.toList $ DMap.intersectionWithKey moveOrDelete (unPatchDMapWithMove p) oldParents
1762 return (toDelete, applyAlways p' oldParents)
1820 return (toDelete, applyAlways p' oldParents)
1763− getInitialSubscribers :: MergeInitFunc k x (MergeSubscribedParentWithMove x k)
1821+ getInitialSubscribers :: MergeInitFunc k v q x (MergeSubscribedParentWithMove x k)
1764 getInitialSubscribers initialParents subscriber = do
1822 getInitialSubscribers initialParents subscriber = do
1765 subscribers <- forM (DMap.toList initialParents) $ \(k :=> e) -> do
1823 subscribers <- forM (DMap.toList initialParents) $ \(k :=> e) -> do
1766 keyRef <- liftIO $ newIORef k
1824 keyRef <- liftIO $ newIORef k
1767 let s = subscriber $ liftIO $ readIORef keyRef
1825 let s = subscriber $ liftIO $ readIORef keyRef
1768− (subscription@(EventSubscription _ parentSubd), parentOcc) <- subscribeAndRead e s
1826+ (subscription@(EventSubscription _ parentSubd), parentOcc) <- subscribeAndRead (nt e) s
1769 height <- liftIO $ getEventSubscribedHeight parentSubd
1827 height <- liftIO $ getEventSubscribedHeight parentSubd
1770− return (fmap (\x -> k :=> Identity x) parentOcc, height, k :=> MergeSubscribedParentWithMove subscription keyRef)
1828+ return (fmap (k :=>) parentOcc, height, k :=> MergeSubscribedParentWithMove subscription keyRef)
1771 return ( DMap.fromDistinctAscList $ mapMaybe (\(x, _, _) -> x) subscribers
1829 return ( DMap.fromDistinctAscList $ mapMaybe (\(x, _, _) -> x) subscribers
1772 , fmap (\(_, h, _) -> h) subscribers --TODO: Assert that there's no invalidHeight in here
1830 , fmap (\(_, h, _) -> h) subscribers --TODO: Assert that there's no invalidHeight in here
1773 , DMap.fromDistinctAscList $ map (\(_, _, x) -> x) subscribers
1831 , DMap.fromDistinctAscList $ map (\(_, _, x) -> x) subscribers
1775 destroy :: MergeDestroyFunc k (MergeSubscribedParentWithMove x k)
1834 destroy :: MergeDestroyFunc k (MergeSubscribedParentWithMove x k)
1776 destroy s = forM_ (DMap.toList s) $ \(_ :=> MergeSubscribedParentWithMove sub _) -> unsubscribe sub
1835 destroy s = forM_ (DMap.toList s) $ \(_ :=> MergeSubscribedParentWithMove sub _) -> unsubscribe sub
1778−type MergeUpdateFunc k x p s
1837+type MergeUpdateFunc k v x p s
1779− = (forall a. EventM x (k a) -> Subscriber x a)
1838+ = (forall a. EventM x (k a) -> Subscriber x (v a))
1780 -> IORef HeightBag
1839 -> IORef HeightBag
1781 -> DMap k s
1840 -> DMap k s
1783 -> EventM x ([EventSubscription x], DMap k s)
1842 -> EventM x ([EventSubscription x], DMap k s)
1785−type MergeInitFunc k x s
1844+type MergeInitFunc k v q x s
1786− = DMap k (Event x)
1845+ = DMap k q
1787− -> (forall a. EventM x (k a) -> Subscriber x a)
1846+ -> (forall a. EventM x (k a) -> Subscriber x (v a))
1788− -> EventM x (DMap k Identity, [Height], DMap k s)
1847+ -> EventM x (DMap k v, [Height], DMap k s)
1790type MergeDestroyFunc k s
1849type MergeDestroyFunc k s
1791 = DMap k s
1850 = DMap k s
1792 -> IO ()
1851 -> IO ()
1794−data Merge x k s = Merge
1853+data Merge x k v s = Merge
1795 { _merge_parentsRef :: {-# UNPACK #-} !(IORef (DMap k s))
1854 { _merge_parentsRef :: {-# UNPACK #-} !(IORef (DMap k s))
1796 , _merge_heightBagRef :: {-# UNPACK #-} !(IORef HeightBag)
1855 , _merge_heightBagRef :: {-# UNPACK #-} !(IORef HeightBag)
1797 , _merge_heightRef :: {-# UNPACK #-} !(IORef Height)
1856 , _merge_heightRef :: {-# UNPACK #-} !(IORef Height)
1798− , _merge_sub :: {-# UNPACK #-} !(Subscriber x (DMap k Identity))
1857+ , _merge_sub :: {-# UNPACK #-} !(Subscriber x (DMap k v))
1799− , _merge_accumRef :: {-# UNPACK #-} !(IORef (DMap k Identity))
1858+ , _merge_accumRef :: {-# UNPACK #-} !(IORef (DMap k v))
1802−invalidateMergeHeight :: Merge x k s -> IO ()
1861+invalidateMergeHeight :: Merge x k v s -> IO ()
1803invalidateMergeHeight m = invalidateMergeHeight' (_merge_heightRef m) (_merge_sub m)
1862invalidateMergeHeight m = invalidateMergeHeight' (_merge_heightRef m) (_merge_sub m)
1805invalidateMergeHeight' :: IORef Height -> Subscriber x a -> IO ()
1864invalidateMergeHeight' :: IORef Height -> Subscriber x a -> IO ()
@@ -1809,8 +1868,7 @@ invalidateMergeHeight' heightRef sub = do
1809 writeIORef heightRef $! invalidHeight
1868 writeIORef heightRef $! invalidHeight
1810 subscriberInvalidateHeight sub oldHeight
1869 subscriberInvalidateHeight sub oldHeight
1813−revalidateMergeHeight :: Merge x k s -> IO ()
1871+revalidateMergeHeight :: Merge x k v s -> IO ()
1814revalidateMergeHeight m = do
1872revalidateMergeHeight m = do
1815 currentHeight <- readIORef $ _merge_heightRef m
1873 currentHeight <- readIORef $ _merge_heightRef m
1816 when (currentHeight == invalidHeight) $ do -- revalidateMergeHeight may be called multiple times; perhaps the's a way to finesse it to avoid this check
1874 when (currentHeight == invalidHeight) $ do -- revalidateMergeHeight may be called multiple times; perhaps the's a way to finesse it to avoid this check
@@ -1826,19 +1884,19 @@ revalidateMergeHeight m = do
1826 subscriberRecalculateHeight (_merge_sub m) height
1884 subscriberRecalculateHeight (_merge_sub m) height
1827 GT -> error $ "revalidateMergeHeight: more heights (" <> show (heightBagSize heights) <> ") than parents (" <> show (DMap.size parents) <> ") for Merge"
1885 GT -> error $ "revalidateMergeHeight: more heights (" <> show (heightBagSize heights) <> ") than parents (" <> show (DMap.size parents) <> ") for Merge"
1829−scheduleMergeSelf :: HasSpiderTimeline x => Merge x k s -> Height -> EventM x ()
1887+scheduleMergeSelf :: HasSpiderTimeline x => Merge x k v s -> Height -> EventM x ()
1830scheduleMergeSelf m height = scheduleMerge' height (_merge_heightRef m) $ do
1888scheduleMergeSelf m height = scheduleMerge' height (_merge_heightRef m) $ do
1831 vals <- liftIO $ readIORef $ _merge_accumRef m
1889 vals <- liftIO $ readIORef $ _merge_accumRef m
1832 liftIO $ writeIORef (_merge_accumRef m) $! DMap.empty -- Once we're done with this, we can clear it immediately, because if there's a cacheEvent in front of us, it'll handle subsequent subscribers, and if not, we won't get subsequent subscribers
1890 liftIO $ writeIORef (_merge_accumRef m) $! DMap.empty -- Once we're done with this, we can clear it immediately, because if there's a cacheEvent in front of us, it'll handle subsequent subscribers, and if not, we won't get subsequent subscribers
1833 --TODO: Assert that m is not empty
1891 --TODO: Assert that m is not empty
1834 subscriberPropagate (_merge_sub m) vals
1892 subscriberPropagate (_merge_sub m) vals
1836−mergeSubscriber :: forall x k s a. (HasSpiderTimeline x, GCompare k) => Merge x k s -> EventM x (k a) -> Subscriber x a
1894+mergeSubscriber :: forall x k v s a. (HasSpiderTimeline x, GCompare k) => Merge x k v s -> EventM x (k a) -> Subscriber x (v a)
1837mergeSubscriber m getKey = Subscriber
1895mergeSubscriber m getKey = Subscriber
1838 { subscriberPropagate = \a -> do
1896 { subscriberPropagate = \a -> do
1839 oldM <- liftIO $ readIORef $ _merge_accumRef m
1897 oldM <- liftIO $ readIORef $ _merge_accumRef m
1840 k <- getKey
1898 k <- getKey
1841− let newM = DMap.insertWith (error $ "Same key fired multiple times for Merge") k (Identity a) oldM
1899+ let newM = DMap.insertWith (error $ "Same key fired multiple times for Merge") k a oldM
1842 tracePropagate (Proxy :: Proxy x) $ " DMap.size oldM = " <> show (DMap.size oldM) <> "; DMap.size newM = " <> show (DMap.size newM)
1900 tracePropagate (Proxy :: Proxy x) $ " DMap.size oldM = " <> show (DMap.size oldM) <> "; DMap.size newM = " <> show (DMap.size newM)
1843 liftIO $ writeIORef (_merge_accumRef m) $! newM
1901 liftIO $ writeIORef (_merge_accumRef m) $! newM
1844 when (DMap.null oldM) $ do -- Only schedule the firing once
1902 when (DMap.null oldM) $ do -- Only schedule the firing once
@@ -1853,7 +1911,7 @@ mergeSubscriber m getKey = Subscriber
1853 else liftIO $ do
1911 else liftIO $ do
1854#ifdef DEBUG_CYCLES
1912#ifdef DEBUG_CYCLES
1855 nodesInvolvedInCycle <- walkInvalidHeightParents $ eventSubscribedMerge subscribed
1913 nodesInvolvedInCycle <- walkInvalidHeightParents $ eventSubscribedMerge subscribed
1856− stacks <- forM nodesInvolvedInCycle $ \(Some.This es) -> whoCreatedEventSubscribed es
1914+ stacks <- forM nodesInvolvedInCycle $ \(Some es) -> whoCreatedEventSubscribed es
1857 let cycleInfo = ":\n" <> drawForest (listsToForest stacks)
1915 let cycleInfo = ":\n" <> drawForest (listsToForest stacks)
1859 let cycleInfo = ""
1917 let cycleInfo = ""
@@ -1869,7 +1927,7 @@ mergeSubscriber m getKey = Subscriber
1871--TODO: Be able to run as much of this as possible promptly
1929--TODO: Be able to run as much of this as possible promptly
1872−updateMerge :: (HasSpiderTimeline x, GCompare k) => Merge x k s -> MergeUpdateFunc k x p s -> p -> SomeMergeUpdate x
1930+updateMerge :: (HasSpiderTimeline x, GCompare k) => Merge x k v s -> MergeUpdateFunc k v x p s -> p -> SomeMergeUpdate x
1873updateMerge m updateFunc p = SomeMergeUpdate updateMe (invalidateMergeHeight m) (revalidateMergeHeight m)
1931updateMerge m updateFunc p = SomeMergeUpdate updateMe (invalidateMergeHeight m) (revalidateMergeHeight m)
1874 where updateMe = do
1932 where updateMe = do
1875 oldParents <- liftIO $ readIORef $ _merge_parentsRef m
1933 oldParents <- liftIO $ readIORef $ _merge_parentsRef m
@@ -1877,9 +1935,10 @@ updateMerge m updateFunc p = SomeMergeUpdate updateMe (invalidateMergeHeight m)
1877 liftIO $ writeIORef (_merge_parentsRef m) $! newParents
1935 liftIO $ writeIORef (_merge_parentsRef m) $! newParents
1878 return subscriptionsToKill
1936 return subscriptionsToKill
1880−{-# INLINE mergeCheap' #-}
1938+{-# INLINE mergeGCheap' #-}
1939+mergeGCheap' :: forall k v x p s q. (HasSpiderTimeline x, GCompare k, PatchTarget p ~ DMap k q)
1881−mergeCheap' :: forall k x p s. (HasSpiderTimeline x, GCompare k, PatchTarget p ~ DMap k (Event x)) => MergeInitFunc k x s -> MergeUpdateFunc k x p s -> MergeDestroyFunc k s -> Dynamic x p -> Event x (DMap k Identity)
1940+ => MergeInitFunc k v q x s -> MergeUpdateFunc k v x p s -> MergeDestroyFunc k s -> DynamicS x p -> Event x (DMap k v)
1882−mergeCheap' getInitialSubscribers updateFunc destroy d = Event $ \sub -> do
1941+mergeGCheap' getInitialSubscribers updateFunc destroy d = Event $ \sub -> do
1883 initialParents <- readBehaviorUntracked $ dynamicCurrent d
1942 initialParents <- readBehaviorUntracked $ dynamicCurrent d
1884 accumRef <- liftIO $ newIORef $ error "merge: accumRef not yet initialized"
1943 accumRef <- liftIO $ newIORef $ error "merge: accumRef not yet initialized"
1885 heightRef <- liftIO $ newIORef $ error "merge: heightRef not yet initialized"
1944 heightRef <- liftIO $ newIORef $ error "merge: heightRef not yet initialized"
@@ -1927,11 +1986,11 @@ mergeCheap' getInitialSubscribers updateFunc destroy d = Event $ \sub -> do
1930−mergeInt :: forall x a. (HasSpiderTimeline x) => Dynamic x (PatchIntMap (Event x a)) -> Event x (IntMap a)
1989+mergeInt :: forall x a. (HasSpiderTimeline x) => DynamicS x (PatchIntMap (Event x a)) -> Event x (IntMap a)
1931mergeInt = cacheEvent . mergeIntCheap
1990mergeInt = cacheEvent . mergeIntCheap
1933{-# INLINABLE mergeIntCheap #-}
1992{-# INLINABLE mergeIntCheap #-}
1934−mergeIntCheap :: forall x a. (HasSpiderTimeline x) => Dynamic x (PatchIntMap (Event x a)) -> Event x (IntMap a)
1993+mergeIntCheap :: forall x a. (HasSpiderTimeline x) => DynamicS x (PatchIntMap (Event x a)) -> Event x (IntMap a)
1935mergeIntCheap d = Event $ \sub -> do
1994mergeIntCheap d = Event $ \sub -> do
1936 initialParents <- readBehaviorUntracked $ dynamicCurrent d
1995 initialParents <- readBehaviorUntracked $ dynamicCurrent d
1937 accum <- liftIO $ FastMutableIntMap.newEmpty
1996 accum <- liftIO $ FastMutableIntMap.newEmpty
@@ -2028,14 +2087,16 @@ mergeIntCheap d = Event $ \sub -> do
2030newtype EventSelector x k = EventSelector { select :: forall a. k a -> Event x a }
2089newtype EventSelector x k = EventSelector { select :: forall a. k a -> Event x a }
2090+newtype EventSelectorG x k v = EventSelectorG { selectG :: forall a. k a -> Event x (v a) }
2032−fan :: (HasSpiderTimeline x, GCompare k) => Event x (DMap k Identity) -> EventSelector x k
2092+fanG :: (HasSpiderTimeline x, GCompare k) => Event x (DMap k v) -> EventSelectorG x k v
2033−fan e =
2093+fanG e = unsafePerformIO $ do
2094+ ref <- newIORef Nothing
2034 let f = Fan
2095 let f = Fan
2035 { fanParent = e
2096 { fanParent = e
2036− , fanSubscribed = unsafeNewIORef e Nothing
2097+ , fanSubscribed = ref
2038− in EventSelector $ \k -> eventFan k f
2099+ pure $ EventSelectorG $ \k -> eventFan k f
2040runHoldInits :: HasSpiderTimeline x => IORef [SomeHoldInit x] -> IORef [SomeDynInit x] -> IORef [SomeMergeInit x] -> EventM x ()
2101runHoldInits :: HasSpiderTimeline x => IORef [SomeHoldInit x] -> IORef [SomeDynInit x] -> IORef [SomeMergeInit x] -> EventM x ()
2041runHoldInits holdInitRef dynInitRef mergeInitRef = do
2102runHoldInits holdInitRef dynInitRef mergeInitRef = do
@@ -2089,18 +2150,18 @@ clearEventEnv (EventEnv toAssignRef holdInitRef dynInitRef mergeUpdateRef mergeI
2089-- | Run an event action outside of a frame
2150-- | Run an event action outside of a frame
2090runFrame :: forall x a. HasSpiderTimeline x => EventM x a -> SpiderHost x a --TODO: This function also needs to hold the mutex
2151runFrame :: forall x a. HasSpiderTimeline x => EventM x a -> SpiderHost x a --TODO: This function also needs to hold the mutex
2091runFrame a = SpiderHost $ do
2152runFrame a = SpiderHost $ do
2092− let env = _spiderTimeline_eventEnv (spiderTimeline :: SpiderTimelineEnv x)
2153+ let env = _spiderTimeline_eventEnv $ unSTE (spiderTimeline :: SpiderTimelineEnv x)
2093 let go = do
2154 let go = do
2094 result <- a
2155 result <- a
2095 runHoldInits (eventEnvHoldInits env) (eventEnvDynInits env) (eventEnvMergeInits env) -- This must happen before doing the assignments, in case subscribing a Hold causes existing Holds to be read by the newly-propagated events
2156 runHoldInits (eventEnvHoldInits env) (eventEnvDynInits env) (eventEnvMergeInits env) -- This must happen before doing the assignments, in case subscribing a Hold causes existing Holds to be read by the newly-propagated events
2096 return result
2157 return result
2097 result <- runEventM go
2158 result <- runEventM go
2098 toClear <- readIORef $ eventEnvClears env
2159 toClear <- readIORef $ eventEnvClears env
2099− forM_ toClear $ \(Some.This (Clear ref)) -> {-# SCC "clear" #-} writeIORef ref Nothing
2160+ forM_ toClear $ \(Some (Clear ref)) -> {-# SCC "clear" #-} writeIORef ref Nothing
2100 toClearInt <- readIORef $ eventEnvIntClears env
2161 toClearInt <- readIORef $ eventEnvIntClears env
2101− forM_ toClearInt $ \(Some.This (IntClear ref)) -> {-# SCC "intClear" #-} writeIORef ref $! IntMap.empty
2162+ forM_ toClearInt $ \(Some (IntClear ref)) -> {-# SCC "intClear" #-} writeIORef ref $! IntMap.empty
2102 toClearRoot <- readIORef $ eventEnvRootClears env
2163 toClearRoot <- readIORef $ eventEnvRootClears env
2103− forM_ toClearRoot $ \(Some.This (RootClear ref)) -> {-# SCC "rootClear" #-} writeIORef ref $! DMap.empty
2164+ forM_ toClearRoot $ \(Some (RootClear ref)) -> {-# SCC "rootClear" #-} writeIORef ref $! DMap.empty
2104 toAssign <- readIORef $ eventEnvAssignments env
2165 toAssign <- readIORef $ eventEnvAssignments env
2105 toReconnectRef <- newIORef []
2166 toReconnectRef <- newIORef []
2106 coincidenceInfos <- readIORef $ eventEnvResetCoincidences env
2167 coincidenceInfos <- readIORef $ eventEnvResetCoincidences env
@@ -2147,7 +2208,7 @@ runFrame a = SpiderHost $ do
2147 myHeight <- readIORef $ switchSubscribedHeight subscribed
2208 myHeight <- readIORef $ switchSubscribedHeight subscribed
2148 when (parentHeight /= myHeight) $ do
2209 when (parentHeight /= myHeight) $ do
2149 writeIORef (switchSubscribedHeight subscribed) $! invalidHeight
2210 writeIORef (switchSubscribedHeight subscribed) $! invalidHeight
2150− WeakBag.traverse (switchSubscribedSubscribers subscribed) $ invalidateSubscriberHeight myHeight
2211+ WeakBag.traverse_ (switchSubscribedSubscribers subscribed) $ invalidateSubscriberHeight myHeight
2151 mapM_ _someMergeUpdate_invalidateHeight mergeUpdates --TODO: In addition to when the patch is completely empty, we should also not run this if it has some Nothing values, but none of them have actually had any effect; potentially, we could even check for Just values with no effect (e.g. by comparing their IORefs and ignoring them if they are unchanged); actually, we could just check if the new height is different
2212 mapM_ _someMergeUpdate_invalidateHeight mergeUpdates --TODO: In addition to when the patch is completely empty, we should also not run this if it has some Nothing values, but none of them have actually had any effect; potentially, we could even check for Just values with no effect (e.g. by comparing their IORefs and ignoring them if they are unchanged); actually, we could just check if the new height is different
2152 forM_ coincidenceInfos $ \(SomeResetCoincidence subscription mcs) -> do
2213 forM_ coincidenceInfos $ \(SomeResetCoincidence subscription mcs) -> do
2153 unsubscribe subscription
2214 unsubscribe subscription
@@ -2188,7 +2249,7 @@ invalidateCoincidenceHeight subscribed = do
2188 oldHeight <- readIORef $ coincidenceSubscribedHeight subscribed
2249 oldHeight <- readIORef $ coincidenceSubscribedHeight subscribed
2189 when (oldHeight /= invalidHeight) $ do
2250 when (oldHeight /= invalidHeight) $ do
2190 writeIORef (coincidenceSubscribedHeight subscribed) $! invalidHeight
2251 writeIORef (coincidenceSubscribedHeight subscribed) $! invalidHeight
2191− WeakBag.traverse (coincidenceSubscribedSubscribers subscribed) $ invalidateSubscriberHeight oldHeight
2252+ WeakBag.traverse_ (coincidenceSubscribedSubscribers subscribed) $ invalidateSubscriberHeight oldHeight
2193updateSwitchHeight :: Height -> SwitchSubscribed x a -> IO ()
2254updateSwitchHeight :: Height -> SwitchSubscribed x a -> IO ()
2194updateSwitchHeight new subscribed = do
2255updateSwitchHeight new subscribed = do
@@ -2196,7 +2257,7 @@ updateSwitchHeight new subscribed = do
2196 when (oldHeight == invalidHeight) $ do --TODO: This 'when' should probably be an assertion
2257 when (oldHeight == invalidHeight) $ do --TODO: This 'when' should probably be an assertion
2197 when (new /= invalidHeight) $ do --TODO: This 'when' should probably be an assertion
2258 when (new /= invalidHeight) $ do --TODO: This 'when' should probably be an assertion
2198 writeIORef (switchSubscribedHeight subscribed) $! new
2259 writeIORef (switchSubscribedHeight subscribed) $! new
2199− WeakBag.traverse (switchSubscribedSubscribers subscribed) $ recalculateSubscriberHeight new
2260+ WeakBag.traverse_ (switchSubscribedSubscribers subscribed) $ recalculateSubscriberHeight new
2201recalculateCoincidenceHeight :: CoincidenceSubscribed x a -> IO ()
2262recalculateCoincidenceHeight :: CoincidenceSubscribed x a -> IO ()
2202recalculateCoincidenceHeight subscribed = do
2263recalculateCoincidenceHeight subscribed = do
@@ -2205,7 +2266,7 @@ recalculateCoincidenceHeight subscribed = do
2205 height <- calculateCoincidenceHeight subscribed
2266 height <- calculateCoincidenceHeight subscribed
2206 when (height /= invalidHeight) $ do
2267 when (height /= invalidHeight) $ do
2207 writeIORef (coincidenceSubscribedHeight subscribed) $! height
2268 writeIORef (coincidenceSubscribedHeight subscribed) $! height
2208− WeakBag.traverse (coincidenceSubscribedSubscribers subscribed) $ recalculateSubscriberHeight height
2269+ WeakBag.traverse_ (coincidenceSubscribedSubscribers subscribed) $ recalculateSubscriberHeight height
2210calculateSwitchHeight :: SwitchSubscribed x a -> IO Height
2271calculateSwitchHeight :: SwitchSubscribed x a -> IO Height
2211calculateSwitchHeight subscribed = getEventSubscribedHeight . _eventSubscription_subscribed =<< readIORef (switchSubscribedCurrentParent subscribed)
2272calculateSwitchHeight subscribed = getEventSubscribedHeight . _eventSubscription_subscribed =<< readIORef (switchSubscribedCurrentParent subscribed)
@@ -2300,7 +2361,7 @@ instance HasSpiderTimeline x => Monad (Reflex.Class.Dynamic (SpiderTimeline x))
2300 fail _ = error "Dynamic does not support 'fail'"
2361 fail _ = error "Dynamic does not support 'fail'"
2302{-# INLINABLE newJoinDyn #-}
2363{-# INLINABLE newJoinDyn #-}
2303−newJoinDyn :: HasSpiderTimeline x => Reflex.Spider.Internal.Dynamic x (Identity (Reflex.Spider.Internal.Dynamic x (Identity a))) -> Reflex.Spider.Internal.Dyn x (Identity a)
2364+newJoinDyn :: HasSpiderTimeline x => DynamicS x (Identity (DynamicS x (Identity a))) -> Reflex.Spider.Internal.Dyn x (Identity a)
2304newJoinDyn d =
2365newJoinDyn d =
2305 let readV0 = readBehaviorTracked . dynamicCurrent =<< readBehaviorTracked (dynamicCurrent d)
2366 let readV0 = readBehaviorTracked . dynamicCurrent =<< readBehaviorTracked (dynamicCurrent d)
2306 eOuter = Reflex.Spider.Internal.push (fmap (Just . Identity) . readBehaviorUntracked . dynamicCurrent . runIdentity) $ dynamicUpdated d
2367 eOuter = Reflex.Spider.Internal.push (fmap (Just . Identity) . readBehaviorUntracked . dynamicCurrent . runIdentity) $ dynamicUpdated d
@@ -2450,7 +2511,7 @@ unsafeNewSpiderTimelineEnv = do
2450#ifdef DEBUG
2511#ifdef DEBUG
2451 depthRef <- newIORef 0
2512 depthRef <- newIORef 0
2453− return $ SpiderTimelineEnv
2514+ return $ STE $ SpiderTimelineEnv
2454 { _spiderTimeline_lock = lock
2515 { _spiderTimeline_lock = lock
2455 , _spiderTimeline_eventEnv = env
2516 , _spiderTimeline_eventEnv = env
2456#ifdef DEBUG
2517#ifdef DEBUG
@@ -2460,19 +2521,19 @@ unsafeNewSpiderTimelineEnv = do
2461-- | Create a new SpiderTimelineEnv
2522-- | Create a new SpiderTimelineEnv
2462newSpiderTimeline :: IO (Some SpiderTimelineEnv)
2523newSpiderTimeline :: IO (Some SpiderTimelineEnv)
2463−newSpiderTimeline = withSpiderTimeline (pure . Some.This)
2524+newSpiderTimeline = withSpiderTimeline (pure . Some)
2465−data LocalSpiderTimeline x s
2526+data LocalSpiderTimeline (x :: Type) s
2467instance Reifies s (SpiderTimelineEnv x) =>
2528instance Reifies s (SpiderTimelineEnv x) =>
2468 HasSpiderTimeline (LocalSpiderTimeline x s) where
2529 HasSpiderTimeline (LocalSpiderTimeline x s) where
2469− spiderTimeline = localSpiderTimeline (Proxy :: Proxy s) $ reflect (Proxy :: Proxy s)
2530+ spiderTimeline = localSpiderTimeline Proxy $ reflect (Proxy :: Proxy s)
2471localSpiderTimeline
2532localSpiderTimeline
2472− :: Proxy s
2533+ :: proxy s
2473 -> SpiderTimelineEnv x
2534 -> SpiderTimelineEnv x
2474 -> SpiderTimelineEnv (LocalSpiderTimeline x s)
2535 -> SpiderTimelineEnv (LocalSpiderTimeline x s)
2475−localSpiderTimeline _ = unsafeCoerce
2536+localSpiderTimeline _ = coerce
2477-- | Pass a new timeline to the given function.
2538-- | Pass a new timeline to the given function.
2478withSpiderTimeline :: (forall x. HasSpiderTimeline x => SpiderTimelineEnv x -> IO r) -> IO r
2539withSpiderTimeline :: (forall x. HasSpiderTimeline x => SpiderTimelineEnv x -> IO r) -> IO r
@@ -2480,18 +2541,18 @@ withSpiderTimeline k = do
2480 env <- unsafeNewSpiderTimelineEnv
2541 env <- unsafeNewSpiderTimelineEnv
2481 reify env $ \s -> k $ localSpiderTimeline s env
2542 reify env $ \s -> k $ localSpiderTimeline s env
2483−newtype SpiderPullM x a = SpiderPullM (BehaviorM x a) deriving (Functor, Applicative, Monad, MonadIO, MonadFix)
2544+newtype SpiderPullM (x :: Type) a = SpiderPullM (BehaviorM x a) deriving (Functor, Applicative, Monad, MonadIO, MonadFix)
2485type ComputeM = EventM
2546type ComputeM = EventM
2487−newtype SpiderPushM x a = SpiderPushM (ComputeM x a) deriving (Functor, Applicative, Monad, MonadIO, MonadFix)
2548+newtype SpiderPushM (x :: Type) a = SpiderPushM (ComputeM x a) deriving (Functor, Applicative, Monad, MonadIO, MonadFix)
2489instance HasSpiderTimeline x => R.Reflex (SpiderTimeline x) where
2550instance HasSpiderTimeline x => R.Reflex (SpiderTimeline x) where
2490 {-# SPECIALIZE instance R.Reflex (SpiderTimeline Global) #-}
2551 {-# SPECIALIZE instance R.Reflex (SpiderTimeline Global) #-}
2491 newtype Behavior (SpiderTimeline x) a = SpiderBehavior { unSpiderBehavior :: Behavior x a }
2552 newtype Behavior (SpiderTimeline x) a = SpiderBehavior { unSpiderBehavior :: Behavior x a }
2492 newtype Event (SpiderTimeline x) a = SpiderEvent { unSpiderEvent :: Event x a }
2553 newtype Event (SpiderTimeline x) a = SpiderEvent { unSpiderEvent :: Event x a }
2493− newtype Dynamic (SpiderTimeline x) a = SpiderDynamic { unSpiderDynamic :: Dynamic x (Identity a) } -- deriving (Functor, Applicative, Monad)
2554+ newtype Dynamic (SpiderTimeline x) a = SpiderDynamic { unSpiderDynamic :: DynamicS x (Identity a) } -- deriving (Functor, Applicative, Monad)
2494− newtype Incremental (SpiderTimeline x) p = SpiderIncremental { unSpiderIncremental :: Dynamic x p }
2555+ newtype Incremental (SpiderTimeline x) p = SpiderIncremental { unSpiderIncremental :: DynamicS x p }
2495 type PullM (SpiderTimeline x) = SpiderPullM x
2556 type PullM (SpiderTimeline x) = SpiderPullM x
2496 type PushM (SpiderTimeline x) = SpiderPushM x
2557 type PushM (SpiderTimeline x) = SpiderPushM x
2497 {-# INLINABLE never #-}
2558 {-# INLINABLE never #-}
@@ -2504,10 +2565,15 @@ instance HasSpiderTimeline x => R.Reflex (SpiderTimeline x) where
2504 pushCheap f = SpiderEvent . pushCheap (coerce f) . unSpiderEvent
2565 pushCheap f = SpiderEvent . pushCheap (coerce f) . unSpiderEvent
2505 {-# INLINABLE pull #-}
2566 {-# INLINABLE pull #-}
2506 pull = SpiderBehavior . pull . coerce
2567 pull = SpiderBehavior . pull . coerce
2507− {-# INLINABLE merge #-}
2568+ {-# INLINABLE fanG #-}
2508− merge = SpiderEvent . merge . dynamicConst . (coerce :: DMap k (R.Event (SpiderTimeline x)) -> DMap k (Event x))
2509− {-# INLINABLE fan #-}
2510− fan e = R.EventSelector $ SpiderEvent . select (fan (unSpiderEvent e))
2569+ fanG e = R.EventSelectorG $ SpiderEvent . selectG (fanG (unSpiderEvent e))
2570+ {-# INLINABLE mergeG #-}
2572+ :: forall (k :: k2 -> *) q (v :: k2 -> *). GCompare k
2573+ => (forall a. q a -> R.Event (SpiderTimeline x) (v a))
2575+ -> R.Event (SpiderTimeline x) (DMap k v)
2576+ mergeG nt = SpiderEvent . mergeG (unSpiderEvent #. nt) . dynamicConst
2511 {-# INLINABLE switch #-}
2577 {-# INLINABLE switch #-}
2512 switch = SpiderEvent . switch . (coerce :: Behavior x (R.Event (SpiderTimeline x) a) -> Behavior x (Event x a)) . unSpiderBehavior
2578 switch = SpiderEvent . switch . (coerce :: Behavior x (R.Event (SpiderTimeline x) a) -> Behavior x (Event x a)) . unSpiderBehavior
2513 {-# INLINABLE coincidence #-}
2579 {-# INLINABLE coincidence #-}
@@ -2515,15 +2581,15 @@ instance HasSpiderTimeline x => R.Reflex (SpiderTimeline x) where
2515 {-# INLINABLE current #-}
2581 {-# INLINABLE current #-}
2516 current = SpiderBehavior . dynamicCurrent . unSpiderDynamic
2582 current = SpiderBehavior . dynamicCurrent . unSpiderDynamic
2517 {-# INLINABLE updated #-}
2583 {-# INLINABLE updated #-}
2518− updated = coerce $ SpiderEvent . dynamicUpdated . unSpiderDynamic
2584+ updated = SpiderEvent #. dynamicUpdated .# fmap coerce . unSpiderDynamic
2519 {-# INLINABLE unsafeBuildDynamic #-}
2585 {-# INLINABLE unsafeBuildDynamic #-}
2520 unsafeBuildDynamic readV0 v' = SpiderDynamic $ dynamicDynIdentity $ unsafeBuildDynamic (coerce readV0) $ coerce $ unSpiderEvent v'
2586 unsafeBuildDynamic readV0 v' = SpiderDynamic $ dynamicDynIdentity $ unsafeBuildDynamic (coerce readV0) $ coerce $ unSpiderEvent v'
2521 {-# INLINABLE unsafeBuildIncremental #-}
2587 {-# INLINABLE unsafeBuildIncremental #-}
2522 unsafeBuildIncremental readV0 dv = SpiderIncremental $ dynamicDyn $ unsafeBuildDynamic (coerce readV0) $ unSpiderEvent dv
2588 unsafeBuildIncremental readV0 dv = SpiderIncremental $ dynamicDyn $ unsafeBuildDynamic (coerce readV0) $ unSpiderEvent dv
2523− {-# INLINABLE mergeIncremental #-}
2589+ {-# INLINABLE mergeIncrementalG #-}
2524− mergeIncremental = SpiderEvent . merge . (unsafeCoerce :: Dynamic x (PatchDMap k (R.Event (SpiderTimeline x))) -> Dynamic x (PatchDMap k (Event x))) . unSpiderIncremental
2590+ mergeIncrementalG nt = SpiderEvent #. mergeG (coerce #. nt) .# unSpiderIncremental
2525− {-# INLINABLE mergeIncrementalWithMove #-}
2591+ {-# INLINABLE mergeIncrementalWithMoveG #-}
2526− mergeIncrementalWithMove = SpiderEvent . mergeWithMove . (unsafeCoerce :: Dynamic x (PatchDMapWithMove k (R.Event (SpiderTimeline x))) -> Dynamic x (PatchDMapWithMove k (Event x))) . unSpiderIncremental
2592+ mergeIncrementalWithMoveG nt = SpiderEvent #. mergeWithMove (coerce #. nt) .# unSpiderIncremental
2527 {-# INLINABLE currentIncremental #-}
2593 {-# INLINABLE currentIncremental #-}
2528 currentIncremental = SpiderBehavior . dynamicCurrent . unSpiderIncremental
2594 currentIncremental = SpiderBehavior . dynamicCurrent . unSpiderIncremental
2529 {-# INLINABLE updatedIncremental #-}
2595 {-# INLINABLE updatedIncremental #-}
@@ -2534,9 +2600,10 @@ instance HasSpiderTimeline x => R.Reflex (SpiderTimeline x) where
2534 return $ Identity <$> apply p c --TODO: Avoid the redundant 'apply'
2600 return $ Identity <$> apply p c --TODO: Avoid the redundant 'apply'
2535 eventCoercion Coercion = Coercion
2601 eventCoercion Coercion = Coercion
2536 behaviorCoercion Coercion = Coercion
2602 behaviorCoercion Coercion = Coercion
2537− dynamicCoercion = unsafeCoerce --TODO: How can we avoid this unsafeCoerce? This is safe only because we know how Identity works as a Patch instance
2603+ dynamicCoercion Coercion = Coercion
2604+ incrementalCoercion Coercion Coercion = Coercion
2538 {-# INLINABLE mergeIntIncremental #-}
2605 {-# INLINABLE mergeIntIncremental #-}
2539− mergeIntIncremental = SpiderEvent . mergeInt . (unsafeCoerce :: Dynamic x (PatchIntMap (R.Event (SpiderTimeline x) a)) -> Dynamic x (PatchIntMap (Event x a))) . unSpiderIncremental
2606+ mergeIntIncremental = SpiderEvent . mergeInt . coerce
2540 {-# INLINABLE fanInt #-}
2607 {-# INLINABLE fanInt #-}
2541 fanInt e = R.EventSelectorInt $ SpiderEvent . selectInt (fanInt (unSpiderEvent e))
2608 fanInt e = R.EventSelectorInt $ SpiderEvent . selectInt (fanInt (unSpiderEvent e))
@@ -2561,7 +2628,7 @@ instance MonadAtomicRef (EventM x) where
2561 atomicModifyRef r f = liftIO $ atomicModifyRef r f
2628 atomicModifyRef r f = liftIO $ atomicModifyRef r f
2563-- | The monad for actions that manipulate a Spider timeline identified by @x@
2630-- | The monad for actions that manipulate a Spider timeline identified by @x@
2564−newtype SpiderHost x a = SpiderHost { unSpiderHost :: IO a } deriving (Functor, Applicative, MonadFix, MonadIO, MonadException, MonadAsyncException)
2631+newtype SpiderHost (x :: Type) a = SpiderHost { unSpiderHost :: IO a } deriving (Functor, Applicative, MonadFix, MonadIO, MonadException, MonadAsyncException)
2566instance Monad (SpiderHost x) where
2633instance Monad (SpiderHost x) where
2567 {-# INLINABLE (>>=) #-}
2634 {-# INLINABLE (>>=) #-}
@@ -2583,7 +2650,7 @@ runSpiderHost (SpiderHost a) = a
2583runSpiderHostForTimeline :: SpiderHost x a -> SpiderTimelineEnv x -> IO a
2650runSpiderHostForTimeline :: SpiderHost x a -> SpiderTimelineEnv x -> IO a
2584runSpiderHostForTimeline (SpiderHost a) _ = a
2651runSpiderHostForTimeline (SpiderHost a) _ = a
2586−newtype SpiderHostFrame x a = SpiderHostFrame { runSpiderHostFrame :: EventM x a }
2653+newtype SpiderHostFrame (x :: Type) a = SpiderHostFrame { runSpiderHostFrame :: EventM x a }
2587 deriving (Functor, Applicative, MonadFix, MonadIO, MonadException, MonadAsyncException)
2654 deriving (Functor, Applicative, MonadFix, MonadIO, MonadException, MonadAsyncException)
2589instance Monad (SpiderHostFrame x) where
2656instance Monad (SpiderHostFrame x) where
@@ -2639,3 +2706,11 @@ instance MonadAtomicRef (SpiderHostFrame x) where
2639instance PrimMonad (SpiderHostFrame x) where
2706instance PrimMonad (SpiderHostFrame x) where
2640 type PrimState (SpiderHostFrame x) = PrimState IO
2707 type PrimState (SpiderHostFrame x) = PrimState IO
2641 primitive = SpiderHostFrame . EventM . primitive
2708 primitive = SpiderHostFrame . EventM . primitive
2710+instance NotReady (SpiderTimeline x) (SpiderHost x) where
2711+ notReadyUntil _ = return ()
2712+ notReady = return ()
2714+instance HasSpiderTimeline x => NotReady (SpiderTimeline x) (PerformEventT (SpiderTimeline x) (SpiderHost x)) where
2715+ notReadyUntil _ = return ()
2716+ notReady = return ()