summaryrefslogtreecommitdiff
path: root/src/compiler/scala/tools
diff options
context:
space:
mode:
authorEugene Burmako <xeno.by@gmail.com>2014-02-16 16:16:49 +0100
committerEugene Burmako <xeno.by@gmail.com>2014-02-16 16:16:49 +0100
commitb0ac4da8a300f3a2c73423ec6f783d1bfb708843 (patch)
treed4f4b5d1acb4f60d0a0ef532093a3d662499306a /src/compiler/scala/tools
parent23326def4bf5bcfb7f5286707eed2f57a5da731d (diff)
parent8a27336c0e896d3fee6213068c77f23e62a0cd18 (diff)
downloadscala-b0ac4da8a300f3a2c73423ec6f783d1bfb708843.tar.gz
scala-b0ac4da8a300f3a2c73423ec6f783d1bfb708843.tar.bz2
scala-b0ac4da8a300f3a2c73423ec6f783d1bfb708843.zip
Merge pull request #3455 from densh/topic/patdef
Fix SI-8202 and improve support for splicing patterns into vals
Diffstat (limited to 'src/compiler/scala/tools')
-rw-r--r--src/compiler/scala/tools/nsc/ast/parser/Parsers.scala2
-rw-r--r--src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala2
-rw-r--r--src/compiler/scala/tools/reflect/quasiquotes/Parsers.scala41
-rw-r--r--src/compiler/scala/tools/reflect/quasiquotes/Placeholders.scala28
-rw-r--r--src/compiler/scala/tools/reflect/quasiquotes/Reifiers.scala25
5 files changed, 64 insertions, 34 deletions
diff --git a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala
index 5dadbd0825..8271363527 100644
--- a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala
+++ b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala
@@ -2492,7 +2492,7 @@ self =>
def mkDefs(p: Tree, tp: Tree, rhs: Tree): List[Tree] = {
val trees = {
val pat = if (tp.isEmpty) p else Typed(p, tp) setPos (p.pos union tp.pos)
- gen.mkPatDef(newmods, pat, rhs)
+ makePatDef(newmods, pat, rhs)
}
if (newmods.isDeferred) {
trees match {
diff --git a/src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala b/src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala
index 525dcffb0c..6e5a3f6ef7 100644
--- a/src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala
+++ b/src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala
@@ -168,4 +168,6 @@ abstract class TreeBuilder {
vparamss ::: List(evidenceParams)
}
}
+
+ def makePatDef(mods: Modifiers, pat: Tree, rhs: Tree) = gen.mkPatDef(mods, pat, rhs)
}
diff --git a/src/compiler/scala/tools/reflect/quasiquotes/Parsers.scala b/src/compiler/scala/tools/reflect/quasiquotes/Parsers.scala
index 9f6807fe17..301e7051df 100644
--- a/src/compiler/scala/tools/reflect/quasiquotes/Parsers.scala
+++ b/src/compiler/scala/tools/reflect/quasiquotes/Parsers.scala
@@ -14,6 +14,7 @@ import scala.util.Try
*/
trait Parsers { self: Quasiquotes =>
import global.{Try => _, _}
+ import build.implodePatDefs
abstract class Parser extends {
val global: self.global.type = self.global
@@ -61,12 +62,10 @@ trait Parsers { self: Quasiquotes =>
override implicit def fresh: FreshNameCreator = parser.fresh
// q"(..$xs)"
- override def makeTupleTerm(trees: List[Tree]): Tree =
- Apply(Ident(nme.QUASIQUOTE_TUPLE), trees)
+ override def makeTupleTerm(trees: List[Tree]): Tree = TuplePlaceholder(trees)
// tq"(..$xs)"
- override def makeTupleType(trees: List[Tree]): Tree =
- AppliedTypeTree(Ident(tpnme.QUASIQUOTE_TUPLE), trees)
+ override def makeTupleType(trees: List[Tree]): Tree = TupleTypePlaceholder(trees)
// q"{ $x }"
override def makeBlock(stats: List[Tree]): Tree = stats match {
@@ -75,30 +74,32 @@ trait Parsers { self: Quasiquotes =>
}
// tq"$a => $b"
- override def makeFunctionTypeTree(argtpes: List[Tree], restpe: Tree): Tree =
- AppliedTypeTree(Ident(tpnme.QUASIQUOTE_FUNCTION), argtpes :+ restpe)
+ override def makeFunctionTypeTree(argtpes: List[Tree], restpe: Tree): Tree = FunctionTypePlaceholder(argtpes, restpe)
+
+ // make q"val (x: T) = rhs" be equivalent to q"val x: T = rhs" for sake of bug compatibility (SI-8211)
+ override def makePatDef(mods: Modifiers, pat: Tree, rhs: Tree) = pat match {
+ case TuplePlaceholder(inParensPat :: Nil) => super.makePatDef(mods, inParensPat, rhs)
+ case _ => super.makePatDef(mods, pat, rhs)
+ }
}
import treeBuilder.{global => _, unit => _, _}
- def quasiquoteParam(name: Name, flags: FlagSet = NoFlags) =
- ValDef(Modifiers(flags), name.toTermName, Ident(tpnme.QUASIQUOTE_PARAM), EmptyTree)
-
// q"def foo($x)"
override def param(owner: Name, implicitmod: Int, caseParam: Boolean): ValDef =
if (isHole && lookingAhead { in.token == COMMA || in.token == RPAREN }) {
- quasiquoteParam(ident(), implicitmod)
+ ParamPlaceholder(implicitmod, ident())
} else super.param(owner, implicitmod, caseParam)
// q"($x) => ..." && q"class X { selfie => }
override def convertToParam(tree: Tree): ValDef = tree match {
- case Ident(name) if isHole(name) => quasiquoteParam(name)
+ case Ident(name) if isHole(name) => ParamPlaceholder(NoFlags, name)
case _ => super.convertToParam(tree)
}
// q"foo match { case $x }"
override def caseClause(): CaseDef =
if (isHole && lookingAhead { in.token == CASE || in.token == RBRACE || in.token == SEMI }) {
- val c = makeCaseDef(Apply(Ident(nme.QUASIQUOTE_CASE), List(Ident(ident()))), EmptyTree, EmptyTree)
+ val c = CasePlaceholder(ident())
while (in.token == SEMI) in.nextToken()
c
} else
@@ -132,7 +133,7 @@ trait Parsers { self: Quasiquotes =>
in.nextToken()
annot :: readAnnots(annot)
case _ if isHole && lookingAhead { isAnnotation || isModifier || isDefIntro || isIdent || isStatSep || in.token == LPAREN } =>
- val ann = Apply(Select(New(Ident(tpnme.QUASIQUOTE_MODS)), nme.CONSTRUCTOR), List(Literal(Constant(in.name.toString))))
+ val ann = ModsPlaceholder(in.name)
in.nextToken()
ann :: readAnnots(annot)
case _ =>
@@ -141,13 +142,13 @@ trait Parsers { self: Quasiquotes =>
override def refineStat(): List[Tree] =
if (isHole && !isDclIntro) {
- val result = ValDef(NoMods, in.name, Ident(tpnme.QUASIQUOTE_REFINE_STAT), EmptyTree) :: Nil
+ val result = RefineStatPlaceholder(in.name) :: Nil
in.nextToken()
result
} else super.refineStat()
override def ensureEarlyDef(tree: Tree) = tree match {
- case Ident(name: TermName) if isHole(name) => ValDef(NoMods | Flag.PRESUPER, name, Ident(tpnme.QUASIQUOTE_EARLY_DEF), EmptyTree)
+ case Ident(name: TermName) if isHole(name) => EarlyDefPlaceholder(name)
case _ => super.ensureEarlyDef(tree)
}
@@ -158,14 +159,14 @@ trait Parsers { self: Quasiquotes =>
override def topStat = super.topStat.orElse {
case _ if isHole =>
- val stats = ValDef(NoMods, in.name, Ident(tpnme.QUASIQUOTE_PACKAGE_STAT), EmptyTree) :: Nil
+ val stats = PackageStatPlaceholder(in.name) :: Nil
in.nextToken()
stats
}
override def enumerator(isFirst: Boolean, allowNestedIf: Boolean = true) =
if (isHole && lookingAhead { in.token == EOF || in.token == RPAREN || isStatSep }) {
- val res = build.SyntacticValFrom(Bind(in.name, Ident(nme.WILDCARD)), Ident(nme.QUASIQUOTE_FOR_ENUM)) :: Nil
+ val res = ForEnumPlaceholder(in.name) :: Nil
in.nextToken()
res
} else super.enumerator(isFirst, allowNestedIf)
@@ -182,7 +183,7 @@ trait Parsers { self: Quasiquotes =>
}
object TermParser extends Parser {
- def entryPoint = parser => Q(gen.mkTreeOrBlock(parser.templateOrTopStatSeq()))
+ def entryPoint = parser => Q(implodePatDefs(gen.mkTreeOrBlock(parser.templateOrTopStatSeq())))
}
object TypeParser extends Parser {
@@ -195,7 +196,7 @@ trait Parsers { self: Quasiquotes =>
}
object CaseParser extends Parser {
- def entryPoint = _.caseClause()
+ def entryPoint = parser => implodePatDefs(parser.caseClause())
}
object PatternParser extends Parser {
@@ -209,7 +210,7 @@ trait Parsers { self: Quasiquotes =>
def entryPoint = { parser =>
val enums = parser.enumerator(isFirst = false, allowNestedIf = false)
assert(enums.length == 1)
- enums.head
+ implodePatDefs(enums.head)
}
}
diff --git a/src/compiler/scala/tools/reflect/quasiquotes/Placeholders.scala b/src/compiler/scala/tools/reflect/quasiquotes/Placeholders.scala
index 825d0c04f3..130a01332b 100644
--- a/src/compiler/scala/tools/reflect/quasiquotes/Placeholders.scala
+++ b/src/compiler/scala/tools/reflect/quasiquotes/Placeholders.scala
@@ -100,6 +100,8 @@ trait Placeholders { self: Quasiquotes =>
}
object ModsPlaceholder extends HolePlaceholder {
+ def apply(name: Name) =
+ Apply(Select(New(Ident(tpnme.QUASIQUOTE_MODS)), nme.CONSTRUCTOR), List(Literal(Constant(name.toString))))
def matching = {
case Apply(Select(New(Ident(tpnme.QUASIQUOTE_MODS)), nme.CONSTRUCTOR), List(Literal(Constant(s: String)))) => TermName(s)
}
@@ -112,12 +114,16 @@ trait Placeholders { self: Quasiquotes =>
}
object ParamPlaceholder extends HolePlaceholder {
+ def apply(flags: FlagSet, name: Name) =
+ ValDef(Modifiers(flags), nme.QUASIQUOTE_PARAM, Ident(name), EmptyTree)
def matching = {
- case ValDef(_, name, Ident(tpnme.QUASIQUOTE_PARAM), EmptyTree) => name
+ case ValDef(_, nme.QUASIQUOTE_PARAM, Ident(name), EmptyTree) => name
}
}
object TuplePlaceholder {
+ def apply(args: List[Tree]) =
+ Apply(Ident(nme.QUASIQUOTE_TUPLE), args)
def unapply(tree: Tree): Option[List[Tree]] = tree match {
case Apply(Ident(nme.QUASIQUOTE_TUPLE), args) => Some(args)
case _ => None
@@ -125,6 +131,8 @@ trait Placeholders { self: Quasiquotes =>
}
object TupleTypePlaceholder {
+ def apply(args: List[Tree]) =
+ AppliedTypeTree(Ident(tpnme.QUASIQUOTE_TUPLE), args)
def unapply(tree: Tree): Option[List[Tree]] = tree match {
case AppliedTypeTree(Ident(tpnme.QUASIQUOTE_TUPLE), args) => Some(args)
case _ => None
@@ -132,6 +140,8 @@ trait Placeholders { self: Quasiquotes =>
}
object FunctionTypePlaceholder {
+ def apply(args: List[Tree], res: Tree) =
+ AppliedTypeTree(Ident(tpnme.QUASIQUOTE_FUNCTION), args :+ res)
def unapply(tree: Tree): Option[(List[Tree], Tree)] = tree match {
case AppliedTypeTree(Ident(tpnme.QUASIQUOTE_FUNCTION), args :+ res) => Some((args, res))
case _ => None
@@ -146,6 +156,8 @@ trait Placeholders { self: Quasiquotes =>
}
object CasePlaceholder {
+ def apply(name: Name) =
+ CaseDef(Apply(Ident(nme.QUASIQUOTE_CASE), Ident(name) :: Nil), EmptyTree, EmptyTree)
def unapply(tree: Tree): Option[Hole] = tree match {
case CaseDef(Apply(Ident(nme.QUASIQUOTE_CASE), List(Placeholder(hole))), EmptyTree, EmptyTree) => Some(hole)
case _ => None
@@ -153,27 +165,35 @@ trait Placeholders { self: Quasiquotes =>
}
object RefineStatPlaceholder {
+ def apply(name: Name) =
+ ValDef(NoMods, nme.QUASIQUOTE_REFINE_STAT, Ident(name), EmptyTree)
def unapply(tree: Tree): Option[Hole] = tree match {
- case ValDef(_, Placeholder(hole), Ident(tpnme.QUASIQUOTE_REFINE_STAT), _) => Some(hole)
+ case ValDef(_, nme.QUASIQUOTE_REFINE_STAT, Ident(Placeholder(hole)), _) => Some(hole)
case _ => None
}
}
object EarlyDefPlaceholder {
+ def apply(name: Name) =
+ ValDef(Modifiers(Flag.PRESUPER), nme.QUASIQUOTE_EARLY_DEF, Ident(name), EmptyTree)
def unapply(tree: Tree): Option[Hole] = tree match {
- case ValDef(_, Placeholder(hole), Ident(tpnme.QUASIQUOTE_EARLY_DEF), _) => Some(hole)
+ case ValDef(_, nme.QUASIQUOTE_EARLY_DEF, Ident(Placeholder(hole)), _) => Some(hole)
case _ => None
}
}
object PackageStatPlaceholder {
+ def apply(name: Name) =
+ ValDef(NoMods, nme.QUASIQUOTE_PACKAGE_STAT, Ident(name), EmptyTree)
def unapply(tree: Tree): Option[Hole] = tree match {
- case ValDef(NoMods, Placeholder(hole), Ident(tpnme.QUASIQUOTE_PACKAGE_STAT), EmptyTree) => Some(hole)
+ case ValDef(NoMods, nme.QUASIQUOTE_PACKAGE_STAT, Ident(Placeholder(hole)), EmptyTree) => Some(hole)
case _ => None
}
}
object ForEnumPlaceholder {
+ def apply(name: Name) =
+ build.SyntacticValFrom(Bind(name, Ident(nme.WILDCARD)), Ident(nme.QUASIQUOTE_FOR_ENUM))
def unapply(tree: Tree): Option[Hole] = tree match {
case build.SyntacticValFrom(Bind(Placeholder(hole), Ident(nme.WILDCARD)), Ident(nme.QUASIQUOTE_FOR_ENUM)) =>
Some(hole)
diff --git a/src/compiler/scala/tools/reflect/quasiquotes/Reifiers.scala b/src/compiler/scala/tools/reflect/quasiquotes/Reifiers.scala
index 017e966f63..70580adbce 100644
--- a/src/compiler/scala/tools/reflect/quasiquotes/Reifiers.scala
+++ b/src/compiler/scala/tools/reflect/quasiquotes/Reifiers.scala
@@ -194,8 +194,8 @@ trait Reifiers { self: Quasiquotes =>
reifyBuildCall(nme.SyntacticEmptyTypeTree)
case SyntacticImport(expr, selectors) =>
reifyBuildCall(nme.SyntacticImport, expr, selectors)
- case Q(Placeholder(Hole(tree, DotDot))) =>
- mirrorBuildCall(nme.SyntacticBlock, tree)
+ case Q(tree) if fillListHole.isDefinedAt(tree) =>
+ mirrorBuildCall(nme.SyntacticBlock, fillListHole(tree))
case Q(other) =>
reifyTree(other)
// Syntactic block always matches so we have to be careful
@@ -311,11 +311,7 @@ trait Reifiers { self: Quasiquotes =>
*/
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
- * elements.
- */
- override def reifyList(xs: List[Any]): Tree = reifyMultiCardinalityList(xs) {
+ val fillListHole: PartialFunction[Any, Tree] = {
case Placeholder(Hole(tree, DotDot)) => tree
case CasePlaceholder(Hole(tree, DotDot)) => tree
case RefineStatPlaceholder(h @ Hole(_, DotDot)) => reifyRefineStat(h)
@@ -323,12 +319,23 @@ trait Reifiers { self: Quasiquotes =>
case PackageStatPlaceholder(h @ Hole(_, DotDot)) => reifyPackageStat(h)
case ForEnumPlaceholder(Hole(tree, DotDot)) => tree
case ParamPlaceholder(Hole(tree, DotDot)) => tree
+ case SyntacticPatDef(mods, pat, tpt, rhs) =>
+ reifyBuildCall(nme.SyntacticPatDef, mods, pat, tpt, rhs)
+ case SyntacticValDef(mods, p @ Placeholder(h: ApplyHole), tpt, rhs) if h.tpe <:< treeType =>
+ mirrorBuildCall(nme.SyntacticPatDef, reify(mods), h.tree, reify(tpt), reify(rhs))
+ }
+
+ val fillListOfListsHole: PartialFunction[Any, Tree] = {
case List(ParamPlaceholder(Hole(tree, DotDotDot))) => tree
case List(Placeholder(Hole(tree, DotDotDot))) => tree
- } {
- reify(_)
}
+ /** Reifies arbitrary list filling ..$x and ...$y holeMap when they are put
+ * in the correct position. Fallbacks to regular reification for non-high cardinality
+ * elements.
+ */
+ override def reifyList(xs: List[Any]): Tree = reifyMultiCardinalityList(xs)(fillListHole.orElse(fillListOfListsHole))(reify)
+
def reifyAnnotList(annots: List[Tree]): Tree = reifyMultiCardinalityList(annots) {
case AnnotPlaceholder(h @ Hole(_, DotDot)) => reifyAnnotation(h)
} {