summaryrefslogtreecommitdiff
path: root/src
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
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')
-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
8 files changed, 70 insertions, 55 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)
}