Skip to content

Commit 377b92a

Browse files
committed
Misc changes to the build stuff
1 parent 1466166 commit 377b92a

File tree

1 file changed

+63
-104
lines changed

1 file changed

+63
-104
lines changed

examples/lib/Build.hs

Lines changed: 63 additions & 104 deletions
Original file line numberDiff line numberDiff line change
@@ -15,26 +15,19 @@ module Build
1515
, useOld
1616
) where
1717

18-
import Algebra.Graph.AdjacencyIntMap ( AdjacencyIntMap
19-
, fromAdjacencyIntSets
20-
, induce
21-
, postIntSet
22-
, transitiveClosure
23-
24-
)
25-
import Algebra.Graph.AdjacencyIntMap.Algorithm
26-
( topSort )
2718
import Barbies
28-
import Control.Monad
2919
import Control.Monad.Fix
3020
import Control.Monad.Trans.Class
3121
import Control.Monad.Trans.Reader
3222
import Control.Monad.Trans.State
3323
import Data.Bifunctor
24+
import Data.Bool
3425
import Data.Coerce ( coerce )
3526
import Data.Dependent.Map ( DMap )
3627
import qualified Data.Dependent.Map as DMap
3728
import Data.Dependent.Sum
29+
import Data.Foldable
30+
import Data.Functor.Compose
3831
import Data.Functor.Identity
3932
import Data.Functor.Product
4033
import Data.GADT.Compare ( GCompare(..)
@@ -45,15 +38,11 @@ import qualified Data.IntMap as Map
4538
import Data.IntMap.Strict ( IntMap )
4639
import qualified Data.IntSet as Set
4740
import Data.IntSet ( IntSet )
48-
import Data.List ( intercalate
49-
)
41+
import Data.List ( intercalate )
42+
import Data.Maybe
5043
import Data.Some ( Some(Some) )
5144
import Data.Type.Equality ( (:~:)(Refl) )
5245
import Unsafe.Coerce ( unsafeCoerce )
53-
import Data.Functor.Compose
54-
import Data.Bool
55-
import Data.Foldable
56-
import Data.Maybe
5746

5847
newtype Ref s a = Ref { unRef :: Int }
5948
deriving (Show)
@@ -70,12 +59,11 @@ instance GCompare (Ref s) where
7059
Refl -> GEQ
7160
GT -> GGT
7261

73-
7462
data Action s a where
7563
Pure ::a -> Action s a
7664
Ap ::Action s (a -> b) -> Action s a -> Action s b
7765
FMap ::(a -> b) -> Action s a -> Action s b
78-
-- This has to be lazy so that the MonadFix instance for Actions is useful
66+
-- These have to be lazy so that the MonadFix instance for Actions is useful
7967
UseRef :: Cond a -> ~(Ref s a) -> Action s a
8068
UseOldRef :: ~(Ref s a) -> Action s (Maybe a)
8169

@@ -148,28 +136,22 @@ initialActionState = ActionsState { asNextRef = 0
148136
, asNames = mempty
149137
}
150138

151-
sortRefs
152-
:: AdjacencyIntMap
153-
-> IntSet
154-
-> ActionsState s m
155-
-> [DSum (Ref s) (LookupRef s m)]
156-
sortRefs graph initInts ActionsState {..} =
157-
let reachable =
158-
let t = transitiveClosure graph
159-
in Set.unions
160-
(initInts : [ postIntSet i t | i <- Set.toList initInts ])
161-
filtered = induce (`Set.member` reachable) graph
162-
sorted = reverse $ case topSort filtered of
163-
Left _ -> error "cycle in graph"
164-
Right r -> r
165-
acts = DMap.toAscList asCreate
166-
in (acts !!) <$> sorted
167-
139+
-- |
140+
--
141+
-- @
142+
-- {-# language ApplicativeDo #-}
143+
-- foo myOtherRef = do
144+
-- myDependency <- 'use' myOtherRef
145+
-- pure $ do
146+
-- some action using myDependency
147+
-- @
168148
create
169149
:: forall m a s
170150
. Monad m
171151
=> String
152+
-- ^ Name of node when rendered with 'actionsGraph'
172153
-> Action s (m a)
154+
-- ^ The dependencies of this action, and the action itself
173155
-> Actions s m (Ref s a)
174156
create name act = do
175157
r <- newRef @s @m @a
@@ -190,67 +172,34 @@ create name act = do
190172
unCondDeps :: DMap (Ref s) f -> IntSet
191173
unCondDeps = Set.fromList . fmap (\(Some (Ref r)) -> r) . DMap.keys
192174

193-
makeNew
194-
:: (Foldable t, Monad m)
195-
=> t (DSum (Ref s) (LookupRef s m))
196-
-> (DMap (Ref s) Identity -> b)
197-
-> m b
198-
makeNew sorted fromResolved = do
199-
resolved <- foldM
200-
(\done (r :=> m) -> do
201-
m' <- runLookupRef mempty done m
202-
pure $ DMap.insert r (Identity m') done
203-
)
204-
mempty
205-
sorted
206-
pure $ fromResolved resolved
175+
----------------------------------------------------------------
176+
-- Consuming 'Actions'
177+
----------------------------------------------------------------
207178

179+
-- | Consume an 'Actions' and create the specified structure
208180
runActions
209-
:: (Monad m, TraversableB f)
181+
:: (Monad m, TraversableB f, ApplicativeB f)
210182
=> (forall s . Actions s m (f (Ref s)))
211183
-> m (f Identity)
212-
runActions (Actions c) =
213-
let (rs, s@ActionsState {..}) = runState c initialActionState
214-
needed = bfoldMap (Set.singleton . unRef) rs
215-
graph =
216-
fromAdjacencyIntSets
217-
. fmap (fmap unCondDeps)
218-
. Map.toList
219-
$ asDepends
220-
sorted = sortRefs graph needed s
221-
fromResolved resolved =
222-
runIdentity
223-
. runLookupRef mempty resolved
224-
. btraverse (fmap Identity . lookupRef)
225-
$ rs
226-
in makeNew sorted fromResolved
184+
runActions a = snd (runActionsWithRecreator a)
227185

186+
type Recreator m f = f DoRecreate -> f Identity -> m (f Identity)
187+
188+
data DoRecreate a = DoRecreate | DoNotRecreate
189+
190+
-- | Consume an 'Actions' and create the specified structure, also return a
191+
-- function to run the creation program again selectivly regenerating elements
228192
runActionsWithRecreator
229193
:: forall m f
230194
. (Monad m, TraversableB f, ApplicativeB f)
231195
=> (forall s . Actions s m (f (Ref s)))
232196
-> (Recreator m f, m (f Identity))
233197
runActionsWithRecreator (Actions c) =
234198
let
235-
(rs, s@ActionsState {..}) = runState c initialActionState
236-
needed = bfoldMap (Set.singleton . unRef) rs
237-
graph =
238-
fromAdjacencyIntSets . fmap (fmap unCondDeps) . Map.toList $ asDepends
239-
sorted = sortRefs graph needed s
240-
fromResolved oldMap resolved =
241-
runIdentity
242-
. runLookupRef oldMap resolved
243-
. btraverse (fmap Identity . lookupRef)
244-
$ rs
245-
246-
reverseDeps :: DMap (Ref ()) CondDependees
247-
reverseDeps = DMap.fromListWithKey
248-
(const (<>))
249-
[ childRef :=> CondDependees [(p, cond)]
250-
| (p, children) <- Map.toList asDepends
251-
, (childRef :=> cond) <- DMap.toList children
252-
]
199+
(rs, ActionsState {..}) = runState c initialActionState
253200

201+
-- Get ref from oldRefs, if it isn't there (because it wasn't persisted in
202+
-- the ref set) then regenerate it.
254203
realiseOldRef
255204
:: forall a
256205
. RefMap ()
@@ -260,19 +209,23 @@ runActionsWithRecreator (Actions c) =
260209
Just v -> pure v
261210
Nothing -> Identity <$> realiseRef (Just oldRefs) ref
262211

212+
-- Ensure that a ref has been generated, if it hasn't already been
213+
-- generated then make sure that its direct dependencies have been realised
214+
-- before creating it.
263215
realiseRef
264216
:: forall a
265-
. Maybe ( RefMap ())
217+
. Maybe (RefMap ())
266218
-> Ref () a
267219
-> StateT (RefMap (), IntSet) m a
268220
realiseRef oldRefsMb ref = do
269221
(refsWeHave, foundDirty) <- get
270222
case DMap.lookup ref refsWeHave of
271223
Just v -> pure (runIdentity v)
272224
Nothing
273-
| unRef ref `Set.notMember` foundDirty, Just oldRefs <- oldRefsMb, Just r <- DMap.lookup
274-
ref
275-
oldRefs -> do
225+
| unRef ref `Set.notMember` foundDirty
226+
, Just oldRefs <- oldRefsMb
227+
, Just r <- DMap.lookup ref oldRefs
228+
-> do
276229
modify' (first $ DMap.insert ref r)
277230
pure $ runIdentity r
278231
Nothing -> do
@@ -285,34 +238,43 @@ runActionsWithRecreator (Actions c) =
285238
case oldRefsMb of
286239
Nothing -> pure ()
287240
Just oldRefs ->
288-
for_ (Set.toList oldDeps)
289-
$ realiseOldRef oldRefs
290-
. Ref
241+
for_ (Set.toList oldDeps) $ realiseOldRef oldRefs . Ref
291242

292243
-- Then create this value
293244
let ourCreate =
294245
DMap.findWithDefault (error "missing ref creator") ref asCreate
295246
newRefs <- gets fst
296-
r <- lift $ runLookupRef (fromMaybe mempty oldRefsMb) newRefs ourCreate
247+
r <- lift
248+
$ runLookupRef (fromMaybe mempty oldRefsMb) newRefs ourCreate
297249
modify' (first $ DMap.insert ref (Identity r))
298250
pure r
299251

300-
regenRef
301-
:: Maybe (RefMap ()) -> Ref () a -> StateT (RefMap (), IntSet) m (Identity a)
252+
-- A map from references to the ones which depend on them, along with
253+
-- the condition for regeneration
254+
reverseDeps :: DMap (Ref ()) CondDependees
255+
reverseDeps = DMap.fromListWithKey
256+
(const (<>))
257+
[ childRef :=> CondDependees [(p, cond)]
258+
| (p, children) <- Map.toList asDepends
259+
, (childRef :=> cond) <- DMap.toList children
260+
]
261+
262+
-- Realise a ref, and mark its children as dirty if their condition says
263+
-- so.
264+
regenRef :: Maybe (RefMap ()) -> Ref () a -> StateT (RefMap (), IntSet) m a
302265
regenRef oldRefs ref = do
303266
r <- realiseRef oldRefs ref
304267
-- Mark its dependees as dirty if they fail the condition
305-
let CondDependees dependees =
306-
DMap.findWithDefault mempty ref reverseDeps
307-
dirtyDependees = Set.fromList
268+
let CondDependees dependees = DMap.findWithDefault mempty ref reverseDeps
269+
dirtyDependees = Set.fromList
308270
[ d
309271
| (d, Cond cond) <- dependees
310272
, case DMap.lookup ref =<< oldRefs of
311273
Nothing -> True
312274
Just (Identity oldR) -> cond oldR r
313275
]
314276
modify' $ second (Set.union dirtyDependees)
315-
pure $ Identity r
277+
pure r
316278

317279
recreate dirty old = do
318280
let initialDirtyRefs = bfoldMap
@@ -328,27 +290,24 @@ runActionsWithRecreator (Actions c) =
328290
flip evalStateT (mempty, initialDirtyRefs) $ btraverse
329291
(\case
330292
-- We have been explicitly asked to recreate this one
331-
Pair DoRecreate (Pair _ ref) -> regenRef (Just oldRefs) ref
293+
Pair DoRecreate (Pair _ ref) ->
294+
Identity <$> regenRef (Just oldRefs) ref
332295
Pair DoNotRecreate (Pair oldValue ref) -> do
333296
foundDirty <- gets snd
334297
if unRef ref `Set.member` foundDirty
335-
then regenRef (Just oldRefs) ref
298+
then Identity <$> regenRef (Just oldRefs) ref
336299
else pure oldValue
337300
)
338301
(bzip dirty (bzip old rs))
339302

340303
createNew = do
341-
flip evalStateT mempty $ btraverse (regenRef mempty) rs
304+
flip evalStateT mempty $ btraverse (fmap Identity . realiseRef mempty) rs
342305
in
343306
(recreate, createNew)
344307

345308
newtype CondDependees a = CondDependees [(Int, Cond a)]
346309
deriving newtype (Semigroup, Monoid)
347310

348-
type Recreator m f = f DoRecreate -> f Identity -> m (f Identity)
349-
350-
data DoRecreate a = DoRecreate | DoNotRecreate
351-
352311
-- | Generate a graphviz description for this set of actions
353312
--
354313
-- Dependencies on old values are shown with dotted lines

0 commit comments

Comments
 (0)