@@ -1,144 +0,0 @@
1−--------------------------------------------------------------------------------
2−module Hakyll.Core.DependencyAnalyzer
8−--------------------------------------------------------------------------------
9−import Control.Applicative ((<$>))
10−import Control.DeepSeq (NFData (..))
11−import Control.Monad (filterM, forM_, msum, when)
12−import Control.Monad.Reader (ask)
13−import Control.Monad.RWS (RWS, runRWS)
14−import Control.Monad.State (evalState, get, modify)
15−import Control.Monad.Writer (tell)
16−import qualified Data.Map as M
18−import qualified Data.Set as S
21−--------------------------------------------------------------------------------
22−import Hakyll.Core.DirectedGraph
25−--------------------------------------------------------------------------------
32−--------------------------------------------------------------------------------
33−instance NFData a => NFData (Analysis a) where
34− rnf (Cycle c) = rnf c `seq` ()
35− rnf (Order o) = rnf o `seq` ()
38−--------------------------------------------------------------------------------
40− => DirectedGraph a -- ^ Old graph
41− -> DirectedGraph a -- ^ New graph
42− -> (a -> Bool) -- ^ Out of date?
43− -> Analysis a -- ^ Result
44−analyze old new ood = case findCycle new of
46− Nothing -> Order $ findOrder old new ood
49−--------------------------------------------------------------------------------
50−-- | Simple algorithm do find a cycle in a graph, if any exists. This one can
51−-- still be optimised by a lot.
55−findCycle dg = fmap reverse $ msum
57− | x <- S.toList $ nodes dg
58− , n <- neighbours x dg
61− findCycle' stack start x
62− | x == start = Just (x : stack)
64− [ findCycle' (x : stack) start n
65− | n <- neighbours x dg
69−--------------------------------------------------------------------------------
70−-- | Do not call this on graphs with cycles
76−findOrder old new ood = ls
78− -- Make an extension of ood: an item is ood when it is actually ood OR if
79− -- the list of its dependencies has changed. Based on that, create a set of
81− ood' x = ood x || neighbours x old /= neighbours x new
82− dirty' = dirty ood' new
84− -- Run all walks in our own little monad...
85− (_, _, ls) = runRWS walks new dirty'
88−--------------------------------------------------------------------------------
89−type Analyzer i a = RWS (DirectedGraph i) [i] (Set i) a
92−--------------------------------------------------------------------------------
93−isDirty :: Ord a => a -> Analyzer a Bool
94−isDirty x = (x `S.member`) <$> get
97−--------------------------------------------------------------------------------
105− walk $ S.findMin dirty'
109−--------------------------------------------------------------------------------
110−-- | Invariant: given node to walk /must/ be dirty
115− -- Determine dirty neighbours and walk them
117− forM_ (neighbours x dg) $ \n -> do
121− -- Once all dirty neighbours are done, we're safe to go
126−--------------------------------------------------------------------------------
127−-- | This auxiliary function checks which nodes are dirty: a node is dirty if
128−-- it's out-of-date or if one of its dependencies is dirty.
130− => (a -> Bool) -- ^ Out of date?
131− -> DirectedGraph a -- ^ Graph
132− -> Set a -- ^ All dirty items
133−dirty ood dg = S.fromList $ flip evalState M.empty $
134− filterM go $ S.toList $ nodes dg
138− case M.lookup x m of
141− nd <- mapM go $ neighbours x dg
142− let d = ood x || or nd
143− modify $ M.insert x d