diff options
author | Den Shabalin <den.shabalin@gmail.com> | 2013-09-11 19:22:48 +0200 |
---|---|---|
committer | Den Shabalin <den.shabalin@gmail.com> | 2013-09-18 20:36:17 +0200 |
commit | c8a9329ff9b2a6ea99eef7234c9f84c0bfe0166b (patch) | |
tree | ddb01dd1c77344bc1b7768ad7460dd021274faa4 /src/reflect | |
parent | a8543ef28f8fc0152208f4eef763344657bf9e5a (diff) | |
download | scala-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/reflect')
4 files changed, 27 insertions, 1 deletions
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) + } } |