aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJason Zaugg <jzaugg@gmail.com>2014-04-06 17:47:41 +0200
committerJason Zaugg <jzaugg@gmail.com>2014-04-06 17:47:41 +0200
commitdc5ee63a57109c7f0dabb439306a311a850e87f5 (patch)
tree45d6288e890897045348b6b7b084c54626a3daba
parentf53c3bb75be003c12fa6b999ed34eba2a2a38b41 (diff)
parent92ab5b74abcff8b49a408f4bf46c285c0016a44b (diff)
downloadscala-async-dc5ee63a57109c7f0dabb439306a311a850e87f5.tar.gz
scala-async-dc5ee63a57109c7f0dabb439306a311a850e87f5.tar.bz2
scala-async-dc5ee63a57109c7f0dabb439306a311a850e87f5.zip
Merge pull request #71 from retronym/topic/quasiquote-applied
Update to Scala 2.11.0-RC4, adapting to change in quasiquotes
-rw-r--r--build.sbt2
-rw-r--r--src/main/scala/scala/async/internal/AnfTransform.scala18
-rw-r--r--src/main/scala/scala/async/internal/TransformUtils.scala68
3 files changed, 71 insertions, 17 deletions
diff --git a/build.sbt b/build.sbt
index 15a1ca5..6b494be 100644
--- a/build.sbt
+++ b/build.sbt
@@ -1,4 +1,4 @@
-scalaVersion := "2.11.0-RC3"
+scalaVersion := "2.11.0-RC4"
// Uncomment to test with a locally built copy of Scala.
// scalaHome := Some(file("/code/scala2/build/pack"))
diff --git a/src/main/scala/scala/async/internal/AnfTransform.scala b/src/main/scala/scala/async/internal/AnfTransform.scala
index 0e58fa7..e54eb54 100644
--- a/src/main/scala/scala/async/internal/AnfTransform.scala
+++ b/src/main/scala/scala/async/internal/AnfTransform.scala
@@ -161,7 +161,7 @@ private[async] trait AnfTransform {
val stats :+ expr1 = linearize.transformToList(expr)
stats :+ treeCopy.Typed(tree, expr1, tpt)
- case q"$fun[..$targs](...$argss)" if argss.nonEmpty =>
+ case Applied(fun, targs, argss) if argss.nonEmpty =>
// we can assume that no await call appears in a by-name argument position,
// this has already been checked.
val funStats :+ simpleFun = linearize.transformToList(fun)
@@ -188,21 +188,7 @@ private[async] trait AnfTransform {
}
}
-
- /** The depth of the nested applies: e.g. Apply(Apply(Apply(_, _), _), _)
- * has depth 3. Continues through type applications (without counting them.)
- */
- def applyDepth: Int = {
- def loop(tree: Tree): Int = tree match {
- case Apply(fn, _) => 1 + loop(fn)
- case TypeApply(fn, _) => loop(fn)
- case AppliedTypeTree(fn, _) => loop(fn)
- case _ => 0
- }
- loop(tree)
- }
-
- val typedNewApply = copyApplied(tree, applyDepth)
+ val typedNewApply = copyApplied(tree, argss.length)
funStats ++ argStatss.flatten.flatten :+ typedNewApply
diff --git a/src/main/scala/scala/async/internal/TransformUtils.scala b/src/main/scala/scala/async/internal/TransformUtils.scala
index 5d0a96f..a01a801 100644
--- a/src/main/scala/scala/async/internal/TransformUtils.scala
+++ b/src/main/scala/scala/async/internal/TransformUtils.scala
@@ -41,6 +41,74 @@ private[async] trait TransformUtils {
def isAwait(fun: Tree) =
fun.symbol == defn.Async_await
+ // Copy pasted from TreeInfo in the compiler.
+ // Using a quasiquote pattern like `case q"$fun[..$targs](...$args)" => is not
+ // sufficient since https://github.com/scala/scala/pull/3656 as it doesn't match
+ // constructor invocations.
+ class Applied(val tree: Tree) {
+ /** The tree stripped of the possibly nested applications.
+ * The original tree if it's not an application.
+ */
+ def callee: Tree = {
+ def loop(tree: Tree): Tree = tree match {
+ case Apply(fn, _) => loop(fn)
+ case tree => tree
+ }
+ loop(tree)
+ }
+
+ /** The `callee` unwrapped from type applications.
+ * The original `callee` if it's not a type application.
+ */
+ def core: Tree = callee match {
+ case TypeApply(fn, _) => fn
+ case AppliedTypeTree(fn, _) => fn
+ case tree => tree
+ }
+
+ /** The type arguments of the `callee`.
+ * `Nil` if the `callee` is not a type application.
+ */
+ def targs: List[Tree] = callee match {
+ case TypeApply(_, args) => args
+ case AppliedTypeTree(_, args) => args
+ case _ => Nil
+ }
+
+ /** (Possibly multiple lists of) value arguments of an application.
+ * `Nil` if the `callee` is not an application.
+ */
+ def argss: List[List[Tree]] = {
+ def loop(tree: Tree): List[List[Tree]] = tree match {
+ case Apply(fn, args) => loop(fn) :+ args
+ case _ => Nil
+ }
+ loop(tree)
+ }
+ }
+
+ /** Returns a wrapper that knows how to destructure and analyze applications.
+ */
+ def dissectApplied(tree: Tree) = new Applied(tree)
+
+ /** Destructures applications into important subparts described in `Applied` class,
+ * namely into: core, targs and argss (in the specified order).
+ *
+ * Trees which are not applications are also accepted. Their callee and core will
+ * be equal to the input, while targs and argss will be Nil.
+ *
+ * The provided extractors don't expose all the API of the `Applied` class.
+ * For advanced use, call `dissectApplied` explicitly and use its methods instead of pattern matching.
+ */
+ object Applied {
+ def apply(tree: Tree): Applied = new Applied(tree)
+
+ def unapply(applied: Applied): Option[(Tree, List[Tree], List[List[Tree]])] =
+ Some((applied.core, applied.targs, applied.argss))
+
+ def unapply(tree: Tree): Option[(Tree, List[Tree], List[List[Tree]])] =
+ unapply(dissectApplied(tree))
+ }
private lazy val Boolean_ShortCircuits: Set[Symbol] = {
import definitions.BooleanClass
def BooleanTermMember(name: String) = BooleanClass.typeSignature.member(newTermName(name).encodedName)