diff options
author | Li Haoyi <haoyi.sg@gmail.com> | 2017-11-05 16:19:30 -0800 |
---|---|---|
committer | Li Haoyi <haoyi.sg@gmail.com> | 2017-11-05 16:19:30 -0800 |
commit | 427134c820f4c9a9e281ba3607ab4879c6185613 (patch) | |
tree | f53529f14234e00a2ac41c3275d4898298e74957 /core/src/main | |
parent | 44bd42587532755439fcdc175eb95604966bbea8 (diff) | |
download | mill-427134c820f4c9a9e281ba3607ab4879c6185613.tar.gz mill-427134c820f4c9a9e281ba3607ab4879c6185613.tar.bz2 mill-427134c820f4c9a9e281ba3607ab4879c6185613.zip |
Break out `Cacher.scala` from `Applicative.scala` to fully separate the gnarly macros
Diffstat (limited to 'core/src/main')
-rw-r--r-- | core/src/main/scala/forge/define/Applicative.scala | 36 | ||||
-rw-r--r-- | core/src/main/scala/forge/define/Cacher.scala | 35 | ||||
-rw-r--r-- | core/src/main/scala/forge/define/Target.scala | 14 |
3 files changed, 50 insertions, 35 deletions
diff --git a/core/src/main/scala/forge/define/Applicative.scala b/core/src/main/scala/forge/define/Applicative.scala index 2185c3d4..6a4d1d0c 100644 --- a/core/src/main/scala/forge/define/Applicative.scala +++ b/core/src/main/scala/forge/define/Applicative.scala @@ -37,18 +37,9 @@ object Applicative { def zip[A, B, C, D, E, F](a: T[A], b: T[B], c: T[C], d: T[D], e: T[E], f: T[F]): T[(A, B, C, D, E, F)] def zip[A, B, C, D, E, F, G](a: T[A], b: T[B], c: T[C], d: T[D], e: T[E], f: T[F], g: T[G]): T[(A, B, C, D, E, F, G)] } - 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] - } - } - def impl0[M[_], T: c.WeakTypeTag](c: Context)(t: c.Expr[M[T]]): c.Expr[M[T]] = { - wrapCached(c)(t.tree) - } - def impl[M[_], T: c.WeakTypeTag](c: Context)(t: c.Expr[T])(implicit tt: c.WeakTypeTag[M[_]]): c.Expr[M[T]] = { + def impl[M[_], T: c.WeakTypeTag](c: Context) + (t: c.Expr[T]): c.Expr[M[T]] = { import c.universe._ def rec(t: Tree): Iterator[c.Tree] = Iterator(t) ++ t.children.flatMap(rec(_)) @@ -92,26 +83,7 @@ object Applicative { c.internal.changeOwner(transformed, c.internal.enclosingOwner, callback.symbol) - wrapCached(c)(res) - } - def wrapCached[M[_], T](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.Applicative.Cacher") - - if (ownerIsCacherClass && !owner.isMethod){ - c.abort( - c.enclosingPosition, - "T{} members defined in a Cacher class/trait/object body must be defs" - ) - }else{ - val embedded = - if (!ownerIsCacherClass) t - else q"this.cachedTarget($t)" - - c.Expr[M[T]](embedded) - } + c.Expr[M[T]](res) } + } diff --git a/core/src/main/scala/forge/define/Cacher.scala b/core/src/main/scala/forge/define/Cacher.scala new file mode 100644 index 00000000..8d4d836c --- /dev/null +++ b/core/src/main/scala/forge/define/Cacher.scala @@ -0,0 +1,35 @@ +package forge.define + +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] + } +} +object Cacher{ + def impl0[M[_], T: c.WeakTypeTag](c: Context)(t: c.Expr[M[T]]): c.Expr[M[T]] = { + wrapCached(c)(t) + } + def wrapCached[M[_], T](c: Context)(t: c.Expr[M[T]]) = { + 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)") + } + } +}
\ 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 index b30db434..1d7a49f1 100644 --- a/core/src/main/scala/forge/define/Target.scala +++ b/core/src/main/scala/forge/define/Target.scala @@ -7,6 +7,7 @@ import forge.util.{Args, JsonFormatters} import play.api.libs.json.{Format, Json} import scala.language.experimental.macros +import scala.reflect.macros.blackbox.Context abstract class Target[T] extends Target.Ops[T] with Applyable[T]{ /** @@ -28,14 +29,21 @@ abstract class Target[T] extends Target.Ops[T] with Applyable[T]{ object Target extends Applicative.Applyer[Target, Target]{ def underlying[A](v: Target[A]) = v - type Cacher = Applicative.Cacher[Target[_]] + 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 Applicative.impl0[Target, T] - def apply[T](t: T): Target[T] = macro Applicative.impl[Target, T] + def apply[T](t: Target[T]): Target[T] = macro forge.define.Cacher.impl0[Target, T] + def apply[T](t: T): Target[T] = macro impl[Target, T] + def impl[M[_], T: c.WeakTypeTag](c: Context) + (t: c.Expr[T]) + (implicit tt: c.WeakTypeTag[M[_]]): c.Expr[M[T]] = { + forge.define.Cacher.wrapCached(c)( + Applicative.impl(c)(t) + ) + } abstract class Ops[T]{ this: Target[T] => def map[V](f: T => V) = new Target.Mapped(this, f) |