3
3
{-# OPTIONS_GHC -Wno-redundant-constraints #-}
4
4
5
5
{-# LANGUAGE DerivingStrategies #-}
6
+ {-# LANGUAGE LambdaCase #-}
6
7
{-# LANGUAGE RecordWildCards #-}
7
8
{-# LANGUAGE TypeFamilies #-}
8
- {-# LANGUAGE ViewPatterns #-}
9
9
10
10
module Development.IDE.Graph.Internal.Database (newDatabase , incDatabase , build , getDirtySet , getKeysAndVisitAge ) where
11
11
@@ -25,7 +25,7 @@ import Control.Monad.Trans.Reader
25
25
import qualified Control.Monad.Trans.State.Strict as State
26
26
import Data.Dynamic
27
27
import Data.Either
28
- import Data.Foldable (for_ , traverse_ )
28
+ import Data.Foldable (fold , for_ , traverse_ )
29
29
import Data.IORef.Extra
30
30
import Data.List.NonEmpty (unzip )
31
31
import Data.Maybe
@@ -133,6 +133,27 @@ builder db@Database{..} stack keys = withRunInIO $ \(RunInIO run) -> do
133
133
waitAll
134
134
pure results
135
135
136
+ isDirty :: Foldable t => Result -> t (a , Result ) -> Bool
137
+ isDirty me = any (\ (_,dep) -> resultBuilt me < resultChanged dep)
138
+
139
+ refreshDeps :: Database -> Stack -> Key -> Result -> [KeySet ] -> AIO (IO Result )
140
+ refreshDeps db stack key result = \ case
141
+ -- no more deps to refresh
142
+ [] -> pure $ compute db stack key RunDependenciesSame (Just result)
143
+ (dep: deps) -> do
144
+ res <- builder db stack (toListKeySet dep)
145
+ case res of
146
+ Left res -> if isDirty result res
147
+ -- restart the computation if any of the deps are dirty
148
+ then asyncWithCleanUp $ liftIO $ compute db stack key RunDependenciesChanged (Just result)
149
+ -- else kick the rest of the deps
150
+ else refreshDeps db stack key result deps
151
+ Right iores -> asyncWithCleanUp $ liftIO $ do
152
+ res <- iores
153
+ if isDirty result res
154
+ then compute db stack key RunDependenciesChanged (Just result)
155
+ else join $ runAIO $ refreshDeps db stack key result deps
156
+
136
157
-- | Refresh a key:
137
158
-- * If no dirty dependencies and we have evaluated the key previously, then we refresh it in the current thread.
138
159
-- This assumes that the implementation will be a lookup
@@ -141,18 +162,7 @@ refresh :: Database -> Stack -> Key -> Maybe Result -> AIO (IO Result)
141
162
-- refresh _ st k _ | traceShow ("refresh", st, k) False = undefined
142
163
refresh db stack key result = case (addStack key stack, result) of
143
164
(Left e, _) -> throw e
144
- (Right stack, Just me@ Result {resultDeps = ResultDeps (toListKeySet -> deps)}) -> do
145
- res <- builder db stack deps
146
- let isDirty = any (\ (_,dep) -> resultBuilt me < resultChanged dep)
147
- case res of
148
- Left res ->
149
- if isDirty res
150
- then asyncWithCleanUp $ liftIO $ compute db stack key RunDependenciesChanged result
151
- else pure $ compute db stack key RunDependenciesSame result
152
- Right iores -> asyncWithCleanUp $ liftIO $ do
153
- res <- iores
154
- let mode = if isDirty res then RunDependenciesChanged else RunDependenciesSame
155
- compute db stack key mode result
165
+ (Right stack, Just me@ Result {resultDeps = ResultDeps deps}) -> refreshDeps db stack key me (reverse deps)
156
166
(Right stack, _) ->
157
167
asyncWithCleanUp $ liftIO $ compute db stack key RunDependenciesChanged result
158
168
@@ -172,8 +182,8 @@ compute db@Database{..} stack key mode result = do
172
182
actualDeps = if runChanged /= ChangedNothing then deps else previousDeps
173
183
previousDeps= maybe UnknownDeps resultDeps result
174
184
let res = Result runValue built' changed built actualDeps execution runStore
175
- case getResultDepsDefault mempty actualDeps of
176
- deps | not (nullKeySet deps)
185
+ case fold $ getResultDepsDefault mempty actualDeps of
186
+ deps | not (nullKeySet deps)
177
187
&& runChanged /= ChangedNothing
178
188
-> do
179
189
-- IMPORTANT: record the reverse deps **before** marking the key Clean.
@@ -182,7 +192,7 @@ compute db@Database{..} stack key mode result = do
182
192
-- on the next build.
183
193
void $
184
194
updateReverseDeps key db
185
- (getResultDepsDefault mempty previousDeps)
195
+ (fold $ getResultDepsDefault mempty previousDeps)
186
196
deps
187
197
_ -> pure ()
188
198
atomicallyNamed " compute" $ SMap. focus (updateStatus $ Clean res) key databaseValues
0 commit comments