summaryrefslogtreecommitdiff
path: root/core/src/main
diff options
context:
space:
mode:
authorLi Haoyi <haoyi.sg@gmail.com>2017-11-05 08:18:46 -0800
committerLi Haoyi <haoyi.sg@gmail.com>2017-11-05 08:18:46 -0800
commit8a873f3336400035a9fae5ed64a57b022d9b48da (patch)
treefc6b9a982b5a3573bd3b3eb694c11619bcdb4289 /core/src/main
parent3ebb8788b8fb3d09dedb7ac11956d780dfadb34b (diff)
downloadmill-8a873f3336400035a9fae5ed64a57b022d9b48da.tar.gz
mill-8a873f3336400035a9fae5ed64a57b022d9b48da.tar.bz2
mill-8a873f3336400035a9fae5ed64a57b022d9b48da.zip
First set of standalone tests for the gnarly `Applicative` logic
Diffstat (limited to 'core/src/main')
-rw-r--r--core/src/main/scala/forge/define/Applicative.scala18
-rw-r--r--core/src/main/scala/forge/define/Target.scala7
2 files changed, 9 insertions, 16 deletions
diff --git a/core/src/main/scala/forge/define/Applicative.scala b/core/src/main/scala/forge/define/Applicative.scala
index ba71221e..ac7c6de5 100644
--- a/core/src/main/scala/forge/define/Applicative.scala
+++ b/core/src/main/scala/forge/define/Applicative.scala
@@ -11,7 +11,9 @@ object Applicative {
@compileTimeOnly("Target#apply() can only be used with a T{...} block")
def apply(): T = ???
}
- trait Applyer[T[_]]{
+ trait Applyer[W[_], T[_]]{
+ def underlying[A](v: W[A]): T[_]
+
def map[A, B](a: T[A], f: A => B): T[B]
def zipMap[R]()(f: () => R) = map(zip(), (_: Unit) => f())
def zipMap[A, R](a: T[A])(f: A => R) = map(a, f)
@@ -55,20 +57,14 @@ object Applicative {
// Derived from @olafurpg's
// https://gist.github.com/olafurpg/596d62f87bf3360a29488b725fbc7608
- val (startPos, endPos) = rec(t.tree)
- .map(t => (t.pos.start, t.pos.end))
- .reduce[(Int, Int)]{ case ((s1, e1), (s2, e2)) => (math.min(s1, s2), math.max(e1, e2))}
+ val defs = rec(t.tree).filter(_.isDef).map(_.symbol).toSet
- val macroSource = t.tree.pos.source
val transformed = c.internal.typingTransform(t.tree) {
case (t @ q"$fun.apply()", api) if t.symbol == targetApplySym =>
+ val localDefs = rec(fun).filter(_.isDef).map(_.symbol).toSet
val used = rec(t)
- val banned = used.filter(x =>
- x.symbol.pos.source == macroSource &&
- x.symbol.pos.start >= startPos &&
- x.symbol.pos.end <= endPos
- )
+ val banned = used.filter(x => defs(x.symbol) && !localDefs(x.symbol))
if (banned.hasNext){
val banned0 = banned.next()
c.abort(
@@ -81,7 +77,7 @@ object Applicative {
c.internal.setInfo(tempSym, t.tpe)
val tempIdent = Ident(tempSym)
c.internal.setType(tempIdent, t.tpe)
- bound.append((fun, tempSym))
+ bound.append((q"${c.prefix}.underlying($fun)", tempSym))
tempIdent
case (t, api) => api.default(t)
}
diff --git a/core/src/main/scala/forge/define/Target.scala b/core/src/main/scala/forge/define/Target.scala
index 0aafee89..b30db434 100644
--- a/core/src/main/scala/forge/define/Target.scala
+++ b/core/src/main/scala/forge/define/Target.scala
@@ -6,10 +6,7 @@ import forge.eval.PathRef
import forge.util.{Args, JsonFormatters}
import play.api.libs.json.{Format, Json}
-import scala.annotation.compileTimeOnly
-import scala.collection.mutable
import scala.language.experimental.macros
-import scala.reflect.macros.blackbox.Context
abstract class Target[T] extends Target.Ops[T] with Applyable[T]{
/**
@@ -29,8 +26,8 @@ abstract class Target[T] extends Target.Ops[T] with Applyable[T]{
def sideHash: Int = 0
}
-object Target extends Applicative.Applyer[Target]{
-
+object Target extends Applicative.Applyer[Target, Target]{
+ def underlying[A](v: Target[A]) = v
type Cacher = Applicative.Cacher[Target[_]]
class Target0[T](t: T) extends Target[T]{
lazy val t0 = t