From 3b10725ee3a1f84855a0654c5e386bc7465816d3 Mon Sep 17 00:00:00 2001 From: Li Haoyi Date: Sat, 4 Nov 2017 09:09:02 -0700 Subject: First experiment using `Cacher interface` combined with `Caller` implicits to turn `def foo = T{}` into pseudo-`lazy val`s, that we can override in subclasses using stackable traits --- core/src/main/scala/forge/Discovered.scala | 6 +++++- core/src/main/scala/forge/Evaluator.scala | 1 + core/src/main/scala/forge/Target.scala | 15 ++++++++++++++- core/src/main/scala/forge/util/Caller.scala | 12 ++++++++++++ 4 files changed, 32 insertions(+), 2 deletions(-) create mode 100644 core/src/main/scala/forge/util/Caller.scala (limited to 'core/src/main') diff --git a/core/src/main/scala/forge/Discovered.scala b/core/src/main/scala/forge/Discovered.scala index 03577b1f..e3aa31f9 100644 --- a/core/src/main/scala/forge/Discovered.scala +++ b/core/src/main/scala/forge/Discovered.scala @@ -29,7 +29,11 @@ object Discovered { val tpe = c.weakTypeTag[T].tpe def rec(segments: List[String], t: c.Type): Seq[Seq[String]] = for { m <- t.members.toSeq - if m.isTerm && (m.asTerm.isGetter || m.asTerm.isLazy) || m.isModule + if + (m.isTerm && (m.asTerm.isGetter || m.asTerm.isLazy)) || + m.isModule || + (m.isMethod && m.typeSignature.paramLists.isEmpty && m.typeSignature.resultType <:< c.weakTypeOf[Target[_]]) + res <- { val extendedSegments = m.name.toString :: segments val self = diff --git a/core/src/main/scala/forge/Evaluator.scala b/core/src/main/scala/forge/Evaluator.scala index 50dc46d4..3ef605b7 100644 --- a/core/src/main/scala/forge/Evaluator.scala +++ b/core/src/main/scala/forge/Evaluator.scala @@ -105,6 +105,7 @@ class Evaluator(workspacePath: Path, ) val args = new Args(targetInputValues, targetDestPath) + val res = target.evaluate(args) for(targetLabel <- labeling.get(target)){ terminalResults(target) = targetLabel diff --git a/core/src/main/scala/forge/Target.scala b/core/src/main/scala/forge/Target.scala index c1790960..df9d9cc3 100644 --- a/core/src/main/scala/forge/Target.scala +++ b/core/src/main/scala/forge/Target.scala @@ -32,6 +32,14 @@ abstract class Target[T] extends Target.Ops[T]{ } object Target{ + trait Cacher{ + val cacherLazyMap = mutable.Map.empty[(Any, sourcecode.Line, sourcecode.Enclosing), Target[_]] + def T[T](t: T): Target[T] = macro impl[T] + def T[T](t: => Target[T]) + (implicit c: forge.util.Caller, l: sourcecode.Line, e: sourcecode.Enclosing): Target[T] = { + cacherLazyMap.getOrElseUpdate((c, l, e), t).asInstanceOf[Target[T]] + } + } class Target0[T](t: T) extends Target[T]{ lazy val t0 = t val inputs = Nil @@ -68,7 +76,12 @@ object Target{ val bindings = symbols.map(c.internal.valDef(_)) - val embedded = q"new forge.Target.Target1(forge.zipMap(..$exprs){ (..$bindings) => $transformed })" + val newTargetTree = q"new forge.Target.Target1(forge.zipMap(..$exprs){ (..$bindings) => $transformed })" + + val embedded = + if (!(c.prefix.tree.tpe <:< typeOf[Cacher])) newTargetTree + else q"${c.prefix}.T($newTargetTree)" + c.Expr[Target[T]](embedded) } diff --git a/core/src/main/scala/forge/util/Caller.scala b/core/src/main/scala/forge/util/Caller.scala new file mode 100644 index 00000000..30dcb22a --- /dev/null +++ b/core/src/main/scala/forge/util/Caller.scala @@ -0,0 +1,12 @@ +package forge.util + +import scala.reflect.macros.blackbox +import language.experimental.macros +case class Caller(value: Any) +object Caller { + implicit def generate: Caller = macro impl + def impl(c: blackbox.Context): c.Tree = { + import c.universe._ + q"new _root_.forge.util.Caller(this)" + } +} -- cgit v1.2.3