@@ -9,7 +9,6 @@
99{-# LANGUAGE GADTs #-}
1010{-# LANGUAGE GeneralizedNewtypeDeriving #-}
1111{-# LANGUAGE LambdaCase #-}
12−{-# LANGUAGE MultiParamTypeClasses #-}
1312{-# LANGUAGE MultiWayIf #-}
1413{-# LANGUAGE RankNTypes #-}
1514{-# LANGUAGE RoleAnnotations #-}
@@ -17,9 +16,15 @@
1716{-# LANGUAGE TypeFamilies #-}
1817{-# LANGUAGE TypeOperators #-}
1918{-# LANGUAGE UndecidableInstances #-}
19+{-# LANGUAGE PolyKinds #-}
20+{-# LANGUAGE DeriveFunctor #-}
21+{-# LANGUAGE StandaloneDeriving #-}
22+{-# LANGUAGE InstanceSigs #-}
23+
2024#ifdef USE_REFLEX_OPTIMIZER
2125{-# OPTIONS_GHC -fplugin=Reflex.Optimizer #-}
2226#endif
27+{-# OPTIONS_GHC -Wunused-binds #-}
2328-- | This module is the implementation of the 'Spider' 'Reflex' engine. It uses
2429-- a graph traversal algorithm to propagate 'Event's and 'Behavior's.
2530module Reflex.Spider.Internal (module Reflex.Spider.Internal) where
@@ -33,7 +38,10 @@ import Control.Monad hiding (forM, forM_, mapM, mapM_)
3338import Control.Monad.Exception
3439import Control.Monad.Identity hiding (forM, forM_, mapM, mapM_)
3540import 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
3745import Control.Monad.Ref
3846import Data.Align
3947import Data.Coerce
@@ -49,6 +57,7 @@ import Data.GADT.Compare
4957import Data.IntMap.Strict (IntMap)
5058import qualified Data.IntMap.Strict as IntMap
5159import Data.IORef
60+import Data.Kind (Type)
5261import Data.Maybe hiding (mapMaybe)
5362import Data.Monoid ((<>))
5463import Data.Proxy
@@ -63,6 +72,12 @@ import System.IO.Unsafe
6372import System.Mem.Weak
6473import Unsafe.Coerce
6574
75+#if defined(MIN_VERSION_semialign)
76+#if MIN_VERSION_these(0,8,0)
77+import Data.These.Combinators (justThese)
78+#endif
79+#endif
80+
6681#ifdef DEBUG_CYCLES
6782import Control.Monad.State hiding (forM, forM_, mapM, mapM_, sequence)
6883import Data.List.NonEmpty (NonEmpty (..), nonEmpty)
@@ -76,6 +91,7 @@ import qualified Data.FastWeakBag as FastWeakBag
7691import Data.Reflection
7792import Data.Some (Some(Some))
7893import Data.Type.Coercion
94+import Data.Profunctor.Unsafe ((#.), (.#))
7995import Data.WeakBag (WeakBag, WeakBagTicket, _weakBag_children)
8096import qualified Data.WeakBag as WeakBag
8197import qualified Reflex.Class
@@ -192,12 +208,6 @@ nextNodeIdRef = unsafePerformIO $ newIORef 1
192208
193209newNodeId :: IO Int
194210newNodeId = atomicModifyIORef' nextNodeIdRef $ \n -> (succ n, n)
195−
196−{-# NOINLINE unsafeNodeId #-}
197−unsafeNodeId :: a -> Int
198−unsafeNodeId a = unsafePerformIO $ do
199− touch a
200− newNodeId
201211#endif
202212
203213--------------------------------------------------------------------------------
@@ -301,9 +311,10 @@ cacheEvent e =
301311#else
302312 Event $
303313#endif
304− let mSubscribedRef :: IORef (FastWeak (CacheSubscribed x a))
305− !mSubscribedRef = unsafeNewIORef e emptyFastWeak
306− in \sub -> {-# SCC "cacheEvent" #-} do
314+ unsafePerformIO $ do
315+ mSubscribedRef :: IORef (FastWeak (CacheSubscribed x a))
316+ <- newIORef emptyFastWeak
317+ pure $ \sub -> {-# SCC "cacheEvent" #-} do
307318#ifdef DEBUG_TRACE_EVENTS
308319 unless (BS8.null callSite) $ liftIO $ BS8.hPutStrLn stderr callSite
309320#endif
@@ -369,7 +380,7 @@ eventRoot !k !r = Event $ wrap eventSubscribedRoot $ liftIO . getRootSubscribed
369380eventNever :: Event x a
370381eventNever = Event $ \_ -> return (EventSubscription (return ()) eventSubscribedNever, Nothing)
371382
372−eventFan :: (GCompare k, HasSpiderTimeline x) => k a -> Fan x k -> Event x a
383+eventFan :: (GCompare k, HasSpiderTimeline x) => k a -> Fan x k v -> Event x (v a)
373384eventFan !k !f = Event $ wrap eventSubscribedFan $ getFanSubscribed k f
374385
375386eventSwitch :: HasSpiderTimeline x => Switch x a -> Event x a
@@ -421,14 +432,14 @@ newSubscriberHold h = return $ Subscriber
421432 , subscriberRecalculateHeight = \_ -> return ()
422433 }
423434
424−newSubscriberFan :: forall x k. (HasSpiderTimeline x, GCompare k) => FanSubscribed x k -> IO (Subscriber x (DMap k Identity))
435+newSubscriberFan :: forall x k v. (HasSpiderTimeline x, GCompare k) => FanSubscribed x k v -> IO (Subscriber x (DMap k v))
425436newSubscriberFan subscribed = return $ Subscriber
426437 { subscriberPropagate = \a -> {-# SCC "traverseFan" #-} do
427438 subs <- liftIO $ readIORef $ fanSubscribedSubscribers subscribed
428439 tracePropagate (Proxy :: Proxy x) $ "SubscriberFan" <> showNodeId subscribed <> ": " ++ show (DMap.size subs) ++ " keys subscribed, " ++ show (DMap.size a) ++ " keys firing"
429440 liftIO $ writeIORef (fanSubscribedOccurrence subscribed) $ Just a
430441 scheduleClear $ fanSubscribedOccurrence subscribed
431− let f _ (Pair (Identity v) subsubs) = do
442+ let f _ (Pair v subsubs) = do
432443 propagate v $ _fanSubscribedChildren_list subsubs
433444 return $ Constant ()
434445 _ <- DMap.traverseWithKey f $ DMap.intersectionWithKey (\_ -> Pair) a subs --TODO: Would be nice to have DMap.traverse_
@@ -544,6 +555,11 @@ propagateFast a subscribers = withIncreasedDepth $ do
544555toAny :: a -> Any
545556toAny = unsafeCoerce
546557
558+-- Why do we use Any here, instead of just giving eventSubscribedRetained an
559+-- existential type? Sadly, GHC does not currently know how to unbox types
560+-- with existentially quantified fields. So instead we just coerce values
561+-- to type Any on the way in. Since we never coerce them back, this is
562+-- perfectly safe.
547563data EventSubscribed x = EventSubscribed
548564 { eventSubscribedHeightRef :: {-# UNPACK #-} !(IORef Height)
549565 , eventSubscribedRetained :: {-# NOUNPACK #-} !Any
@@ -576,7 +592,7 @@ eventSubscribedNever = EventSubscribed
576592#endif
577593 }
578594
579−eventSubscribedFan :: FanSubscribed x k -> EventSubscribed x
595+eventSubscribedFan :: FanSubscribed x k v -> EventSubscribed x
580596eventSubscribedFan !subscribed = EventSubscribed
581597 { eventSubscribedHeightRef = eventSubscribedHeightRef $ _eventSubscription_subscribed $ fanSubscribedParent subscribed
582598 , eventSubscribedRetained = toAny subscribed
@@ -667,7 +683,7 @@ behaviorPull !p = Behavior $ do
667683 wi <- liftIO $ mkWeakPtrWithDebug i "InvalidatorPull"
668684 parentsRef <- liftIO $ newIORef []
669685 holdInits <- askBehaviorHoldInits
670− a <- liftIO $ runReaderT (unBehaviorM $ pullCompute p) (Just (wi, parentsRef), holdInits)
686+ a <- liftIO $ runReaderIO (unBehaviorM $ pullCompute p) (Just (wi, parentsRef), holdInits)
671687 invsRef <- liftIO . newIORef . maybeToList =<< askInvalidator
672688 parents <- liftIO $ readIORef parentsRef
673689 let subscribed = PullSubscribed
@@ -702,42 +718,46 @@ readBehaviorUntracked b = do
702718-- Dynamic
703719--------------------------------------------------------------------------------
704720
705−data Dynamic x p = Dynamic
706− { dynamicCurrent :: !(Behavior x (PatchTarget p))
721+type DynamicS x p = Dynamic x (PatchTarget p) p
722+
723+data Dynamic x target p = Dynamic
724+ { dynamicCurrent :: !(Behavior x target)
707725 , dynamicUpdated :: Event x p -- This must be lazy; see the comment on holdEvent --TODO: Would this let us eliminate `Dyn`?
708726 }
709727
710−dynamicHold :: Hold x p -> Dynamic x p
728+deriving instance (HasSpiderTimeline x) => Functor (Dynamic x target)
729+
730+
731+
732+
733+dynamicHold :: Hold x p -> DynamicS x p
711734dynamicHold !h = Dynamic
712735 { dynamicCurrent = behaviorHold h
713736 , dynamicUpdated = eventHold h
714737 }
715738
716−dynamicHoldIdentity :: Hold x (Identity a) -> Dynamic x (Identity a)
739+dynamicHoldIdentity :: Hold x (Identity a) -> DynamicS x (Identity a)
717740dynamicHoldIdentity = dynamicHold
718741
719−dynamicConst :: PatchTarget p -> Dynamic x p
742+dynamicConst :: PatchTarget p -> DynamicS x p
720743dynamicConst !a = Dynamic
721744 { dynamicCurrent = behaviorConst a
722745 , dynamicUpdated = eventNever
723746 }
724747
725−dynamicDyn :: (HasSpiderTimeline x, Patch p) => Dyn x p -> Dynamic x p
748+dynamicDyn :: (HasSpiderTimeline x, Patch p) => Dyn x p -> DynamicS x p
726749dynamicDyn !d = Dynamic
727750 { dynamicCurrent = behaviorDyn d
728751 , dynamicUpdated = eventDyn d
729752 }
730753
731−dynamicDynIdentity :: HasSpiderTimeline x => Dyn x (Identity a) -> Dynamic x (Identity a)
754+dynamicDynIdentity :: HasSpiderTimeline x => Dyn x (Identity a) -> DynamicS x (Identity a)
732755dynamicDynIdentity = dynamicDyn
733756
734757--------------------------------------------------------------------------------
735758-- Combinators
736759--------------------------------------------------------------------------------
737760
738−--TODO: Figure out why certain things are not 'representational', then make them
739−--representational so we can use coerce
740−
741761--type role Hold representational
742762data Hold x p
743763 = Hold { holdValue :: !(IORef (PatchTarget p))
@@ -758,20 +778,25 @@ globalSpiderTimelineEnv = unsafePerformIO unsafeNewSpiderTimelineEnv
758778
759779-- | Stores all global data relevant to a particular Spider timeline; only one
760780-- value should exist for each type @x@
761−data SpiderTimelineEnv x = SpiderTimelineEnv
781+newtype SpiderTimelineEnv x = STE {unSTE :: SpiderTimelineEnv' x}
782+-- We implement SpiderTimelineEnv with a newtype wrapper so
783+-- we can get the coercions we want safely.
784+type role SpiderTimelineEnv nominal
785+
786+data SpiderTimelineEnv' x = SpiderTimelineEnv
762787 { _spiderTimeline_lock :: {-# UNPACK #-} !(MVar ())
763788 , _spiderTimeline_eventEnv :: {-# UNPACK #-} !(EventEnv x)
764789#ifdef DEBUG
765790 , _spiderTimeline_depth :: {-# UNPACK #-} !(IORef Int)
766791#endif
767792 }
768−type role SpiderTimelineEnv nominal
793+type role SpiderTimelineEnv' phantom
769794
770795instance Eq (SpiderTimelineEnv x) where
771796 _ == _ = True -- Since only one exists of each type
772797
773798instance GEq SpiderTimelineEnv where
774− a `geq` b = if _spiderTimeline_lock a == _spiderTimeline_lock b
799+ a `geq` b = if _spiderTimeline_lock (unSTE a) == _spiderTimeline_lock (unSTE b)
775800 then Just $ unsafeCoerce Refl -- This unsafeCoerce is safe because the same SpiderTimelineEnv can't have two different 'x' arguments
776801 else Nothing
777802
@@ -794,7 +819,7 @@ runEventM :: EventM x a -> IO a
794819runEventM = unEventM
795820
796821asksEventEnv :: forall x a. HasSpiderTimeline x => (EventEnv x -> a) -> EventM x a
797−asksEventEnv f = return $ f $ _spiderTimeline_eventEnv (spiderTimeline :: SpiderTimelineEnv x)
822+asksEventEnv f = return $ f $ _spiderTimeline_eventEnv (unSTE (spiderTimeline :: SpiderTimelineEnv x))
798823
799824class MonadIO m => Defer a m where
800825 getDeferralQueue :: m (IORef [a])
@@ -932,9 +957,9 @@ getHoldEventSubscription h = do
932957
933958type BehaviorEnv x = (Maybe (Weak (Invalidator x), IORef [SomeBehaviorSubscribed x]), IORef [SomeHoldInit x])
934959
935−--type role BehaviorM representational
936960-- BehaviorM can sample behaviors
937−newtype BehaviorM x a = BehaviorM { unBehaviorM :: ReaderT (BehaviorEnv x) IO a } deriving (Functor, Applicative, MonadIO, MonadFix)
961+newtype BehaviorM x a = BehaviorM { unBehaviorM :: ReaderIO (BehaviorEnv x) a }
962+ deriving (Functor, Applicative, MonadIO, MonadFix, MonadReader (BehaviorEnv x))
938963
939964instance Monad (BehaviorM x) where
940965 {-# INLINE (>>=) #-}
@@ -985,7 +1010,7 @@ data RootSubscribed x a = forall k. GCompare k => RootSubscribed
9851010#endif
9861011 }
9871012
988−data Root x (k :: * -> *)
1013+data Root x k
9891014 = Root { rootOccurrence :: !(IORef (DMap k Identity)) -- The currently-firing occurrence of this event
9901015 , rootSubscribed :: !(IORef (DMap k (RootSubscribed x)))
9911016 , rootInit :: !(forall a. k a -> RootTrigger x a -> IO (IO ()))
@@ -1055,25 +1080,25 @@ heightBagVerify b@(HeightBag s c) = if
10551080heightBagVerify = id
10561081#endif
10571082
1058−data FanSubscribedChildren (x :: *) k a = FanSubscribedChildren
1059− { _fanSubscribedChildren_list :: !(WeakBag (Subscriber x a))
1060− , _fanSubscribedChildren_self :: {-# NOUNPACK #-} !(k a, FanSubscribed x k)
1061− , _fanSubscribedChildren_weakSelf :: !(IORef (Weak (k a, FanSubscribed x k)))
1083+data FanSubscribedChildren x k v a = FanSubscribedChildren
1084+ { _fanSubscribedChildren_list :: !(WeakBag (Subscriber x (v a)))
1085+ , _fanSubscribedChildren_self :: {-# NOUNPACK #-} !(k a, FanSubscribed x k v)
1086+ , _fanSubscribedChildren_weakSelf :: !(IORef (Weak (k a, FanSubscribed x k v)))
10621087 }
10631088
1064−data FanSubscribed (x :: *) k
1065− = FanSubscribed { fanSubscribedCachedSubscribed :: !(IORef (Maybe (FanSubscribed x k)))
1066− , fanSubscribedOccurrence :: !(IORef (Maybe (DMap k Identity)))
1067− , fanSubscribedSubscribers :: !(IORef (DMap k (FanSubscribedChildren x k))) -- This DMap should never be empty
1089+data FanSubscribed x k v
1090+ = FanSubscribed { fanSubscribedCachedSubscribed :: !(IORef (Maybe (FanSubscribed x k v)))
1091+ , fanSubscribedOccurrence :: !(IORef (Maybe (DMap k v)))
1092+ , fanSubscribedSubscribers :: !(IORef (DMap k (FanSubscribedChildren x k v))) -- This DMap should never be empty
10681093 , fanSubscribedParent :: !(EventSubscription x)
10691094#ifdef DEBUG_NODEIDS
10701095 , fanSubscribedNodeId :: Int
10711096#endif
10721097 }
10731098
1074−data Fan x k
1075− = Fan { fanParent :: !(Event x (DMap k Identity))
1076− , fanSubscribed :: !(IORef (Maybe (FanSubscribed x k)))
1099+data Fan x k v
1100+ = Fan { fanParent :: !(Event x (DMap k v))
1101+ , fanSubscribed :: !(IORef (Maybe (FanSubscribed x k v)))
10771102 }
10781103
10791104data SwitchSubscribed x a
@@ -1135,19 +1160,24 @@ instance HasSpiderTimeline x => Align (Event x) where
11351160#if MIN_VERSION_these(0, 8, 0)
11361161instance HasSpiderTimeline x => Semialign (Event x) where
11371162#endif
1138− align ea eb = mapMaybe dmapToThese $ merge $ dynamicConst $ DMap.fromDistinctAscList [LeftTag :=> ea, RightTag :=> eb]
1163+ align ea eb = mapMaybe dmapToThese $ mergeG coerce $ dynamicConst $
1164+ DMap.fromDistinctAscList [LeftTag :=> ea, RightTag :=> eb]
1165+
1166+#if defined(MIN_VERSION_semialign)
1167+ zip x y = mapMaybe justThese $ align x y
1168+#endif
11391169
11401170data DynType x p = UnsafeDyn !(BehaviorM x (PatchTarget p), Event x p)
11411171 | BuildDyn !(EventM x (PatchTarget p), Event x p)
11421172 | HoldDyn !(Hold x p)
11431173
1144−newtype Dyn x p = Dyn { unDyn :: IORef (DynType x p) }
1174+newtype Dyn (x :: Type) p = Dyn { unDyn :: IORef (DynType x p) }
11451175
1146−newMapDyn :: HasSpiderTimeline x => (a -> b) -> Dynamic x (Identity a) -> Dynamic x (Identity b)
1176+newMapDyn :: HasSpiderTimeline x => (a -> b) -> DynamicS x (Identity a) -> DynamicS x (Identity b)
11471177newMapDyn f d = dynamicDynIdentity $ unsafeBuildDynamic (fmap f $ readBehaviorTracked $ dynamicCurrent d) (Identity . f . runIdentity <$> dynamicUpdated d)
11481178
11491179--TODO: Avoid the duplication between this and R.zipDynWith
1150−zipDynWith :: HasSpiderTimeline x => (a -> b -> c) -> Dynamic x (Identity a) -> Dynamic x (Identity b) -> Dynamic x (Identity c)
1180+zipDynWith :: HasSpiderTimeline x => (a -> b -> c) -> DynamicS x (Identity a) -> DynamicS x (Identity b) -> DynamicS x (Identity c)
11511181zipDynWith f da db =
11521182 let eab = align (dynamicUpdated da) (dynamicUpdated db)
11531183 ec = flip push eab $ \o -> do
@@ -1170,18 +1200,12 @@ buildDynamic readV0 v' = do
11701200 return d
11711201
11721202unsafeBuildDynamic :: BehaviorM x (PatchTarget p) -> Event x p -> Dyn x p
1173−unsafeBuildDynamic readV0 v' = Dyn $ unsafeNewIORef x $ UnsafeDyn x
1174− where x = (readV0, v')
1203+unsafeBuildDynamic readV0 v' =
1204+ Dyn $ unsafePerformIO $ newIORef $ UnsafeDyn (readV0, v')
11751205
11761206-- ResultM can read behaviors and events
11771207type ResultM = EventM
11781208
1179−{-# NOINLINE unsafeNewIORef #-}
1180−unsafeNewIORef :: a -> b -> IORef b
1181−unsafeNewIORef a b = unsafePerformIO $ do
1182− touch a
1183− newIORef b
1184−
11851209instance HasSpiderTimeline x => Functor (Event x) where
11861210 fmap f = push $ return . Just . f
11871211
@@ -1194,33 +1218,42 @@ push f e = cacheEvent (pushCheap f e)
11941218
11951219{-# INLINABLE pull #-}
11961220pull :: BehaviorM x a -> Behavior x a
1197−pull a = behaviorPull $ Pull
1198− { pullCompute = a
1199− , pullValue = unsafeNewIORef a Nothing
1221+pull a = unsafePerformIO $ do
1222+ ref <- newIORef Nothing
12001223#ifdef DEBUG_NODEIDS
1201− , pullNodeId = unsafeNodeId a
1224+ nid <- newNodeId
12021225#endif
1203− }
1226+ pure $ behaviorPull $ Pull
1227+ { pullCompute = a
1228+ , pullValue = ref
1229+#ifdef DEBUG_NODEIDS
1230+ , pullNodeId = nid
1231+#endif
1232+ }
12041233
12051234{-# INLINABLE switch #-}
12061235switch :: HasSpiderTimeline x => Behavior x (Event x a) -> Event x a
1207−switch a = eventSwitch $ Switch
1208− { switchParent = a
1209− , switchSubscribed = unsafeNewIORef a Nothing
1210− }
1236+switch a = unsafePerformIO $ do
1237+ ref <- newIORef Nothing
1238+ pure $ eventSwitch $ Switch
1239+ { switchParent = a
1240+ , switchSubscribed = ref
1241+ }
12111242
12121243coincidence :: HasSpiderTimeline x => Event x (Event x a) -> Event x a
1213−coincidence a = eventCoincidence $ Coincidence
1214− { coincidenceParent = a
1215− , coincidenceSubscribed = unsafeNewIORef a Nothing
1216− }
1244+coincidence a = unsafePerformIO $ do
1245+ ref <- newIORef Nothing
1246+ pure $ eventCoincidence $ Coincidence
1247+ { coincidenceParent = a
1248+ , coincidenceSubscribed = ref
1249+ }
12171250
12181251-- Propagate the given event occurrence; before cleaning up, run the given action, which may read the state of events and behaviors
12191252run :: forall x b. HasSpiderTimeline x => [DSum (RootTrigger x) Identity] -> ResultM x b -> SpiderHost x b
12201253run roots after = do
12211254 tracePropagate (Proxy :: Proxy x) $ "Running an event frame with " <> show (length roots) <> " events"
12221255 let t = spiderTimeline :: SpiderTimelineEnv x
1223− result <- SpiderHost $ withMVar (_spiderTimeline_lock t) $ \_ -> unSpiderHost $ runFrame $ do
1256+ result <- SpiderHost $ withMVar (_spiderTimeline_lock (unSTE t)) $ \_ -> unSpiderHost $ runFrame $ do
12241257 rootsToPropagate <- forM roots $ \r@(RootTrigger (_, occRef, k) :=> a) -> do
12251258 occBefore <- liftIO $ do
12261259 occBefore <- readIORef occRef
@@ -1284,9 +1317,9 @@ type WeakList a = [Weak a]
12841317withIncreasedDepth :: CanTrace x m => m a -> m a
12851318withIncreasedDepth a = do
12861319 spiderTimeline <- askSpiderTimelineEnv
1287− liftIO $ modifyIORef' (_spiderTimeline_depth spiderTimeline) succ
1320+ liftIO $ modifyIORef' (_spiderTimeline_depth (unSTE spiderTimeline)) succ
12881321 result <- a
1289− liftIO $ modifyIORef' (_spiderTimeline_depth spiderTimeline) pred
1322+ liftIO $ modifyIORef' (_spiderTimeline_depth (unSTE spiderTimeline)) pred
12901323 return result
12911324#else
12921325withIncreasedDepth :: m a -> m a
@@ -1313,7 +1346,7 @@ traceMWhen _ b getMessage = when b $ do
13131346 message <- getMessage
13141347#ifdef DEBUG
13151348 spiderTimeline <- askSpiderTimelineEnv
1316− d <- liftIO $ readIORef $ _spiderTimeline_depth spiderTimeline
1349+ d <- liftIO $ readIORef $ _spiderTimeline_depth $ unSTE spiderTimeline
13171350#else
13181351 let d = 0
13191352#endif
@@ -1354,25 +1387,25 @@ propagateSubscriberHold h a = do
13541387data SomeResetCoincidence x = forall a. SomeResetCoincidence !(EventSubscription x) !(Maybe (CoincidenceSubscribed x a)) -- The CoincidenceSubscriber will be present only if heights need to be reset
13551388
13561389runBehaviorM :: BehaviorM x a -> Maybe (Weak (Invalidator x), IORef [SomeBehaviorSubscribed x]) -> IORef [SomeHoldInit x] -> IO a
1357−runBehaviorM a mwi holdInits = runReaderT (unBehaviorM a) (mwi, holdInits)
1390+runBehaviorM a mwi holdInits = runReaderIO (unBehaviorM a) (mwi, holdInits)
13581391
13591392askInvalidator :: BehaviorM x (Maybe (Weak (Invalidator x)))
13601393askInvalidator = do
1361− (!m, _) <- BehaviorM ask
1394+ (!m, _) <- ask
13621395 case m of
13631396 Nothing -> return Nothing
13641397 Just (!wi, _) -> return $ Just wi
13651398
13661399askParentsRef :: BehaviorM x (Maybe (IORef [SomeBehaviorSubscribed x]))
13671400askParentsRef = do
1368− (!m, _) <- BehaviorM ask
1401+ (!m, _) <- ask
13691402 case m of
13701403 Nothing -> return Nothing
13711404 Just (_, !p) -> return $ Just p
13721405
13731406askBehaviorHoldInits :: BehaviorM x (IORef [SomeHoldInit x])
13741407askBehaviorHoldInits = do
1375− (_, !his) <- BehaviorM ask
1408+ (_, !his) <- ask
13761409 return his
13771410
13781411{-# INLINE getDynHold #-}
@@ -1417,6 +1450,9 @@ getRootSubscribed k r sub = do
14171450 when debugPropagate $ putStrLn $ "getRootSubscribed: calling rootInit"
14181451 uninit <- rootInit r k $ RootTrigger (subs, rootOccurrence r, k)
14191452 writeIORef uninitRef $! uninit
1453+#ifdef DEBUG_NODEIDS
1454+ nid <- newNodeId
1455+#endif
14201456 let !subscribed = RootSubscribed
14211457 { rootSubscribedKey = k
14221458 , rootSubscribedCachedSubscribed = cached
@@ -1425,7 +1461,7 @@ getRootSubscribed k r sub = do
14251461 , rootSubscribedUninit = uninit
14261462 , rootSubscribedWeakSelf = weakSelf
14271463#ifdef DEBUG_NODEIDS
1428− , rootSubscribedNodeId = unsafeNodeId (k, r, subs)
1464+ , rootSubscribedNodeId = nid
14291465#endif
14301466 }
14311467 -- If we die at the same moment that all our children die, they will
@@ -1474,16 +1510,10 @@ newFanInt = do
14741510 , _fanInt_occRef = occRef
14751511 }
14761512
1477−{-# NOINLINE unsafeNewFanInt #-}
1478−unsafeNewFanInt :: b -> FanInt x a
1479−unsafeNewFanInt b = unsafePerformIO $ do
1480− touch b
1481− newFanInt
1482−
14831513fanInt :: HasSpiderTimeline x => Event x (IntMap a) -> EventSelectorInt x a
1484−fanInt p =
1485− let self = unsafeNewFanInt p
1486− in EventSelectorInt $ \k -> Event $ \sub -> do
1514+fanInt p = unsafePerformIO $ do
1515+ self <- newFanInt
1516+ pure $ EventSelectorInt $ \k -> Event $ \sub -> do
14871517 isEmpty <- liftIO $ FastMutableIntMap.isEmpty (_fanInt_subscribers self)
14881518 when isEmpty $ do -- This is the first subscriber, so we need to subscribe to our input
14891519 (subscription, parentOcc) <- subscribeAndRead p $ Subscriber
@@ -1519,7 +1549,7 @@ fanInt p =
15191549 return (EventSubscription (FastWeakBag.remove t) $! EventSubscribed heightRef $! toAny (_fanInt_subscriptionRef self, t), IntMap.lookup k currentOcc)
15201550
15211551{-# INLINABLE getFanSubscribed #-}
1522−getFanSubscribed :: (HasSpiderTimeline x, GCompare k) => k a -> Fan x k -> Subscriber x a -> EventM x (WeakBagTicket, FanSubscribed x k, Maybe a)
1552+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))
15231553getFanSubscribed k f sub = do
15241554 mSubscribed <- liftIO $ readIORef $ fanSubscribed f
15251555 case mSubscribed of
@@ -1537,13 +1567,16 @@ getFanSubscribed k f sub = do
15371567 subscribersRef <- liftIO $ newIORef $ error "getFanSubscribed: subscribersRef not yet initialized"
15381568 occRef <- liftIO $ newIORef parentOcc
15391569 when (isJust parentOcc) $ scheduleClear occRef
1570+#ifdef DEBUG_NODEIDS
1571+ nid <- liftIO newNodeId
1572+#endif
15401573 let subscribed = FanSubscribed
15411574 { fanSubscribedCachedSubscribed = fanSubscribed f
15421575 , fanSubscribedOccurrence = occRef
15431576 , fanSubscribedParent = subscription
15441577 , fanSubscribedSubscribers = subscribersRef
15451578#ifdef DEBUG_NODEIDS
1546− , fanSubscribedNodeId = unsafeNodeId f
1579+ , fanSubscribedNodeId = nid
15471580#endif
15481581 }
15491582 let !self = (k, subscribed)
@@ -1553,7 +1586,7 @@ getFanSubscribed k f sub = do
15531586 liftIO $ writeIORef (fanSubscribed f) $ Just subscribed
15541587 return (slnForSub, subscribed, coerce $ DMap.lookup k =<< parentOcc)
15551588
1556−cleanupFanSubscribed :: GCompare k => (k a, FanSubscribed x k) -> IO ()
1589+cleanupFanSubscribed :: GCompare k => (k a, FanSubscribed x k v) -> IO ()
15571590cleanupFanSubscribed (k, subscribed) = do
15581591 subscribers <- readIORef $ fanSubscribedSubscribers subscribed
15591592 let reducedSubscribers = DMap.delete k subscribers
@@ -1565,7 +1598,7 @@ cleanupFanSubscribed (k, subscribed) = do
15651598 else writeIORef (fanSubscribedSubscribers subscribed) $! reducedSubscribers
15661599
15671600{-# INLINE subscribeFanSubscribed #-}
1568−subscribeFanSubscribed :: GCompare k => k a -> FanSubscribed x k -> Subscriber x a -> IO WeakBagTicket
1601+subscribeFanSubscribed :: GCompare k => k a -> FanSubscribed x k v -> Subscriber x (v a) -> IO WeakBagTicket
15691602subscribeFanSubscribed k subscribed sub = do
15701603 subscribers <- readIORef $ fanSubscribedSubscribers subscribed
15711604 case DMap.lookup k subscribers of
@@ -1603,6 +1636,9 @@ getSwitchSubscribed s sub = do
16031636 when (isJust parentOcc) $ scheduleClear occRef
16041637 weakSelf <- liftIO $ newIORef $ error "getSwitchSubscribed: weakSelf not yet initialized"
16051638 (subs, slnForSub) <- liftIO $ WeakBag.singleton sub weakSelf cleanupSwitchSubscribed
1639+#ifdef DEBUG_NODEIDS
1640+ nid <- liftIO newNodeId
1641+#endif
16061642 let !subscribed = SwitchSubscribed
16071643 { switchSubscribedCachedSubscribed = switchSubscribed s
16081644 , switchSubscribedOccurrence = occRef
@@ -1615,7 +1651,7 @@ getSwitchSubscribed s sub = do
16151651 , switchSubscribedCurrentParent = subscriptionRef
16161652 , switchSubscribedWeakSelf = weakSelf
16171653#ifdef DEBUG_NODEIDS
1618− , switchSubscribedNodeId = unsafeNodeId s
1654+ , switchSubscribedNodeId = nid
16191655#endif
16201656 }
16211657 liftIO $ writeIORef weakSelf =<< evaluate =<< mkWeakPtrWithDebug subscribed "switchSubscribedWeakSelf"
@@ -1660,6 +1696,9 @@ getCoincidenceSubscribed c sub = do
16601696 scheduleClear innerSubdRef
16611697 weakSelf <- liftIO $ newIORef $ error "getCoincidenceSubscribed: weakSelf not yet implemented"
16621698 (subs, slnForSub) <- liftIO $ WeakBag.singleton sub weakSelf cleanupCoincidenceSubscribed
1699+#ifdef DEBUG_NODEIDS
1700+ nid <- liftIO newNodeId
1701+#endif
16631702 let subscribed = CoincidenceSubscribed
16641703 { coincidenceSubscribedCachedSubscribed = coincidenceSubscribed c
16651704 , coincidenceSubscribedOccurrence = occRef
@@ -1670,7 +1709,7 @@ getCoincidenceSubscribed c sub = do
16701709 , coincidenceSubscribedInnerParent = innerSubdRef
16711710 , coincidenceSubscribedWeakSelf = weakSelf
16721711#ifdef DEBUG_NODEIDS
1673− , coincidenceSubscribedNodeId = unsafeNodeId c
1712+ , coincidenceSubscribedNodeId = nid
16741713#endif
16751714 }
16761715 liftIO $ writeIORef weakSelf =<< evaluate =<< mkWeakPtrWithDebug subscribed "CoincidenceSubscribed"
@@ -1687,26 +1726,34 @@ cleanupCoincidenceSubscribed subscribed = do
16871726subscribeCoincidenceSubscribed :: CoincidenceSubscribed x a -> Subscriber x a -> IO WeakBagTicket
16881727subscribeCoincidenceSubscribed subscribed sub = WeakBag.insert sub (coincidenceSubscribedSubscribers subscribed) (coincidenceSubscribedWeakSelf subscribed) cleanupCoincidenceSubscribed
16891728
1690−{-# INLINE merge #-}
1691−merge :: forall k x. (HasSpiderTimeline x, GCompare k) => Dynamic x (PatchDMap k (Event x)) -> Event x (DMap k Identity)
1692−merge d = cacheEvent (mergeCheap d)
1729+{-# INLINE mergeG #-}
1730+mergeG :: forall k q x v. (HasSpiderTimeline x, GCompare k)
1731+ => (forall a. q a -> Event x (v a))
1732+ -> DynamicS x (PatchDMap k q) -> Event x (DMap k v)
1733+mergeG nt d = cacheEvent (mergeCheap nt d)
16931734
16941735{-# INLINE mergeWithMove #-}
1695−mergeWithMove :: forall k x. (HasSpiderTimeline x, GCompare k) => Dynamic x (PatchDMapWithMove k (Event x)) -> Event x (DMap k Identity)
1696−mergeWithMove d = cacheEvent (mergeCheapWithMove d)
1736+mergeWithMove :: forall k v q x. (HasSpiderTimeline x, GCompare k)
1737+ => (forall a. q a -> Event x (v a))
1738+ -> DynamicS x (PatchDMapWithMove k q) -> Event x (DMap k v)
1739+mergeWithMove nt d = cacheEvent (mergeCheapWithMove nt d)
16971740
16981741{-# INLINE [1] mergeCheap #-}
1699−mergeCheap :: forall k x. (HasSpiderTimeline x, GCompare k) => Dynamic x (PatchDMap k (Event x)) -> Event x (DMap k Identity)
1700−mergeCheap = mergeCheap' getInitialSubscribers updateMe destroy
1742+mergeCheap
1743+ :: forall k x q v. (HasSpiderTimeline x, GCompare k)
1744+ => (forall a. q a -> Event x (v a))
1745+ -> DynamicS x (PatchDMap k q)
1746+ -> Event x (DMap k v)
1747+mergeCheap nt = mergeGCheap' getInitialSubscribers updateMe destroy
17011748 where
1702− updateMe :: MergeUpdateFunc k x (PatchDMap k (Event x)) (MergeSubscribedParent x)
1749+ updateMe :: MergeUpdateFunc k v x (PatchDMap k q) (MergeSubscribedParent x)
17031750 updateMe subscriber heightBagRef oldParents (PatchDMap p) = do
17041751 let f (subscriptionsToKill, ps) (k :=> ComposeMaybe me) = do
17051752 (mOldSubd, newPs) <- case me of
17061753 Nothing -> return $ DMap.updateLookupWithKey (\_ _ -> Nothing) k ps
17071754 Just e -> do
17081755 let s = subscriber $ return k
1709− subscription@(EventSubscription _ subd) <- subscribe e s
1756+ subscription@(EventSubscription _ subd) <- subscribe (nt e) s
17101757 newParentHeight <- liftIO $ getEventSubscribedHeight subd
17111758 let newParent = MergeSubscribedParent subscription
17121759 liftIO $ modifyIORef' heightBagRef $ heightBagAdd newParentHeight
@@ -1716,28 +1763,33 @@ mergeCheap = mergeCheap' getInitialSubscribers updateMe destroy
17161763 liftIO $ modifyIORef heightBagRef $ heightBagRemove oldHeight
17171764 return (maybeToList (unMergeSubscribedParent <$> mOldSubd) ++ subscriptionsToKill, newPs)
17181765 foldM f ([], oldParents) $ DMap.toList p
1719− getInitialSubscribers :: MergeInitFunc k x (MergeSubscribedParent x)
1766+
1767+ getInitialSubscribers :: MergeInitFunc k v q x (MergeSubscribedParent x)
17201768 getInitialSubscribers initialParents subscriber = do
17211769 subscribers <- forM (DMap.toList initialParents) $ \(k :=> e) -> do
17221770 let s = subscriber $ return k
1723− (subscription@(EventSubscription _ parentSubd), parentOcc) <- subscribeAndRead e s
1771+ (subscription@(EventSubscription _ parentSubd), parentOcc) <- subscribeAndRead (nt e) s
17241772 height <- liftIO $ getEventSubscribedHeight parentSubd
1725− return (fmap (\x -> k :=> Identity x) parentOcc, height, k :=> MergeSubscribedParent subscription)
1773+ return (fmap (k :=>) parentOcc, height, k :=> MergeSubscribedParent subscription)
17261774 return ( DMap.fromDistinctAscList $ mapMaybe (\(x, _, _) -> x) subscribers
17271775 , fmap (\(_, h, _) -> h) subscribers --TODO: Assert that there's no invalidHeight in here
17281776 , DMap.fromDistinctAscList $ map (\(_, _, x) -> x) subscribers
17291777 )
1778+
17301779 destroy :: MergeDestroyFunc k (MergeSubscribedParent x)
17311780 destroy s = forM_ (DMap.toList s) $ \(_ :=> MergeSubscribedParent sub) -> unsubscribe sub
17321781
17331782{-# INLINE [1] mergeCheapWithMove #-}
1734−mergeCheapWithMove :: forall k x. (HasSpiderTimeline x, GCompare k) => Dynamic x (PatchDMapWithMove k (Event x)) -> Event x (DMap k Identity)
1735−mergeCheapWithMove = mergeCheap' getInitialSubscribers updateMe destroy
1783+mergeCheapWithMove :: forall k x v q. (HasSpiderTimeline x, GCompare k)
1784+ => (forall a. q a -> Event x (v a))
1785+ -> DynamicS x (PatchDMapWithMove k q)
1786+ -> Event x (DMap k v)
1787+mergeCheapWithMove nt = mergeGCheap' getInitialSubscribers updateMe destroy
17361788 where
1737− updateMe :: MergeUpdateFunc k x (PatchDMapWithMove k (Event x)) (MergeSubscribedParentWithMove x k)
1789+ updateMe :: MergeUpdateFunc k v x (PatchDMapWithMove k q) (MergeSubscribedParentWithMove x k)
17381790 updateMe subscriber heightBagRef oldParents p = do
17391791 -- Prepare new parents for insertion
1740− let subscribeParent :: forall a. k a -> Event x a -> EventM x (MergeSubscribedParentWithMove x k a)
1792+ let subscribeParent :: forall a. k a -> Event x (v a) -> EventM x (MergeSubscribedParentWithMove x k a)
17411793 subscribeParent k e = do
17421794 keyRef <- liftIO $ newIORef k
17431795 let s = subscriber $ liftIO $ readIORef keyRef
@@ -1746,9 +1798,9 @@ mergeCheapWithMove = mergeCheap' getInitialSubscribers updateMe destroy
17461798 newParentHeight <- getEventSubscribedHeight subd
17471799 modifyIORef' heightBagRef $ heightBagAdd newParentHeight
17481800 return $ MergeSubscribedParentWithMove subscription keyRef
1749− p' <- PatchDMapWithMove.traversePatchDMapWithMoveWithKey subscribeParent p
1801+ p' <- PatchDMapWithMove.traversePatchDMapWithMoveWithKey (\k q -> subscribeParent k (nt q)) p
17501802 -- Collect old parents for deletion and update the keys of moved parents
1751− let moveOrDelete :: forall a. k a -> PatchDMapWithMove.NodeInfo k (Event x) a -> MergeSubscribedParentWithMove x k a -> Constant (EventM x (Maybe (EventSubscription x))) a
1803+ let moveOrDelete :: forall a. k a -> PatchDMapWithMove.NodeInfo k q a -> MergeSubscribedParentWithMove x k a -> Constant (EventM x (Maybe (EventSubscription x))) a
17521804 moveOrDelete _ ni parent = Constant $ case getComposeMaybe $ PatchDMapWithMove._nodeInfo_to ni of
17531805 Nothing -> do
17541806 oldHeight <- liftIO $ getEventSubscribedHeight $ _eventSubscription_subscribed $ _mergeSubscribedParentWithMove_subscription parent
@@ -1759,46 +1811,47 @@ mergeCheapWithMove = mergeCheap' getInitialSubscribers updateMe destroy
17591811 return Nothing
17601812 toDelete <- fmap catMaybes $ mapM (\(_ :=> v) -> getConstant v) $ DMap.toList $ DMap.intersectionWithKey moveOrDelete (unPatchDMapWithMove p) oldParents
17611813 return (toDelete, applyAlways p' oldParents)
1762− getInitialSubscribers :: MergeInitFunc k x (MergeSubscribedParentWithMove x k)
1814+ getInitialSubscribers :: MergeInitFunc k v q x (MergeSubscribedParentWithMove x k)
17631815 getInitialSubscribers initialParents subscriber = do
17641816 subscribers <- forM (DMap.toList initialParents) $ \(k :=> e) -> do
17651817 keyRef <- liftIO $ newIORef k
17661818 let s = subscriber $ liftIO $ readIORef keyRef
1767− (subscription@(EventSubscription _ parentSubd), parentOcc) <- subscribeAndRead e s
1819+ (subscription@(EventSubscription _ parentSubd), parentOcc) <- subscribeAndRead (nt e) s
17681820 height <- liftIO $ getEventSubscribedHeight parentSubd
1769− return (fmap (\x -> k :=> Identity x) parentOcc, height, k :=> MergeSubscribedParentWithMove subscription keyRef)
1821+ return (fmap (k :=>) parentOcc, height, k :=> MergeSubscribedParentWithMove subscription keyRef)
17701822 return ( DMap.fromDistinctAscList $ mapMaybe (\(x, _, _) -> x) subscribers
17711823 , fmap (\(_, h, _) -> h) subscribers --TODO: Assert that there's no invalidHeight in here
17721824 , DMap.fromDistinctAscList $ map (\(_, _, x) -> x) subscribers
17731825 )
1826+
17741827 destroy :: MergeDestroyFunc k (MergeSubscribedParentWithMove x k)
17751828 destroy s = forM_ (DMap.toList s) $ \(_ :=> MergeSubscribedParentWithMove sub _) -> unsubscribe sub
17761829
1777−type MergeUpdateFunc k x p s
1778− = (forall a. EventM x (k a) -> Subscriber x a)
1830+type MergeUpdateFunc k v x p s
1831+ = (forall a. EventM x (k a) -> Subscriber x (v a))
17791832 -> IORef HeightBag
17801833 -> DMap k s
17811834 -> p
17821835 -> EventM x ([EventSubscription x], DMap k s)
17831836
1784−type MergeInitFunc k x s
1785− = DMap k (Event x)
1786− -> (forall a. EventM x (k a) -> Subscriber x a)
1787− -> EventM x (DMap k Identity, [Height], DMap k s)
1837+type MergeInitFunc k v q x s
1838+ = DMap k q
1839+ -> (forall a. EventM x (k a) -> Subscriber x (v a))
1840+ -> EventM x (DMap k v, [Height], DMap k s)
17881841
17891842type MergeDestroyFunc k s
17901843 = DMap k s
17911844 -> IO ()
17921845
1793−data Merge x k s = Merge
1846+data Merge x k v s = Merge
17941847 { _merge_parentsRef :: {-# UNPACK #-} !(IORef (DMap k s))
17951848 , _merge_heightBagRef :: {-# UNPACK #-} !(IORef HeightBag)
17961849 , _merge_heightRef :: {-# UNPACK #-} !(IORef Height)
1797− , _merge_sub :: {-# UNPACK #-} !(Subscriber x (DMap k Identity))
1798− , _merge_accumRef :: {-# UNPACK #-} !(IORef (DMap k Identity))
1850+ , _merge_sub :: {-# UNPACK #-} !(Subscriber x (DMap k v))
1851+ , _merge_accumRef :: {-# UNPACK #-} !(IORef (DMap k v))
17991852 }
18001853
1801−invalidateMergeHeight :: Merge x k s -> IO ()
1854+invalidateMergeHeight :: Merge x k v s -> IO ()
18021855invalidateMergeHeight m = invalidateMergeHeight' (_merge_heightRef m) (_merge_sub m)
18031856
18041857invalidateMergeHeight' :: IORef Height -> Subscriber x a -> IO ()
@@ -1808,8 +1861,7 @@ invalidateMergeHeight' heightRef sub = do
18081861 writeIORef heightRef $! invalidHeight
18091862 subscriberInvalidateHeight sub oldHeight
18101863
1811−
1812−revalidateMergeHeight :: Merge x k s -> IO ()
1864+revalidateMergeHeight :: Merge x k v s -> IO ()
18131865revalidateMergeHeight m = do
18141866 currentHeight <- readIORef $ _merge_heightRef m
18151867 when (currentHeight == invalidHeight) $ do -- revalidateMergeHeight may be called multiple times; perhaps the's a way to finesse it to avoid this check
@@ -1825,19 +1877,19 @@ revalidateMergeHeight m = do
18251877 subscriberRecalculateHeight (_merge_sub m) height
18261878 GT -> error $ "revalidateMergeHeight: more heights (" <> show (heightBagSize heights) <> ") than parents (" <> show (DMap.size parents) <> ") for Merge"
18271879
1828−scheduleMergeSelf :: HasSpiderTimeline x => Merge x k s -> Height -> EventM x ()
1880+scheduleMergeSelf :: HasSpiderTimeline x => Merge x k v s -> Height -> EventM x ()
18291881scheduleMergeSelf m height = scheduleMerge' height (_merge_heightRef m) $ do
18301882 vals <- liftIO $ readIORef $ _merge_accumRef m
18311883 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
18321884 --TODO: Assert that m is not empty
18331885 subscriberPropagate (_merge_sub m) vals
18341886
1835−mergeSubscriber :: forall x k s a. (HasSpiderTimeline x, GCompare k) => Merge x k s -> EventM x (k a) -> Subscriber x a
1887+mergeSubscriber :: forall x k v s a. (HasSpiderTimeline x, GCompare k) => Merge x k v s -> EventM x (k a) -> Subscriber x (v a)
18361888mergeSubscriber m getKey = Subscriber
18371889 { subscriberPropagate = \a -> do
18381890 oldM <- liftIO $ readIORef $ _merge_accumRef m
18391891 k <- getKey
1840− let newM = DMap.insertWith (error $ "Same key fired multiple times for Merge") k (Identity a) oldM
1892+ let newM = DMap.insertWith (error $ "Same key fired multiple times for Merge") k a oldM
18411893 tracePropagate (Proxy :: Proxy x) $ " DMap.size oldM = " <> show (DMap.size oldM) <> "; DMap.size newM = " <> show (DMap.size newM)
18421894 liftIO $ writeIORef (_merge_accumRef m) $! newM
18431895 when (DMap.null oldM) $ do -- Only schedule the firing once
@@ -1868,7 +1920,7 @@ mergeSubscriber m getKey = Subscriber
18681920 }
18691921
18701922--TODO: Be able to run as much of this as possible promptly
1871−updateMerge :: (HasSpiderTimeline x, GCompare k) => Merge x k s -> MergeUpdateFunc k x p s -> p -> SomeMergeUpdate x
1923+updateMerge :: (HasSpiderTimeline x, GCompare k) => Merge x k v s -> MergeUpdateFunc k v x p s -> p -> SomeMergeUpdate x
18721924updateMerge m updateFunc p = SomeMergeUpdate updateMe (invalidateMergeHeight m) (revalidateMergeHeight m)
18731925 where updateMe = do
18741926 oldParents <- liftIO $ readIORef $ _merge_parentsRef m
@@ -1876,9 +1928,10 @@ updateMerge m updateFunc p = SomeMergeUpdate updateMe (invalidateMergeHeight m)
18761928 liftIO $ writeIORef (_merge_parentsRef m) $! newParents
18771929 return subscriptionsToKill
18781930
1879−{-# INLINE mergeCheap' #-}
1880−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)
1881−mergeCheap' getInitialSubscribers updateFunc destroy d = Event $ \sub -> do
1931+{-# INLINE mergeGCheap' #-}
1932+mergeGCheap' :: forall k v x p s q. (HasSpiderTimeline x, GCompare k, PatchTarget p ~ DMap k q)
1933+ => MergeInitFunc k v q x s -> MergeUpdateFunc k v x p s -> MergeDestroyFunc k s -> DynamicS x p -> Event x (DMap k v)
1934+mergeGCheap' getInitialSubscribers updateFunc destroy d = Event $ \sub -> do
18821935 initialParents <- readBehaviorUntracked $ dynamicCurrent d
18831936 accumRef <- liftIO $ newIORef $ error "merge: accumRef not yet initialized"
18841937 heightRef <- liftIO $ newIORef $ error "merge: heightRef not yet initialized"
@@ -1926,11 +1979,11 @@ mergeCheap' getInitialSubscribers updateFunc destroy d = Event $ \sub -> do
19261979 , occ
19271980 )
19281981
1929−mergeInt :: forall x a. (HasSpiderTimeline x) => Dynamic x (PatchIntMap (Event x a)) -> Event x (IntMap a)
1982+mergeInt :: forall x a. (HasSpiderTimeline x) => DynamicS x (PatchIntMap (Event x a)) -> Event x (IntMap a)
19301983mergeInt = cacheEvent . mergeIntCheap
19311984
19321985{-# INLINABLE mergeIntCheap #-}
1933−mergeIntCheap :: forall x a. (HasSpiderTimeline x) => Dynamic x (PatchIntMap (Event x a)) -> Event x (IntMap a)
1986+mergeIntCheap :: forall x a. (HasSpiderTimeline x) => DynamicS x (PatchIntMap (Event x a)) -> Event x (IntMap a)
19341987mergeIntCheap d = Event $ \sub -> do
19351988 initialParents <- readBehaviorUntracked $ dynamicCurrent d
19361989 accum <- liftIO $ FastMutableIntMap.newEmpty
@@ -2027,14 +2080,16 @@ mergeIntCheap d = Event $ \sub -> do
20272080 )
20282081
20292082newtype EventSelector x k = EventSelector { select :: forall a. k a -> Event x a }
2083+newtype EventSelectorG x k v = EventSelectorG { selectG :: forall a. k a -> Event x (v a) }
20302084
2031−fan :: (HasSpiderTimeline x, GCompare k) => Event x (DMap k Identity) -> EventSelector x k
2032−fan e =
2085+fanG :: (HasSpiderTimeline x, GCompare k) => Event x (DMap k v) -> EventSelectorG x k v
2086+fanG e = unsafePerformIO $ do
2087+ ref <- newIORef Nothing
20332088 let f = Fan
20342089 { fanParent = e
2035− , fanSubscribed = unsafeNewIORef e Nothing
2090+ , fanSubscribed = ref
20362091 }
2037− in EventSelector $ \k -> eventFan k f
2092+ pure $ EventSelectorG $ \k -> eventFan k f
20382093
20392094runHoldInits :: HasSpiderTimeline x => IORef [SomeHoldInit x] -> IORef [SomeDynInit x] -> IORef [SomeMergeInit x] -> EventM x ()
20402095runHoldInits holdInitRef dynInitRef mergeInitRef = do
@@ -2088,7 +2143,7 @@ clearEventEnv (EventEnv toAssignRef holdInitRef dynInitRef mergeUpdateRef mergeI
20882143-- | Run an event action outside of a frame
20892144runFrame :: forall x a. HasSpiderTimeline x => EventM x a -> SpiderHost x a --TODO: This function also needs to hold the mutex
20902145runFrame a = SpiderHost $ do
2091− let env = _spiderTimeline_eventEnv (spiderTimeline :: SpiderTimelineEnv x)
2146+ let env = _spiderTimeline_eventEnv $ unSTE (spiderTimeline :: SpiderTimelineEnv x)
20922147 let go = do
20932148 result <- a
20942149 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
@@ -2299,7 +2354,7 @@ instance HasSpiderTimeline x => Monad (Reflex.Class.Dynamic (SpiderTimeline x))
22992354 fail _ = error "Dynamic does not support 'fail'"
23002355
23012356{-# INLINABLE newJoinDyn #-}
2302−newJoinDyn :: HasSpiderTimeline x => Reflex.Spider.Internal.Dynamic x (Identity (Reflex.Spider.Internal.Dynamic x (Identity a))) -> Reflex.Spider.Internal.Dyn x (Identity a)
2357+newJoinDyn :: HasSpiderTimeline x => DynamicS x (Identity (DynamicS x (Identity a))) -> Reflex.Spider.Internal.Dyn x (Identity a)
23032358newJoinDyn d =
23042359 let readV0 = readBehaviorTracked . dynamicCurrent =<< readBehaviorTracked (dynamicCurrent d)
23052360 eOuter = Reflex.Spider.Internal.push (fmap (Just . Identity) . readBehaviorUntracked . dynamicCurrent . runIdentity) $ dynamicUpdated d
@@ -2449,7 +2504,7 @@ unsafeNewSpiderTimelineEnv = do
24492504#ifdef DEBUG
24502505 depthRef <- newIORef 0
24512506#endif
2452− return $ SpiderTimelineEnv
2507+ return $ STE $ SpiderTimelineEnv
24532508 { _spiderTimeline_lock = lock
24542509 , _spiderTimeline_eventEnv = env
24552510#ifdef DEBUG
@@ -2461,17 +2516,17 @@ unsafeNewSpiderTimelineEnv = do
24612516newSpiderTimeline :: IO (Some SpiderTimelineEnv)
24622517newSpiderTimeline = withSpiderTimeline (pure . Some)
24632518
2464−data LocalSpiderTimeline x s
2519+data LocalSpiderTimeline (x :: Type) s
24652520
24662521instance Reifies s (SpiderTimelineEnv x) =>
24672522 HasSpiderTimeline (LocalSpiderTimeline x s) where
2468− spiderTimeline = localSpiderTimeline (Proxy :: Proxy s) $ reflect (Proxy :: Proxy s)
2523+ spiderTimeline = localSpiderTimeline Proxy $ reflect (Proxy :: Proxy s)
24692524
24702525localSpiderTimeline
2471− :: Proxy s
2526+ :: proxy s
24722527 -> SpiderTimelineEnv x
24732528 -> SpiderTimelineEnv (LocalSpiderTimeline x s)
2474−localSpiderTimeline _ = unsafeCoerce
2529+localSpiderTimeline _ = coerce
24752530
24762531-- | Pass a new timeline to the given function.
24772532withSpiderTimeline :: (forall x. HasSpiderTimeline x => SpiderTimelineEnv x -> IO r) -> IO r
@@ -2479,18 +2534,18 @@ withSpiderTimeline k = do
24792534 env <- unsafeNewSpiderTimelineEnv
24802535 reify env $ \s -> k $ localSpiderTimeline s env
24812536
2482−newtype SpiderPullM x a = SpiderPullM (BehaviorM x a) deriving (Functor, Applicative, Monad, MonadIO, MonadFix)
2537+newtype SpiderPullM (x :: Type) a = SpiderPullM (BehaviorM x a) deriving (Functor, Applicative, Monad, MonadIO, MonadFix)
24832538
24842539type ComputeM = EventM
24852540
2486−newtype SpiderPushM x a = SpiderPushM (ComputeM x a) deriving (Functor, Applicative, Monad, MonadIO, MonadFix)
2541+newtype SpiderPushM (x :: Type) a = SpiderPushM (ComputeM x a) deriving (Functor, Applicative, Monad, MonadIO, MonadFix)
24872542
24882543instance HasSpiderTimeline x => R.Reflex (SpiderTimeline x) where
24892544 {-# SPECIALIZE instance R.Reflex (SpiderTimeline Global) #-}
24902545 newtype Behavior (SpiderTimeline x) a = SpiderBehavior { unSpiderBehavior :: Behavior x a }
24912546 newtype Event (SpiderTimeline x) a = SpiderEvent { unSpiderEvent :: Event x a }
2492− newtype Dynamic (SpiderTimeline x) a = SpiderDynamic { unSpiderDynamic :: Dynamic x (Identity a) } -- deriving (Functor, Applicative, Monad)
2493− newtype Incremental (SpiderTimeline x) p = SpiderIncremental { unSpiderIncremental :: Dynamic x p }
2547+ newtype Dynamic (SpiderTimeline x) a = SpiderDynamic { unSpiderDynamic :: DynamicS x (Identity a) } -- deriving (Functor, Applicative, Monad)
2548+ newtype Incremental (SpiderTimeline x) p = SpiderIncremental { unSpiderIncremental :: DynamicS x p }
24942549 type PullM (SpiderTimeline x) = SpiderPullM x
24952550 type PushM (SpiderTimeline x) = SpiderPushM x
24962551 {-# INLINABLE never #-}
@@ -2503,10 +2558,15 @@ instance HasSpiderTimeline x => R.Reflex (SpiderTimeline x) where
25032558 pushCheap f = SpiderEvent . pushCheap (coerce f) . unSpiderEvent
25042559 {-# INLINABLE pull #-}
25052560 pull = SpiderBehavior . pull . coerce
2506− {-# INLINABLE merge #-}
2507− merge = SpiderEvent . merge . dynamicConst . (coerce :: DMap k (R.Event (SpiderTimeline x)) -> DMap k (Event x))
2508− {-# INLINABLE fan #-}
2509− fan e = R.EventSelector $ SpiderEvent . select (fan (unSpiderEvent e))
2561+ {-# INLINABLE fanG #-}
2562+ fanG e = R.EventSelectorG $ SpiderEvent . selectG (fanG (unSpiderEvent e))
2563+ {-# INLINABLE mergeG #-}
2564+ mergeG
2565+ :: forall (k :: k2 -> *) q (v :: k2 -> *). GCompare k
2566+ => (forall a. q a -> R.Event (SpiderTimeline x) (v a))
2567+ -> DMap k q
2568+ -> R.Event (SpiderTimeline x) (DMap k v)
2569+ mergeG nt = SpiderEvent . mergeG (unSpiderEvent #. nt) . dynamicConst
25102570 {-# INLINABLE switch #-}
25112571 switch = SpiderEvent . switch . (coerce :: Behavior x (R.Event (SpiderTimeline x) a) -> Behavior x (Event x a)) . unSpiderBehavior
25122572 {-# INLINABLE coincidence #-}
@@ -2514,15 +2574,15 @@ instance HasSpiderTimeline x => R.Reflex (SpiderTimeline x) where
25142574 {-# INLINABLE current #-}
25152575 current = SpiderBehavior . dynamicCurrent . unSpiderDynamic
25162576 {-# INLINABLE updated #-}
2517− updated = coerce $ SpiderEvent . dynamicUpdated . unSpiderDynamic
2577+ updated = SpiderEvent #. dynamicUpdated .# fmap coerce . unSpiderDynamic
25182578 {-# INLINABLE unsafeBuildDynamic #-}
25192579 unsafeBuildDynamic readV0 v' = SpiderDynamic $ dynamicDynIdentity $ unsafeBuildDynamic (coerce readV0) $ coerce $ unSpiderEvent v'
25202580 {-# INLINABLE unsafeBuildIncremental #-}
25212581 unsafeBuildIncremental readV0 dv = SpiderIncremental $ dynamicDyn $ unsafeBuildDynamic (coerce readV0) $ unSpiderEvent dv
2522− {-# INLINABLE mergeIncremental #-}
2523− mergeIncremental = SpiderEvent . merge . (unsafeCoerce :: Dynamic x (PatchDMap k (R.Event (SpiderTimeline x))) -> Dynamic x (PatchDMap k (Event x))) . unSpiderIncremental
2524− {-# INLINABLE mergeIncrementalWithMove #-}
2525− mergeIncrementalWithMove = SpiderEvent . mergeWithMove . (unsafeCoerce :: Dynamic x (PatchDMapWithMove k (R.Event (SpiderTimeline x))) -> Dynamic x (PatchDMapWithMove k (Event x))) . unSpiderIncremental
2582+ {-# INLINABLE mergeIncrementalG #-}
2583+ mergeIncrementalG nt = SpiderEvent #. mergeG (coerce #. nt) .# unSpiderIncremental
2584+ {-# INLINABLE mergeIncrementalWithMoveG #-}
2585+ mergeIncrementalWithMoveG nt = SpiderEvent #. mergeWithMove (coerce #. nt) .# unSpiderIncremental
25262586 {-# INLINABLE currentIncremental #-}
25272587 currentIncremental = SpiderBehavior . dynamicCurrent . unSpiderIncremental
25282588 {-# INLINABLE updatedIncremental #-}
@@ -2533,9 +2593,10 @@ instance HasSpiderTimeline x => R.Reflex (SpiderTimeline x) where
25332593 return $ Identity <$> apply p c --TODO: Avoid the redundant 'apply'
25342594 eventCoercion Coercion = Coercion
25352595 behaviorCoercion Coercion = Coercion
2536− dynamicCoercion = unsafeCoerce --TODO: How can we avoid this unsafeCoerce? This is safe only because we know how Identity works as a Patch instance
2596+ dynamicCoercion Coercion = Coercion
2597+ incrementalCoercion Coercion Coercion = Coercion
25372598 {-# INLINABLE mergeIntIncremental #-}
2538− mergeIntIncremental = SpiderEvent . mergeInt . (unsafeCoerce :: Dynamic x (PatchIntMap (R.Event (SpiderTimeline x) a)) -> Dynamic x (PatchIntMap (Event x a))) . unSpiderIncremental
2599+ mergeIntIncremental = SpiderEvent . mergeInt . coerce
25392600 {-# INLINABLE fanInt #-}
25402601 fanInt e = R.EventSelectorInt $ SpiderEvent . selectInt (fanInt (unSpiderEvent e))
25412602
@@ -2560,7 +2621,7 @@ instance MonadAtomicRef (EventM x) where
25602621 atomicModifyRef r f = liftIO $ atomicModifyRef r f
25612622
25622623-- | The monad for actions that manipulate a Spider timeline identified by @x@
2563−newtype SpiderHost x a = SpiderHost { unSpiderHost :: IO a } deriving (Functor, Applicative, MonadFix, MonadIO, MonadException, MonadAsyncException)
2624+newtype SpiderHost (x :: Type) a = SpiderHost { unSpiderHost :: IO a } deriving (Functor, Applicative, MonadFix, MonadIO, MonadException, MonadAsyncException)
25642625
25652626instance Monad (SpiderHost x) where
25662627 {-# INLINABLE (>>=) #-}
@@ -2582,7 +2643,7 @@ runSpiderHost (SpiderHost a) = a
25822643runSpiderHostForTimeline :: SpiderHost x a -> SpiderTimelineEnv x -> IO a
25832644runSpiderHostForTimeline (SpiderHost a) _ = a
25842645
2585−newtype SpiderHostFrame x a = SpiderHostFrame { runSpiderHostFrame :: EventM x a }
2646+newtype SpiderHostFrame (x :: Type) a = SpiderHostFrame { runSpiderHostFrame :: EventM x a }
25862647 deriving (Functor, Applicative, MonadFix, MonadIO, MonadException, MonadAsyncException)
25872648
25882649instance Monad (SpiderHostFrame x) where