diff options
author | Den Shabalin <den.shabalin@gmail.com> | 2013-07-08 20:24:45 +0200 |
---|---|---|
committer | Eugene Burmako <xeno.by@gmail.com> | 2013-07-08 21:02:30 +0200 |
commit | 310df92551c33ed0242e9a50606732a9b02bfee8 (patch) | |
tree | d605db96d7ce1fa8b590d48617853f46513e0c2c /src/compiler | |
parent | 9e064f783e7ee42b9d27655e2b15d830f8bae5f0 (diff) | |
download | scala-310df92551c33ed0242e9a50606732a9b02bfee8.tar.gz scala-310df92551c33ed0242e9a50606732a9b02bfee8.tar.bz2 scala-310df92551c33ed0242e9a50606732a9b02bfee8.zip |
moves TreeBuilder into the parser
This is the first of the two patches to the parser necessary for
quasiquotes to function.
This one moves TreeBuilder from Global to the internals of the Parsers,
so that quasiquotes will be able to override it later to support some
corner cases arising from splicing (see the subsequent quasiquote commit
for more details).
Surprisingly enough, almost noone used TreeBuilder outside the parser,
and it was necessary to move just a couple of methods to TreeGen to
satisfy broken dependencies.
Diffstat (limited to 'src/compiler')
-rw-r--r-- | src/compiler/scala/reflect/reify/package.scala | 2 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/Global.scala | 11 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/ast/TreeGen.scala | 48 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/ast/parser/Parsers.scala | 18 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala | 49 |
5 files changed, 64 insertions, 64 deletions
diff --git a/src/compiler/scala/reflect/reify/package.scala b/src/compiler/scala/reflect/reify/package.scala index d3cae3d123..30cfec8e2a 100644 --- a/src/compiler/scala/reflect/reify/package.scala +++ b/src/compiler/scala/reflect/reify/package.scala @@ -32,7 +32,7 @@ package object reify { // If we're in the constructor of an object or others don't have easy access to `this`, we have no good way to grab // the class of that object. Instead, we construct an anonymous class and grab his class file, assuming // this is enough to get the correct class loadeer for the class we *want* a mirror for, the object itself. - rClassTree orElse Apply(Select(treeBuilder.makeAnonymousNew(Nil), sn.GetClass), Nil) + rClassTree orElse Apply(Select(gen.mkAnonymousNew(Nil), sn.GetClass), Nil) } // JavaUniverse is defined in scala-reflect.jar, so we must be very careful in case someone reifies stuff having only scala-library.jar on the classpath val isJavaUniverse = JavaUniverseClass != NoSymbol && universe.tpe <:< JavaUniverseClass.toTypeConstructor diff --git a/src/compiler/scala/tools/nsc/Global.scala b/src/compiler/scala/tools/nsc/Global.scala index 603f9af1b4..ed97f78032 100644 --- a/src/compiler/scala/tools/nsc/Global.scala +++ b/src/compiler/scala/tools/nsc/Global.scala @@ -103,17 +103,6 @@ class Global(var currentSettings: Settings, var reporter: Reporter) typer.typed(mkCast(tree, pt)) } - /** Trees fresh from the oven, mostly for use by the parser. */ - object treeBuilder extends { - val global: Global.this.type = Global.this - } with TreeBuilder { - def freshName(prefix: String): Name = freshTermName(prefix) - def freshTermName(prefix: String): TermName = currentUnit.freshTermName(prefix) - def freshTypeName(prefix: String): TypeName = currentUnit.freshTypeName(prefix) - def o2p(offset: Int): Position = new OffsetPosition(currentUnit.source, offset) - def r2p(start: Int, mid: Int, end: Int): Position = rangePos(currentUnit.source, start, mid, end) - } - /** Fold constants */ object constfold extends { val global: Global.this.type = Global.this diff --git a/src/compiler/scala/tools/nsc/ast/TreeGen.scala b/src/compiler/scala/tools/nsc/ast/TreeGen.scala index c28a6ba337..d60daaa2bc 100644 --- a/src/compiler/scala/tools/nsc/ast/TreeGen.scala +++ b/src/compiler/scala/tools/nsc/ast/TreeGen.scala @@ -255,4 +255,52 @@ abstract class TreeGen extends scala.reflect.internal.TreeGen with TreeDSL { attrThis, If(cond, Block(syncBody: _*), EmptyTree)) :: stats: _*) + + /** Creates a tree representing new Object { stats }. + * To make sure an anonymous subclass of Object is created, + * if there are no stats, a () is added. + */ + def mkAnonymousNew(stats: List[Tree]): Tree = { + val stats1 = if (stats.isEmpty) List(Literal(Constant(()))) else stats + mkNew(Nil, emptyValDef, stats1, NoPosition, NoPosition) + } + + /** Create positioned tree representing an object creation <new parents { stats } + * @param npos the position of the new + * @param cpos the position of the anonymous class starting with parents + */ + def mkNew(parents: List[Tree], self: ValDef, stats: List[Tree], + npos: Position, cpos: Position): Tree = + if (parents.isEmpty) + mkNew(List(scalaAnyRefConstr), self, stats, npos, cpos) + else if (parents.tail.isEmpty && stats.isEmpty) { + // `Parsers.template` no longer differentiates tpts and their argss + // e.g. `C()` will be represented as a single tree Apply(Ident(C), Nil) + // instead of parents = Ident(C), argss = Nil as before + // this change works great for things that are actually templates + // but in this degenerate case we need to perform postprocessing + val app = treeInfo.dissectApplied(parents.head) + atPos(npos union cpos) { New(app.callee, app.argss) } + } else { + val x = tpnme.ANON_CLASS_NAME + atPos(npos union cpos) { + Block( + List( + atPos(cpos) { + ClassDef( + Modifiers(FINAL), x, Nil, + Template(parents, self, NoMods, ListOfNil, stats, cpos.focus)) + }), + atPos(npos) { + New( + Ident(x) setPos npos.focus, + Nil) + } + ) + } + } + + def mkSyntheticParam(pname: TermName) = + ValDef(Modifiers(PARAM | SYNTHETIC), pname, TypeTree(), EmptyTree) + } diff --git a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala index ef5872986c..8778a655c1 100644 --- a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala +++ b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala @@ -26,13 +26,22 @@ import util.FreshNameCreator * the beginnings of a campaign against this latest incursion by Cutty * McPastington and his army of very similar soldiers. */ -trait ParsersCommon extends ScannersCommon { +trait ParsersCommon extends ScannersCommon { self => val global : Global import global._ def newLiteral(const: Any) = Literal(Constant(const)) def literalUnit = newLiteral(()) + class ParserTreeBuilder extends TreeBuilder { + val global: self.global.type = self.global + def freshName(prefix: String): Name = freshTermName(prefix) + def freshTermName(prefix: String): TermName = currentUnit.freshTermName(prefix) + def freshTypeName(prefix: String): TypeName = currentUnit.freshTypeName(prefix) + def o2p(offset: Int): Position = new OffsetPosition(currentUnit.source, offset) + def r2p(start: Int, mid: Int, end: Int): Position = rangePos(currentUnit.source, start, mid, end) + } + /** This is now an abstract class, only to work around the optimizer: * methods in traits are never inlined. */ @@ -290,6 +299,7 @@ self => /** whether a non-continuable syntax error has been seen */ private var lastErrorOffset : Int = -1 + val treeBuilder = new ParserTreeBuilder import treeBuilder.{global => _, _} /** The types of the context bounds of type parameters of the surrounding class @@ -399,7 +409,7 @@ self => def mainParamType = AppliedTypeTree(Ident(tpnme.Array), List(Ident(tpnme.String))) def mainParameter = List(ValDef(Modifiers(Flags.PARAM), nme.argv, mainParamType, EmptyTree)) def mainSetArgv = List(ValDef(NoMods, nme.args, TypeTree(), Ident(nme.argv))) - def mainDef = DefDef(NoMods, nme.main, Nil, List(mainParameter), scalaDot(tpnme.Unit), Block(mainSetArgv, makeAnonymousNew(stmts))) + def mainDef = DefDef(NoMods, nme.main, Nil, List(mainParameter), scalaDot(tpnme.Unit), Block(mainSetArgv, gen.mkAnonymousNew(stmts))) // object Main def moduleName = newTermName(ScriptRunner scriptMain settings) @@ -1501,7 +1511,7 @@ self => val pname = freshName("x$") in.nextToken() val id = atPos(start) (Ident(pname)) - val param = atPos(id.pos.focus){ makeSyntheticParam(pname.toTermName) } + val param = atPos(id.pos.focus){ gen.mkSyntheticParam(pname.toTermName) } placeholderParams = param :: placeholderParams id case LPAREN => @@ -1516,7 +1526,7 @@ self => val tstart = in.offset val (parents, self, stats) = template() val cpos = r2p(tstart, tstart, in.lastOffset max tstart) - makeNew(parents, self, stats, npos, cpos) + gen.mkNew(parents, self, stats, npos, cpos) case _ => syntaxErrorOrIncompleteAnd("illegal start of simple expression", skipIt = true)(errorTermTree) } diff --git a/src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala b/src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala index 0ef71fa1b5..666f19851d 100644 --- a/src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala +++ b/src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala @@ -190,50 +190,6 @@ abstract class TreeBuilder { } } - /** Creates a tree representing new Object { stats }. - * To make sure an anonymous subclass of Object is created, - * if there are no stats, a () is added. - */ - def makeAnonymousNew(stats: List[Tree]): Tree = { - val stats1 = if (stats.isEmpty) List(Literal(Constant(()))) else stats - makeNew(Nil, emptyValDef, stats1, NoPosition, NoPosition) - } - - /** Create positioned tree representing an object creation <new parents { stats } - * @param npos the position of the new - * @param cpos the position of the anonymous class starting with parents - */ - def makeNew(parents: List[Tree], self: ValDef, stats: List[Tree], - npos: Position, cpos: Position): Tree = - if (parents.isEmpty) - makeNew(List(scalaAnyRefConstr), self, stats, npos, cpos) - else if (parents.tail.isEmpty && stats.isEmpty) { - // `Parsers.template` no longer differentiates tpts and their argss - // e.g. `C()` will be represented as a single tree Apply(Ident(C), Nil) - // instead of parents = Ident(C), argss = Nil as before - // this change works great for things that are actually templates - // but in this degenerate case we need to perform postprocessing - val app = treeInfo.dissectApplied(parents.head) - atPos(npos union cpos) { New(app.callee, app.argss) } - } else { - val x = tpnme.ANON_CLASS_NAME - atPos(npos union cpos) { - Block( - List( - atPos(cpos) { - ClassDef( - Modifiers(FINAL), x, Nil, - Template(parents, self, NoMods, ListOfNil, stats, cpos.focus)) - }), - atPos(npos) { - New( - Ident(x) setPos npos.focus, - Nil) - } - ) - } - } - /** Create a tree representing an assignment <lhs = rhs> */ def makeAssign(lhs: Tree, rhs: Tree): Tree = lhs match { case Apply(fn, args) => @@ -303,9 +259,6 @@ abstract class TreeBuilder { def makeParam(pname: TermName, tpe: Tree) = ValDef(Modifiers(PARAM), pname, tpe, EmptyTree) - def makeSyntheticParam(pname: TermName) = - ValDef(Modifiers(PARAM | SYNTHETIC), pname, TypeTree(), EmptyTree) - def makeSyntheticTypeParam(pname: TypeName, bounds: Tree) = TypeDef(Modifiers(DEFERRED | SYNTHETIC), pname, Nil, bounds) @@ -467,7 +420,7 @@ abstract class TreeBuilder { val x = freshTermName(prefix) val id = Ident(x) val sel = if (checkExhaustive) id else gen.mkUnchecked(id) - Function(List(makeSyntheticParam(x)), Match(sel, cases)) + Function(List(gen.mkSyntheticParam(x)), Match(sel, cases)) } /** Create tree for case definition <case pat if guard => rhs> */ |