summaryrefslogtreecommitdiff
path: root/src/compiler
diff options
context:
space:
mode:
authorEugene Burmako <xeno.by@gmail.com>2014-02-06 15:59:00 +0100
committerEugene Burmako <xeno.by@gmail.com>2014-02-06 15:59:00 +0100
commitfa02c15d7033714f94cc8510a3a505d60668bf66 (patch)
tree3487352459b6631660d19a8fb311ca496d048cfb /src/compiler
parent0c16bb0af13c1b30224dcb9de0b88354663d834b (diff)
parentffc3203c3688b6fc5f47f4043bf3a0090de9d985 (diff)
downloadscala-fa02c15d7033714f94cc8510a3a505d60668bf66.tar.gz
scala-fa02c15d7033714f94cc8510a3a505d60668bf66.tar.bz2
scala-fa02c15d7033714f94cc8510a3a505d60668bf66.zip
Merge pull request #3458 from densh/si/8173
SI-8173 add support for patterns like init :+ last to quasiquotes
Diffstat (limited to 'src/compiler')
-rw-r--r--src/compiler/scala/tools/reflect/quasiquotes/Quasiquotes.scala6
-rw-r--r--src/compiler/scala/tools/reflect/quasiquotes/Reifiers.scala36
2 files changed, 27 insertions, 15 deletions
diff --git a/src/compiler/scala/tools/reflect/quasiquotes/Quasiquotes.scala b/src/compiler/scala/tools/reflect/quasiquotes/Quasiquotes.scala
index 3e703924e8..396688c437 100644
--- a/src/compiler/scala/tools/reflect/quasiquotes/Quasiquotes.scala
+++ b/src/compiler/scala/tools/reflect/quasiquotes/Quasiquotes.scala
@@ -16,7 +16,7 @@ abstract class Quasiquotes extends Parsers
lazy val (universe: Tree, args, parts, parse, reify, method) = c.macroApplication match {
case Apply(build.SyntacticTypeApplied(Select(Select(Apply(Select(universe0, _), List(Apply(_, parts0))), interpolator0), method0), _), args0) =>
- debug(s"\nparse prefix:\nuniverse=$universe0\nparts=$parts0\ninterpolator=$interpolator0\nmethod=$method0\nargs=$args0\n")
+ debug(s"parse prefix:\nuniverse=$universe0\nparts=$parts0\ninterpolator=$interpolator0\nmethod=$method0\nargs=$args0\n")
val parts1 = parts0.map {
case lit @ Literal(Constant(s: String)) => s -> lit.pos
case part => c.abort(part.pos, "Quasiquotes can only be used with literal strings")
@@ -43,8 +43,8 @@ abstract class Quasiquotes extends Parsers
lazy val universeTypes = new definitions.UniverseDependentTypes(universe)
def expandQuasiquote = {
- debug(s"\nmacro application:\n${c.macroApplication}\n")
- debug(s"\ncode to parse:\n$code\n")
+ debug(s"macro application:\n${c.macroApplication}\n")
+ debug(s"code to parse:\n$code\n")
val tree = parse(code)
debug(s"parsed:\n${showRaw(tree)}\n$tree\n")
val reified = reify(tree)
diff --git a/src/compiler/scala/tools/reflect/quasiquotes/Reifiers.scala b/src/compiler/scala/tools/reflect/quasiquotes/Reifiers.scala
index 273245f7bd..c2f4a6fdab 100644
--- a/src/compiler/scala/tools/reflect/quasiquotes/Reifiers.scala
+++ b/src/compiler/scala/tools/reflect/quasiquotes/Reifiers.scala
@@ -162,7 +162,7 @@ trait Reifiers { self: Quasiquotes =>
reifyBuildCall(nme.SyntacticNew, earlyDefs, parents, selfdef, body)
case SyntacticDefDef(mods, name, tparams, build.ImplicitParams(vparamss, implparams), tpt, rhs) =>
if (implparams.nonEmpty)
- mirrorBuildCall(nme.SyntacticDefDef, reify(mods), reify(name), reify(tparams),
+ mirrorBuildCall(nme.SyntacticDefDef, reify(mods), reify(name), reify(tparams),
reifyBuildCall(nme.ImplicitParams, vparamss, implparams), reify(tpt), reify(rhs))
else
reifyBuildCall(nme.SyntacticDefDef, mods, name, tparams, vparamss, tpt, rhs)
@@ -305,7 +305,7 @@ trait Reifiers { self: Quasiquotes =>
* > reifyMultiCardinalityList(lst) { ... } { ... }
* q"List($foo, $bar) ++ ${holeMap(qq$f3948f9s$1).tree}"
*/
- def reifyMultiCardinalityList[T](xs: List[T])(fill: PartialFunction[T, Tree])(fallback: T => Tree): Tree
+ def reifyMultiCardinalityList(xs: List[Any])(fill: PartialFunction[Any, Tree])(fallback: Any => Tree): Tree
/** Reifies arbitrary list filling ..$x and ...$y holeMap when they are put
* in the correct position. Fallbacks to regular reification for non-high cardinality
@@ -361,10 +361,10 @@ trait Reifiers { self: Quasiquotes =>
}
class ApplyReifier extends Reifier(isReifyingExpressions = true) {
- def reifyMultiCardinalityList[T](xs: List[T])(fill: PartialFunction[T, Tree])(fallback: T => Tree): Tree =
+ def reifyMultiCardinalityList(xs: List[Any])(fill: PartialFunction[Any, Tree])(fallback: Any => Tree): Tree =
if (xs.isEmpty) mkList(Nil)
else {
- def reifyGroup(group: List[T]): Tree = group match {
+ def reifyGroup(group: List[Any]): Tree = group match {
case List(elem) if fill.isDefinedAt(elem) => fill(elem)
case elems => mkList(elems.map(fallback))
}
@@ -403,14 +403,26 @@ trait Reifiers { self: Quasiquotes =>
}
class UnapplyReifier extends Reifier(isReifyingExpressions = false) {
- def reifyMultiCardinalityList[T](xs: List[T])(fill: PartialFunction[T, Tree])(fallback: T => Tree): Tree = xs match {
- case init :+ last if fill.isDefinedAt(last) =>
- init.foldRight[Tree](fill(last)) { (el, rest) =>
- val cons = Select(Select(Select(Ident(nme.scala_), nme.collection), nme.immutable), nme.CONS)
- Apply(cons, List(fallback(el), rest))
- }
- case _ =>
- mkList(xs.map(fallback))
+ private def collection = ScalaDot(nme.collection)
+ private def collectionColonPlus = Select(collection, nme.COLONPLUS)
+ private def collectionCons = Select(Select(collection, nme.immutable), nme.CONS)
+ private def collectionNil = Select(Select(collection, nme.immutable), nme.Nil)
+ // pq"$lhs :+ $rhs"
+ private def append(lhs: Tree, rhs: Tree) = Apply(collectionColonPlus, lhs :: rhs :: Nil)
+ // pq"$lhs :: $rhs"
+ private def cons(lhs: Tree, rhs: Tree) = Apply(collectionCons, lhs :: rhs :: Nil)
+
+ def reifyMultiCardinalityList(xs: List[Any])(fill: PartialFunction[Any, Tree])(fallback: Any => Tree): Tree = {
+ val grouped = group(xs) { (a, b) => !fill.isDefinedAt(a) && !fill.isDefinedAt(b) }
+ def appended(lst: List[Any], init: Tree) = lst.foldLeft(init) { (l, r) => append(l, fallback(r)) }
+ def prepended(lst: List[Any], init: Tree) = lst.foldRight(init) { (l, r) => cons(fallback(l), r) }
+ grouped match {
+ case init :: List(hole) :: last :: Nil if fill.isDefinedAt(hole) => appended(last, prepended(init, fill(hole)))
+ case init :: List(hole) :: Nil if fill.isDefinedAt(hole) => prepended(init, fill(hole))
+ case List(hole) :: last :: Nil if fill.isDefinedAt(hole) => appended(last, fill(hole))
+ case List(hole) :: Nil if fill.isDefinedAt(hole) => fill(hole)
+ case _ => prepended(xs, collectionNil)
+ }
}
override def reifyModifiers(m: Modifiers) =