summaryrefslogtreecommitdiff
path: root/src/reflect
diff options
context:
space:
mode:
authorDen Shabalin <den.shabalin@gmail.com>2013-09-02 15:51:56 +0200
committerDen Shabalin <den.shabalin@gmail.com>2013-09-05 14:39:12 +0200
commit901cdc1855e8e80957b18add4991736b9f458d77 (patch)
treeb6ac94c657f262d3a4e398e36b07d042ba4fbfa1 /src/reflect
parentf9d5e3d4e8cca61ee75072ab13c2935061a1850e (diff)
downloadscala-901cdc1855e8e80957b18add4991736b9f458d77.tar.gz
scala-901cdc1855e8e80957b18add4991736b9f458d77.tar.bz2
scala-901cdc1855e8e80957b18add4991736b9f458d77.zip
refine block and applied/typeapplied splicing/matching semantics
1. blocks now match single term-level expressions to account for automatic block elimination. E.g. val q"{ ..$stats }" = q"foo" will match into stats = List(q"foo"). This is useful to uniformly deal with blocks on term level. 2. blocks in quasiquotes collapse into single expressions 3. Applied and TypeApplied now have constructors too which helps to unify matching and extraction in quasiquote reifier 4. TypeApplied now matches AppliedTypeTree too 5. Add Syntactic prefix to Applied and TypeApplied
Diffstat (limited to 'src/reflect')
-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
4 files changed, 48 insertions, 22 deletions
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)
}