summaryrefslogtreecommitdiff
path: root/core/src/main/scala
diff options
context:
space:
mode:
authorLi Haoyi <haoyi.sg@gmail.com>2018-01-13 23:23:39 -0800
committerLi Haoyi <haoyi.sg@gmail.com>2018-01-13 23:23:39 -0800
commit3733cb5e4d041453aff84b35f25fa4162fae5818 (patch)
treecd15c7cff7a6759fde7190bfe58b8a7f68c1bebe /core/src/main/scala
parentff7eadd0d926a980ae31261bb84900640ca4cd9b (diff)
downloadmill-3733cb5e4d041453aff84b35f25fa4162fae5818.tar.gz
mill-3733cb5e4d041453aff84b35f25fa4162fae5818.tar.bz2
mill-3733cb5e4d041453aff84b35f25fa4162fae5818.zip
WIP getting rid of `discover/` phase: `core/test:compile` works, but some things still stubbed out with `???`
Diffstat (limited to 'core/src/main/scala')
-rw-r--r--core/src/main/scala/mill/define/Cross.scala13
-rw-r--r--core/src/main/scala/mill/define/Ctx.scala62
-rw-r--r--core/src/main/scala/mill/define/Module.scala82
-rw-r--r--core/src/main/scala/mill/define/Task.scala90
-rw-r--r--core/src/main/scala/mill/define/Worker.scala7
-rw-r--r--core/src/main/scala/mill/discover/Discovered.scala120
-rw-r--r--core/src/main/scala/mill/discover/Mirror.scala49
-rw-r--r--core/src/main/scala/mill/eval/Evaluator.scala12
-rw-r--r--core/src/main/scala/mill/main/MainRunner.scala2
-rw-r--r--core/src/main/scala/mill/main/ReplApplyHandler.scala20
-rw-r--r--core/src/main/scala/mill/main/Resolve.scala49
-rw-r--r--core/src/main/scala/mill/main/RunScript.scala29
-rw-r--r--core/src/main/scala/mill/package.scala1
13 files changed, 194 insertions, 342 deletions
diff --git a/core/src/main/scala/mill/define/Cross.scala b/core/src/main/scala/mill/define/Cross.scala
index 8e27c714..b40dc844 100644
--- a/core/src/main/scala/mill/define/Cross.scala
+++ b/core/src/main/scala/mill/define/Cross.scala
@@ -4,7 +4,7 @@ import scala.reflect.macros.blackbox
object Cross{
- case class Factory[T](make: (Product, Module.Ctx) => T)
+ case class Factory[T](make: (Product, mill.define.Ctx) => T)
object Factory{
implicit def make[T]: Factory[T] = macro makeImpl[T]
@@ -19,7 +19,7 @@ object Cross{
for((a, n) <- primaryConstructorArgs.zipWithIndex)
yield q"v.productElement($n).asInstanceOf[${a.info}]"
- val instance = c.Expr[(Product, Module.Ctx) => T](
+ val instance = c.Expr[(Product, mill.define.Ctx) => T](
q"{ (v, ctx0) => new $tpe(..$argTupleValues){ override def ctx = ctx0 } }"
)
@@ -44,7 +44,14 @@ object Cross{
*/
class Cross[T](cases: Any*)
(implicit ci: Cross.Factory[T],
- ctx: Module.Ctx) extends mill.define.Module()(ctx) {
+ ctx: mill.define.Ctx) extends mill.define.Module()(ctx) {
+
+ override def traverse[T](f: (Module, Segments) => Seq[T]): Seq[T] = {
+ ???
+// f(this) ++
+// this.reflect[mill.Module].flatMap(f) ++
+// items.map(_._2).flatMap{case t: mill.Module => f(t)}
+ }
val items = for(c0 <- cases.toList) yield{
val c = c0 match{
diff --git a/core/src/main/scala/mill/define/Ctx.scala b/core/src/main/scala/mill/define/Ctx.scala
new file mode 100644
index 00000000..fc8bf85a
--- /dev/null
+++ b/core/src/main/scala/mill/define/Ctx.scala
@@ -0,0 +1,62 @@
+package mill.define
+
+import ammonite.main.Router.Overrides
+import ammonite.ops.Path
+
+import scala.annotation.implicitNotFound
+
+sealed trait Segment
+object Segment{
+ case class Label(value: String) extends Segment
+ case class Cross(value: Seq[Any]) extends Segment
+}
+
+case class BasePath(value: Path)
+
+
+/**
+ * Models a path with the Mill build hierarchy, e.g.
+ *
+ * amm.util[2.11].test.compile
+ *
+ * .-separated segments are [[Segment.Label]]s, while []-delimited
+ * segments are [[Segment.Cross]]s
+ */
+case class Segments(value: Segment*){
+ def ++(other: Seq[Segment]): Segments = Segments(value ++ other:_*)
+ def ++(other: Segments): Segments = Segments(value ++ other.value:_*)
+ def render = value match {
+ case Nil => ""
+ case Segment.Label(head) :: rest =>
+ val stringSegments = rest.map{
+ case Segment.Label(s) => "." + s
+ case Segment.Cross(vs) => "[" + vs.mkString(",") + "]"
+ }
+ head + stringSegments.mkString
+ }
+}
+
+@implicitNotFound("Modules, Targets and Commands can only be defined within a mill Module")
+case class Ctx(enclosing: String,
+ lineNum: Int,
+ segment: Segment,
+ basePath: Path,
+ segments0: Segments,
+ overrides: Int){
+ def segments = Segments(segments0.value.drop(1):_*)
+}
+object Ctx{
+ implicit def make(implicit millModuleEnclosing0: sourcecode.Enclosing,
+ millModuleLine0: sourcecode.Line,
+ millName0: sourcecode.Name,
+ millModuleBasePath0: BasePath,
+ segments0: Segments,
+ overrides0: Overrides): Ctx = Ctx(
+ millModuleEnclosing0.value,
+ millModuleLine0.value,
+ Segment.Label(millName0.value),
+ millModuleBasePath0.value,
+ segments0,
+ overrides0.value
+ )
+} \ No newline at end of file
diff --git a/core/src/main/scala/mill/define/Module.scala b/core/src/main/scala/mill/define/Module.scala
index 5eee6ddf..f4a332a2 100644
--- a/core/src/main/scala/mill/define/Module.scala
+++ b/core/src/main/scala/mill/define/Module.scala
@@ -2,48 +2,38 @@ package mill.define
import java.lang.reflect.Modifier
-import ammonite.main.Router.Overrides
+import ammonite.main.Router.{EntryPoint, Overrides}
import ammonite.ops.Path
import scala.annotation.implicitNotFound
import scala.reflect.ClassTag
-sealed trait Segment
-object Segment{
- case class Label(value: String) extends Segment
- case class Cross(value: Seq[Any]) extends Segment
-}
-
-case class BasePath(value: Path)
-
-/**
- * Models a path with the Mill build hierarchy, e.g.
- *
- * amm.util[2.11].test.compile
- *
- * .-separated segments are [[Segment.Label]]s, while []-delimited
- * segments are [[Segment.Cross]]s
- */
-case class Segments(value: Segment*){
- def ++(other: Seq[Segment]): Segments = Segments(value ++ other:_*)
- def ++(other: Segments): Segments = Segments(value ++ other.value:_*)
- def render = value match {
- case Nil => ""
- case Segment.Label(head) :: rest =>
- val stringSegments = rest.map{
- case Segment.Label(s) => "." + s
- case Segment.Cross(vs) => "[" + vs.mkString(",") + "]"
- }
- head + stringSegments.mkString
- }
-}
/**
* `Module` is a class meant to be extended by `trait`s *only*, in order to
* propagate the implicit parameters forward to the final concrete
* instantiation site so they can capture the enclosing/line information of
* the concrete instance.
*/
-class Module(implicit ctx0: Module.Ctx) extends mill.moduledefs.Cacher{
+class Module(implicit ctx0: mill.define.Ctx) extends mill.moduledefs.Cacher{
+ def commands: Seq[EntryPoint[Module]] = ???
+
+ def traverse[T](f: (Module, Segments) => Seq[T]): Seq[T] = {
+ ???
+ }
+
+ lazy val segmentsToModules = traverse{(m, s) => Seq(s -> m)}
+ .toMap
+
+ lazy val modules = segmentsToModules.valuesIterator.toSet
+ lazy val segmentsToTargets = traverse{(m, s) => m.reflect[Target[_]]}
+ .map(t => (t.ctx.segments, t))
+ .toMap
+
+ lazy val targets = segmentsToTargets.valuesIterator.toSet
+ lazy val segmentsToCommands = traverse{
+ (m, s) => m.commands.map(e => s ++ Seq(Segment.Label(e.name)) -> e)
+ }.toMap
+
def ctx = ctx0
// Ensure we do not propagate the implicit parameters as implicits within
// the body of any inheriting class/trait/objects, as it would screw up any
@@ -68,37 +58,15 @@ class Module(implicit ctx0: Module.Ctx) extends mill.moduledefs.Cacher{
.map(_.invoke(this).asInstanceOf[T])
}
}
-object Module{
- @implicitNotFound("Modules, Targets and Commands can only be defined within a mill Module")
- case class Ctx(enclosing: String,
- lineNum: Int,
- segment: Segment,
- basePath: Path,
- segments0: Segments,
- overrides: Int){
- def segments = Segments(segments0.value.drop(1):_*)
- }
- object Ctx{
- implicit def make(implicit millModuleEnclosing0: sourcecode.Enclosing,
- millModuleLine0: sourcecode.Line,
- millName0: sourcecode.Name,
- millModuleBasePath0: BasePath,
- segments0: Segments,
- overrides0: Overrides): Ctx = Ctx(
- millModuleEnclosing0.value,
- millModuleLine0.value,
- Segment.Label(millName0.value),
- millModuleBasePath0.value,
- segments0,
- overrides0.value
- )
- }
+trait TaskModule extends Module {
+ def defaultCommandName(): String
}
+
class BaseModule(basePath: Path)
(implicit millModuleEnclosing0: sourcecode.Enclosing,
millModuleLine0: sourcecode.Line,
millName0: sourcecode.Name,
overrides0: Overrides)
extends Module()(
- Module.Ctx.make(implicitly, implicitly, implicitly, BasePath(basePath), Segments(), implicitly)
+ mill.define.Ctx.make(implicitly, implicitly, implicitly, BasePath(basePath), Segments(), implicitly)
) \ No newline at end of file
diff --git a/core/src/main/scala/mill/define/Task.scala b/core/src/main/scala/mill/define/Task.scala
index 2a670d21..c0892743 100644
--- a/core/src/main/scala/mill/define/Task.scala
+++ b/core/src/main/scala/mill/define/Task.scala
@@ -2,7 +2,7 @@ package mill.define
import mill.define.Applicative.Applyable
import mill.eval.{PathRef, Result}
-import mill.util.Ctx
+
import upickle.default.{ReadWriter => RW, Reader => R, Writer => W}
import scala.language.experimental.macros
@@ -24,7 +24,7 @@ abstract class Task[+T] extends Task.Ops[T] with Applyable[Task, T]{
/**
* Evaluate this target
*/
- def evaluate(args: Ctx): Result[T]
+ def evaluate(args: mill.util.Ctx): Result[T]
/**
* Even if this target's inputs did not change, does it need to re-evaluate
@@ -41,7 +41,7 @@ abstract class Task[+T] extends Task.Ops[T] with Applyable[Task, T]{
}
trait NamedTask[+T] extends Task[T]{
- def ctx: Module.Ctx
+ def ctx: mill.define.Ctx
def label = ctx.segment match{case Segment.Label(v) => v}
}
trait Target[+T] extends NamedTask[T]{
@@ -49,20 +49,20 @@ trait Target[+T] extends NamedTask[T]{
def readWrite: RW[_]
}
-object Target extends TargetGenerated with Applicative.Applyer[Task, Task, Result, Ctx] {
+object Target extends TargetGenerated with Applicative.Applyer[Task, Task, Result, mill.util.Ctx] {
implicit def apply[T](t: T)
(implicit r: R[T],
w: W[T],
- ctx: Module.Ctx): Target[T] = macro targetImpl[T]
+ ctx: mill.define.Ctx): Target[T] = macro targetImpl[T]
def targetImpl[T: c.WeakTypeTag](c: Context)
(t: c.Expr[T])
(r: c.Expr[R[T]],
w: c.Expr[W[T]],
- ctx: c.Expr[Module.Ctx]): c.Expr[Target[T]] = {
+ ctx: c.Expr[mill.define.Ctx]): c.Expr[Target[T]] = {
import c.universe._
- val lhs = Applicative.impl0[Task, T, Ctx](c)(reify(Result.Success(t.splice)).tree)
+ val lhs = Applicative.impl0[Task, T, mill.util.Ctx](c)(reify(Result.Success(t.splice)).tree)
mill.moduledefs.Cacher.impl0[TargetImpl[T]](c)(
reify(
@@ -74,18 +74,18 @@ object Target extends TargetGenerated with Applicative.Applyer[Task, Task, Resul
implicit def apply[T](t: Result[T])
(implicit r: R[T],
w: W[T],
- ctx: Module.Ctx): Target[T] = macro targetResultImpl[T]
+ ctx: mill.define.Ctx): Target[T] = macro targetResultImpl[T]
def targetResultImpl[T: c.WeakTypeTag](c: Context)
(t: c.Expr[Result[T]])
(r: c.Expr[R[T]],
w: c.Expr[W[T]],
- ctx: c.Expr[Module.Ctx]): c.Expr[Target[T]] = {
+ ctx: c.Expr[mill.define.Ctx]): c.Expr[Target[T]] = {
import c.universe._
mill.moduledefs.Cacher.impl0[Target[T]](c)(
reify(
new TargetImpl[T](
- Applicative.impl0[Task, T, Ctx](c)(t.tree).splice,
+ Applicative.impl0[Task, T, mill.util.Ctx](c)(t.tree).splice,
ctx.splice,
RW(w.splice.write, r.splice.read)
)
@@ -96,13 +96,13 @@ object Target extends TargetGenerated with Applicative.Applyer[Task, Task, Resul
def apply[T](t: Task[T])
(implicit r: R[T],
w: W[T],
- ctx: Module.Ctx): Target[T] = macro targetTaskImpl[T]
+ ctx: mill.define.Ctx): Target[T] = macro targetTaskImpl[T]
def targetTaskImpl[T: c.WeakTypeTag](c: Context)
(t: c.Expr[Task[T]])
(r: c.Expr[R[T]],
w: c.Expr[W[T]],
- ctx: c.Expr[Module.Ctx]): c.Expr[Target[T]] = {
+ ctx: c.Expr[mill.define.Ctx]): c.Expr[Target[T]] = {
import c.universe._
mill.moduledefs.Cacher.impl0[Target[T]](c)(
reify(
@@ -114,13 +114,13 @@ object Target extends TargetGenerated with Applicative.Applyer[Task, Task, Resul
def source(value: Result[ammonite.ops.Path])
(implicit r: R[PathRef],
w: W[PathRef],
- ctx: Module.Ctx): Input[PathRef] = macro sourceImpl
+ ctx: mill.define.Ctx): Input[PathRef] = macro sourceImpl
def sourceImpl(c: Context)
(value: c.Expr[Result[ammonite.ops.Path]])
(r: c.Expr[R[PathRef]],
w: c.Expr[W[PathRef]],
- ctx: c.Expr[Module.Ctx]): c.Expr[Input[PathRef]] = {
+ ctx: c.Expr[mill.define.Ctx]): c.Expr[Input[PathRef]] = {
import c.universe._
val wrapped: c.Expr[Result[PathRef]] = reify(value.splice match{
case Result.Success(p) => Result.Success(PathRef(p))
@@ -129,7 +129,7 @@ object Target extends TargetGenerated with Applicative.Applyer[Task, Task, Resul
mill.moduledefs.Cacher.impl0[Input[PathRef]](c)(
reify(
new Input[PathRef](
- Applicative.impl0[Task, PathRef, Ctx](c)(wrapped.tree).splice,
+ Applicative.impl0[Task, PathRef, mill.util.Ctx](c)(wrapped.tree).splice,
ctx.splice,
RW(w.splice.write, r.splice.read),
)
@@ -140,19 +140,19 @@ object Target extends TargetGenerated with Applicative.Applyer[Task, Task, Resul
def input[T](value: Result[T])
(implicit r: R[T],
w: W[T],
- ctx: Module.Ctx): Input[T] = macro inputImpl[T]
+ ctx: mill.define.Ctx): Input[T] = macro inputImpl[T]
def inputImpl[T: c.WeakTypeTag](c: Context)
(value: c.Expr[T])
(r: c.Expr[R[T]],
w: c.Expr[W[T]],
- ctx: c.Expr[Module.Ctx]): c.Expr[Input[T]] = {
+ ctx: c.Expr[mill.define.Ctx]): c.Expr[Input[T]] = {
import c.universe._
mill.moduledefs.Cacher.impl0[Input[T]](c)(
reify(
new Input[T](
- Applicative.impl[Task, T, Ctx](c)(value).splice,
+ Applicative.impl[Task, T, mill.util.Ctx](c)(value).splice,
ctx.splice,
RW(w.splice.write, r.splice.read)
)
@@ -161,41 +161,41 @@ object Target extends TargetGenerated with Applicative.Applyer[Task, Task, Resul
}
def command[T](t: Task[T])
- (implicit ctx: Module.Ctx,
+ (implicit ctx: mill.define.Ctx,
w: W[T]): Command[T] = new Command(t, ctx, w)
def command[T](t: Result[T])
(implicit w: W[T],
- ctx: Module.Ctx): Command[T] = macro commandImpl[T]
+ ctx: mill.define.Ctx): Command[T] = macro commandImpl[T]
def commandImpl[T: c.WeakTypeTag](c: Context)
(t: c.Expr[T])
(w: c.Expr[W[T]],
- ctx: c.Expr[Module.Ctx]): c.Expr[Command[T]] = {
+ ctx: c.Expr[mill.define.Ctx]): c.Expr[Command[T]] = {
import c.universe._
reify(
- new Command[T](Applicative.impl[Task, T, Ctx](c)(t).splice, ctx.splice, w.splice)
+ new Command[T](Applicative.impl[Task, T, mill.util.Ctx](c)(t).splice, ctx.splice, w.splice)
)
}
- def task[T](t: Result[T]): Task[T] = macro Applicative.impl[Task, T, Ctx]
+ def task[T](t: Result[T]): Task[T] = macro Applicative.impl[Task, T, mill.util.Ctx]
def persistent[T](t: Result[T])(implicit r: R[T],
w: W[T],
- ctx: Module.Ctx): Target[T] = macro persistentImpl[T]
+ ctx: mill.define.Ctx): Target[T] = macro persistentImpl[T]
def persistentImpl[T: c.WeakTypeTag](c: Context)
(t: c.Expr[T])
(r: c.Expr[R[T]],
w: c.Expr[W[T]],
- ctx: c.Expr[Module.Ctx]): c.Expr[Persistent[T]] = {
+ ctx: c.Expr[mill.define.Ctx]): c.Expr[Persistent[T]] = {
import c.universe._
mill.moduledefs.Cacher.impl0[Persistent[T]](c)(
reify(
new Persistent[T](
- Applicative.impl[Task, T, Ctx](c)(t).splice,
+ Applicative.impl[Task, T, mill.util.Ctx](c)(t).splice,
ctx.splice,
RW(w.splice.write, r.splice.read)
)
@@ -204,13 +204,13 @@ object Target extends TargetGenerated with Applicative.Applyer[Task, Task, Resul
}
type TT[+X] = Task[X]
- def makeT[X](inputs0: Seq[TT[_]], evaluate0: Ctx => Result[X]) = new Task[X] {
+ def makeT[X](inputs0: Seq[TT[_]], evaluate0: mill.util.Ctx => Result[X]) = new Task[X] {
val inputs = inputs0
- def evaluate(x: Ctx) = evaluate0(x)
+ def evaluate(x: mill.util.Ctx) = evaluate0(x)
}
def underlying[A](v: Task[A]) = v
- def mapCtx[A, B](t: Task[A])(f: (A, Ctx) => Result[B]) = t.mapDest(f)
+ def mapCtx[A, B](t: Task[A])(f: (A, mill.util.Ctx) => Result[B]) = t.mapDest(f)
def zip() = new Task.Task0(())
def zip[A](a: Task[A]) = a.map(Tuple1(_))
def zip[A, B](a: Task[A], b: Task[B]) = a.zip(b)
@@ -227,23 +227,23 @@ object Caller {
}
class TargetImpl[+T](t: Task[T],
- ctx0: Module.Ctx,
+ ctx0: mill.define.Ctx,
val readWrite: RW[_]) extends Target[T] {
val ctx = ctx0.copy(segments0 = ctx0.segments0 ++ Seq(ctx0.segment))
val inputs = Seq(t)
- def evaluate(args: Ctx) = args[T](0)
+ def evaluate(args: mill.util.Ctx) = args[T](0)
override def toString = ctx.enclosing + "@" + Integer.toHexString(System.identityHashCode(this))
}
class Command[+T](t: Task[T],
- ctx0: Module.Ctx,
+ ctx0: mill.define.Ctx,
val writer: W[_]) extends NamedTask[T] {
val ctx = ctx0.copy(segments0 = ctx0.segments0 ++ Seq(ctx0.segment))
val inputs = Seq(t)
- def evaluate(args: Ctx) = args[T](0)
+ def evaluate(args: mill.util.Ctx) = args[T](0)
override def asCommand = Some(this)
}
class Persistent[+T](t: Task[T],
- ctx0: Module.Ctx,
+ ctx0: mill.define.Ctx,
readWrite: RW[_])
extends TargetImpl[T](t, ctx0, readWrite) {
@@ -251,30 +251,28 @@ class Persistent[+T](t: Task[T],
override def asPersistent = Some(this)
}
class Input[T](t: Task[T],
- ctx0: Module.Ctx,
+ ctx0: mill.define.Ctx,
val readWrite: RW[_]) extends Target[T]{
val ctx = ctx0.copy(segments0 = ctx0.segments0 ++ Seq(ctx0.segment))
val inputs = Seq(t)
- def evaluate(args: Ctx) = args[T](0)
+ def evaluate(args: mill.util.Ctx) = args[T](0)
override def sideHash = util.Random.nextInt()
}
object Task {
- trait TaskModule extends Module {
- def defaultCommandName(): String
- }
+
class Task0[T](t: T) extends Task[T]{
lazy val t0 = t
val inputs = Nil
- def evaluate(args: Ctx) = t0
+ def evaluate(args: mill.util.Ctx) = t0
}
abstract class Ops[+T]{ this: Task[T] =>
def map[V](f: T => V) = new Task.Mapped(this, f)
- def mapDest[V](f: (T, Ctx) => Result[V]) = new Task.MappedDest(this, f)
+ def mapDest[V](f: (T, mill.util.Ctx) => Result[V]) = new Task.MappedDest(this, f)
def filter(f: T => Boolean) = this
def withFilter(f: T => Boolean) = this
@@ -289,22 +287,22 @@ object Task {
class Sequence[+T](inputs0: Seq[Task[T]]) extends Task[Seq[T]]{
val inputs = inputs0
- def evaluate(args: Ctx) = {
+ def evaluate(args: mill.util.Ctx) = {
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: Ctx) = f(args(0))
+ def evaluate(args: mill.util.Ctx) = f(args(0))
val inputs = List(source)
}
- class MappedDest[+T, +V](source: Task[T], f: (T, Ctx) => Result[V]) extends Task[V]{
- def evaluate(args: Ctx) = f(args(0), args)
+ class MappedDest[+T, +V](source: Task[T], f: (T, mill.util.Ctx) => Result[V]) extends Task[V]{
+ def evaluate(args: mill.util.Ctx) = 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: Ctx) = (args(0), args(1))
+ def evaluate(args: mill.util.Ctx) = (args(0), args(1))
val inputs = List(source1, source2)
}
}
diff --git a/core/src/main/scala/mill/define/Worker.scala b/core/src/main/scala/mill/define/Worker.scala
index 0a6d31d2..3d35d2e0 100644
--- a/core/src/main/scala/mill/define/Worker.scala
+++ b/core/src/main/scala/mill/define/Worker.scala
@@ -1,6 +1,5 @@
package mill.define
-import mill.util.Ctx
/**
* Worker serves three purposes:
@@ -25,9 +24,9 @@ import mill.util.Ctx
* evaluating the task graph. The Worker defines how it is evaluated, but it's
* evaluation/caching/lifecycle are controlled by the `Evaluator`
*/
-trait Worker[V] extends Task[V] with Ctx.Loader[V]{
+trait Worker[V] extends Task[V] with mill.util.Ctx.Loader[V]{
val inputs = Nil
def make(): V
- def evaluate(args: Ctx) = args.load(this)
+ def evaluate(args: mill.util.Ctx) = args.load(this)
def path = this.getClass.getCanonicalName.filter(_ != '$').split('.')
-} \ No newline at end of file
+}
diff --git a/core/src/main/scala/mill/discover/Discovered.scala b/core/src/main/scala/mill/discover/Discovered.scala
deleted file mode 100644
index 6296645a..00000000
--- a/core/src/main/scala/mill/discover/Discovered.scala
+++ /dev/null
@@ -1,120 +0,0 @@
-package mill.discover
-
-import mill.define._
-import ammonite.main.Router
-import ammonite.main.Router.EntryPoint
-import mill.util.Ctx.Loader
-import mill.util.Strict.Agg
-
-import scala.language.experimental.macros
-import scala.reflect.macros.blackbox.Context
-
-/**
- * Allows you to implicitly summon up a build [[Mirror]] for arbitrary types
- */
-class Discovered[T](val mirror: Mirror[T, T]){
- def mapping(t: T) = Discovered.Mapping(mirror, t)
-}
-
-object Discovered {
- object Mapping extends Loader[Mapping[_]] {
- // Magically injected by the `Evaluator`, rather than being constructed here
- def make() = ???
- }
- case class Mapping[T](mirror: Mirror[T, T],
- base: T){
- val modulesToMirrors = Mirror.traverseNode[T, T, (Any, Mirror[_, _])](base, mirror){
- (mirror, segments, resolvedNode) => Seq(resolvedNode -> mirror)
- }.toMap
-
- val targets = Agg.from(
- Mirror.traverseNode(base, mirror){ (mirror, segmentsRev, resolvedNode) =>
- resolvedNode.asInstanceOf[mill.Module].reflect[Target[_]]
- }
- )
-
- val segmentsToCommands = Mirror.traverse[T, T, (Segments, EntryPoint[_])](base, mirror){ (mirror, segments) =>
- for(command <- mirror.commands)
- yield segments ++ Seq(Segment.Label(command.name)) -> command
- }.toMap
-
- val segmentsToTargets = targets.map(t => (t.ctx.segments, t)).toMap
- val targetsToSegments = segmentsToTargets.map(_.swap)
- }
-
- def consistencyCheck[T](mapping: Discovered.Mapping[T]): Agg[Segments] = {
- val mapping2 = Discovered.Mapping(mapping.mirror, mapping.base)
- for{
- (t1, t2) <- mapping2.targets.zip(mapping.targets)
- if t1 ne t2
- } yield t1.ctx.segments
- }
-
-
- def make[T]: Discovered[T] = macro applyImpl[T]
- def mapping[T](t: T): Discovered.Mapping[T] = macro mappingImpl[T]
- def tupleLeft[T, V](items: List[(T, V)]) = items.map(_._1)
- def mappingImpl[T: c.WeakTypeTag](c: Context)(t: c.Expr[T]): c.Expr[Discovered.Mapping[T]] = {
- import c.universe._
- c.Expr[Discovered.Mapping[T]](q"${applyImpl[T](c)}.mapping($t)")
- }
- def applyImpl[T: c.WeakTypeTag](c: Context): c.Expr[Discovered[T]] = {
-
- import c.universe._
- val baseType = c.weakTypeTag[T].tpe
- def rec(segments: List[Option[String]],
- t: c.Type): Tree = {
-
- val r = new Router(c)
-
- val crossChildren =
- if (!(t <:< c.weakTypeOf[Cross[_]])) q"None"
- else {
-
- val TypeRef(_, _, Seq(arg)) = t.baseType(weakTypeOf[Cross[_]].typeSymbol)
- val innerMirror = rec(None :: segments, arg)
- q"Some(((c: mill.define.Cross[_]) => mill.discover.Discovered.tupleLeft(c.items), $innerMirror))"
- }
- val childHierarchies = for{
- m <- t.members.toList
- if m.typeSignature.paramLists.isEmpty && m.isPublic
- if (m.typeSignature.finalResultType <:< c.weakTypeOf[Module]) ||
- (m.typeSignature.finalResultType <:< c.weakTypeOf[Cross[_]])
-
- } yield {
- val name = m.name.toString.trim
- q"($name, ${rec(Some(name) :: segments, m.typeSignature.finalResultType)})"
- }
-
-
- val crossName = q"${TermName(c.freshName())}"
- val hierarchySelector = {
- val base = q"${TermName(c.freshName())}"
- val ident = segments.reverse.zipWithIndex.foldLeft[Tree](base) {
- case (prefix, (Some(name), i)) => q"$prefix.${TermName(name)}"
- case (prefix, (None, i)) => q"$prefix.get($crossName($i))"
- }
- q"($base: $baseType, $crossName: List[List[Any]]) => $ident.asInstanceOf[$t]"
- }
-
- val commands =
- r.getAllRoutesForClass(
- t.asInstanceOf[r.c.Type],
- _.returnType <:< weakTypeOf[mill.define.Command[_]].asInstanceOf[r.c.Type]
- )
- .asInstanceOf[Seq[c.Tree]]
- .toList
-
- q"""mill.discover.Mirror[$baseType, $t](
- $hierarchySelector,
- $commands,
- $childHierarchies,
- $crossChildren
- )"""
- }
-
- val res = q"new _root_.mill.discover.Discovered(${rec(Nil, baseType)})"
-// println(res)
- c.Expr[Discovered[T]](res)
- }
-}
diff --git a/core/src/main/scala/mill/discover/Mirror.scala b/core/src/main/scala/mill/discover/Mirror.scala
deleted file mode 100644
index ffa86225..00000000
--- a/core/src/main/scala/mill/discover/Mirror.scala
+++ /dev/null
@@ -1,49 +0,0 @@
-package mill.discover
-
-import mill.define.{Segment, Segments, Target, Task}
-import ammonite.main.Router.EntryPoint
-
-import scala.language.experimental.macros
-
-/**
- * Metadata about a build that is extracted & materialized at compile-time,
- * letting us use it at run-time without needing to use the heavy weight
- * scala-reflect library.
- *
- * Note that [[Mirror]] allows you to store and inspect metadata of a type
- * [[T]] even without a concrete instance of [[T]] itself.
- */
-case class Mirror[-T, V](node: (T, List[List[Any]]) => V,
- commands: Seq[EntryPoint[V]],
- children: List[(String, Mirror[T, _])],
- crossChildren: Option[(V => List[List[Any]], Mirror[T, _])])
-
-object Mirror{
-
- def traverseNode[T, V, R](t: T, hierarchy: Mirror[T, V])
- (f: (Mirror[T, _], => Segments, => Any) => Seq[R]): Seq[R] = {
- traverse(t, hierarchy){ (mirror, segmentsRev) =>
- lazy val resolvedNode = mirror.node(
- t,
- segmentsRev.value.map{case Segment.Cross(vs) => vs.toList case _ => Nil}.toList
- )
- f(mirror, segmentsRev, resolvedNode)
- }
- }
- def traverse[T, V, R](t: T, hierarchy: Mirror[T, V])
- (f: (Mirror[T, _], => Segments) => Seq[R]): Seq[R] = {
- def rec[C](segmentsRev: List[Segment], h: Mirror[T, C]): Seq[R]= {
- val crossValues = segmentsRev.map{case Segment.Cross(vs) => vs case _ => Nil}
- val self = f(h, Segments(segmentsRev.reverse:_*))
- self ++
- h.children.flatMap{case (label, c) => rec(Segment.Label(label) :: segmentsRev, c)} ++
- h.crossChildren.toSeq.flatMap{
- case (crossGen, c) =>
- crossGen(h.node(t, crossValues.reverse.map(_.toList))).flatMap(cross =>
- rec(Segment.Cross(cross) :: segmentsRev, c)
- )
- }
- }
- rec(Nil, hierarchy)
- }
-}
diff --git a/core/src/main/scala/mill/eval/Evaluator.scala b/core/src/main/scala/mill/eval/Evaluator.scala
index 28d90fcf..ee4ec27b 100644
--- a/core/src/main/scala/mill/eval/Evaluator.scala
+++ b/core/src/main/scala/mill/eval/Evaluator.scala
@@ -4,9 +4,7 @@ import java.net.URLClassLoader
import ammonite.ops._
import ammonite.runtime.SpecialClassLoader
-import mill.define._
-import mill.discover.{Discovered, Mirror}
-import mill.define.Segment
+import mill.define.{Segment, Segments, NamedTask, Graph, Target, Task}
import mill.util
import mill.util._
import mill.util.Strict.Agg
@@ -27,14 +25,14 @@ case class Labelled[T](target: NamedTask[T],
}
class Evaluator[T](val workspacePath: Path,
val basePath: Path,
- val mapping: Discovered.Mapping[T],
+ val rootModule: mill.Module,
log: Logger,
val classLoaderSig: Seq[(Path, Long)] = Evaluator.classLoaderSig){
val workerCache = mutable.Map.empty[Ctx.Loader[_], Any]
- workerCache(Discovered.Mapping) = mapping
+// workerCache(Discovered.Mapping) = rootModule
def evaluate(goals: Agg[Task[_]]): Evaluator.Results = {
mkdir(workspacePath)
@@ -44,8 +42,8 @@ class Evaluator[T](val workspacePath: Path,
case t: NamedTask[Any] =>
val segments = t.ctx.segments
val (finalTaskOverrides, enclosing) = t match{
- case t: Target[_] => mapping.segmentsToTargets(segments).ctx.overrides -> t.ctx.enclosing
- case c: mill.define.Command[_] => mapping.segmentsToCommands(segments).overrides -> c.ctx.enclosing
+ case t: Target[_] => rootModule.segmentsToTargets(segments).ctx.overrides -> t.ctx.enclosing
+ case c: mill.define.Command[_] => rootModule.segmentsToCommands(segments).overrides -> c.ctx.enclosing
}
val additional =
if (finalTaskOverrides == t.ctx.overrides) Nil
diff --git a/core/src/main/scala/mill/main/MainRunner.scala b/core/src/main/scala/mill/main/MainRunner.scala
index 2305c11e..49fcfe2a 100644
--- a/core/src/main/scala/mill/main/MainRunner.scala
+++ b/core/src/main/scala/mill/main/MainRunner.scala
@@ -5,7 +5,6 @@ import ammonite.Main
import ammonite.interp.{Interpreter, Preprocessor}
import ammonite.ops.Path
import ammonite.util._
-import mill.discover.Discovered
import mill.eval.{Evaluator, PathRef}
import mill.util.PrintLogger
import upickle.Js
@@ -97,7 +96,6 @@ class MainRunner(config: ammonite.main.Cli.Config,
| // Stub to make sure Ammonite has something to call after it evaluates a script,
| // even if it does nothing...
| def $$main() = Iterator[String]()
- | lazy val mapping = mill.discover.Discovered.make[$wrapName].mapping(this)
|}
|
|sealed trait $wrapName extends mill.Module{
diff --git a/core/src/main/scala/mill/main/ReplApplyHandler.scala b/core/src/main/scala/mill/main/ReplApplyHandler.scala
index 718ca358..f7f44270 100644
--- a/core/src/main/scala/mill/main/ReplApplyHandler.scala
+++ b/core/src/main/scala/mill/main/ReplApplyHandler.scala
@@ -3,7 +3,6 @@ package mill.main
import mill.define.Applicative.ApplyHandler
import mill.define._
-import mill.discover.{Discovered, Mirror}
import mill.eval.{Evaluator, Result}
import mill.util.Strict.Agg
@@ -11,13 +10,13 @@ import scala.collection.mutable
object ReplApplyHandler{
def apply[T](colors: ammonite.util.Colors,
pprinter0: pprint.PPrinter,
- mapping: Discovered.Mapping[T]) = {
+ rootModule: mill.Module) = {
new ReplApplyHandler(
pprinter0,
new mill.eval.Evaluator(
ammonite.ops.pwd / 'out,
ammonite.ops.pwd,
- mapping,
+ rootModule,
new mill.util.PrintLogger(
colors != ammonite.util.Colors.BlackWhite,
colors,
@@ -71,14 +70,13 @@ class ReplApplyHandler(pprinter0: pprint.PPrinter, evaluator: Evaluator[_]) exte
"\n (" + x._1.map(pprint.PPrinter.BlackWhite.apply(_)).mkString(", ") + ")"
)
)
- case m: mill.Module if evaluator.mapping.modulesToMirrors.contains(m) =>
- val mirror = evaluator.mapping.modulesToMirrors(m)
+ case m: mill.Module if evaluator.rootModule.modules.contains(m) =>
pprint.Tree.Lazy( ctx =>
Iterator(m.millModuleEnclosing, ":", m.millModuleLine.toString) ++
- (if (mirror.children.isEmpty) Nil
- else ctx.applyPrefixColor("\nChildren:").toString +: mirror.children.map("\n ." + _._1)) ++
- (if (mirror.commands.isEmpty) Nil
- else ctx.applyPrefixColor("\nCommands:").toString +: mirror.commands.sortBy(_.name).map{c =>
+ (if (m.reflect[mill.Module].isEmpty) Nil
+ else ctx.applyPrefixColor("\nChildren:").toString +: m.reflect[mill.Module].map("\n ." + _.ctx.segments.render)) ++
+ (if (m.commands.isEmpty) Nil
+ else ctx.applyPrefixColor("\nCommands:").toString +: m.commands.sortBy(_.name).map{c =>
"\n ." + c.name + "(" +
c.argSignatures.map(s => s.name + ": " + s.typeString).mkString(", ") +
")()"
@@ -92,12 +90,12 @@ class ReplApplyHandler(pprinter0: pprint.PPrinter, evaluator: Evaluator[_]) exte
})
)
- case t: mill.define.Target[_] if evaluator.mapping.targets.contains(t) =>
+ case t: mill.define.Target[_] if evaluator.rootModule.targets.contains(t) =>
val seen = mutable.Set.empty[Task[_]]
def rec(t: Task[_]): Seq[Segments] = {
if (seen(t)) Nil // do nothing
else t match {
- case t: Target[_] if evaluator.mapping.targets.contains(t) =>
+ case t: Target[_] if evaluator.rootModule.targets.contains(t) =>
Seq(t.ctx.segments)
case _ =>
seen.add(t)
diff --git a/core/src/main/scala/mill/main/Resolve.scala b/core/src/main/scala/mill/main/Resolve.scala
index 1567f26a..e50e0ca9 100644
--- a/core/src/main/scala/mill/main/Resolve.scala
+++ b/core/src/main/scala/mill/main/Resolve.scala
@@ -1,14 +1,12 @@
package mill.main
-import mill.define.{Segment, Segments, Target, Task}
-import mill.define.Task.TaskModule
-import mill.discover.Mirror
+import mill.define._
+import mill.define.TaskModule
import ammonite.main.Router
object Resolve {
def resolve[T, V](remainingSelector: List[Segment],
- hierarchy: Mirror[T, V],
- obj: T,
+ obj: mill.Module,
rest: Seq[String],
remainingCrossSelectors: List[List[String]],
revSelectorsSoFar: List[Segment]): Either[String, Task[Any]] = {
@@ -17,31 +15,28 @@ object Resolve {
case Segment.Cross(_) :: Nil => Left("Selector cannot start with a [cross] segment")
case Segment.Label(last) :: Nil =>
def target =
- hierarchy.node(obj, remainingCrossSelectors).asInstanceOf[mill.Module]
+ obj
.reflect[Target[_]]
.find(_.label == last)
.map(Right(_))
- def invokeCommand[V](mirror: Mirror[T, V], name: String) = for{
- cmd <- mirror.commands.find(_.name == name)
- } yield cmd.invoke(
- mirror.node(obj, remainingCrossSelectors),
- ammonite.main.Scripts.groupArgs(rest.toList)
- ) match {
+ def invokeCommand[V](target: mill.Module, name: String) = for{
+ cmd <- target.commands.find(_.name == name)
+ } yield cmd.invoke(target, ammonite.main.Scripts.groupArgs(rest.toList)) match {
case Router.Result.Success(v) => Right(v)
case _ => Left(s"Command failed $last")
}
def runDefault = for{
- (label, child) <- hierarchy.children
- if label == last
- res <- child.node(obj, remainingCrossSelectors) match{
+ child <- obj.reflect[mill.Module]
+ if child.ctx.segment == Segment.Label(last)
+ res <- child match{
case taskMod: TaskModule => Some(invokeCommand(child, taskMod.defaultCommandName()))
case _ => None
}
} yield res
- def command = invokeCommand(hierarchy, last)
+ def command = invokeCommand(obj, last)
command orElse target orElse runDefault.headOption.flatten match{
case None => Left("Cannot resolve task " +
@@ -57,23 +52,23 @@ object Resolve {
val newRevSelectorsSoFar = head :: revSelectorsSoFar
head match{
case Segment.Label(singleLabel) =>
- hierarchy.children.collectFirst{
- case (label, child) if label == singleLabel => child
+ obj.reflect[mill.Module].find{
+ _.ctx.segment == Segment.Label(singleLabel)
} match{
- case Some(child) => resolve(tail, child, obj, rest, remainingCrossSelectors, newRevSelectorsSoFar)
+ case Some(child: mill.Module) => resolve(tail, child, rest, remainingCrossSelectors, newRevSelectorsSoFar)
case None => Left("Cannot resolve module " + Segments(newRevSelectorsSoFar.reverse:_*).render)
}
case Segment.Cross(cross) =>
- val Some((crossGen, childMirror)) = hierarchy.crossChildren
- val crossOptions = crossGen(hierarchy.node(obj, remainingCrossSelectors))
- if (crossOptions.contains(cross)){
- resolve(tail, childMirror, obj, rest, remainingCrossSelectors, newRevSelectorsSoFar)
- }else{
- Left("Cannot resolve cross " + Segments(newRevSelectorsSoFar.reverse:_*).render)
- }
-
+ obj match{
+ case c: Cross[_] =>
+ c.itemMap.get(cross.toList) match{
+ case Some(m: mill.Module) => resolve(tail, m, rest, remainingCrossSelectors, newRevSelectorsSoFar)
+ case None => Left("Cannot resolve cross " + Segments(newRevSelectorsSoFar.reverse:_*).render)
+ }
+ case _ => Left("Cannot resolve cross " + Segments(newRevSelectorsSoFar.reverse:_*).render)
+ }
}
case Nil => Left("Selector cannot be empty")
diff --git a/core/src/main/scala/mill/main/RunScript.scala b/core/src/main/scala/mill/main/RunScript.scala
index 785db80e..acabcf0a 100644
--- a/core/src/main/scala/mill/main/RunScript.scala
+++ b/core/src/main/scala/mill/main/RunScript.scala
@@ -9,7 +9,6 @@ import ammonite.util.{Name, Res, Util}
import mill.{PathRef, define}
import mill.define.Task
import mill.define.Segment
-import mill.discover.Discovered
import mill.eval.{Evaluator, Result}
import mill.util.{EitherOps, Logger}
import mill.util.Strict.Agg
@@ -73,7 +72,7 @@ object RunScript{
def evaluateMapping(wd: Path,
path: Path,
- interp: ammonite.interp.Interpreter): Res[Discovered.Mapping[_]] = {
+ interp: ammonite.interp.Interpreter): Res[mill.Module] = {
val (pkg, wrapper) = Util.pathToPackageWrapper(Seq(), path relativeTo wd)
@@ -102,15 +101,15 @@ object RunScript{
mapping <- try {
Util.withContextClassloader(interp.evalClassloader) {
Res.Success(
- buildCls.getDeclaredMethod("mapping")
- .invoke(null)
- .asInstanceOf[Discovered.Mapping[_]]
+ buildCls.getField("MODULE$")
+ .get(buildCls)
+ .asInstanceOf[mill.Module]
)
}
} catch {
case e: Throwable => Res.Exception(e, "")
}
- _ <- Res(consistencyCheck(mapping))
+// _ <- Res(consistencyCheck(mapping))
} yield mapping
}
@@ -126,7 +125,7 @@ object RunScript{
case _ => Nil
}
mill.main.Resolve.resolve(
- sel, evaluator.mapping.mirror, evaluator.mapping.base,
+ sel, evaluator.rootModule,
args, crossSelectors, Nil
)
}
@@ -180,12 +179,12 @@ object RunScript{
}
}
- def consistencyCheck[T](mapping: Discovered.Mapping[T]): Either[String, Unit] = {
- val consistencyErrors = Discovered.consistencyCheck(mapping)
- if (consistencyErrors.nonEmpty) {
- Left(s"Failed Discovered.consistencyCheck: ${consistencyErrors.map(_.render)}")
- } else {
- Right(())
- }
- }
+// def consistencyCheck[T](mapping: Discovered.Mapping[T]): Either[String, Unit] = {
+// val consistencyErrors = Discovered.consistencyCheck(mapping)
+// if (consistencyErrors.nonEmpty) {
+// Left(s"Failed Discovered.consistencyCheck: ${consistencyErrors.map(_.render)}")
+// } else {
+// Right(())
+// }
+// }
}
diff --git a/core/src/main/scala/mill/package.scala b/core/src/main/scala/mill/package.scala
index 78233cad..93916c8b 100644
--- a/core/src/main/scala/mill/package.scala
+++ b/core/src/main/scala/mill/package.scala
@@ -6,7 +6,6 @@ package object mill extends JsonFormatters{
val PathRef = mill.eval.PathRef
type PathRef = mill.eval.PathRef
type Module = define.Module
- val Module = define.Module
type Cross[T] = define.Cross[T]
type Agg[T] = util.Loose.Agg[T]
val Agg = util.Loose.Agg