diff options
Diffstat (limited to 'src/main/scala')
-rw-r--r-- | src/main/scala/forge/DefCtx.scala | 69 | ||||
-rw-r--r-- | src/main/scala/forge/Evaluator.scala | 24 | ||||
-rw-r--r-- | src/main/scala/forge/Target.scala | 5 |
3 files changed, 68 insertions, 30 deletions
diff --git a/src/main/scala/forge/DefCtx.scala b/src/main/scala/forge/DefCtx.scala index b9c02602..97f9bf3f 100644 --- a/src/main/scala/forge/DefCtx.scala +++ b/src/main/scala/forge/DefCtx.scala @@ -1,14 +1,15 @@ package forge +import scala.annotation.compileTimeOnly import scala.language.experimental.macros -import scala.reflect.macros._ +import scala.reflect.macros.blackbox._ -sealed abstract class DefCtx(val value: Option[String]) +final case class DefCtx(label: String) object DefCtx{ - implicit object Anonymous extends DefCtx(None) - case class Labeled(label: String) extends DefCtx(Some(label)) + @compileTimeOnly("A DefCtx can only be provided directly within a T{} macro") + implicit def dummy: DefCtx with Int = ??? } object T{ @@ -16,19 +17,61 @@ object T{ def applyImpl[T: c.WeakTypeTag](c: Context)(expr: c.Expr[T]): c.Expr[T] = { import c.universe._ - val transformed = expr.tree match{ + var count = 0 + object transformer extends c.universe.Transformer { + override def transform(tree: c.Tree): c.Tree = { + if (tree.toString.startsWith("forge.") && tree.toString.endsWith(".DefCtx.dummy")) { + count += 1 + c.typecheck(q"forge.DefCtx(sourcecode.Enclosing() + $count)") + }else tree match{ + case Apply(fun, args) => + val extendedParams = fun.tpe.paramLists.head.padTo( + args.length, + fun.tpe.paramLists.head.lastOption.getOrElse(null) + ) + val newArgs = + for((sym, tree) <- extendedParams.zip(args)) + yield { + if (sym.asTerm.isByNameParam) tree + else transform(tree) + } + treeCopy.Apply(tree, transform(fun), newArgs) + + case t: DefDef => t + case t: ClassDef => t + case t: Function => t + case t: LabelDef => t + case t => super.transform(t) + } + + } + } + + + def transformTerminal(tree: c.Tree): c.Tree = tree match{ + case Block(stats, returnExpr) => + treeCopy.Block( + tree, + stats.map(transformer.transform(_)), + transformTerminal(returnExpr) + ) + case Apply(fun, args) => - var transformed = false - val newArgs = args.map{ - case x if x.tpe == weakTypeOf[DefCtx.Anonymous.type] => - transformed = true - q"forge.DefCtx.Labeled(sourcecode.Enclosing())" - case x => x + var isTransformed = false + val newArgs = for(x <- args) yield { + if (x.toString.startsWith("forge.") && x.toString.endsWith(".DefCtx.dummy")) { + isTransformed = true + c.typecheck(q"forge.DefCtx(sourcecode.Enclosing())") + }else transformer.transform(x) } - assert(transformed) - Apply(fun, newArgs) + + assert(isTransformed) + treeCopy.Apply(tree, transformer.transform(fun), newArgs) + case _ => ??? } + + val transformed = transformTerminal(expr.tree) c.Expr[T](transformed) } }
\ No newline at end of file diff --git a/src/main/scala/forge/Evaluator.scala b/src/main/scala/forge/Evaluator.scala index d6ff39a2..43b4f353 100644 --- a/src/main/scala/forge/Evaluator.scala +++ b/src/main/scala/forge/Evaluator.scala @@ -20,27 +20,25 @@ class Evaluator(workspacePath: jnio.Path, for (target <- sortedTargets){ val inputResults = target.inputs.map(results).toIndexedSeq - val targetDestPath = target.defCtx.value match{ - case Some(enclosingStr) => - val targetDestPath = workspacePath.resolve( - jnio.Paths.get(enclosingStr.stripSuffix(enclosingBase.value.getOrElse(""))) - ) - deleteRec(targetDestPath) - targetDestPath - - case None => jnio.Files.createTempDirectory(null) + val targetDestPath = { + val enclosingStr = target.defCtx.label + val targetDestPath = workspacePath.resolve( + jnio.Paths.get(enclosingStr.stripSuffix(enclosingBase.label)) + ) + deleteRec(targetDestPath) + targetDestPath + } val inputsHash = inputResults.hashCode - target.defCtx.value.flatMap(resultCache.get) match{ + resultCache.get(target.defCtx.label) match{ case Some((hash, res)) if hash == inputsHash && !target.dirty => results(target) = res case _ => evaluated.append(target) val res = target.evaluate(new Args(inputResults, targetDestPath)) - for(label <- target.defCtx.value) { - resultCache(label) = (inputsHash, res) - } + + resultCache(target.defCtx.label) = (inputsHash, res) results(target) = res } diff --git a/src/main/scala/forge/Target.scala b/src/main/scala/forge/Target.scala index d7edc188..4d356d29 100644 --- a/src/main/scala/forge/Target.scala +++ b/src/main/scala/forge/Target.scala @@ -14,10 +14,7 @@ trait TargetOps[T]{ this: Target[T] => this.zip(other).map(s.apply _ tupled) } - override def toString = defCtx.value match{ - case None => this.getClass.getSimpleName + "@" + Integer.toHexString(System.identityHashCode(this)) - case Some(s) => this.getClass.getName + "@" + s - } + override def toString = this.getClass.getName + "@" + defCtx.label } trait Target[T] extends TargetOps[T]{ /** |