summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLi Haoyi <haoyi.sg@gmail.com>2017-11-09 22:36:47 -0800
committerLi Haoyi <haoyi.sg@gmail.com>2017-11-09 22:36:47 -0800
commit550772d7515757339269c28c41fd0d8109e0fa2c (patch)
tree13ed3c93b85788dadbcd938930ed05ebc460f646
parentc7ab7da7ccd21c63740f6494811a09722a0d2ce0 (diff)
downloadmill-550772d7515757339269c28c41fd0d8109e0fa2c.tar.gz
mill-550772d7515757339269c28c41fd0d8109e0fa2c.tar.bz2
mill-550772d7515757339269c28c41fd0d8109e0fa2c.zip
Migrate over to the new `Task`/`Target`/`Command` split
-rw-r--r--core/src/main/scala/forge/Main.scala4
-rw-r--r--core/src/main/scala/forge/define/Cacher.scala29
-rw-r--r--core/src/main/scala/forge/define/Target.scala119
-rw-r--r--core/src/main/scala/forge/define/Task.scala134
-rw-r--r--core/src/main/scala/forge/discover/Discovered.scala18
-rw-r--r--core/src/main/scala/forge/discover/Router.scala6
-rw-r--r--core/src/main/scala/forge/eval/Evaluator.scala48
-rw-r--r--core/src/main/scala/forge/modules/Jvm.scala4
-rw-r--r--core/src/main/scala/forge/package.scala4
-rw-r--r--core/src/test/examples/javac/build.sc14
-rw-r--r--core/src/test/scala/forge/CacherTests.scala6
-rw-r--r--core/src/test/scala/forge/EvaluationTests.scala6
-rw-r--r--core/src/test/scala/forge/GraphTests.scala35
-rw-r--r--core/src/test/scala/forge/JavaCompileJarTests.scala21
-rw-r--r--core/src/test/scala/forge/MacroErrorTests.scala42
-rw-r--r--core/src/test/scala/forge/TestGraphs.scala8
-rw-r--r--core/src/test/scala/forge/TestUtil.scala12
-rw-r--r--scalaplugin/src/main/scala/forge/scalaplugin/Subproject.scala13
18 files changed, 271 insertions, 252 deletions
diff --git a/core/src/main/scala/forge/Main.scala b/core/src/main/scala/forge/Main.scala
index e66f5fd8..bb1d5d69 100644
--- a/core/src/main/scala/forge/Main.scala
+++ b/core/src/main/scala/forge/Main.scala
@@ -2,7 +2,7 @@ package forge
import ammonite.ops._
import ammonite.util.{Name, Res}
-import forge.define.Target
+import forge.define.Task
import forge.discover.{Discovered, NestedEntry}
import forge.eval.Evaluator
import forge.util.OSet
@@ -35,7 +35,7 @@ object Main {
val targetRoutes = discovered.targets.map(x => x._1 -> Right(x))
val allRoutes = (mainRoutes ++ targetRoutes).toMap[
Seq[String],
- Either[NestedEntry[Any, _], (Seq[String], Format[_], Any => Target[_])]
+ Either[NestedEntry[Any, _], (Seq[String], Format[_], Any => Task[_])]
]
allRoutes.get(selector) match{
case Some(Left(nestedEntryPoint)) =>
diff --git a/core/src/main/scala/forge/define/Cacher.scala b/core/src/main/scala/forge/define/Cacher.scala
index 8d4d836c..56eeb892 100644
--- a/core/src/main/scala/forge/define/Cacher.scala
+++ b/core/src/main/scala/forge/define/Cacher.scala
@@ -4,32 +4,29 @@ import scala.collection.mutable
import scala.reflect.macros.blackbox.Context
-trait Cacher[C]{
- private[this] val cacherLazyMap = mutable.Map.empty[sourcecode.Enclosing, C]
- protected[this] def cachedTarget[T <: C](t: => T)
- (implicit c: sourcecode.Enclosing): T = synchronized{
- cacherLazyMap.getOrElseUpdate(c, t).asInstanceOf[T]
+trait Cacher[C[_], V[_]]{
+ private[this] val cacherLazyMap = mutable.Map.empty[sourcecode.Enclosing, V[_]]
+ def wrapCached[T](in: C[T]): V[T]
+ protected[this] def cachedTarget[T](t: => C[T])
+ (implicit c: sourcecode.Enclosing): V[T] = synchronized{
+ cacherLazyMap.getOrElseUpdate(c, wrapCached(t)).asInstanceOf[V[T]]
}
}
object Cacher{
def impl0[M[_], T: c.WeakTypeTag](c: Context)(t: c.Expr[M[T]]): c.Expr[M[T]] = {
- wrapCached(c)(t)
+ c.Expr[M[T]](wrapCached(c)(t.tree))
}
- def wrapCached[M[_], T](c: Context)(t: c.Expr[M[T]]) = {
+ def wrapCached(c: Context)(t: c.Tree) = {
import c.universe._
val owner = c.internal.enclosingOwner
val ownerIsCacherClass =
owner.owner.isClass &&
owner.owner.asClass.baseClasses.exists(_.fullName == "forge.define.Cacher")
- if (ownerIsCacherClass && !owner.isMethod){
- c.abort(
- c.enclosingPosition,
- "T{} members defined in a Cacher class/trait/object body must be defs"
- )
- }else{
- if (!ownerIsCacherClass) t
- else c.Expr[M[T]](q"this.cachedTarget($t)")
- }
+ if (ownerIsCacherClass && owner.isMethod) q"this.cachedTarget($t)"
+ else c.abort(
+ c.enclosingPosition,
+ "T{} members must be defs defined in a Cacher class/trait/object body"
+ )
}
} \ No newline at end of file
diff --git a/core/src/main/scala/forge/define/Target.scala b/core/src/main/scala/forge/define/Target.scala
deleted file mode 100644
index b98d3902..00000000
--- a/core/src/main/scala/forge/define/Target.scala
+++ /dev/null
@@ -1,119 +0,0 @@
-package forge.define
-
-import ammonite.ops.{CommandResult, mkdir}
-import forge.define.Applicative.Applyable
-import forge.eval.PathRef
-import forge.util.{Args, JsonFormatters}
-import play.api.libs.json.{Format, Json}
-
-import scala.annotation.compileTimeOnly
-import scala.language.experimental.macros
-import scala.reflect.macros.blackbox.Context
-
-abstract class Target[+T] extends Target.Ops[T] with Applyable[T]{
- /**
- * What other Targets does this Target depend on?
- */
- val inputs: Seq[Target[_]]
-
- /**
- * Evaluate this target
- */
- def evaluate(args: Args): T
-
- /**
- * Even if this target's inputs did not change, does it need to re-evaluate
- * anyway?
- */
- def sideHash: Int = 0
-}
-
-
-object Target extends Applicative.Applyer[Target, Target, Args]{
- def underlying[A](v: Target[A]) = v
-
- type Cacher = forge.define.Cacher[Target[_]]
- class Target0[T](t: T) extends Target[T]{
- lazy val t0 = t
- val inputs = Nil
- def evaluate(args: Args) = t0
- }
- def apply[T](t: Target[T]): Target[T] = macro forge.define.Cacher.impl0[Target, T]
- def command[T](t: T): Target[T] = macro Applicative.impl[Target, T, Args]
- def apply[T](t: T): Target[T] = macro impl[Target, T, Args]
- def impl[M[_], T: c.WeakTypeTag, Ctx: c.WeakTypeTag]
- (c: Context)
- (t: c.Expr[T])
- (implicit tt: c.WeakTypeTag[M[_]]): c.Expr[M[T]] = {
- forge.define.Cacher.wrapCached[M, T](c)(
- Applicative.impl[M, T, Ctx](c)(t)
- )
- }
-
- abstract class Ops[+T]{ this: Target[T] =>
- def map[V](f: T => V) = new Target.Mapped(this, f)
- def mapDest[V](f: (T, Args) => V) = new Target.MappedDest(this, f)
-
- def filter(f: T => Boolean) = this
- def withFilter(f: T => Boolean) = this
- def zip[V](other: Target[V]) = new Target.Zipped(this, other)
-
- }
-
- def traverse[T](source: Seq[Target[T]]) = {
- new Traverse[T](source)
- }
- class Traverse[+T](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](source: Target[T], f: T => V) extends Target[V]{
- def evaluate(args: Args) = f(args(0))
- val inputs = List(source)
- }
- class MappedDest[+T, +V](source: Target[T], f: (T, Args) => V) extends Target[V]{
- def evaluate(args: Args) = f(args(0), args)
- val inputs = List(source)
- }
- class Zipped[+T, +V](source1: Target[T], source2: Target[V]) extends Target[(T, V)]{
- def evaluate(args: Args) = (args(0), args(1))
- val inputs = List(source1, source2)
- }
-
- def path(path: ammonite.ops.Path) = new Path(path)
- class Path(path: ammonite.ops.Path) extends Target[PathRef]{
- def handle = PathRef(path)
- def evaluate(args: Args) = handle
- override def sideHash = handle.hashCode()
- val inputs = Nil
- }
-
-
- def mapCtx[A, B](t: Target[A])(f: (A, Args) => B) = t.mapDest(f)
- def zip() = new Target.Target0(())
- def zip[A](a: Target[A]) = a.map(Tuple1(_))
- def zip[A, B](a: Target[A], b: Target[B]) = a.zip(b)
- def zip[A, B, C](a: Target[A], b: Target[B], c: Target[C]) = new Target[(A, B, C)]{
- val inputs = Seq(a, b, c)
- def evaluate(args: Args) = (args[A](0), args[B](1), args[C](2))
- }
- def zip[A, B, C, D](a: Target[A], b: Target[B], c: Target[C], d: Target[D]) = new Target[(A, B, C, D)]{
- val inputs = Seq(a, b, c, d)
- def evaluate(args: Args) = (args[A](0), args[B](1), args[C](2), args[D](3))
- }
- def zip[A, B, C, D, E](a: Target[A], b: Target[B], c: Target[C], d: Target[D], e: Target[E]) = new Target[(A, B, C, D, E)]{
- val inputs = Seq(a, b, c, d, e)
- def evaluate(args: Args) = (args[A](0), args[B](1), args[C](2), args[D](3), args[E](4))
- }
- def zip[A, B, C, D, E, F](a: Target[A], b: Target[B], c: Target[C], d: Target[D], e: Target[E], f: Target[F]) = new Target[(A, B, C, D, E, F)]{
- val inputs = Seq(a, b, c, d, e, f)
- def evaluate(args: Args) = (args[A](0), args[B](1), args[C](2), args[D](3), args[E](4), args[F](5))
- }
- def zip[A, B, C, D, E, F, G](a: Target[A], b: Target[B], c: Target[C], d: Target[D], e: Target[E], f: Target[F], g: Target[G]) = new Target[(A, B, C, D, E, F, G)]{
- val inputs = Seq(a, b, c, d, e, f, g)
- def evaluate(args: Args) = (args[A](0), args[B](1), args[C](2), args[D](3), args[E](4), args[F](5), args[G](6))
- }
-}
diff --git a/core/src/main/scala/forge/define/Task.scala b/core/src/main/scala/forge/define/Task.scala
new file mode 100644
index 00000000..a78fcaa7
--- /dev/null
+++ b/core/src/main/scala/forge/define/Task.scala
@@ -0,0 +1,134 @@
+package forge.define
+
+import forge.define.Applicative.Applyable
+import forge.eval.PathRef
+import forge.util.Args
+import scala.language.experimental.macros
+import scala.reflect.macros.blackbox.Context
+
+abstract class Task[+T] extends Task.Ops[T] with Applyable[T]{
+ /**
+ * What other Targets does this Target depend on?
+ */
+ val inputs: Seq[Task[_]]
+
+ /**
+ * Evaluate this target
+ */
+ def evaluate(args: Args): T
+
+ /**
+ * Even if this target's inputs did not change, does it need to re-evaluate
+ * anyway?
+ */
+ def sideHash: Int = 0
+}
+
+class Target[+T](t: Task[T]) extends Task[T] {
+ val inputs = Seq(t)
+ def evaluate(args: Args) = args[T](0)
+}
+class Command[+T](t: Task[T]) extends Task[T] {
+ val inputs = Seq(t)
+ def evaluate(args: Args) = args[T](0)
+}
+object Task extends Applicative.Applyer[Task, Task, Args]{
+
+ def underlying[A](v: Task[A]) = v
+
+ trait Cacher extends forge.define.Cacher[Task, Target]{
+ def wrapCached[T](t: Task[T]): Target[T] = new Target(t)
+ }
+ class Target0[T](t: T) extends Task[T]{
+ lazy val t0 = t
+ val inputs = Nil
+ def evaluate(args: Args) = t0
+ }
+ def apply[T](t: Task[T]): Target[T] = macro Cacher.impl0[Task, T]
+
+ def cmd[T](t: T): Command[T] = macro targetCommandImpl[T]
+ def targetCommandImpl[T: c.WeakTypeTag](c: Context)(t: c.Expr[T]): c.Expr[Command[T]] = {
+ import c.universe._
+ c.Expr[Command[T]](
+ q"new forge.define.Command(${Applicative.impl[Task, T, Args](c)(t).tree})"
+ )
+ }
+ def task[T](t: T): Task[T] = macro Applicative.impl[Task, T, Args]
+
+ def apply[T](t: T): Target[T] = macro targetCachedImpl[T]
+
+ def targetCachedImpl[T: c.WeakTypeTag](c: Context)(t: c.Expr[T]): c.Expr[Target[T]] = {
+ c.Expr[Target[T]](
+ forge.define.Cacher.wrapCached(c)(
+ Applicative.impl[Task, T, Args](c)(t).tree
+ )
+ )
+ }
+
+ abstract class Ops[+T]{ this: Task[T] =>
+ def map[V](f: T => V) = new Task.Mapped(this, f)
+ def mapDest[V](f: (T, Args) => V) = new Task.MappedDest(this, f)
+
+ def filter(f: T => Boolean) = this
+ def withFilter(f: T => Boolean) = this
+ def zip[V](other: Task[V]) = new Task.Zipped(this, other)
+
+ }
+
+ def traverse[T](source: Seq[Task[T]]) = {
+ new Traverse[T](source)
+ }
+ class Traverse[+T](val inputs: Seq[Task[T]]) extends Task[Seq[T]]{
+ def evaluate(args: Args) = {
+ for (i <- 0 until args.length)
+ yield args(i).asInstanceOf[T]
+ }
+
+ }
+ class Mapped[+T, +V](source: Task[T], f: T => V) extends Task[V]{
+ def evaluate(args: Args) = f(args(0))
+ val inputs = List(source)
+ }
+ class MappedDest[+T, +V](source: Task[T], f: (T, Args) => V) extends Task[V]{
+ def evaluate(args: Args) = f(args(0), args)
+ val inputs = List(source)
+ }
+ class Zipped[+T, +V](source1: Task[T], source2: Task[V]) extends Task[(T, V)]{
+ def evaluate(args: Args) = (args(0), args(1))
+ val inputs = List(source1, source2)
+ }
+
+ def path(path: ammonite.ops.Path) = new Path(path)
+ class Path(path: ammonite.ops.Path) extends Task[PathRef]{
+ def handle = PathRef(path)
+ def evaluate(args: Args) = handle
+ override def sideHash = handle.hashCode()
+ val inputs = Nil
+ }
+
+
+ def mapCtx[A, B](t: Task[A])(f: (A, Args) => B) = t.mapDest(f)
+ def zip() = new Task.Target0(())
+ def zip[A](a: Task[A]) = a.map(Tuple1(_))
+ def zip[A, B](a: Task[A], b: Task[B]) = a.zip(b)
+ def zip[A, B, C](a: Task[A], b: Task[B], c: Task[C]) = new Task[(A, B, C)]{
+ val inputs = Seq(a, b, c)
+ def evaluate(args: Args) = (args[A](0), args[B](1), args[C](2))
+ }
+ def zip[A, B, C, D](a: Task[A], b: Task[B], c: Task[C], d: Task[D]) = new Task[(A, B, C, D)]{
+ val inputs = Seq(a, b, c, d)
+ def evaluate(args: Args) = (args[A](0), args[B](1), args[C](2), args[D](3))
+ }
+ def zip[A, B, C, D, E](a: Task[A], b: Task[B], c: Task[C], d: Task[D], e: Task[E]) = new Task[(A, B, C, D, E)]{
+ val inputs = Seq(a, b, c, d, e)
+ def evaluate(args: Args) = (args[A](0), args[B](1), args[C](2), args[D](3), args[E](4))
+ }
+ def zip[A, B, C, D, E, F](a: Task[A], b: Task[B], c: Task[C], d: Task[D], e: Task[E], f: Task[F]) = new Task[(A, B, C, D, E, F)]{
+ val inputs = Seq(a, b, c, d, e, f)
+ def evaluate(args: Args) = (args[A](0), args[B](1), args[C](2), args[D](3), args[E](4), args[F](5))
+ }
+ def zip[A, B, C, D, E, F, G](a: Task[A], b: Task[B], c: Task[C], d: Task[D], e: Task[E], f: Task[F], g: Task[G]) = new Task[(A, B, C, D, E, F, G)]{
+ val inputs = Seq(a, b, c, d, e, f, g)
+ def evaluate(args: Args) = (args[A](0), args[B](1), args[C](2), args[D](3), args[E](4), args[F](5), args[G](6))
+ }
+}
diff --git a/core/src/main/scala/forge/discover/Discovered.scala b/core/src/main/scala/forge/discover/Discovered.scala
index 3b08f7f7..53536e49 100644
--- a/core/src/main/scala/forge/discover/Discovered.scala
+++ b/core/src/main/scala/forge/discover/Discovered.scala
@@ -1,24 +1,24 @@
package forge.discover
-import forge.define.Target
+import forge.define.Task
import forge.discover.Router.{EntryPoint, Result}
import play.api.libs.json.Format
import scala.language.experimental.macros
import scala.reflect.macros.blackbox.Context
-class Discovered[T](val targets: Seq[(Seq[String], Format[_], T => Target[_])],
+class Discovered[T](val targets: Seq[(Seq[String], Format[_], T => Task[_])],
val mains: Seq[NestedEntry[T, _]]){
def apply(t: T) = targets.map{case (a, f, b) => (a, f, b(t)) }
}
-case class Labelled[T](target: Target[T],
+case class Labelled[T](target: Task[T],
format: Format[T],
segments: Seq[String])
case class NestedEntry[T, V](path: Seq[String], resolve: T => V, entryPoint: EntryPoint[V]){
- def invoke(target: T, groupedArgs: Seq[(String, Option[String])]): Result[Target[Any]] = {
+ def invoke(target: T, groupedArgs: Seq[(String, Option[String])]): Result[Task[Any]] = {
entryPoint.invoke(resolve(target),groupedArgs)
}
}
@@ -34,14 +34,14 @@ object Discovered {
} yield path
inconsistent
}
- def makeTuple[T, V](path: Seq[String], func: T => Target[V])(implicit f: Format[V]) = {
+ def makeTuple[T, V](path: Seq[String], func: T => Task[V])(implicit f: Format[V]) = {
(path, f, func)
}
- def mapping[T: Discovered](t: T): Map[Target[_], Labelled[_]] = {
+ def mapping[T: Discovered](t: T): Map[Task[_], Labelled[_]] = {
implicitly[Discovered[T]].apply(t)
- .map(x => x._3 -> Labelled(x._3.asInstanceOf[Target[Any]], x._2.asInstanceOf[Format[Any]], x._1))
+ .map(x => x._3 -> Labelled(x._3.asInstanceOf[Task[Any]], x._2.asInstanceOf[Format[Any]], x._1))
.toMap
}
@@ -62,12 +62,12 @@ object Discovered {
if
(m.isTerm && (m.asTerm.isGetter || m.asTerm.isLazy)) ||
m.isModule ||
- (m.isMethod && m.typeSignature.paramLists.isEmpty && m.typeSignature.resultType <:< c.weakTypeOf[Target[_]])
+ (m.isMethod && m.typeSignature.paramLists.isEmpty && m.typeSignature.resultType <:< c.weakTypeOf[Task[_]])
if !m.name.toString.contains('$')
} yield {
val extendedSegments = m.name.toString :: segments
val self =
- if (m.typeSignature.resultType <:< c.weakTypeOf[Target[_]]) Seq(extendedSegments)
+ if (m.typeSignature.resultType <:< c.weakTypeOf[Task[_]]) Seq(extendedSegments)
else Nil
val (mains, children) = rec(extendedSegments, m.typeSignature)
diff --git a/core/src/main/scala/forge/discover/Router.scala b/core/src/main/scala/forge/discover/Router.scala
index afb526c7..2c92d847 100644
--- a/core/src/main/scala/forge/discover/Router.scala
+++ b/core/src/main/scala/forge/discover/Router.scala
@@ -1,7 +1,7 @@
package forge.discover
import ammonite.main.Compat
-import forge.define.Target
+import forge.define.Task
import sourcecode.Compat.Context
import scala.annotation.StaticAnnotation
@@ -57,8 +57,8 @@ object Router{
argSignatures: Seq[ArgSig[T]],
doc: Option[String],
varargs: Boolean,
- invoke0: (T, Map[String, String], Seq[String]) => Result[Target[Any]]){
- def invoke(target: T, groupedArgs: Seq[(String, Option[String])]): Result[Target[Any]] = {
+ invoke0: (T, Map[String, String], Seq[String]) => Result[Task[Any]]){
+ def invoke(target: T, groupedArgs: Seq[(String, Option[String])]): Result[Task[Any]] = {
var remainingArgSignatures = argSignatures.toList
diff --git a/core/src/main/scala/forge/eval/Evaluator.scala b/core/src/main/scala/forge/eval/Evaluator.scala
index 6f2d43f0..7f50873a 100644
--- a/core/src/main/scala/forge/eval/Evaluator.scala
+++ b/core/src/main/scala/forge/eval/Evaluator.scala
@@ -1,16 +1,16 @@
package forge.eval
import ammonite.ops._
-import forge.define.Target
+import forge.define.Task
import forge.discover.Labelled
import forge.util.{Args, MultiBiMap, OSet}
import play.api.libs.json.{Format, JsValue, Json}
import scala.collection.mutable
class Evaluator(workspacePath: Path,
- labeling: Map[Target[_], Labelled[_]]){
+ labeling: Map[Task[_], Labelled[_]]){
- def evaluate(targets: OSet[Target[_]]): Evaluator.Results = {
+ def evaluate(targets: OSet[Task[_]]): Evaluator.Results = {
mkdir(workspacePath)
val sortedGroups = Evaluator.groupAroundNamedTargets(
@@ -18,8 +18,8 @@ class Evaluator(workspacePath: Path,
labeling
)
- val evaluated = new OSet.Mutable[Target[_]]
- val results = mutable.LinkedHashMap.empty[Target[_], Any]
+ val evaluated = new OSet.Mutable[Task[_]]
+ val results = mutable.LinkedHashMap.empty[Task[_], Any]
for (groupIndex <- sortedGroups.keys()){
val group = sortedGroups.lookupKey(groupIndex)
@@ -37,9 +37,9 @@ class Evaluator(workspacePath: Path,
Evaluator.Results(targets.items.map(results), evaluated)
}
- def evaluateGroupCached(group: OSet[Target[_]],
- results: collection.Map[Target[_], Any],
- sortedGroups: MultiBiMap[Int, Target[_]]): (collection.Map[Target[_], Any], Seq[Target[_]]) = {
+ def evaluateGroupCached(group: OSet[Task[_]],
+ results: collection.Map[Task[_], Any],
+ sortedGroups: MultiBiMap[Int, Task[_]]): (collection.Map[Task[_], Any], Seq[Task[_]]) = {
val (externalInputs, terminals) = partitionGroupInputOutput(group, results)
@@ -65,7 +65,7 @@ class Evaluator(workspacePath: Path,
cached match{
case Some(terminalResults) =>
- val newResults = mutable.LinkedHashMap.empty[Target[_], Any]
+ val newResults = mutable.LinkedHashMap.empty[Task[_], Any]
for((terminal, res) <- terminals.items.zip(terminalResults)){
newResults(terminal) = labeling(terminal).format.reads(res).get
}
@@ -87,8 +87,8 @@ class Evaluator(workspacePath: Path,
}
}
- def partitionGroupInputOutput(group: OSet[Target[_]],
- results: collection.Map[Target[_], Any]) = {
+ def partitionGroupInputOutput(group: OSet[Task[_]],
+ results: collection.Map[Task[_], Any]) = {
val allInputs = group.items.flatMap(_.inputs)
val (internalInputs, externalInputs) = allInputs.partition(group.contains)
val internalInputSet = internalInputs.toSet
@@ -96,14 +96,14 @@ class Evaluator(workspacePath: Path,
(OSet.from(externalInputs.distinct), terminals)
}
- def evaluateGroup(group: OSet[Target[_]],
- results: collection.Map[Target[_], Any],
+ def evaluateGroup(group: OSet[Task[_]],
+ results: collection.Map[Task[_], Any],
targetDestPath: Option[Path]) = {
targetDestPath.foreach(rm)
- val terminalResults = mutable.LinkedHashMap.empty[Target[_], JsValue]
- val newEvaluated = mutable.Buffer.empty[Target[_]]
- val newResults = mutable.LinkedHashMap.empty[Target[_], Any]
+ val terminalResults = mutable.LinkedHashMap.empty[Task[_], JsValue]
+ val newEvaluated = mutable.Buffer.empty[Task[_]]
+ val newResults = mutable.LinkedHashMap.empty[Task[_], Any]
for (target <- group.items) {
newEvaluated.append(target)
val targetInputValues = target.inputs.toVector.map(x =>
@@ -129,12 +129,12 @@ class Evaluator(workspacePath: Path,
object Evaluator{
- class TopoSorted private[Evaluator] (val values: OSet[Target[_]])
- case class Results(values: Seq[Any], targets: OSet[Target[_]])
+ class TopoSorted private[Evaluator] (val values: OSet[Task[_]])
+ case class Results(values: Seq[Any], targets: OSet[Task[_]])
def groupAroundNamedTargets(topoSortedTargets: TopoSorted,
- labeling: Map[Target[_], Labelled[_]]): MultiBiMap[Int, Target[_]] = {
+ labeling: Map[Task[_], Labelled[_]]): MultiBiMap[Int, Task[_]] = {
- val grouping = new MultiBiMap.Mutable[Int, Target[_]]()
+ val grouping = new MultiBiMap.Mutable[Int, Task[_]]()
var groupCount = 0
@@ -159,7 +159,7 @@ object Evaluator{
}
val targetOrdering = topoSortedTargets.values.items.zipWithIndex.toMap
- val output = new MultiBiMap.Mutable[Int, Target[_]]
+ val output = new MultiBiMap.Mutable[Int, Task[_]]
// Sort groups amongst themselves, and sort the contents of each group
// before aggregating it into the final output
@@ -173,9 +173,9 @@ object Evaluator{
* Takes the given targets, finds all the targets they transitively depend
* on, and sort them topologically. Fails if there are dependency cycles
*/
- def topoSortedTransitiveTargets(sourceTargets: OSet[Target[_]]): TopoSorted = {
- val transitiveTargets = new OSet.Mutable[Target[_]]
- def rec(t: Target[_]): Unit = {
+ def topoSortedTransitiveTargets(sourceTargets: OSet[Task[_]]): TopoSorted = {
+ val transitiveTargets = new OSet.Mutable[Task[_]]
+ def rec(t: Task[_]): Unit = {
if (transitiveTargets.contains(t)) () // do nothing
else {
transitiveTargets.append(t)
diff --git a/core/src/main/scala/forge/modules/Jvm.scala b/core/src/main/scala/forge/modules/Jvm.scala
index 79a2c989..e707df29 100644
--- a/core/src/main/scala/forge/modules/Jvm.scala
+++ b/core/src/main/scala/forge/modules/Jvm.scala
@@ -4,7 +4,7 @@ import java.io.FileOutputStream
import java.util.jar.{JarEntry, JarOutputStream}
import ammonite.ops._
-import forge.define.Target
+import forge.define.Task
import forge.eval.PathRef
import forge.util.Args
@@ -59,7 +59,7 @@ object Jvm {
Some(outputPath)
}
}
- case class jarUp(roots: Target[PathRef]*) extends Target[PathRef]{
+ case class jarUp(roots: Task[PathRef]*) extends Task[PathRef]{
val inputs = roots
def evaluate(args: Args): PathRef = {
diff --git a/core/src/main/scala/forge/package.scala b/core/src/main/scala/forge/package.scala
index 48f5132a..6484c48e 100644
--- a/core/src/main/scala/forge/package.scala
+++ b/core/src/main/scala/forge/package.scala
@@ -1,6 +1,6 @@
import forge.util.JsonFormatters
package object forge extends JsonFormatters{
- val T = define.Target
- type T[T] = define.Target[T]
+ val T = define.Task
+ type T[T] = define.Task[T]
}
diff --git a/core/src/test/examples/javac/build.sc b/core/src/test/examples/javac/build.sc
index d7ba5662..37d7a5a6 100644
--- a/core/src/test/examples/javac/build.sc
+++ b/core/src/test/examples/javac/build.sc
@@ -1,4 +1,4 @@
-import forge.define.Target
+import forge.define.Task
import forge.eval.PathRef
object Foo {
@@ -21,14 +21,14 @@ object Foo {
// |
// v
// resourceRoot ----> jar
- val sourceRoot = Target.path(sourceRootPath)
- val resourceRoot = Target.path(resourceRootPath)
+ val sourceRoot = Task.path(sourceRootPath)
+ val resourceRoot = Task.path(resourceRootPath)
val allSources = list(sourceRoot)
val classFiles = compileAll(allSources)
val jar = jarUp(resourceRoot, classFiles)
- def compileAll(sources: Target[Seq[PathRef]]) = {
- new Target.Subprocess(
+ def compileAll(sources: Task[Seq[PathRef]]) = {
+ new Task.Subprocess(
Seq(sources),
args =>
Seq("javac") ++
@@ -37,11 +37,11 @@ object Foo {
).map(_.dest)
}
- def list(root: Target[PathRef]): Target[Seq[PathRef]] = {
+ def list(root: Task[PathRef]): Task[Seq[PathRef]] = {
root.map(x => ls.rec(x.path).map(PathRef(_)))
}
- case class jarUp(roots: Target[PathRef]*) extends Target[PathRef] {
+ case class jarUp(roots: Task[PathRef]*) extends Task[PathRef] {
val inputs = roots
diff --git a/core/src/test/scala/forge/CacherTests.scala b/core/src/test/scala/forge/CacherTests.scala
index 24a540ff..5f40ee20 100644
--- a/core/src/test/scala/forge/CacherTests.scala
+++ b/core/src/test/scala/forge/CacherTests.scala
@@ -1,6 +1,6 @@
package forge
-import forge.define.Target
+import forge.define.Task
import forge.discover.Discovered
import forge.eval.Evaluator
import forge.util.OSet
@@ -9,7 +9,7 @@ import utest.framework.TestPath
object CacherTests extends TestSuite{
object Base extends Base
- trait Base extends Target.Cacher{
+ trait Base extends Task.Cacher{
def value = T{ 1 }
}
object Middle extends Middle
@@ -25,7 +25,7 @@ object CacherTests extends TestSuite{
val tests = Tests{
- def eval[T: Discovered, V](base: T, v: Target[V])(implicit tp: TestPath) = {
+ def eval[T: Discovered, V](base: T, v: Task[V])(implicit tp: TestPath) = {
val workspace = ammonite.ops.pwd / 'target / 'workspace / tp.value
val evaluator = new Evaluator(workspace, Discovered.mapping(base))
evaluator.evaluate(OSet(v)).values(0)
diff --git a/core/src/test/scala/forge/EvaluationTests.scala b/core/src/test/scala/forge/EvaluationTests.scala
index 66fe7b8d..72b7deff 100644
--- a/core/src/test/scala/forge/EvaluationTests.scala
+++ b/core/src/test/scala/forge/EvaluationTests.scala
@@ -1,7 +1,7 @@
package forge
-import forge.define.Target
+import forge.define.Task
import forge.discover.Discovered
import forge.eval.Evaluator
import forge.util.OSet
@@ -24,8 +24,8 @@ object EvaluationTests extends TestSuite{
Discovered.mapping(base)
)
- def apply(target: Target[_], expValue: Any,
- expEvaled: OSet[Target[_]],
+ def apply(target: Task[_], expValue: Any,
+ expEvaled: OSet[Task[_]],
extraEvaled: Int = 0) = {
val Evaluator.Results(returnedValues, returnedEvaluated) = evaluator.evaluate(OSet(target))
diff --git a/core/src/test/scala/forge/GraphTests.scala b/core/src/test/scala/forge/GraphTests.scala
index 1b542882..db522fff 100644
--- a/core/src/test/scala/forge/GraphTests.scala
+++ b/core/src/test/scala/forge/GraphTests.scala
@@ -2,7 +2,7 @@ package forge
import utest._
import TestUtil.test
-import forge.define.Target
+import forge.define.Task
import forge.discover.Discovered
import forge.eval.Evaluator
import forge.util.OSet
@@ -64,14 +64,7 @@ object GraphTests extends TestSuite{
assert(inconsistent == Nil)
}
- 'borkedCachedDiamond1 - {
- val inconsistent = Discovered.consistencyCheck(
- borkedCachedDiamond1,
- Discovered[borkedCachedDiamond1.type]
- )
- assert(inconsistent == expected)
- }
'borkedCachedDiamond2 - {
val inconsistent = Discovered.consistencyCheck(
borkedCachedDiamond2,
@@ -90,7 +83,7 @@ object GraphTests extends TestSuite{
'topoSortedTransitiveTargets - {
- def check(targets: OSet[Target[_]], expected: OSet[Target[_]]) = {
+ def check(targets: OSet[Task[_]], expected: OSet[Task[_]]) = {
val result = Evaluator.topoSortedTransitiveTargets(targets).values
TestUtil.checkTopological(result)
assert(result == expected)
@@ -124,9 +117,13 @@ object GraphTests extends TestSuite{
'defCachedDiamond - check(
targets = OSet(defCachedDiamond.down),
expected = OSet(
+ defCachedDiamond.up.inputs(0),
defCachedDiamond.up,
+ defCachedDiamond.down.inputs(0).inputs(0).inputs(0),
+ defCachedDiamond.down.inputs(0).inputs(0),
+ defCachedDiamond.down.inputs(0).inputs(1).inputs(0),
+ defCachedDiamond.down.inputs(0).inputs(1),
defCachedDiamond.down.inputs(0),
- defCachedDiamond.down.inputs(1),
defCachedDiamond.down
)
)
@@ -138,9 +135,9 @@ object GraphTests extends TestSuite{
}
'groupAroundNamedTargets - {
- def check[T: Discovered, R <: Target[Int]](base: T,
- target: R,
- expected: OSet[(OSet[R], Int)]) = {
+ def check[T: Discovered, R <: Task[Int]](base: T,
+ target: R,
+ expected: OSet[(OSet[R], Int)]) = {
val mapping = Discovered.mapping(base)
val topoSortedTransitive = Evaluator.topoSortedTransitiveTargets(OSet(target))
@@ -187,10 +184,10 @@ object GraphTests extends TestSuite{
defCachedDiamond,
defCachedDiamond.down,
OSet(
- OSet(defCachedDiamond.up) -> 1,
- OSet(defCachedDiamond.left) -> 1,
- OSet(defCachedDiamond.right) -> 1,
- OSet(defCachedDiamond.down) -> 1
+ OSet(defCachedDiamond.up) -> 2,
+ OSet(defCachedDiamond.left) -> 2,
+ OSet(defCachedDiamond.right) -> 2,
+ OSet(defCachedDiamond.down) -> 2
)
)
@@ -218,10 +215,10 @@ object GraphTests extends TestSuite{
'labeling - {
- def check[T: Discovered](base: T, t: Target[_], relPath: Option[String]) = {
+ def check[T: Discovered](base: T, t: Task[_], relPath: Option[String]) = {
- val names: Seq[(Target[_], Seq[String])] = Discovered.mapping(base).mapValues(_.segments).toSeq
+ val names: Seq[(Task[_], Seq[String])] = Discovered.mapping(base).mapValues(_.segments).toSeq
val nameMap = names.toMap
val targetLabel = nameMap.get(t).map(_.mkString("."))
diff --git a/core/src/test/scala/forge/JavaCompileJarTests.scala b/core/src/test/scala/forge/JavaCompileJarTests.scala
index 4c3ce06c..fcd81588 100644
--- a/core/src/test/scala/forge/JavaCompileJarTests.scala
+++ b/core/src/test/scala/forge/JavaCompileJarTests.scala
@@ -3,7 +3,7 @@ package forge
import ammonite.ops._
import ImplicitWd._
-import forge.define.Target
+import forge.define.Task
import forge.discover.Discovered
import forge.eval.{Evaluator, PathRef}
import forge.modules.Jvm.jarUp
@@ -30,7 +30,7 @@ object JavaCompileJarTests extends TestSuite{
mkdir(pwd / 'target / 'workspace / 'javac)
cp(javacSrcPath, javacDestPath)
- object Build extends Target.Cacher{
+ object Build extends Task.Cacher{
def sourceRootPath = javacDestPath / 'src
def resourceRootPath = javacDestPath / 'resources
@@ -38,26 +38,29 @@ object JavaCompileJarTests extends TestSuite{
// |
// v
// resourceRoot ----> jar
- def sourceRoot = T{ Target.path(sourceRootPath) }
- def resourceRoot = T{ Target.path(resourceRootPath) }
+ def sourceRoot = T{ Task.path(sourceRootPath) }
+ def resourceRoot = T{ Task.path(resourceRootPath) }
def allSources = T{ ls.rec(sourceRoot().path).map(PathRef(_)) }
- def classFiles = T{ compileAll(Target.ctx().dest, allSources()) }
+ def classFiles = T{ compileAll(Task.ctx().dest, allSources()) }
def jar = T{ jarUp(resourceRoot, classFiles) }
@forge.discover.Router.main
- def run(mainClsName: String): Target[CommandResult] = T.command{
+ def run(mainClsName: String): Task[CommandResult] = T.cmd{
%%('java, "-cp", classFiles().path, mainClsName)
}
}
import Build._
val mapping = Discovered.mapping(Build)
- def eval[T](t: Target[T]): (T, Int) = {
+ def eval[T](t: Task[T]): (T, Int) = {
val evaluator = new Evaluator(workspacePath, mapping)
val evaluated = evaluator.evaluate(OSet(t))
- (evaluated.values(0).asInstanceOf[T], evaluated.targets.size)
+ Tuple2(
+ evaluated.values(0).asInstanceOf[T],
+ evaluated.targets.filter(x => mapping.contains(x) || x.isInstanceOf[forge.define.Command[_]]).size
+ )
}
- def check(targets: OSet[Target[_]], expected: OSet[Target[_]]) = {
+ def check(targets: OSet[Task[_]], expected: OSet[Task[_]]) = {
val evaluator = new Evaluator(workspacePath, mapping)
val evaluated = evaluator.evaluate(targets).targets.filter(mapping.contains)
diff --git a/core/src/test/scala/forge/MacroErrorTests.scala b/core/src/test/scala/forge/MacroErrorTests.scala
index 9f41fadc..6e76cd17 100644
--- a/core/src/test/scala/forge/MacroErrorTests.scala
+++ b/core/src/test/scala/forge/MacroErrorTests.scala
@@ -8,7 +8,7 @@ object MacroErrorTests extends TestSuite{
'errors{
val expectedMsg =
- "T{} members defined in a Cacher class/trait/object body must be defs"
+ "T{} members must be defs defined in a Cacher class/trait/object body"
val err = compileError("object Foo extends forge.define.Target.Cacher{ val x = T{1} }")
assert(err.msg == expectedMsg)
@@ -19,23 +19,26 @@ object MacroErrorTests extends TestSuite{
// of our `Target#apply()` calls, but we cannot reference any values that
// come from inside the T{...} block
'pos - {
- val a = T{ 1 }
- val arr = Array(a)
- val b = {
- val c = 0
- T{
- arr(c)()
+ val e = compileError("""
+ val a = T{ 1 }
+ val arr = Array(a)
+ val b = {
+ val c = 0
+ T{
+ arr(c)()
+ }
}
- }
+ """)
+ assert(e.msg.contains("must be defs"))
}
'neg - {
val expectedMsg =
"Target#apply() call cannot use `value n` defined within the T{...} block"
- val err = compileError("""{
- val a = T{ 1 }
+ val err = compileError("""new forge.define.Target.Cacher{
+ def a = T{ 1 }
val arr = Array(a)
- val b = {
+ def b = {
T{
val n = 0
arr(n)()
@@ -48,10 +51,10 @@ object MacroErrorTests extends TestSuite{
val expectedMsg =
"Target#apply() call cannot use `value x` defined within the T{...} block"
- val err = compileError("""{
- val a = T{ 1 }
+ val err = compileError("""new forge.define.Target.Cacher{
+ def a = T{ 1 }
val arr = Array(a)
- val b = {
+ def b = {
T{
arr.map{x => x()}
}
@@ -59,6 +62,17 @@ object MacroErrorTests extends TestSuite{
}""")
assert(err.msg == expectedMsg)
}
+ 'neg3{
+ val borkedCachedDiamond1 = utest.compileError("""
+ object borkedCachedDiamond1 {
+ def up = T{ TestUtil.test() }
+ def left = T{ TestUtil.test(up) }
+ def right = T{ TestUtil.test(up) }
+ def down = T{ TestUtil.test(left, right) }
+ }
+ """)
+ assert(borkedCachedDiamond1.msg.contains("must be defs"))
+ }
}
}
}
diff --git a/core/src/test/scala/forge/TestGraphs.scala b/core/src/test/scala/forge/TestGraphs.scala
index 5c30f948..9709979d 100644
--- a/core/src/test/scala/forge/TestGraphs.scala
+++ b/core/src/test/scala/forge/TestGraphs.scala
@@ -1,6 +1,6 @@
package forge
-import forge.define.Target.Cacher
+import forge.define.Task.Cacher
import forge.TestUtil.test
class TestGraphs(){
@@ -50,12 +50,6 @@ class TestGraphs(){
def down = T{ test(left, right) }
}
- object borkedCachedDiamond1 {
- def up = T{ test() }
- def left = T{ test(up) }
- def right = T{ test(up) }
- def down = T{ test(left, right) }
- }
object borkedCachedDiamond2 extends Cacher {
def up = test()
diff --git a/core/src/test/scala/forge/TestUtil.scala b/core/src/test/scala/forge/TestUtil.scala
index 005bcfef..91dc3da9 100644
--- a/core/src/test/scala/forge/TestUtil.scala
+++ b/core/src/test/scala/forge/TestUtil.scala
@@ -1,13 +1,13 @@
package forge
-import forge.define.Target
+import forge.define.Task
import forge.util.{Args, OSet}
import utest.assert
import scala.collection.mutable
object TestUtil {
- def test(inputs: Target[Int]*) = {
+ def test(inputs: Task[Int]*) = {
new Test(inputs, pure = inputs.nonEmpty)
}
@@ -16,8 +16,8 @@ object TestUtil {
* controlled externally, so you can construct arbitrary dataflow graphs and
* test how changes propagate.
*/
- class Test(val inputs: Seq[Target[Int]],
- val pure: Boolean) extends Target[Int]{
+ class Test(val inputs: Seq[Task[Int]],
+ val pure: Boolean) extends Task[Int]{
var counter = 0
def evaluate(args: Args) = {
counter + args.args.map(_.asInstanceOf[Int]).sum
@@ -25,8 +25,8 @@ object TestUtil {
override def sideHash = counter
}
- def checkTopological(targets: OSet[Target[_]]) = {
- val seen = mutable.Set.empty[Target[_]]
+ def checkTopological(targets: OSet[Task[_]]) = {
+ val seen = mutable.Set.empty[Task[_]]
for(t <- targets.items.reverseIterator){
seen.add(t)
for(upstream <- t.inputs){
diff --git a/scalaplugin/src/main/scala/forge/scalaplugin/Subproject.scala b/scalaplugin/src/main/scala/forge/scalaplugin/Subproject.scala
index 93c341ae..09f51b69 100644
--- a/scalaplugin/src/main/scala/forge/scalaplugin/Subproject.scala
+++ b/scalaplugin/src/main/scala/forge/scalaplugin/Subproject.scala
@@ -5,8 +5,8 @@ import java.io.File
import ammonite.ops.{Path, ls, mkdir, pwd}
import coursier.{Cache, Dependency, Fetch, MavenRepository, Module, Repository, Resolution}
-import forge.define.Target
-import forge.define.Target.Cacher
+import forge.define.Task
+import forge.define.Task.Cacher
import forge.eval.PathRef
import forge.util.Args
import play.api.libs.json._
@@ -16,7 +16,6 @@ import sbt.util.LogExchange
import xsbti.api.{ClassLike, DependencyContext}
import xsbti.compile.DependencyChanges
-import scalaz.concurrent.Task
object Subproject{
def compileScala(scalaVersion: String,
sources: PathRef,
@@ -97,7 +96,7 @@ object Subproject{
val fetch = Fetch.from(repositories, Cache.fetch())
val resolution = start.process.run(fetch).unsafePerformSync
- val localArtifacts: Seq[File] = Task
+ val localArtifacts: Seq[File] = scalaz.concurrent.Task
.gatherUnordered(resolution.artifacts.map(Cache.file(_).run))
.unsafePerformSync
.flatMap(_.toOption)
@@ -178,19 +177,19 @@ abstract class Subproject extends Cacher{
def sources = T{ PathRef(basePath() / 'src) }
def resources = T{ PathRef(basePath() / 'resources) }
def compiled = T{
- compileScala(scalaVersion(), sources(), compileDepClasspath(), Target.ctx().dest)
+ compileScala(scalaVersion(), sources(), compileDepClasspath(), Task.ctx().dest)
}
def classpath = T{ Seq(resources(), compiled()) }
def jar = T{ modules.Jvm.jarUp(resources, compiled) }
@forge.discover.Router.main
- def run(mainClass: String) = T.command{
+ def run(mainClass: String) = T.cmd{
import ammonite.ops._, ImplicitWd._
%('java, "-cp", (runDepClasspath().map(_.path) :+ compiled()).mkString(":"), mainClass)
}
@forge.discover.Router.main
- def console() = T.command{
+ def console() = T.cmd{
import ammonite.ops._, ImplicitWd._
%('java,
"-cp",