summaryrefslogtreecommitdiff
path: root/src/compiler/scala/tools/reflect/quasiquotes/Holes.scala
diff options
context:
space:
mode:
authorDenys Shabalin <denys.shabalin@typesafe.com>2014-01-22 19:49:21 +0100
committerDenys Shabalin <denys.shabalin@typesafe.com>2014-01-23 13:59:06 +0100
commitadf990ac516d8e04c725a4c7be7c23bdbf922ffa (patch)
tree33039f07740854ed2b6e5ffd1d3bf8624f040294 /src/compiler/scala/tools/reflect/quasiquotes/Holes.scala
parent01f9ab52111712a6f4bc677415e9ad7a3bfe41a2 (diff)
downloadscala-adf990ac516d8e04c725a4c7be7c23bdbf922ffa.tar.gz
scala-adf990ac516d8e04c725a4c7be7c23bdbf922ffa.tar.bz2
scala-adf990ac516d8e04c725a4c7be7c23bdbf922ffa.zip
SI-7275 allow flattening of blocks with ..$
This commit extends current splicing rules to allow flattening of trees into other trees. Without such support it is impossible to correctly create vals with patterns and use it in other location as they could expand into multiple-statement blocks: scala> q"val (a, b) = (1, 2)" res0: reflect.runtime.universe.Tree = { <synthetic> <artifact> private[this] val x$1 = scala.Tuple2(1, 2): @scala.unchecked match { case scala.Tuple2((a @ _), (b @ _)) => scala.Tuple2(a, b) }; val a = x$1._1; val b = x$1._2; () } scala> q"..$res0; println(a + b)" res1: reflect.runtime.universe.Tree = { <synthetic> <artifact> private[this] val x$1 = scala.Tuple2(1, 2): @scala.unchecked match { case scala.Tuple2((a @ _), (b @ _)) => scala.Tuple2(a, b) }; val a = x$1._1; val b = x$1._2; println(a.$plus(b)) }
Diffstat (limited to 'src/compiler/scala/tools/reflect/quasiquotes/Holes.scala')
-rw-r--r--src/compiler/scala/tools/reflect/quasiquotes/Holes.scala13
1 files changed, 11 insertions, 2 deletions
diff --git a/src/compiler/scala/tools/reflect/quasiquotes/Holes.scala b/src/compiler/scala/tools/reflect/quasiquotes/Holes.scala
index 6e1dfcd5e7..057a168b9b 100644
--- a/src/compiler/scala/tools/reflect/quasiquotes/Holes.scala
+++ b/src/compiler/scala/tools/reflect/quasiquotes/Holes.scala
@@ -76,8 +76,7 @@ trait Holes { self: Quasiquotes =>
class ApplyHole(card: Cardinality, splicee: Tree) extends Hole {
val (strippedTpe, tpe): (Type, Type) = {
- if (stripIterable(splicee.tpe)._1.value < card.value) cantSplice()
- val (_, strippedTpe) = stripIterable(splicee.tpe, limit = Some(card))
+ val (strippedCard, strippedTpe) = stripIterable(splicee.tpe, limit = Some(card))
if (isBottomType(strippedTpe)) cantSplice()
else if (isNativeType(strippedTpe)) (strippedTpe, iterableTypeFromCard(card, strippedTpe))
else if (isLiftableType(strippedTpe)) (strippedTpe, iterableTypeFromCard(card, treeType))
@@ -120,6 +119,10 @@ trait Holes { self: Quasiquotes =>
atPos(tree.pos)(lifted)
}
+ protected def toStats(tree: Tree): Tree =
+ // q"$u.build.toStats($tree)"
+ Apply(Select(Select(u, nme.build), nme.toStats), tree :: Nil)
+
protected def toList(tree: Tree, tpe: Type): Tree =
if (isListType(tpe)) tree
else Select(tree, nme.toList)
@@ -154,11 +157,15 @@ trait Holes { self: Quasiquotes =>
*
* ..${x: List[T]} x x.map(lift)
* ..${x: Iterable[T]} x.toList x.toList.map(lift)
+ * ..${x: T} toStats(x) toStats(lift(x))
*
* ...${x: List[List[T]]} x x.map { _.map(lift) } }
* ...${x: List[Iterable[T]} x.map { _.toList } x.map { _.toList.map(lift) } }
+ * ...${x: List[T]} x.map { toStats(_) } x.map { toStats(lift(_)) }
* ...${x: Iterable[List[T]]} x.toList x.toList.map { _.map(lift) }
* ...${x: Iterable[Iterable[T]]} x.toList { _.toList } x.toList.map { _.toList.map(lift) }
+ * ...${x: Iterable[T]} x.toList.map { toStats(_) } x.toList.map { toStats(lift(_)) }
+ * ...${x: T} toStats(x).map { toStats(_) } toStats(lift(x)).map(toStats)
*
* As you can see table is quite repetetive. Middle column is equivalent to the right one with
* lift function equal to identity. Cases with List are equivalent to Iterated ones (due to
@@ -166,7 +173,9 @@ trait Holes { self: Quasiquotes =>
*/
protected def iterated(card: Cardinality, tree: Tree, tpe: Type): Tree = (card, tpe) match {
case (DotDot, tpe @ IterableType(LiftedType(lift))) => mapF(toList(tree, tpe), lift)
+ case (DotDot, LiftedType(lift)) => toStats(lift(tree))
case (DotDotDot, tpe @ IterableType(inner)) => mapF(toList(tree, tpe), t => iterated(DotDot, t, inner))
+ case (DotDotDot, LiftedType(lift)) => mapF(toStats(lift(tree)), toStats)
case _ => global.abort("unreachable")
}
}