summaryrefslogtreecommitdiff
path: root/core
diff options
context:
space:
mode:
authorLi Haoyi <haoyi.sg@gmail.com>2017-11-05 16:19:30 -0800
committerLi Haoyi <haoyi.sg@gmail.com>2017-11-05 16:19:30 -0800
commit427134c820f4c9a9e281ba3607ab4879c6185613 (patch)
treef53529f14234e00a2ac41c3275d4898298e74957 /core
parent44bd42587532755439fcdc175eb95604966bbea8 (diff)
downloadmill-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')
-rw-r--r--core/src/main/scala/forge/define/Applicative.scala36
-rw-r--r--core/src/main/scala/forge/define/Cacher.scala35
-rw-r--r--core/src/main/scala/forge/define/Target.scala14
-rw-r--r--core/src/test/scala/forge/ApplicativeTests.scala1
4 files changed, 50 insertions, 36 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)
diff --git a/core/src/test/scala/forge/ApplicativeTests.scala b/core/src/test/scala/forge/ApplicativeTests.scala
index f5c725a2..1da21a5c 100644
--- a/core/src/test/scala/forge/ApplicativeTests.scala
+++ b/core/src/test/scala/forge/ApplicativeTests.scala
@@ -10,7 +10,6 @@ object ApplicativeTests extends TestSuite {
object Opt extends define.Applicative.Applyer[Opt, Option]{
def underlying[A](v: Opt[A]) = v.o
- def apply[T](t: Option[T]): Option[T] = macro Applicative.impl0[Option, T]
def apply[T](t: T): Option[T] = macro Applicative.impl[Option, T]
type O[+T] = Option[T]