summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorDen Shabalin <den.shabalin@gmail.com>2013-09-11 19:22:48 +0200
committerDen Shabalin <den.shabalin@gmail.com>2013-09-18 20:36:17 +0200
commitc8a9329ff9b2a6ea99eef7234c9f84c0bfe0166b (patch)
treeddb01dd1c77344bc1b7768ad7460dd021274faa4 /src
parenta8543ef28f8fc0152208f4eef763344657bf9e5a (diff)
downloadscala-c8a9329ff9b2a6ea99eef7234c9f84c0bfe0166b.tar.gz
scala-c8a9329ff9b2a6ea99eef7234c9f84c0bfe0166b.tar.bz2
scala-c8a9329ff9b2a6ea99eef7234c9f84c0bfe0166b.zip
add syntactic extractor for assignment-like trees
There are three kinds of assign-like trees: 1. Assign(lhs, rhs) // $lhs = $rhs 3. AssignOrNamedArg(lhs, rhs) // $lhs = $rhs 2. Apply(Select(f, nme.update), args :+ rhs) // $f(..$args) = $rhs New syntactic combinator unifies all of them and lets users not to think about these implementations details.
Diffstat (limited to 'src')
-rw-r--r--src/compiler/scala/tools/nsc/ast/parser/Parsers.scala2
-rw-r--r--src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala8
-rw-r--r--src/compiler/scala/tools/reflect/quasiquotes/Reifiers.scala8
-rw-r--r--src/reflect/scala/reflect/api/BuildUtils.scala7
-rw-r--r--src/reflect/scala/reflect/internal/BuildUtils.scala12
-rw-r--r--src/reflect/scala/reflect/internal/StdNames.scala1
-rw-r--r--src/reflect/scala/reflect/internal/TreeGen.scala8
7 files changed, 32 insertions, 14 deletions
diff --git a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala
index 07e24900e9..a894e38ab4 100644
--- a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala
+++ b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala
@@ -1403,7 +1403,7 @@ self =>
if (in.token == EQUALS) {
t match {
case Ident(_) | Select(_, _) | Apply(_, _) =>
- t = atPos(t.pos.startOrPoint, in.skipToken()) { makeAssign(t, expr()) }
+ t = atPos(t.pos.startOrPoint, in.skipToken()) { gen.mkAssign(t, expr()) }
case _ =>
}
} else if (in.token == COLON) {
diff --git a/src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala b/src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala
index 91ff530e05..0d93a1b427 100644
--- a/src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala
+++ b/src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala
@@ -191,14 +191,6 @@ abstract class TreeBuilder {
}
}
- /** Create a tree representing an assignment <lhs = rhs> */
- def makeAssign(lhs: Tree, rhs: Tree): Tree = lhs match {
- case Apply(fn, args) =>
- Apply(atPos(fn.pos) { Select(fn, nme.update) }, args ::: List(rhs))
- case _ =>
- Assign(lhs, rhs)
- }
-
/** Tree for `od op`, start is start0 if od.pos is borked. */
def makePostfixSelect(start0: Int, end: Int, od: Tree, op: Name): Tree = {
val start = if (od.pos.isDefined) od.pos.startOrPoint else start0
diff --git a/src/compiler/scala/tools/reflect/quasiquotes/Reifiers.scala b/src/compiler/scala/tools/reflect/quasiquotes/Reifiers.scala
index c2d8bcdcd6..0d1fb6be07 100644
--- a/src/compiler/scala/tools/reflect/quasiquotes/Reifiers.scala
+++ b/src/compiler/scala/tools/reflect/quasiquotes/Reifiers.scala
@@ -10,7 +10,7 @@ trait Reifiers { self: Quasiquotes =>
import global.build.{SyntacticClassDef, SyntacticTraitDef, SyntacticModuleDef,
SyntacticDefDef, SyntacticValDef, SyntacticVarDef,
SyntacticBlock, SyntacticApplied, SyntacticTypeApplied,
- SyntacticFunction, SyntacticNew}
+ SyntacticFunction, SyntacticNew, SyntacticAssign}
import global.treeInfo._
import global.definitions._
import Cardinality._
@@ -71,9 +71,9 @@ trait Reifiers { self: Quasiquotes =>
reifyBuildCall(nme.SyntacticValDef, mods, name, tpt, rhs)
case SyntacticVarDef(mods, name, tpt, rhs) =>
reifyBuildCall(nme.SyntacticVarDef, mods, name, tpt, rhs)
- case SyntacticApplied(fun, argss) if argss.length > 1 =>
- reifyBuildCall(nme.SyntacticApplied, fun, argss)
- case SyntacticApplied(fun, argss @ (_ :+ (_ :+ Placeholder(_, _, DotDotDot)))) =>
+ case SyntacticAssign(lhs, rhs) =>
+ reifyBuildCall(nme.SyntacticAssign, lhs, rhs)
+ case SyntacticApplied(fun, argss) if argss.nonEmpty =>
reifyBuildCall(nme.SyntacticApplied, fun, argss)
case SyntacticTypeApplied(fun, targs) if targs.nonEmpty =>
reifyBuildCall(nme.SyntacticTypeApplied, fun, targs)
diff --git a/src/reflect/scala/reflect/api/BuildUtils.scala b/src/reflect/scala/reflect/api/BuildUtils.scala
index 60c2a81947..551c27bf9c 100644
--- a/src/reflect/scala/reflect/api/BuildUtils.scala
+++ b/src/reflect/scala/reflect/api/BuildUtils.scala
@@ -193,5 +193,12 @@ private[reflect] trait BuildUtils { self: Universe =>
def apply(mods: Modifiers, name: TermName, tpt: Tree, rhs: Tree): ValDef
def unapply(tree: Tree): Option[(Modifiers, TermName, Tree, Tree)]
}
+
+ val SyntacticAssign: SyntacticAssignExtractor
+
+ trait SyntacticAssignExtractor {
+ def apply(lhs: Tree, rhs: Tree): Tree
+ def unapply(tree: Tree): Option[(Tree, Tree)]
+ }
}
}
diff --git a/src/reflect/scala/reflect/internal/BuildUtils.scala b/src/reflect/scala/reflect/internal/BuildUtils.scala
index 2584dcb117..1049f83d46 100644
--- a/src/reflect/scala/reflect/internal/BuildUtils.scala
+++ b/src/reflect/scala/reflect/internal/BuildUtils.scala
@@ -139,7 +139,7 @@ trait BuildUtils { self: SymbolTable =>
object SyntacticApplied extends SyntacticAppliedExtractor {
def apply(tree: Tree, argss: List[List[Tree]]): Tree =
- argss.foldLeft(tree) { Apply(_, _) }
+ argss.foldLeft(tree) { (f, args) => Apply(f, args.map(treeInfo.assignmentToMaybeNamedArg)) }
def unapply(tree: Tree): Some[(Tree, List[List[Tree]])] = {
val treeInfo.Applied(fun, targs, argss) = tree
@@ -400,6 +400,16 @@ trait BuildUtils { self: SymbolTable =>
object SyntacticValDef extends SyntacticValDefBase { val isMutable = false }
object SyntacticVarDef extends SyntacticValDefBase { val isMutable = true }
+
+ object SyntacticAssign extends SyntacticAssignExtractor {
+ def apply(lhs: Tree, rhs: Tree): Tree = gen.mkAssign(lhs, rhs)
+ def unapply(tree: Tree): Option[(Tree, Tree)] = tree match {
+ case Assign(lhs, rhs) => Some((lhs, rhs))
+ case AssignOrNamedArg(lhs, rhs) => Some((lhs, rhs))
+ case Apply(Select(fn, nme.update), args :+ rhs) => Some((atPos(fn.pos)(Apply(fn, args)), rhs))
+ 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 6407a3979c..f4eae5590a 100644
--- a/src/reflect/scala/reflect/internal/StdNames.scala
+++ b/src/reflect/scala/reflect/internal/StdNames.scala
@@ -602,6 +602,7 @@ trait StdNames {
val SelectFromTypeTree: NameType = "SelectFromTypeTree"
val StringContext: NameType = "StringContext"
val SyntacticApplied: NameType = "SyntacticApplied"
+ val SyntacticAssign: NameType = "SyntacticAssign"
val SyntacticBlock: NameType = "SyntacticBlock"
val SyntacticClassDef: NameType = "SyntacticClassDef"
val SyntacticDefDef: NameType = "SyntacticDefDef"
diff --git a/src/reflect/scala/reflect/internal/TreeGen.scala b/src/reflect/scala/reflect/internal/TreeGen.scala
index 26adf20c52..0050df67d8 100644
--- a/src/reflect/scala/reflect/internal/TreeGen.scala
+++ b/src/reflect/scala/reflect/internal/TreeGen.scala
@@ -443,4 +443,12 @@ abstract class TreeGen extends macros.TreeBuilder {
case head :: Nil => head
case _ => gen.mkBlock(stats)
}
+
+ /** Create a tree representing an assignment <lhs = rhs> */
+ def mkAssign(lhs: Tree, rhs: Tree): Tree = lhs match {
+ case Apply(fn, args) =>
+ Apply(atPos(fn.pos)(Select(fn, nme.update)), args :+ rhs)
+ case _ =>
+ Assign(lhs, rhs)
+ }
}