diff options
Diffstat (limited to 'src/main/scala')
-rw-r--r-- | src/main/scala/forge/DefCtx.scala | 79 | ||||
-rw-r--r-- | src/main/scala/forge/Evaluator.scala | 23 | ||||
-rw-r--r-- | src/main/scala/forge/Target.scala | 41 |
3 files changed, 28 insertions, 115 deletions
diff --git a/src/main/scala/forge/DefCtx.scala b/src/main/scala/forge/DefCtx.scala deleted file mode 100644 index 3439f755..00000000 --- a/src/main/scala/forge/DefCtx.scala +++ /dev/null @@ -1,79 +0,0 @@ -package forge - - -import scala.annotation.compileTimeOnly -import scala.language.experimental.macros -import scala.reflect.macros.blackbox._ - - -final case class DefCtx(baseLabel: String, anonId: Option[Int]){ - def label = baseLabel + anonId.getOrElse("") -} -object DefCtx{ - @compileTimeOnly("A DefCtx can only be provided directly within a T{} macro") - implicit def dummy: DefCtx with Int = ??? -} - -object T{ - def apply[T](expr: T): T = macro applyImpl[T] - - def applyImpl[T: c.WeakTypeTag](c: Context)(expr: c.Expr[T]): c.Expr[T] = { - import c.universe._ - var count = 0 - object transformer extends c.universe.Transformer { - override def transform(tree: c.Tree): c.Tree = { - if (tree.toString.startsWith("forge.") && tree.toString.endsWith(".DefCtx.dummy")) { - count += 1 - c.typecheck(q"forge.DefCtx(sourcecode.Enclosing(), Some($count))") - }else tree match{ - case Apply(fun, args) => - val extendedParams = fun.tpe.paramLists.head.padTo( - args.length, - fun.tpe.paramLists.head.lastOption.getOrElse(null) - ) - val newArgs = - for((sym, tree) <- extendedParams.zip(args)) - yield { - if (sym.asTerm.isByNameParam) tree - else transform(tree) - } - treeCopy.Apply(tree, transform(fun), newArgs) - - case t: DefDef => t - case t: ClassDef => t - case t: Function => t - case t: LabelDef => t - case t => super.transform(t) - } - - } - } - - - def transformTerminal(tree: c.Tree): c.Tree = tree match{ - case Block(stats, returnExpr) => - treeCopy.Block( - tree, - stats.map(transformer.transform(_)), - transformTerminal(returnExpr) - ) - - case Apply(fun, args) => - var isTransformed = false - val newArgs = for(x <- args) yield { - if (x.toString.startsWith("forge.") && x.toString.endsWith(".DefCtx.dummy")) { - isTransformed = true - c.typecheck(q"forge.DefCtx(sourcecode.Enclosing(), None)") - }else transformer.transform(x) - } - - assert(isTransformed) - treeCopy.Apply(tree, transformer.transform(fun), newArgs) - - case _ => ??? - } - - val transformed = transformTerminal(expr.tree) - c.Expr[T](transformed) - } -}
\ No newline at end of file diff --git a/src/main/scala/forge/Evaluator.scala b/src/main/scala/forge/Evaluator.scala index 32a3c9d0..4d9a435e 100644 --- a/src/main/scala/forge/Evaluator.scala +++ b/src/main/scala/forge/Evaluator.scala @@ -8,7 +8,7 @@ import sourcecode.Enclosing import scala.collection.mutable class Evaluator(workspacePath: jnio.Path, - enclosingBase: DefCtx){ + labeling: Map[Target[_], Seq[String]]){ /** * Cache from the ID of the first terminal target in a group to the has of @@ -20,12 +20,14 @@ class Evaluator(workspacePath: jnio.Path, jnio.Files.createDirectories(workspacePath) val sortedGroups = Evaluator.groupAroundNamedTargets( - Evaluator.topoSortedTransitiveTargets(targets) + Evaluator.topoSortedTransitiveTargets(targets), + labeling ) val evaluated = new MutableOSet[Target[_]] val results = mutable.Map.empty[Target[_], Any] for (group <- sortedGroups){ + println("Evaluating group " + group) val (newResults, newEvaluated) = evaluateGroup(group, results) evaluated.appendAll(newEvaluated) for((k, v) <- newResults) results.put(k, v) @@ -46,19 +48,19 @@ class Evaluator(workspacePath: jnio.Path, val terminals = group.filter(!internalInputSet(_)) val primeTerminal = terminals.items(0) - val enclosingStr = primeTerminal.defCtx.label + + val primeLabel = labeling(primeTerminal).mkString("/") val targetDestPath = workspacePath.resolve( - jnio.Paths.get(enclosingStr.stripSuffix(enclosingBase.label)) + jnio.Paths.get(primeLabel) ) val anyDirty = group.exists(_.dirty) deleteRec(targetDestPath) val inputsHash = inputResults.hashCode - resultCache.get(primeTerminal.defCtx.label) match{ + resultCache.get(primeLabel) match{ case Some((hash, terminalResults)) if hash == inputsHash && !anyDirty => for((terminal, res) <- terminals.items.zip(terminalResults)){ - newResults(terminal) = primeTerminal.formatter.reads(Json.parse(res)).get } @@ -69,7 +71,7 @@ class Evaluator(workspacePath: jnio.Path, val targetInputValues = target.inputs.toVector.map(x => newResults.getOrElse(x, results(x)) ) - if (target.defCtx.anonId.isDefined) { + if (!labeling.contains(target)) { val res = target.evaluate(new Args(targetInputValues, targetDestPath)) newResults(target) = res }else{ @@ -83,7 +85,7 @@ class Evaluator(workspacePath: jnio.Path, newResults(target) = res } } - resultCache(primeTerminal.defCtx.label) = (inputsHash, terminalResults) + resultCache(primeLabel) = (inputsHash, terminalResults) } @@ -105,7 +107,8 @@ class Evaluator(workspacePath: jnio.Path, object Evaluator{ class TopoSorted private[Evaluator] (val values: OSet[Target[_]]) case class Results(values: Seq[Any], evaluated: OSet[Target[_]]) - def groupAroundNamedTargets(topoSortedTargets: TopoSorted): OSet[OSet[Target[_]]] = { + def groupAroundNamedTargets(topoSortedTargets: TopoSorted, + labeling: Map[Target[_], Seq[String]]): OSet[OSet[Target[_]]] = { val grouping = new MultiBiMap[Int, Target[_]]() var groupCount = 0 @@ -120,7 +123,7 @@ object Evaluator{ val targetGroup = grouping.lookupValue(target) for(upstream <- target.inputs){ grouping.lookupValueOpt(upstream) match{ - case None if upstream.defCtx.anonId.nonEmpty => + case None if !labeling.contains(upstream) => grouping.add(targetGroup, upstream) case Some(upstreamGroup) if upstreamGroup == targetGroup => val upstreamTargets = grouping.removeAll(upstreamGroup) diff --git a/src/main/scala/forge/Target.scala b/src/main/scala/forge/Target.scala index 6f434030..8966a729 100644 --- a/src/main/scala/forge/Target.scala +++ b/src/main/scala/forge/Target.scala @@ -5,10 +5,6 @@ import java.nio.{file => jnio} import play.api.libs.json.{Format, Json} abstract class Target[T](implicit formatter: Format[T]) extends Target.Ops[T]{ /** - * Where in the Scala codebase was this target defined? - */ - val defCtx: DefCtx - /** * What other Targets does this Target depend on? */ val inputs: Seq[Target[_]] @@ -33,22 +29,19 @@ object Target{ val str = formatter.writes(res) (res, Json.stringify(str)) } - val defCtx: DefCtx - def map[V: Format](f: T => V)(implicit defCtx: DefCtx) = { - new Target.Mapped(this, f, defCtx) + def map[V: Format](f: T => V) = { + new Target.Mapped(this, f) } - def zip[V: Format](other: Target[V])(implicit defCtx: DefCtx) = { - new Target.Zipped(this, other, defCtx) + def zip[V: Format](other: Target[V]) = { + new Target.Zipped(this, other) } def ~[V: Format, R: Format](other: Target[V]) - (implicit s: Implicits.Sequencer[T, V, R], defCtx: DefCtx): Target[R] = { + (implicit s: Implicits.Sequencer[T, V, R]): Target[R] = { this.zip(other).map(s.apply _ tupled) } - - override def toString = defCtx.label.split('.').last } - def test(inputs: Target[Int]*)(implicit defCtx: DefCtx) = { - new Test(inputs, defCtx, pure = inputs.nonEmpty) + def test(inputs: Target[Int]*) = { + new Test(inputs, pure = inputs.nonEmpty) } /** @@ -57,7 +50,6 @@ object Target{ * test how changes propagate. */ class Test(val inputs: Seq[Target[Int]], - val defCtx: DefCtx, val pure: Boolean) extends Target[Int]{ var counter = 0 var lastCounter = counter @@ -67,36 +59,33 @@ object Target{ } override def dirty = lastCounter != counter } - def traverse[T: Format](source: Seq[Target[T]])(implicit defCtx: DefCtx) = { - new Traverse[T](source, defCtx) + def traverse[T: Format](source: Seq[Target[T]]) = { + new Traverse[T](source) } - class Traverse[T: Format](val inputs: Seq[Target[T]], val defCtx: DefCtx) extends Target[Seq[T]]{ + class Traverse[T: Format](val inputs: Seq[Target[T]]) extends Target[Seq[T]]{ def evaluate(args: Args) = { for (i <- 0 until args.length) yield args(i).asInstanceOf[T] } } - class Mapped[T, V: Format](source: Target[T], f: T => V, - val defCtx: DefCtx) extends Target[V]{ + class Mapped[T, V: Format](source: Target[T], f: T => V) extends Target[V]{ def evaluate(args: Args) = f(args(0)) val inputs = List(source) } class Zipped[T: Format, V: Format](source1: Target[T], - source2: Target[V], - val defCtx: DefCtx) extends Target[(T, V)]{ + source2: Target[V]) extends Target[(T, V)]{ def evaluate(args: Args) = (args(0), args(0)) val inputs = List(source1, source1) } - def path(path: jnio.Path)(implicit defCtx: DefCtx) = new Path(path, defCtx) - class Path(path: jnio.Path, val defCtx: DefCtx) extends Target[jnio.Path]{ + def path(path: jnio.Path) = new Path(path) + class Path(path: jnio.Path) extends Target[jnio.Path]{ def evaluate(args: Args) = path val inputs = Nil } class Subprocess(val inputs: Seq[Target[_]], - command: Args => Seq[String], - val defCtx: DefCtx) extends Target[Subprocess.Result] { + command: Args => Seq[String]) extends Target[Subprocess.Result] { def evaluate(args: Args) = { jnio.Files.createDirectories(args.dest) |