summaryrefslogtreecommitdiff
path: root/src/reflect
diff options
context:
space:
mode:
authorEugene Burmako <xeno.by@gmail.com>2014-01-29 01:51:58 -0800
committerEugene Burmako <xeno.by@gmail.com>2014-01-29 01:51:58 -0800
commit057adc70346414c10273f58fcd44114bf0672933 (patch)
tree9f5cfeac7702c5614bca45cf380d0f314c2f5ed5 /src/reflect
parent1e9dcc2ed603e7179b7b5eee9212e73f773b02fd (diff)
parent0200375e670b5dcc865c8636faf00ae5e767a81b (diff)
downloadscala-057adc70346414c10273f58fcd44114bf0672933.tar.gz
scala-057adc70346414c10273f58fcd44114bf0672933.tar.bz2
scala-057adc70346414c10273f58fcd44114bf0672933.zip
Merge pull request #3402 from densh/si/7275
SI-7275 allow flattening of blocks with ..$
Diffstat (limited to 'src/reflect')
-rw-r--r--src/reflect/scala/reflect/api/BuildUtils.scala2
-rw-r--r--src/reflect/scala/reflect/internal/BuildUtils.scala38
-rw-r--r--src/reflect/scala/reflect/internal/Definitions.scala1
-rw-r--r--src/reflect/scala/reflect/internal/StdAttachments.scala4
-rw-r--r--src/reflect/scala/reflect/internal/StdNames.scala1
-rw-r--r--src/reflect/scala/reflect/internal/TreeGen.scala18
-rw-r--r--src/reflect/scala/reflect/runtime/JavaUniverseForce.scala1
7 files changed, 57 insertions, 8 deletions
diff --git a/src/reflect/scala/reflect/api/BuildUtils.scala b/src/reflect/scala/reflect/api/BuildUtils.scala
index 260974a981..3a69390bcf 100644
--- a/src/reflect/scala/reflect/api/BuildUtils.scala
+++ b/src/reflect/scala/reflect/api/BuildUtils.scala
@@ -72,6 +72,8 @@ private[reflect] trait BuildUtils { self: Universe =>
def setSymbol[T <: Tree](tree: T, sym: Symbol): T
+ def toStats(tree: Tree): List[Tree]
+
def mkAnnotation(tree: Tree): Tree
def mkAnnotation(trees: List[Tree]): List[Tree]
diff --git a/src/reflect/scala/reflect/internal/BuildUtils.scala b/src/reflect/scala/reflect/internal/BuildUtils.scala
index 3061885549..16bb3e5989 100644
--- a/src/reflect/scala/reflect/internal/BuildUtils.scala
+++ b/src/reflect/scala/reflect/internal/BuildUtils.scala
@@ -61,6 +61,8 @@ trait BuildUtils { self: SymbolTable =>
def setSymbol[T <: Tree](tree: T, sym: Symbol): T = { tree.setSymbol(sym); tree }
+ def toStats(tree: Tree): List[Tree] = SyntacticBlock.unapply(tree).get
+
def mkAnnotation(tree: Tree): Tree = tree match {
case SyntacticNew(Nil, SyntacticApplied(SyntacticTypeApplied(_, _), _) :: Nil, noSelfType, Nil) =>
tree
@@ -381,13 +383,41 @@ trait BuildUtils { self: SymbolTable =>
}
}
+ object SyntheticUnit {
+ def unapply(tree: Tree): Boolean = tree match {
+ case Literal(Constant(())) if tree.hasAttachment[SyntheticUnitAttachment.type] => true
+ case _ => false
+ }
+ }
+
+ /** Syntactic combinator that abstracts over Block tree.
+ *
+ * Apart from providing a more straightforward api that exposes
+ * block as a list of elements rather than (stats, expr) pair
+ * it also:
+ *
+ * 1. Treats of q"" (empty tree) as zero-element block.
+ *
+ * 2. Strips trailing synthetic units which are inserted by the
+ * compiler if the block ends with a definition rather
+ * than an expression.
+ *
+ * 3. Matches non-block term trees and recognizes them as
+ * single-element blocks for sake of consistency with
+ * compiler's default to treat single-element blocks with
+ * expressions as just expressions.
+ */
object SyntacticBlock extends SyntacticBlockExtractor {
- def apply(stats: List[Tree]): Tree = gen.mkBlock(stats)
+ def apply(stats: List[Tree]): Tree =
+ if (stats.isEmpty) EmptyTree
+ else 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
+ case self.Block(stats, SyntheticUnit()) => Some(stats)
+ case self.Block(stats, expr) => Some(stats :+ expr)
+ case EmptyTree => Some(Nil)
+ case _ if tree.isTerm => Some(tree :: Nil)
+ case _ => None
}
}
diff --git a/src/reflect/scala/reflect/internal/Definitions.scala b/src/reflect/scala/reflect/internal/Definitions.scala
index 5b06239863..4d24f0b219 100644
--- a/src/reflect/scala/reflect/internal/Definitions.scala
+++ b/src/reflect/scala/reflect/internal/Definitions.scala
@@ -625,6 +625,7 @@ trait Definitions extends api.StandardDefinitions {
def isBlackboxMacroBundleType(tp: Type) =
isMacroBundleType(tp) && (macroBundleParamInfo(tp) <:< BlackboxContextClass.tpe)
+ def isListType(tp: Type) = tp <:< classExistentialType(ListClass)
def isIterableType(tp: Type) = tp <:< classExistentialType(IterableClass)
// These "direct" calls perform no dealiasing. They are most needed when
diff --git a/src/reflect/scala/reflect/internal/StdAttachments.scala b/src/reflect/scala/reflect/internal/StdAttachments.scala
index 09fd996f39..139a79ffe1 100644
--- a/src/reflect/scala/reflect/internal/StdAttachments.scala
+++ b/src/reflect/scala/reflect/internal/StdAttachments.scala
@@ -36,6 +36,10 @@ trait StdAttachments {
*/
case object ForAttachment extends PlainAttachment
+ /** Identifies unit constants which were inserted by the compiler (e.g. gen.mkBlock)
+ */
+ case object SyntheticUnitAttachment extends PlainAttachment
+
/** Untyped list of subpatterns attached to selector dummy. */
case class SubpatternsAttachment(patterns: List[Tree])
}
diff --git a/src/reflect/scala/reflect/internal/StdNames.scala b/src/reflect/scala/reflect/internal/StdNames.scala
index 7015105261..256d5759fa 100644
--- a/src/reflect/scala/reflect/internal/StdNames.scala
+++ b/src/reflect/scala/reflect/internal/StdNames.scala
@@ -752,6 +752,7 @@ trait StdNames {
val toArray: NameType = "toArray"
val toList: NameType = "toList"
val toObjectArray : NameType = "toObjectArray"
+ val toStats: NameType = "toStats"
val TopScope: NameType = "TopScope"
val toString_ : NameType = "toString"
val toTypeConstructor: NameType = "toTypeConstructor"
diff --git a/src/reflect/scala/reflect/internal/TreeGen.scala b/src/reflect/scala/reflect/internal/TreeGen.scala
index b16cbd8325..e602a12175 100644
--- a/src/reflect/scala/reflect/internal/TreeGen.scala
+++ b/src/reflect/scala/reflect/internal/TreeGen.scala
@@ -342,7 +342,7 @@ abstract class TreeGen extends macros.TreeBuilder {
}
param
}
-
+
val (edefs, rest) = body span treeInfo.isEarlyDef
val (evdefs, etdefs) = edefs partition treeInfo.isEarlyValDef
val gvdefs = evdefs map {
@@ -381,11 +381,11 @@ abstract class TreeGen extends macros.TreeBuilder {
}
constr foreach (ensureNonOverlapping(_, parents ::: gvdefs, focus = false))
// Field definitions for the class - remove defaults.
-
+
val fieldDefs = vparamss.flatten map (vd => {
val field = copyValDef(vd)(mods = vd.mods &~ DEFAULTPARAM, rhs = EmptyTree)
// Prevent overlapping of `field` end's position with default argument's start position.
- // This is needed for `Positions.Locator(pos).traverse` to return the correct tree when
+ // This is needed for `Positions.Locator(pos).traverse` to return the correct tree when
// the `pos` is a point position with all its values equal to `vd.rhs.pos.start`.
if(field.pos.isRange && vd.rhs.pos.isRange) field.pos = field.pos.withEnd(vd.rhs.pos.start - 1)
field
@@ -444,13 +444,23 @@ abstract class TreeGen extends macros.TreeBuilder {
def mkFunctionTypeTree(argtpes: List[Tree], restpe: Tree): Tree =
AppliedTypeTree(rootScalaDot(newTypeName("Function" + argtpes.length)), argtpes ::: List(restpe))
+ /** Create a literal unit tree that is inserted by the compiler but not
+ * written by end user. It's important to distinguish the two so that
+ * quasiquotes can strip synthetic ones away.
+ */
+ def mkSyntheticUnit() = Literal(Constant(())).updateAttachment(SyntheticUnitAttachment)
+
/** 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.last.isTerm) Block(stats, mkSyntheticUnit())
else if (stats.length == 1) stats.head
else Block(stats.init, stats.last)
+ /** Create a block that wraps multiple statements but don't
+ * do any wrapping if there is just one statement. Used by
+ * quasiquotes, macro c.parse api and toolbox.
+ */
def mkTreeOrBlock(stats: List[Tree]) = stats match {
case Nil => EmptyTree
case head :: Nil => head
diff --git a/src/reflect/scala/reflect/runtime/JavaUniverseForce.scala b/src/reflect/scala/reflect/runtime/JavaUniverseForce.scala
index b9b171c7ed..8811b5513e 100644
--- a/src/reflect/scala/reflect/runtime/JavaUniverseForce.scala
+++ b/src/reflect/scala/reflect/runtime/JavaUniverseForce.scala
@@ -58,6 +58,7 @@ trait JavaUniverseForce { self: runtime.JavaUniverse =>
this.CompoundTypeTreeOriginalAttachment
this.BackquotedIdentifierAttachment
this.ForAttachment
+ this.SyntheticUnitAttachment
this.SubpatternsAttachment
this.noPrint
this.typeDebug