Skip to content

Commit 330ead5

Browse files
committed
Reducing variation of tree creation methods.
TreeDSL has no future - it was always a temporary measure waiting for something like quasiquotes to come along. In this commit I cull as much of it as I can, especially the delicate matter of creating new DefDefs and ValDefs, which I completely turn over to the old style creators. I unified all the symbol-based DefDef and ValDef creators under a single method, since it was yet another place where ctrl-C and ctrl-V were being punched with glee. Was beaten to the punch on adding copyTypeDef to fill out the *Def creators. Eliminated as many redundant positioning calls as I could find. If you are creating a DefTree tree based on a symbol, it will always have an atPos(sym.pos) { ... } wrapped around it. You don't need another one. All of this is motivated by positions work: positions are assigned in so many places and in such an ad hoc fashion that it is impossible to bring consistency to that without first bringing some consistency to tree creation.
1 parent 55c6fd4 commit 330ead5

23 files changed

+163
-317
lines changed

src/compiler/scala/tools/nsc/ast/TreeDSL.scala

Lines changed: 5 additions & 112 deletions
Original file line numberDiff line numberDiff line change
@@ -133,90 +133,6 @@ trait TreeDSL {
133133
def ==>(body: Tree): CaseDef = CaseDef(pat, guard, body)
134134
}
135135

136-
/** VODD, if it's not obvious, means ValOrDefDef. This is the
137-
* common code between a tree based on a pre-existing symbol and
138-
* one being built from scratch.
139-
*/
140-
trait VODDStart {
141-
def name: Name
142-
def defaultMods: Modifiers
143-
def defaultTpt: Tree
144-
def defaultPos: Position
145-
146-
type ResultTreeType <: ValOrDefDef
147-
def mkTree(rhs: Tree): ResultTreeType
148-
def ===(rhs: Tree): ResultTreeType
149-
150-
private var _tpt: Tree = null
151-
private var _pos: Position = null
152-
153-
def withType(tp: Type): this.type = {
154-
_tpt = TypeTree(tp)
155-
this
156-
}
157-
def withPos(pos: Position): this.type = {
158-
_pos = pos
159-
this
160-
}
161-
162-
final def mods = defaultMods
163-
final def tpt = if (_tpt == null) defaultTpt else _tpt
164-
final def pos = if (_pos == null) defaultPos else _pos
165-
}
166-
trait SymVODDStart extends VODDStart {
167-
def sym: Symbol
168-
def symType: Type
169-
170-
def name = sym.name
171-
def defaultMods = Modifiers(sym.flags)
172-
def defaultTpt = TypeTree(symType) setPos sym.pos.focus
173-
def defaultPos = sym.pos
174-
175-
final def ===(rhs: Tree): ResultTreeType =
176-
atPos(pos)(mkTree(rhs) setSymbol sym)
177-
}
178-
trait ValCreator {
179-
self: VODDStart =>
180-
181-
type ResultTreeType = ValDef
182-
def mkTree(rhs: Tree): ValDef = ValDef(mods, name.toTermName, tpt, rhs)
183-
}
184-
trait DefCreator {
185-
self: VODDStart =>
186-
187-
def tparams: List[TypeDef]
188-
def vparamss: List[List[ValDef]]
189-
190-
type ResultTreeType = DefDef
191-
def mkTree(rhs: Tree): DefDef = DefDef(mods, name.toTermName, tparams, vparamss, tpt, rhs)
192-
}
193-
194-
class DefSymStart(val sym: Symbol) extends SymVODDStart with DefCreator {
195-
def symType = sym.tpe_*.finalResultType
196-
def tparams = sym.typeParams map TypeDef
197-
def vparamss = mapParamss(sym)(ValDef)
198-
}
199-
class ValSymStart(val sym: Symbol) extends SymVODDStart with ValCreator {
200-
def symType = sym.tpe
201-
}
202-
203-
trait TreeVODDStart extends VODDStart {
204-
def defaultMods = NoMods
205-
def defaultTpt = TypeTree()
206-
def defaultPos = NoPosition
207-
208-
final def ===(rhs: Tree): ResultTreeType =
209-
if (pos == NoPosition) mkTree(rhs)
210-
else atPos(pos)(mkTree(rhs))
211-
}
212-
213-
class ValTreeStart(val name: Name) extends TreeVODDStart with ValCreator {
214-
}
215-
class DefTreeStart(val name: Name) extends TreeVODDStart with DefCreator {
216-
def tparams: List[TypeDef] = Nil
217-
def vparamss: List[List[ValDef]] = ListOfNil
218-
}
219-
220136
class IfStart(cond: Tree, thenp: Tree) {
221137
def THEN(x: Tree) = new IfStart(cond, x)
222138
def ELSE(elsep: Tree) = If(cond, thenp, elsep)
@@ -230,46 +146,23 @@ trait TreeDSL {
230146
def CASE(pat: Tree): CaseStart = new CaseStart(pat, EmptyTree)
231147
def DEFAULT: CaseStart = new CaseStart(WILD.empty, EmptyTree)
232148

233-
class SymbolMethods(target: Symbol) {
234-
def IS_NULL() = REF(target) OBJ_EQ NULL
235-
def GET() = fn(REF(target), nme.get)
236-
def ARGS = target.paramss.head
237-
}
238-
239-
/** Top level accessible. */
240-
def MATCHERROR(arg: Tree) = Throw(MatchErrorClass.tpe, arg)
241-
def THROW(sym: Symbol, msg: Tree): Throw = Throw(sym.tpe, msg.TOSTRING())
242-
243149
def NEW(tpt: Tree, args: Tree*): Tree = New(tpt, List(args.toList))
244-
def DEF(sym: Symbol): DefSymStart = new DefSymStart(sym)
245-
def VAL(sym: Symbol): ValSymStart = new ValSymStart(sym)
246150

247-
def AND(guards: Tree*) =
248-
if (guards.isEmpty) EmptyTree
249-
else guards reduceLeft gen.mkAnd
151+
def NOT(tree: Tree) = Select(tree, Boolean_not)
152+
def AND(guards: Tree*) = if (guards.isEmpty) EmptyTree else guards reduceLeft gen.mkAnd
250153

251154
def IF(tree: Tree) = new IfStart(tree, EmptyTree)
252155
def TRY(tree: Tree) = new TryStart(tree, Nil, EmptyTree)
253156
def BLOCK(xs: Tree*) = Block(xs.init.toList, xs.last)
254-
def NOT(tree: Tree) = Select(tree, Boolean_not)
255-
def SOME(xs: Tree*) = Apply(SomeClass.companionSymbol, makeTupleTerm(xs.toList, flattenUnary = true))
157+
def SOME(xs: Tree*) = Apply(SomeClass.companionSymbol, treeBuilder.makeTupleTerm(xs.toList, flattenUnary = true))
256158

257159
/** Typed trees from symbols. */
258-
def THIS(sym: Symbol) = gen.mkAttributedThis(sym)
259-
def ID(sym: Symbol) = gen.mkAttributedIdent(sym)
260-
def REF(sym: Symbol) = gen.mkAttributedRef(sym)
261-
def REF(pre: Type, sym: Symbol) = gen.mkAttributedRef(pre, sym)
262-
263-
def makeTupleTerm(trees: List[Tree], flattenUnary: Boolean): Tree = trees match {
264-
case Nil => UNIT
265-
case List(tree) if flattenUnary => tree
266-
case _ => Apply(TupleClass(trees.length).companionModule, trees: _*)
267-
}
160+
def REF(sym: Symbol) = gen.mkAttributedRef(sym)
161+
def REF(pre: Type, sym: Symbol) = gen.mkAttributedRef(pre, sym)
268162

269163
/** Implicits - some of these should probably disappear **/
270164
implicit def mkTreeMethods(target: Tree): TreeMethods = new TreeMethods(target)
271165
implicit def mkTreeMethodsFromSymbol(target: Symbol): TreeMethods = new TreeMethods(Ident(target))
272-
implicit def mkSymbolMethodsFromSymbol(target: Symbol): SymbolMethods = new SymbolMethods(target)
273166

274167
/** (foo DOT bar) might be simply a Select, but more likely it is to be immediately
275168
* followed by an Apply. We don't want to add an actual apply method to arbitrary

src/compiler/scala/tools/nsc/ast/parser/Parsers.scala

Lines changed: 25 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -703,14 +703,10 @@ self =>
703703

704704
/* ---------- TREE CONSTRUCTION ------------------------------------------- */
705705

706-
def atPos[T <: Tree](offset: Int)(t: T): T =
707-
global.atPos(r2p(offset, offset, in.lastOffset max offset))(t)
708-
def atPos[T <: Tree](start: Int, point: Int)(t: T): T =
709-
global.atPos(r2p(start, point, in.lastOffset max start))(t)
710-
def atPos[T <: Tree](start: Int, point: Int, end: Int)(t: T): T =
711-
global.atPos(r2p(start, point, end))(t)
712-
def atPos[T <: Tree](pos: Position)(t: T): T =
713-
global.atPos(pos)(t)
706+
def atPos[T <: Tree](offset: Int)(t: T): T = atPos(r2p(offset, offset, in.lastOffset max offset))(t)
707+
def atPos[T <: Tree](start: Int, point: Int)(t: T): T = atPos(r2p(start, point, in.lastOffset max start))(t)
708+
def atPos[T <: Tree](start: Int, point: Int, end: Int)(t: T): T = atPos(r2p(start, point, end))(t)
709+
def atPos[T <: Tree](pos: Position)(t: T): T = global.atPos(pos)(t)
714710

715711
def atInPos[T <: Tree](t: T): T = atPos(o2p(in.offset))(t)
716712
def setInPos[T <: Tree](t: T): T = t setPos o2p(in.offset)
@@ -946,21 +942,23 @@ self =>
946942
ts += annotType()
947943
}
948944
newLineOptWhenFollowedBy(LBRACE)
949-
atPos(t.pos.startOrPoint) {
950-
if (in.token == LBRACE) {
951-
// Warn if they are attempting to refine Unit; we can't be certain it's
952-
// scala.Unit they're refining because at this point all we have is an
953-
// identifier, but at a later stage we lose the ability to tell an empty
954-
// refinement from no refinement at all. See bug #284.
955-
for (Ident(name) <- ts) name.toString match {
956-
case "Unit" | "scala.Unit" =>
957-
warning("Detected apparent refinement of Unit; are you missing an '=' sign?")
958-
case _ =>
959-
}
960-
CompoundTypeTree(Template(ts.toList, emptyValDef, refinement()))
961-
}
962-
else
963-
makeIntersectionTypeTree(ts.toList)
945+
val types = ts.toList
946+
val braceOffset = in.offset
947+
val hasRefinement = in.token == LBRACE
948+
val refinements = if (hasRefinement) refinement() else Nil
949+
// Warn if they are attempting to refine Unit; we can't be certain it's
950+
// scala.Unit they're refining because at this point all we have is an
951+
// identifier, but at a later stage we lose the ability to tell an empty
952+
// refinement from no refinement at all. See bug #284.
953+
if (hasRefinement) types match {
954+
case Ident(name) :: Nil if name endsWith "Unit" => warning(braceOffset, "Detected apparent refinement of Unit; are you missing an '=' sign?")
955+
case _ =>
956+
}
957+
// The second case includes an empty refinement - refinements is empty, but
958+
// it still gets a CompoundTypeTree.
959+
ts.toList match {
960+
case tp :: Nil if !hasRefinement => tp // single type, no refinement, already positioned
961+
case tps => atPos(t.pos.startOrPoint)(CompoundTypeTree(Template(tps, emptyValDef, refinements)))
964962
}
965963
}
966964

@@ -2776,8 +2774,10 @@ self =>
27762774
def readAppliedParent() = {
27772775
val start = in.offset
27782776
val parent = startAnnotType()
2779-
val argss = if (in.token == LPAREN) multipleArgumentExprs() else Nil
2780-
parents += atPos(start)((parent /: argss)(Apply.apply))
2777+
parents += (in.token match {
2778+
case LPAREN => atPos(start)((parent /: multipleArgumentExprs())(Apply.apply))
2779+
case _ => parent
2780+
})
27812781
}
27822782
readAppliedParent()
27832783
while (in.token == WITH) { in.nextToken(); readAppliedParent() }

src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -204,11 +204,6 @@ abstract class TreeBuilder {
204204
atPos(r2p(start, end, end + op.length)) { new PostfixSelect(od, op.encode) }
205205
}
206206

207-
/** A type tree corresponding to (possibly unary) intersection type */
208-
def makeIntersectionTypeTree(tps: List[Tree]): Tree =
209-
if (tps.tail.isEmpty) tps.head
210-
else CompoundTypeTree(Template(tps, emptyValDef, Nil))
211-
212207
/** Create tree representing a while loop */
213208
def makeWhile(startPos: Int, cond: Tree, body: Tree): Tree = {
214209
val lname = freshTermName(nme.WHILE_PREFIX)

src/compiler/scala/tools/nsc/transform/CleanUp.scala

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ abstract class CleanUp extends Transform with ast.TreeDSL {
9494
if (!isFinal)
9595
varSym.addAnnotation(VolatileAttr)
9696

97-
val varDef = typedPos( VAL(varSym) === forInit )
97+
val varDef = typedPos(ValDef(varSym, forInit))
9898
newStaticMembers append transform(varDef)
9999

100100
val varInit = typedPos( REF(varSym) === forInit )
@@ -155,13 +155,13 @@ abstract class CleanUp extends Transform with ast.TreeDSL {
155155
val methodSym = reflMethodSym.newVariable(mkTerm("method"), ad.pos) setInfo MethodClass.tpe
156156

157157
BLOCK(
158-
VAL(methodCache) === getPolyCache,
158+
ValDef(methodCache, getPolyCache),
159159
IF (REF(methodCache) OBJ_EQ NULL) THEN BLOCK(
160160
REF(methodCache) === NEW(TypeTree(EmptyMethodCacheClass.tpe)),
161161
REF(reflPolyCacheSym) === gen.mkSoftRef(REF(methodCache))
162162
) ENDIF,
163163

164-
VAL(methodSym) === (REF(methodCache) DOT methodCache_find)(REF(forReceiverSym)),
164+
ValDef(methodSym, (REF(methodCache) DOT methodCache_find)(REF(forReceiverSym))),
165165
IF (REF(methodSym) OBJ_NE NULL) .
166166
THEN (Return(REF(methodSym)))
167167
ELSE {
@@ -372,7 +372,7 @@ abstract class CleanUp extends Transform with ast.TreeDSL {
372372
qual = REF(sym)
373373

374374
BLOCK(
375-
VAL(sym) === qual0,
375+
ValDef(sym, qual0),
376376
callAsReflective(mparams map (_.tpe), resType)
377377
)
378378
}
@@ -543,7 +543,7 @@ abstract class CleanUp extends Transform with ast.TreeDSL {
543543
)
544544

545545
// create field definition and initialization
546-
val stfieldDef = theTyper.typedPos(pos)(VAL(stfieldSym) === rhs)
546+
val stfieldDef = theTyper.typedPos(pos)(ValDef(stfieldSym, rhs))
547547
val stfieldInit = theTyper.typedPos(pos)(REF(stfieldSym) === rhs)
548548

549549
// add field definition to new defs

src/compiler/scala/tools/nsc/transform/Erasure.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -513,7 +513,7 @@ abstract class Erasure extends AddInterfaces
513513

514514
maybeWrap(bridgingCall)
515515
}
516-
atPos(bridge.pos)(DefDef(bridge, rhs))
516+
DefDef(bridge, rhs)
517517
}
518518
}
519519

src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -225,9 +225,10 @@ abstract class ExplicitOuter extends InfoTransform
225225
*
226226
* Will return `EmptyTree` if there is no outer accessor because of a premature self reference.
227227
*/
228-
protected def outerValue: Tree =
229-
if (outerParam != NoSymbol) ID(outerParam)
230-
else outerSelect(THIS(currentClass))
228+
protected def outerValue: Tree = outerParam match {
229+
case NoSymbol => outerSelect(gen.mkAttributedThis(currentClass))
230+
case outerParam => gen.mkAttributedIdent(outerParam)
231+
}
231232

232233
/** Select and apply outer accessor from 'base'
233234
* The result is typed but not positioned.
@@ -368,8 +369,7 @@ abstract class ExplicitOuter extends InfoTransform
368369

369370
/** The definition tree of the outer accessor of current class
370371
*/
371-
def outerFieldDef: Tree =
372-
VAL(outerField(currentClass)) === EmptyTree
372+
def outerFieldDef: Tree = ValDef(outerField(currentClass))
373373

374374
/** The definition tree of the outer accessor of current class
375375
*/

src/compiler/scala/tools/nsc/transform/ExtensionMethods.scala

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -205,7 +205,7 @@ abstract class ExtensionMethods extends Transform with TypingTransformers {
205205
def makeExtensionMethodSymbol = {
206206
val extensionName = extensionNames(origMeth).head.toTermName
207207
val extensionMeth = (
208-
companion.moduleClass.newMethod(extensionName, origMeth.pos, origMeth.flags & ~OVERRIDE & ~PROTECTED | FINAL)
208+
companion.moduleClass.newMethod(extensionName, tree.pos.focus, origMeth.flags & ~OVERRIDE & ~PROTECTED | FINAL)
209209
setAnnotations origMeth.annotations
210210
)
211211
origMeth.removeAnnotation(TailrecClass) // it's on the extension method, now.
@@ -237,7 +237,7 @@ abstract class ExtensionMethods extends Transform with TypingTransformers {
237237
gen.mkCastPreservingAnnotations(extensionBody, extensionMono.finalResultType) // SI-7818 e.g. mismatched existential skolems
238238

239239
// Record the extension method. Later, in `Extender#transformStats`, these will be added to the companion object.
240-
extensionDefs(companion) += atPos(tree.pos)(DefDef(extensionMeth, castBody))
240+
extensionDefs(companion) += DefDef(extensionMeth, castBody)
241241

242242
// These three lines are assembling Foo.bar$extension[T1, T2, ...]($this)
243243
// which leaves the actual argument application for extensionCall.
@@ -294,7 +294,7 @@ abstract class ExtensionMethods extends Transform with TypingTransformers {
294294
val origThis = extensionMeth.owner.companionClass
295295
val baseType = qual.tpe.baseType(origThis)
296296
val allTargs = targs.map(_.tpe) ::: baseType.typeArgs
297-
val fun = gen.mkAttributedTypeApply(THIS(extensionMeth.owner), extensionMeth, allTargs)
297+
val fun = gen.mkAttributedTypeApply(gen.mkAttributedThis(extensionMeth.owner), extensionMeth, allTargs)
298298
allArgss.foldLeft(fun)(Apply(_, _))
299299
}
300300
case _ => super.transform(tree)

src/compiler/scala/tools/nsc/transform/LazyVals.scala

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -199,14 +199,15 @@ abstract class LazyVals extends Transform with TypingTransformers with ast.TreeD
199199
if (bitmaps.contains(lzyVal))
200200
bitmaps(lzyVal).map(_.owner = defSym)
201201
val rhs: Tree = (gen.mkSynchronizedCheck(clazz, cond, syncBody, stats)).changeOwner(currentOwner -> defSym)
202-
DEF(defSym).mkTree(addBitmapDefs(lzyVal, BLOCK(rhs, retVal))) setSymbol defSym
202+
203+
DefDef(defSym, addBitmapDefs(lzyVal, BLOCK(rhs, retVal)))
203204
}
204205

205206

206207
def mkFastPathBody(clazz: Symbol, lzyVal: Symbol, cond: Tree, syncBody: List[Tree],
207208
stats: List[Tree], retVal: Tree): (Tree, Tree) = {
208209
val slowPathDef: Tree = mkSlowPathDef(clazz, lzyVal, cond, syncBody, stats, retVal)
209-
(If(cond, Apply(ID(slowPathDef.symbol), List()), retVal), slowPathDef)
210+
(If(cond, Apply(Ident(slowPathDef.symbol), Nil), retVal), slowPathDef)
210211
}
211212

212213
/** return a 'lazified' version of rhs. Rhs should conform to the

src/compiler/scala/tools/nsc/transform/Mixin.scala

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -472,7 +472,6 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL {
472472
/** The typer */
473473
private var localTyper: erasure.Typer = _
474474
private def typedPos(pos: Position)(tree: Tree): Tree = localTyper.typedPos(pos)(tree)
475-
private def localTyped(pos: Position, tree: Tree, pt: Type) = localTyper.typed(atPos(pos)(tree), pt)
476475

477476
/** Map lazy values to the fields they should null after initialization. */
478477
private var lazyValNullables: Map[Symbol, Set[Symbol]] = _
@@ -695,10 +694,10 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL {
695694
*/
696695
def completeSuperAccessor(stat: Tree) = stat match {
697696
case DefDef(_, _, _, vparams :: Nil, _, EmptyTree) if stat.symbol.isSuperAccessor =>
698-
val rhs0 = (Super(clazz, tpnme.EMPTY) DOT stat.symbol.alias)(vparams map (v => Ident(v.symbol)): _*)
699-
val rhs1 = localTyped(stat.pos, rhs0, stat.symbol.tpe.resultType)
697+
val body = atPos(stat.pos)(Apply(Select(Super(clazz, tpnme.EMPTY), stat.symbol.alias), vparams map (v => Ident(v.symbol))))
698+
val pt = stat.symbol.tpe.resultType
700699

701-
deriveDefDef(stat)(_ => enteringMixin(transform(rhs1)))
700+
copyDefDef(stat)(rhs = enteringMixin(transform(localTyper.typed(body, pt))))
702701
case _ =>
703702
stat
704703
}
@@ -724,8 +723,8 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL {
724723
case _ =>
725724
}
726725
val init = bitmapKind match {
727-
case BooleanClass => VAL(sym) === FALSE
728-
case _ => VAL(sym) === ZERO
726+
case BooleanClass => ValDef(sym, FALSE)
727+
case _ => ValDef(sym, ZERO)
729728
}
730729

731730
sym setFlag PrivateLocal
@@ -775,7 +774,7 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL {
775774
defSym setInfoAndEnter MethodType(params, lzyVal.tpe.resultType)
776775
val rhs: Tree = (gen.mkSynchronizedCheck(attrThis, cond, syncBody, stats)).changeOwner(currentOwner -> defSym)
777776
val strictSubst = new TreeSymSubstituterWithCopying(args.map(_.symbol), params)
778-
addDef(position(defSym), DEF(defSym).mkTree(strictSubst(BLOCK(rhs, retVal))) setSymbol defSym)
777+
addDef(position(defSym), DefDef(defSym, strictSubst(BLOCK(rhs, retVal))))
779778
defSym
780779
}
781780

0 commit comments

Comments
 (0)