diff options
author | Li Haoyi <haoyi.sg@gmail.com> | 2018-01-07 23:53:11 -0800 |
---|---|---|
committer | Li Haoyi <haoyi.sg@gmail.com> | 2018-01-07 23:53:11 -0800 |
commit | 5aa363015646644cc81afdf0120d8df441161e2d (patch) | |
tree | b82f3964f12d5d311004d2a6b5b465fc83f3cd2f /core/src/main/scala | |
parent | 4fd5f8cdfdc924bff2f4fbc6b5d7072d530fa531 (diff) | |
download | mill-5aa363015646644cc81afdf0120d8df441161e2d.tar.gz mill-5aa363015646644cc81afdf0120d8df441161e2d.tar.bz2 mill-5aa363015646644cc81afdf0120d8df441161e2d.zip |
Swap over to a new, concise `CrossModule[T](..cases)` macro syntax that automatically propagates the `ctx` for you
Diffstat (limited to 'core/src/main/scala')
-rw-r--r-- | core/src/main/scala/mill/define/Cross.scala | 104 | ||||
-rw-r--r-- | core/src/main/scala/mill/define/Module.scala | 2 | ||||
-rw-r--r-- | core/src/main/scala/mill/package.scala | 4 |
3 files changed, 60 insertions, 50 deletions
diff --git a/core/src/main/scala/mill/define/Cross.scala b/core/src/main/scala/mill/define/Cross.scala index 4d68ee62..4b0e1b8f 100644 --- a/core/src/main/scala/mill/define/Cross.scala +++ b/core/src/main/scala/mill/define/Cross.scala @@ -1,4 +1,7 @@ package mill.define +import language.experimental.macros +import scala.reflect.ClassTag +import scala.reflect.macros.{Context, blackbox} case class Cross[+T](items: List[(List[Any], T)])(implicit val e: sourcecode.Enclosing, val l: sourcecode.Line){ def flatMap[V](f: T => Cross[V]): Cross[V] = new Cross( @@ -26,53 +29,62 @@ object Cross{ def apply[T](t: T*) = new Cross(t.map(i => List(i) -> i).toList) } -class CrossModule[T, V](constructor: (T, Module.Ctx) => V, cases: T*) - (implicit ctx: Module.Ctx) -extends Cross[V]({ - cases.toList.map(x => - ( - List(x), - constructor( - x, - ctx.copy( - segments0 = Segments(ctx.segments0.value :+ ctx.segment), - segment = Segment.Cross(List(x)) - ) - ) - ) - ) -}) +object CrossModule{ + def autoCast[A](x: Any): A = x.asInstanceOf[A] + abstract class Implicit[T]{ + def make(v: Any, ctx: Module.Ctx): T + def crossValues(v: Any): List[Any] + } + object Implicit{ + implicit def make[T]: Implicit[T] = macro makeImpl[T] + def makeImpl[T: c.WeakTypeTag](c: blackbox.Context): c.Expr[Implicit[T]] = { + import c.universe._ + val tpe = weakTypeOf[T] -class CrossModule2[T1, T2, V](constructor: (T1, T2, Module.Ctx) => V, cases: (T1, T2)*) - (implicit ctx: Module.Ctx) -extends Cross[V]( - cases.toList.map(x => - ( - List(x._2, x._1), - constructor( - x._1, x._2, - ctx.copy( - segments0 = Segments(ctx.segments0.value :+ ctx.segment), - segment = Segment.Cross(List(x._2, x._1)) - ) - ) - ) - ) -) + val primaryConstructorArgs = + tpe.typeSymbol.asClass.primaryConstructor.typeSignature.paramLists.head -class CrossModule3[T1, T2, T3, V](constructor: (T1, T2, T3, Module.Ctx) => V, cases: (T1, T2, T3)*) - (implicit ctx: Module.Ctx) -extends Cross[V]( - cases.toList.map(x => - ( - List(x._3, x._2, x._1), - constructor( - x._1, x._2, x._3, - ctx.copy( - segments0 = Segments(ctx.segments0.value :+ ctx.segment), - segment = Segment.Cross(List(x._3, x._2, x._1)) - ) + val tree = primaryConstructorArgs match{ + case List(arg) => + q""" + new mill.define.CrossModule.Implicit[$tpe]{ + def make(v: Any, ctx0: mill.define.Module.Ctx) = new $tpe(v.asInstanceOf[${arg.info}]){ + override def ctx = ctx0 + } + def crossValues(v: Any) = List(v) + } + """ + case args => + val argTupleValues = for((a, n) <- args.zipWithIndex) yield{ + q"v.asInstanceOf[scala.Product].productElement($n).asInstanceOf[${a.info}]" + } + q""" + new mill.define.CrossModule.Implicit[$tpe]{ + def make(v: Any, ctx0: mill.define.Module.Ctx) = new $tpe(..$argTupleValues){ + override def ctx = ctx0 + } + def crossValues(v: Any) = List(..$argTupleValues) + } + """ + + } + c.Expr[Implicit[T]](tree) + } + } +} +class CrossModule[T](cases: Any*) + (implicit ci: CrossModule.Implicit[T], + ctx: Module.Ctx) +extends Cross[T]({ + for(c <- cases.toList) yield{ + val crossValues = ci.crossValues(c) + val sub = ci.make( + c, + ctx.copy( + segments0 = Segments(ctx.segments0.value :+ ctx.segment), + segment = Segment.Cross(crossValues.reverse) ) ) - ) -)
\ No newline at end of file + (crossValues.reverse, sub) + } +})
\ 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 c5837278..9c830c1a 100644 --- a/core/src/main/scala/mill/define/Module.scala +++ b/core/src/main/scala/mill/define/Module.scala @@ -20,7 +20,7 @@ case class Segments(value: Seq[Segment]) * the concrete instance. */ class Module(implicit ctx0: Module.Ctx) extends mill.moduledefs.Cacher{ - val ctx = ctx0 + 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 // one else trying to use sourcecode.{Enclosing,Line} to capture debug info diff --git a/core/src/main/scala/mill/package.scala b/core/src/main/scala/mill/package.scala index b5ab6429..b578ed3b 100644 --- a/core/src/main/scala/mill/package.scala +++ b/core/src/main/scala/mill/package.scala @@ -7,7 +7,5 @@ package object mill extends JsonFormatters{ type PathRef = mill.eval.PathRef type Module = define.Module val Module = define.Module - type CrossModule[T, V] = define.CrossModule[T, V] - type CrossModule2[T1, T2, V] = define.CrossModule2[T1, T2, V] - type CrossModule3[T1, T2, T3, V] = define.CrossModule3[T1, T2, T3, V] + type CrossModule[T] = define.CrossModule[T] } |