diff options
author | Li Haoyi <haoyi.sg@gmail.com> | 2017-11-09 22:36:47 -0800 |
---|---|---|
committer | Li Haoyi <haoyi.sg@gmail.com> | 2017-11-09 22:36:47 -0800 |
commit | 550772d7515757339269c28c41fd0d8109e0fa2c (patch) | |
tree | 13ed3c93b85788dadbcd938930ed05ebc460f646 /core/src/main/scala/forge/define/Task.scala | |
parent | c7ab7da7ccd21c63740f6494811a09722a0d2ce0 (diff) | |
download | mill-550772d7515757339269c28c41fd0d8109e0fa2c.tar.gz mill-550772d7515757339269c28c41fd0d8109e0fa2c.tar.bz2 mill-550772d7515757339269c28c41fd0d8109e0fa2c.zip |
Migrate over to the new `Task`/`Target`/`Command` split
Diffstat (limited to 'core/src/main/scala/forge/define/Task.scala')
-rw-r--r-- | core/src/main/scala/forge/define/Task.scala | 134 |
1 files changed, 134 insertions, 0 deletions
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)) + } +} |