module Datafix.Worklist.Graph.Dense
( Ref
, newRef
) where
import Control.Monad (forM_)
import Control.Monad.Trans.Class
import Control.Monad.Trans.Reader
import Control.Monad.Trans.State.Strict
import Data.Maybe (fromMaybe)
import Data.Vector.Mutable (IOVector)
import qualified Data.Vector.Mutable as V
import qualified Datafix.IntArgsMonoSet as IntArgsMonoSet
import Datafix.MonoMap (MonoMap, MonoMapKey)
import qualified Datafix.MonoMap as MonoMap
import Datafix.Utils.TypeLevel
import Datafix.Worklist.Graph
type PointMap domain
= MonoMap (Products (ParamTypes domain)) (PointInfo domain)
newtype Ref domain
= Ref (IOVector (PointMap domain))
newRef :: MonoMapKey (Products (ParamTypes domain)) => Int -> IO (Ref domain)
newRef size = Ref <$> V.replicate size MonoMap.empty
zoomNode :: Int -> State (PointMap domain) a -> ReaderT (Ref domain) IO a
zoomNode node s = do
Ref graph <- ask
points <- lift (V.read graph node)
let (ret, points') = runState s points
points' `seq` lift (V.write graph node points')
return ret
instance GraphRef Ref where
updatePoint node args val refs = do
let freshInfo = emptyPointInfo
{ value = Just val
, references = refs
, iterations = 1
}
let merger _ new old = new
{ referrers = referrers old
, iterations = iterations old + 1
}
oldInfo <- fmap (fromMaybe emptyPointInfo) $ zoomNode node $ state $
MonoMap.insertLookupWithKey merger args freshInfo
let diff = computeDiff (references oldInfo) refs
let updater f (depNode, depArgs) = zoomNode depNode $ modify' $
MonoMap.insertWith (const f) depArgs (f emptyPointInfo)
let addReferrer ni = ni { referrers = IntArgsMonoSet.insert node args (referrers ni) }
let removeReferrer ni = ni { referrers = IntArgsMonoSet.delete node args (referrers ni) }
forM_ (IntArgsMonoSet.toList (added diff)) (updater addReferrer)
forM_ (IntArgsMonoSet.toList (removed diff)) (updater removeReferrer)
return oldInfo
lookup node args = ReaderT $ \(Ref graph) ->
MonoMap.lookup args <$> V.read graph node
lookupLT node args = ReaderT $ \(Ref graph) ->
MonoMap.lookupLT args <$> V.read graph node