diff options
author | Li Haoyi <haoyi.sg@gmail.com> | 2017-10-27 08:15:01 -0700 |
---|---|---|
committer | Li Haoyi <haoyi.sg@gmail.com> | 2017-10-27 08:15:01 -0700 |
commit | f53db8482c86f30c917d16b6312ad4804b37f2df (patch) | |
tree | 8758d12808473a6f77e3465243ee848d55272e75 /src/main/scala/forge/Evaluator.scala | |
parent | afd5de935cb11394848c5040909f2f02fc26335f (diff) | |
download | mill-f53db8482c86f30c917d16b6312ad4804b37f2df.tar.gz mill-f53db8482c86f30c917d16b6312ad4804b37f2df.tar.bz2 mill-f53db8482c86f30c917d16b6312ad4804b37f2df.zip |
Migrate everything which shouldn't have duplicates over to a new `OSet` data structure
Diffstat (limited to 'src/main/scala/forge/Evaluator.scala')
-rw-r--r-- | src/main/scala/forge/Evaluator.scala | 134 |
1 files changed, 87 insertions, 47 deletions
diff --git a/src/main/scala/forge/Evaluator.scala b/src/main/scala/forge/Evaluator.scala index 2a3e4470..ecbf4260 100644 --- a/src/main/scala/forge/Evaluator.scala +++ b/src/main/scala/forge/Evaluator.scala @@ -10,44 +10,81 @@ import scala.collection.mutable class Evaluator(workspacePath: jnio.Path, enclosingBase: DefCtx){ - val resultCache = mutable.Map.empty[String, (Int, String)] - def evaluate(targets: Seq[Target[_]]): Evaluator.Results = { + /** + * Cache from the ID of the first terminal target in a group to the has of + * all the group's distinct inputs, and the results of the possibly-multiple + * terminal nodes + */ + val resultCache = mutable.Map.empty[String, (Int, Seq[String])] + def evaluate(targets: OSet[Target[_]]): Evaluator.Results = { jnio.Files.createDirectories(workspacePath) - val sortedTargets = Evaluator.topoSortedTransitiveTargets(targets) - pprint.log(sortedTargets.values) - val evaluated = mutable.Buffer.empty[Target[_]] + val sortedGroups = Evaluator.groupAroundNamedTargets( + Evaluator.topoSortedTransitiveTargets(targets) + ) + + val evaluated = new MutableOSet[Target[_]] val results = mutable.Map.empty[Target[_], Any] - for (target <- sortedTargets.values){ - val inputResults = target.inputs.map(results).toIndexedSeq - - val enclosingStr = target.defCtx.label - val targetDestPath = workspacePath.resolve( - jnio.Paths.get(enclosingStr.stripSuffix(enclosingBase.label)) - ) - deleteRec(targetDestPath) - - val inputsHash = inputResults.hashCode - (target.dirty, resultCache.get(target.defCtx.label)) match{ - case (Some(dirtyCheck), Some((hash, res))) - if hash == inputsHash && !dirtyCheck() => - results(target) = target.formatter.reads(Json.parse(res)).get - - case _ => - evaluated.append(target) + for (group <- sortedGroups){ + val (newResults, newEvaluated) = evaluateGroup(group, results) + evaluated.appendAll(newEvaluated) + for((k, v) <- newResults) results.put(k, v) + + } + Evaluator.Results(targets.items.map(results), evaluated) + } + + def evaluateGroup(group: OSet[Target[_]], + results: collection.Map[Target[_], Any]) = { + val allInputs = group.items.flatMap(_.inputs) + val (internalInputs, externalInputs) = allInputs.partition(group.contains) + val internalInputSet = internalInputs.toSet + val inputResults = externalInputs.distinct.map(results).toIndexedSeq + + val newResults = mutable.Map.empty[Target[_], Any] + val newEvaluated = mutable.Buffer.empty[Target[_]] + + val terminals = group.filter(!internalInputSet(_)) + val primeTerminal = terminals.items(0) + val enclosingStr = primeTerminal.defCtx.label + val targetDestPath = workspacePath.resolve( + jnio.Paths.get(enclosingStr.stripSuffix(enclosingBase.label)) + ) + deleteRec(targetDestPath) + + val inputsHash = inputResults.hashCode + (primeTerminal.dirty, resultCache.get(primeTerminal.defCtx.label)) match{ + case (Some(dirtyCheck), Some((hash, terminalResults))) + if hash == inputsHash && !dirtyCheck() => + for((terminal, res) <- terminals.items.zip(terminalResults)){ + + newResults(terminal) = primeTerminal.formatter.reads(Json.parse(res)).get + } + + case _ => + val terminalResults = mutable.Buffer.empty[String] + for(target <- group.items){ + + newEvaluated.append(target) if (target.defCtx.anonId.isDefined && target.dirty.isEmpty) { val res = target.evaluate(new Args(inputResults, targetDestPath)) - results(target) = res + newResults(target) = res }else{ - val (res, serialized) = target.evaluateAndWrite(new Args(inputResults, targetDestPath)) - resultCache(target.defCtx.label) = (inputsHash, serialized) - results(target) = res + val (res, serialized) = target.evaluateAndWrite( + new Args(inputResults, targetDestPath) + ) + if (!internalInputSet(target)){ + terminalResults.append(serialized) + + } + newResults(target) = res } - - } + } + resultCache(primeTerminal.defCtx.label) = (inputsHash, terminalResults) } - Evaluator.Results(targets.map(results), evaluated) + + (newResults, newEvaluated) } def deleteRec(path: jnio.Path) = { if (jnio.Files.exists(path)){ @@ -63,14 +100,14 @@ class Evaluator(workspacePath: jnio.Path, object Evaluator{ - class TopoSorted private[Evaluator] (val values: Seq[Target[_]]) - case class Results(values: Seq[Any], evaluated: Seq[Target[_]]) - def groupAroundNamedTargets(topoSortedTargets: TopoSorted): Seq[Seq[Target[_]]] = { + class TopoSorted private[Evaluator] (val values: OSet[Target[_]]) + case class Results(values: Seq[Any], evaluated: OSet[Target[_]]) + def groupAroundNamedTargets(topoSortedTargets: TopoSorted): OSet[OSet[Target[_]]] = { val grouping = new MultiBiMap[Int, Target[_]]() var groupCount = 0 - for(target <- topoSortedTargets.values.reverseIterator){ + for(target <- topoSortedTargets.values.items.reverseIterator){ if (!grouping.containsValue(target)){ grouping.add(groupCount, target) @@ -90,40 +127,43 @@ object Evaluator{ } } } - val output = mutable.Buffer.empty[Seq[Target[_]]] - for(target <- topoSortedTargets.values.reverseIterator){ + val output = mutable.Buffer.empty[OSet[Target[_]]] + for(target <- topoSortedTargets.values.items.reverseIterator){ for(targetGroup <- grouping.lookupValueOpt(target)){ - output.append(grouping.removeAll(targetGroup)) + output.append( + OSet.from( + grouping.removeAll(targetGroup) + .sortBy(topoSortedTargets.values.items.indexOf) + ) + ) } } - output.map(_.sortBy(topoSortedTargets.values.indexOf)).reverse + OSet.from(output.reverse) } /** * Takes the given targets, finds */ - def topoSortedTransitiveTargets(sourceTargets: Seq[Target[_]]): TopoSorted = { - val transitiveTargetSet = mutable.Set.empty[Target[_]] - val transitiveTargets = mutable.Buffer.empty[Target[_]] + def topoSortedTransitiveTargets(sourceTargets: OSet[Target[_]]): TopoSorted = { + val transitiveTargets = new MutableOSet[Target[_]] def rec(t: Target[_]): Unit = { - if (transitiveTargetSet.contains(t)) () // do nothing + if (transitiveTargets.contains(t)) () // do nothing else { - transitiveTargetSet.add(t) transitiveTargets.append(t) t.inputs.foreach(rec) } } - sourceTargets.foreach(rec) - val targetIndices = transitiveTargets.zipWithIndex.toMap + sourceTargets.items.foreach(rec) + val targetIndices = transitiveTargets.items.zipWithIndex.toMap val numberedEdges = - for(i <- transitiveTargets.indices) - yield transitiveTargets(i).inputs.map(targetIndices) + for(t <- transitiveTargets.items) + yield t.inputs.map(targetIndices) val sortedClusters = Tarjans(numberedEdges) val nonTrivialClusters = sortedClusters.filter(_.length > 1) assert(nonTrivialClusters.isEmpty, nonTrivialClusters) - new TopoSorted(sortedClusters.flatten.map(transitiveTargets)) + new TopoSorted(OSet.from(sortedClusters.flatten.map(transitiveTargets.items))) } }
\ No newline at end of file |