summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala6
-rw-r--r--src/compiler/scala/tools/reflect/quasiquotes/Parsers.scala5
-rw-r--r--src/compiler/scala/tools/reflect/quasiquotes/Reifiers.scala36
-rw-r--r--src/continuations/plugin/scala/tools/selectivecps/SelectiveCPSTransform.scala8
-rw-r--r--src/reflect/scala/reflect/api/BuildUtils.scala21
-rw-r--r--src/reflect/scala/reflect/internal/BuildUtils.scala37
-rw-r--r--src/reflect/scala/reflect/internal/StdNames.scala5
-rw-r--r--src/reflect/scala/reflect/internal/TreeGen.scala7
-rw-r--r--test/files/scalacheck/quasiquotes/DefinitionConstructionProps.scala2
-rw-r--r--test/files/scalacheck/quasiquotes/PatternConstructionProps.scala2
-rw-r--r--test/files/scalacheck/quasiquotes/TermConstructionProps.scala8
-rw-r--r--test/files/scalacheck/quasiquotes/TermDeconstructionProps.scala5
12 files changed, 82 insertions, 60 deletions
diff --git a/src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala b/src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala
index ed694023d7..ed7c0d1a0a 100644
--- a/src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala
+++ b/src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala
@@ -229,11 +229,7 @@ abstract class TreeBuilder {
}
/** Create block of statements `stats` */
- def makeBlock(stats: List[Tree]): Tree =
- if (stats.isEmpty) Literal(Constant(()))
- else if (!stats.last.isTerm) Block(stats, Literal(Constant(())))
- else if (stats.length == 1) stats.head
- else Block(stats.init, stats.last)
+ def makeBlock(stats: List[Tree]): Tree = gen.mkBlock(stats)
def makeFilter(tree: Tree, condition: Tree, scrutineeName: String): Tree = {
val cases = List(
diff --git a/src/compiler/scala/tools/reflect/quasiquotes/Parsers.scala b/src/compiler/scala/tools/reflect/quasiquotes/Parsers.scala
index d04b65545d..fe0809c869 100644
--- a/src/compiler/scala/tools/reflect/quasiquotes/Parsers.scala
+++ b/src/compiler/scala/tools/reflect/quasiquotes/Parsers.scala
@@ -79,6 +79,11 @@ trait Parsers { self: Quasiquotes =>
} else
super.caseClause()
+ override def caseBlock(): Tree = super.caseBlock() match {
+ case Block(Nil, expr) => expr
+ case other => other
+ }
+
def isHole: Boolean = isIdent && holeMap.contains(in.name)
override def isAnnotation: Boolean = super.isAnnotation || (isHole && lookingAhead { isAnnotation })
diff --git a/src/compiler/scala/tools/reflect/quasiquotes/Reifiers.scala b/src/compiler/scala/tools/reflect/quasiquotes/Reifiers.scala
index d4bc2d67c6..62c246366d 100644
--- a/src/compiler/scala/tools/reflect/quasiquotes/Reifiers.scala
+++ b/src/compiler/scala/tools/reflect/quasiquotes/Reifiers.scala
@@ -7,7 +7,7 @@ import scala.reflect.internal.Flags._
trait Reifiers { self: Quasiquotes =>
import global._
- import global.build.SyntacticClassDef
+ import global.build.{SyntacticClassDef, SyntacticBlock, SyntacticApplied, SyntacticTypeApplied}
import global.treeInfo._
import global.definitions._
import Cardinality._
@@ -54,6 +54,14 @@ trait Reifiers { self: Quasiquotes =>
case SyntacticClassDef(mods, name, tparams, constrmods, vparamss, parents, selfdef, body) =>
reifyBuildCall(nme.SyntacticClassDef, mods, name, tparams, constrmods, vparamss,
parents, selfdef, body)
+ case SyntacticApplied(fun, argss) if argss.length > 1 =>
+ reifyBuildCall(nme.SyntacticApplied, fun, argss)
+ case SyntacticApplied(fun, argss @ (_ :+ (_ :+ Placeholder(_, _, DotDotDot)))) =>
+ reifyBuildCall(nme.SyntacticApplied, fun, argss)
+ case SyntacticTypeApplied(fun, targs) if targs.nonEmpty =>
+ reifyBuildCall(nme.SyntacticTypeApplied, fun, targs)
+ case Block(stats, last) =>
+ reifyBuildCall(nme.SyntacticBlock, stats :+ last)
case _ =>
super.reifyTreeSyntactically(tree)
}
@@ -169,19 +177,10 @@ trait Reifiers { self: Quasiquotes =>
def isReifyingExpressions = true
override def reifyTreeSyntactically(tree: Tree): Tree = tree match {
- case Block(stats, p @ Placeholder(_, _, _)) => reifyBuildCall(nme.Block, stats :+ p)
- case Apply(f, List(Placeholder(argss, _, DotDotDot))) => reifyCallWithArgss(f, argss)
- case RefTree(qual, SymbolPlaceholder(tree)) => mirrorBuildCall(nme.RefTree, reify(qual), tree)
- case _ => super.reifyTreeSyntactically(tree)
- }
-
- def reifyCallWithArgss(f: Tree, argss: Tree) = {
- val f1 = reifyTree(f)
- val foldLeftF1 = Apply(TypeApply(Select(argss, nme.foldLeft), List(Select(u, tpnme.Tree))), List(f1))
- val uDotApply = Function(
- List(gen.mkSyntheticParam(nme.x_1), gen.mkSyntheticParam(nme.x_2)),
- Apply(Select(u, nme.Apply), List(Ident(nme.x_1), Ident(nme.x_2))))
- Apply(foldLeftF1, List(uDotApply))
+ case RefTree(qual, SymbolPlaceholder(tree)) =>
+ mirrorBuildCall(nme.RefTree, reify(qual), tree)
+ case _ =>
+ super.reifyTreeSyntactically(tree)
}
override def reifyMultiCardinalityList[T](xs: List[T])(fill: PartialFunction[T, Tree])(fallback: T => Tree): Tree = xs match {
@@ -245,15 +244,6 @@ trait Reifiers { self: Quasiquotes =>
class UnapplyReifier extends Reifier {
def isReifyingExpressions = false
- override def reifyTreeSyntactically(tree: Tree): Tree = tree match {
- case treeInfo.Applied(fun, Nil, argss) if fun != tree && !tree.isInstanceOf[AppliedTypeTree] =>
- reifyBuildCall(nme.Applied, fun, argss)
- case treeInfo.Applied(fun, targs, argss) if fun != tree & !tree.isInstanceOf[AppliedTypeTree] =>
- mirrorBuildCall(nme.Applied, reifyBuildCall(nme.TypeApplied, fun, targs), reifyList(argss))
- case _ =>
- super.reifyTreeSyntactically(tree)
- }
-
override def scalaFactoryCall(name: String, args: Tree*): Tree =
call("scala." + name, args: _*)
diff --git a/src/continuations/plugin/scala/tools/selectivecps/SelectiveCPSTransform.scala b/src/continuations/plugin/scala/tools/selectivecps/SelectiveCPSTransform.scala
index 908ffb3713..a2c2ebc3e3 100644
--- a/src/continuations/plugin/scala/tools/selectivecps/SelectiveCPSTransform.scala
+++ b/src/continuations/plugin/scala/tools/selectivecps/SelectiveCPSTransform.scala
@@ -330,8 +330,6 @@ abstract class SelectiveCPSTransform extends PluginComponent with
}
}
- def mkBlock(stms: List[Tree], expr: Tree) = if (stms.nonEmpty) Block(stms, expr) else expr
-
try {
if (specialCaseTrivial) {
debuglog("will optimize possible tail call: " + bodyExpr)
@@ -350,9 +348,9 @@ abstract class SelectiveCPSTransform extends PluginComponent with
val argSym = currentOwner.newValue(vd.symbol.name.toTermName).setInfo(tpe)
val argDef = localTyper.typed(ValDef(argSym, Select(ctxRef, ctxRef.tpe.member(cpsNames.getTrivialValue))))
val switchExpr = localTyper.typedPos(vd.symbol.pos) {
- val body2 = mkBlock(bodyStms, bodyExpr).duplicate // dup before typing!
+ val body2 = gen.mkBlock(bodyStms :+ bodyExpr).duplicate // dup before typing!
If(Select(ctxRef, ctxSym.tpe.member(cpsNames.isTrivial)),
- applyTrivial(argSym, mkBlock(argDef::bodyStms, bodyExpr)),
+ applyTrivial(argSym, gen.mkBlock((argDef :: bodyStms) :+ bodyExpr)),
applyCombinatorFun(ctxRef, body2))
}
(List(ctxDef), switchExpr)
@@ -360,7 +358,7 @@ abstract class SelectiveCPSTransform extends PluginComponent with
// ctx.flatMap { <lhs> => ... }
// or
// ctx.map { <lhs> => ... }
- (Nil, applyCombinatorFun(rhs1, mkBlock(bodyStms, bodyExpr)))
+ (Nil, applyCombinatorFun(rhs1, gen.mkBlock(bodyStms :+ bodyExpr)))
}
} catch {
case ex:TypeError =>
diff --git a/src/reflect/scala/reflect/api/BuildUtils.scala b/src/reflect/scala/reflect/api/BuildUtils.scala
index 03980f5f0a..ef9f9ab834 100644
--- a/src/reflect/scala/reflect/api/BuildUtils.scala
+++ b/src/reflect/scala/reflect/api/BuildUtils.scala
@@ -64,8 +64,6 @@ private[reflect] trait BuildUtils { self: Universe =>
def Ident(sym: Symbol): Ident
- def Block(stats: List[Tree]): Block
-
def TypeTree(tp: Type): TypeTree
def thisPrefix(sym: Symbol): Type
@@ -80,6 +78,8 @@ private[reflect] trait BuildUtils { self: Universe =>
def mkRefineStat(stats: List[Tree]): List[Tree]
+ def RefTree(qual: Tree, sym: Symbol): Tree
+
val FlagsRepr: FlagsReprExtractor
trait FlagsReprExtractor {
@@ -87,15 +87,17 @@ private[reflect] trait BuildUtils { self: Universe =>
def unapply(flags: Long): Some[Long]
}
- val TypeApplied: TypeAppliedExtractor
+ val SyntacticTypeApplied: SyntacticTypeAppliedExtractor
- trait TypeAppliedExtractor {
+ trait SyntacticTypeAppliedExtractor {
+ def apply(tree: Tree, targs: List[Tree]): Tree
def unapply(tree: Tree): Some[(Tree, List[Tree])]
}
- val Applied: AppliedExtractor
+ val SyntacticApplied: SyntacticAppliedExtractor
- trait AppliedExtractor {
+ trait SyntacticAppliedExtractor {
+ def apply(tree: Tree, argss: List[List[Tree]]): Tree
def unapply(tree: Tree): Some[(Tree, List[List[Tree]])]
}
@@ -117,6 +119,11 @@ private[reflect] trait BuildUtils { self: Universe =>
def unapply(tree: Tree): Option[List[Tree]]
}
- def RefTree(qual: Tree, sym: Symbol): Tree
+ val SyntacticBlock: SyntacticBlockExtractor
+
+ trait SyntacticBlockExtractor {
+ def apply(stats: List[Tree]): Tree
+ def unapply(tree: Tree): Option[List[Tree]]
+ }
}
}
diff --git a/src/reflect/scala/reflect/internal/BuildUtils.scala b/src/reflect/scala/reflect/internal/BuildUtils.scala
index 208a61d9d3..928395b7c9 100644
--- a/src/reflect/scala/reflect/internal/BuildUtils.scala
+++ b/src/reflect/scala/reflect/internal/BuildUtils.scala
@@ -53,12 +53,6 @@ trait BuildUtils { self: SymbolTable =>
def Ident(sym: Symbol): Ident = self.Ident(sym)
- def Block(stats: List[Tree]): Block = stats match {
- case Nil => self.Block(Nil, Literal(Constant(())))
- case elem :: Nil => self.Block(Nil, elem)
- case elems => self.Block(elems.init, elems.last)
- }
-
def TypeTree(tp: Type): TypeTree = self.TypeTree(tp)
def thisPrefix(sym: Symbol): Type = sym.thisPrefix
@@ -88,25 +82,34 @@ trait BuildUtils { self: SymbolTable =>
def mkRefineStat(stats: List[Tree]): List[Tree] = stats.map(mkRefineStat)
+ def RefTree(qual: Tree, sym: Symbol) = self.RefTree(qual, sym.name) setSymbol sym
+
object FlagsRepr extends FlagsReprExtractor {
def apply(bits: Long): FlagSet = bits
def unapply(flags: Long): Some[Long] = Some(flags)
}
- object TypeApplied extends TypeAppliedExtractor {
+ object SyntacticTypeApplied extends SyntacticTypeAppliedExtractor {
+ def apply(tree: Tree, targs: List[Tree]): Tree =
+ if (targs.isEmpty) tree
+ else if (tree.isTerm) TypeApply(tree, targs)
+ else if (tree.isType) AppliedTypeTree(tree, targs)
+ else throw new IllegalArgumentException(s"can't apply types to $tree")
+
def unapply(tree: Tree): Some[(Tree, List[Tree])] = tree match {
case TypeApply(fun, targs) => Some((fun, targs))
+ case AppliedTypeTree(tpe, targs) => Some((tpe, targs))
case _ => Some((tree, Nil))
}
}
- object Applied extends AppliedExtractor {
+ object SyntacticApplied extends SyntacticAppliedExtractor {
+ def apply(tree: Tree, argss: List[List[Tree]]): Tree =
+ argss.foldLeft(tree) { Apply(_, _) }
+
def unapply(tree: Tree): Some[(Tree, List[List[Tree]])] = {
val treeInfo.Applied(fun, targs, argss) = tree
- targs match {
- case Nil => Some((fun, argss))
- case _ => Some((TypeApply(fun, targs), argss))
- }
+ Some((SyntacticTypeApplied(fun, targs), argss))
}
}
@@ -189,7 +192,15 @@ trait BuildUtils { self: SymbolTable =>
}
}
- def RefTree(qual: Tree, sym: Symbol) = self.RefTree(qual, sym.name) setSymbol sym
+ object SyntacticBlock extends SyntacticBlockExtractor {
+ def apply(stats: List[Tree]): Tree = gen.mkBlock(stats)
+
+ def unapply(tree: Tree): Option[List[Tree]] = tree match {
+ case self.Block(stats, expr) => Some(stats :+ expr)
+ case _ if tree.isTerm => Some(tree :: Nil)
+ case _ => None
+ }
+ }
}
val build: BuildApi = new BuildImpl
diff --git a/src/reflect/scala/reflect/internal/StdNames.scala b/src/reflect/scala/reflect/internal/StdNames.scala
index eb24706f29..6cbf1f1046 100644
--- a/src/reflect/scala/reflect/internal/StdNames.scala
+++ b/src/reflect/scala/reflect/internal/StdNames.scala
@@ -561,7 +561,6 @@ trait StdNames {
val Any: NameType = "Any"
val AnyVal: NameType = "AnyVal"
val Apply: NameType = "Apply"
- val Applied: NameType = "Applied"
val ArrayAnnotArg: NameType = "ArrayAnnotArg"
val Block: NameType = "Block"
val ConstantType: NameType = "ConstantType"
@@ -588,7 +587,10 @@ trait StdNames {
val Select: NameType = "Select"
val SelectFromTypeTree: NameType = "SelectFromTypeTree"
val StringContext: NameType = "StringContext"
+ val SyntacticApplied: NameType = "SyntacticApplied"
+ val SyntacticBlock: NameType = "SyntacticBlock"
val SyntacticClassDef: NameType = "SyntacticClassDef"
+ val SyntacticTypeApplied: NameType = "SyntacticTypeApplied"
val This: NameType = "This"
val ThisType: NameType = "ThisType"
val True : NameType = "True"
@@ -596,7 +598,6 @@ trait StdNames {
val TupleN: NameType = "TupleN"
val TupleTypeN: NameType = "TupleTypeN"
val TYPE_ : NameType = "TYPE"
- val TypeApplied: NameType = "TypeApplied"
val TypeRef: NameType = "TypeRef"
val TypeTree: NameType = "TypeTree"
val UNIT : NameType = "UNIT"
diff --git a/src/reflect/scala/reflect/internal/TreeGen.scala b/src/reflect/scala/reflect/internal/TreeGen.scala
index a7ea8c816f..9623cc31f6 100644
--- a/src/reflect/scala/reflect/internal/TreeGen.scala
+++ b/src/reflect/scala/reflect/internal/TreeGen.scala
@@ -414,4 +414,11 @@ abstract class TreeGen extends macros.TreeBuilder {
)
}
}
+
+ /** Create block of statements `stats` */
+ def mkBlock(stats: List[Tree]): Tree =
+ if (stats.isEmpty) Literal(Constant(()))
+ else if (!stats.last.isTerm) Block(stats, Literal(Constant(())))
+ else if (stats.length == 1) stats.head
+ else Block(stats.init, stats.last)
}
diff --git a/test/files/scalacheck/quasiquotes/DefinitionConstructionProps.scala b/test/files/scalacheck/quasiquotes/DefinitionConstructionProps.scala
index 5d657b931b..dc3fc60f8c 100644
--- a/test/files/scalacheck/quasiquotes/DefinitionConstructionProps.scala
+++ b/test/files/scalacheck/quasiquotes/DefinitionConstructionProps.scala
@@ -118,7 +118,7 @@ trait TypeDefConstruction { self: QuasiquoteProperties =>
property("splice into applied type tree") = forAll { (T1: TypeName, T2: TypeName, args: List[Tree]) =>
q"type $T1 = $T2[..$args]" ≈
TypeDef(Modifiers(), T1, List(),
- AppliedTypeTree(Ident(T2), args))
+ if(args.nonEmpty) AppliedTypeTree(Ident(T2), args) else Ident(T2))
}
}
diff --git a/test/files/scalacheck/quasiquotes/PatternConstructionProps.scala b/test/files/scalacheck/quasiquotes/PatternConstructionProps.scala
index aee50c9c5f..504cb2a77d 100644
--- a/test/files/scalacheck/quasiquotes/PatternConstructionProps.scala
+++ b/test/files/scalacheck/quasiquotes/PatternConstructionProps.scala
@@ -32,6 +32,6 @@ object PatternConstructionProps extends QuasiquoteProperties("pattern constructi
}
property("splice into casedef") = forAll { (pat: Tree, cond: Tree, body: Tree) =>
- cq"$pat if $cond => $body" ≈ CaseDef(pat, cond, Block(List(), body))
+ cq"$pat if $cond => $body" ≈ CaseDef(pat, cond, body)
}
} \ No newline at end of file
diff --git a/test/files/scalacheck/quasiquotes/TermConstructionProps.scala b/test/files/scalacheck/quasiquotes/TermConstructionProps.scala
index 5a765f7911..599dfd442a 100644
--- a/test/files/scalacheck/quasiquotes/TermConstructionProps.scala
+++ b/test/files/scalacheck/quasiquotes/TermConstructionProps.scala
@@ -88,7 +88,7 @@ object TermConstructionProps extends QuasiquoteProperties("term construction") {
}
property("splice trees into type apply") = forAll { (fun: TreeIsTerm, types: List[Tree]) =>
- q"$fun[..$types]" ≈ TypeApply(fun, types)
+ q"$fun[..$types]" ≈ (if (types.nonEmpty) TypeApply(fun, types) else fun)
}
property("splice names into import selector") = forAll {
@@ -122,8 +122,10 @@ object TermConstructionProps extends QuasiquoteProperties("term construction") {
def blockInvariant(quote: Tree, trees: List[Tree]) =
quote ≈ (trees match {
- case Nil => Block(Nil, q"()")
- case _ => Block(trees.init, trees.last)
+ case Nil => q"()"
+ case _ :+ last if !last.isTerm => Block(trees, q"()")
+ case head :: Nil => head
+ case init :+ last => Block(init, last)
})
property("splice list of trees into block (1)") = forAll { (trees: List[Tree]) =>
diff --git a/test/files/scalacheck/quasiquotes/TermDeconstructionProps.scala b/test/files/scalacheck/quasiquotes/TermDeconstructionProps.scala
index 132baeb977..6087bbdb74 100644
--- a/test/files/scalacheck/quasiquotes/TermDeconstructionProps.scala
+++ b/test/files/scalacheck/quasiquotes/TermDeconstructionProps.scala
@@ -62,4 +62,9 @@ object TermDeconstructionProps extends QuasiquoteProperties("term deconstruction
val q"$x match { case ..$cases }" = q"x match { case 1 => case 2 => }"
x ≈ q"x" && cases ≈ List(cq"1 =>", cq"2 =>")
}
+
+ property("deconstruct block") = test {
+ val q"{ ..$xs }" = q"{ x1; x2; x3 }"
+ assert(xs ≈ List(q"x1", q"x2", q"x3"))
+ }
} \ No newline at end of file