From 3733cb5e4d041453aff84b35f25fa4162fae5818 Mon Sep 17 00:00:00 2001 From: Li Haoyi Date: Sat, 13 Jan 2018 23:23:39 -0800 Subject: WIP getting rid of `discover/` phase: `core/test:compile` works, but some things still stubbed out with `???` --- core/src/main/scala/mill/define/Cross.scala | 13 ++- core/src/main/scala/mill/define/Ctx.scala | 62 +++++++++++ core/src/main/scala/mill/define/Module.scala | 82 +++++--------- core/src/main/scala/mill/define/Task.scala | 90 ++++++++-------- core/src/main/scala/mill/define/Worker.scala | 7 +- core/src/main/scala/mill/discover/Discovered.scala | 120 --------------------- core/src/main/scala/mill/discover/Mirror.scala | 49 --------- core/src/main/scala/mill/eval/Evaluator.scala | 12 +-- core/src/main/scala/mill/main/MainRunner.scala | 2 - .../main/scala/mill/main/ReplApplyHandler.scala | 20 ++-- core/src/main/scala/mill/main/Resolve.scala | 49 ++++----- core/src/main/scala/mill/main/RunScript.scala | 29 +++-- core/src/main/scala/mill/package.scala | 1 - 13 files changed, 194 insertions(+), 342 deletions(-) create mode 100644 core/src/main/scala/mill/define/Ctx.scala delete mode 100644 core/src/main/scala/mill/discover/Discovered.scala delete mode 100644 core/src/main/scala/mill/discover/Mirror.scala (limited to 'core/src/main/scala') 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 -- cgit v1.2.3