make computeFrontier more efficient, rename to computeDirty

This commit is contained in:
Mitchell Rosen 2022-01-13 23:58:01 -05:00
parent 875d3847b3
commit b8257d306f

View File

@ -39,6 +39,7 @@ import Unison.Term ( Term )
import Unison.Util.Free ( Free
, eval
)
import Unison.Util.Monoid ( foldMapM )
import qualified Unison.Util.Relation as R
import Unison.Util.TransitiveClosure ( transitiveClosure )
import Unison.Var ( Var )
@ -259,7 +260,7 @@ propagate rootNames patch b = case validatePatch patch of
[] -> Referent.toString r
n : _ -> show n
initialDirty <- R.dom <$> computeFrontier (eval . GetDependents) patch names0
initialDirty <- computeDirty (eval . GetDependents) patch names0
let initialTypeReplacements = Map.mapMaybe TypeEdit.toReference initialTypeEdits
-- TODO: once patches can directly contain constructor replacements, this
@ -623,37 +624,25 @@ applyPropagate patch Edits {..} = do
-- typePreservingTermEdits Patch {..} = Patch termEdits mempty
-- where termEdits = R.filterRan TermEdit.isTypePreserving _termEdits
-- (d, f) when d is "dirty" (needs update),
-- f is in the frontier (an edited dependency of d),
-- and d depends on f
-- a ⋖ b = a depends directly on b
-- dirty(d) ∧ frontier(f) <=> not(edited(d)) ∧ edited(f) ∧ d ⋖ f
-- | Compute the set of "dirty" references. They each:
--
-- The range of this relation is the frontier, and the domain is
-- the set of dirty references.
computeFrontier
-- 1. Depend directly on some reference that was edited in the given patch
-- 2. Have a name in the current namespace (the given Names)
-- 3. Are not themselves edited in the given patch.
computeDirty
:: forall m
. Monad m
=> (Reference -> m (Set Reference)) -- eg Codebase.dependents codebase
-> Patch
-> Names
-> m (R.Relation Reference Reference)
computeFrontier getDependents patch names = do
-- (r,r2) ∈ dependsOn if r depends on r2
dependsOn <- foldM addDependents R.empty edited
-- Dirty is everything that `dependsOn` Frontier, minus already edited defns
pure $ R.filterDom (not . flip Set.member edited) dependsOn
where
-> m (Set Reference)
computeDirty getDependents patch names =
foldMapM (\ref -> keepDirtyDependents <$> getDependents ref) edited
where
-- Given a set of dependent references (satisfying 1. above), keep only the dirty ones (per 2. and 3. above)
keepDirtyDependents :: Set Reference -> Set Reference
keepDirtyDependents =
(`Set.difference` edited) . Set.filter (Names.contains names)
edited :: Set Reference
edited = R.dom (Patch._termEdits patch) <> R.dom (Patch._typeEdits patch)
addDependents
:: R.Relation Reference Reference
-> Reference
-> m (R.Relation Reference Reference)
addDependents dependents ref =
(\ds -> R.insertManyDom ds ref dependents)
. Set.filter isNamed
<$> getDependents ref
isNamed :: Reference -> Bool
isNamed =
Names.contains names