summaryrefslogtreecommitdiff
path: root/core/src/main/scala/forge/define
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 /core/src/main/scala/forge/define
parentc7ab7da7ccd21c63740f6494811a09722a0d2ce0 (diff)
downloadmill-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')
-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
3 files changed, 147 insertions, 135 deletions
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))
+ }
+}