summaryrefslogtreecommitdiff
path: root/src/main/scala
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/scala')
-rw-r--r--src/main/scala/forge/DefCtx.scala69
-rw-r--r--src/main/scala/forge/Evaluator.scala24
-rw-r--r--src/main/scala/forge/Target.scala5
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]{
/**