diff options
author | Denys Shabalin <denys.shabalin@typesafe.com> | 2014-01-22 19:49:21 +0100 |
---|---|---|
committer | Denys Shabalin <denys.shabalin@typesafe.com> | 2014-01-23 13:59:06 +0100 |
commit | adf990ac516d8e04c725a4c7be7c23bdbf922ffa (patch) | |
tree | 33039f07740854ed2b6e5ffd1d3bf8624f040294 /src/compiler | |
parent | 01f9ab52111712a6f4bc677415e9ad7a3bfe41a2 (diff) | |
download | scala-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')
-rw-r--r-- | src/compiler/scala/tools/reflect/quasiquotes/Holes.scala | 13 |
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") } } |