4
abstract class TreeGen extends macros.TreeBuilder {
5
val global: SymbolTable
10
def rootId(name: Name) = Select(Ident(nme.ROOTPKG), name)
11
def rootScalaDot(name: Name) = Select(rootId(nme.scala_) setSymbol ScalaPackage, name)
12
def scalaDot(name: Name) = Select(Ident(nme.scala_) setSymbol ScalaPackage, name)
13
def scalaAnnotationDot(name: Name) = Select(scalaDot(nme.annotation), name)
14
def scalaAnyRefConstr = scalaDot(tpnme.AnyRef) setSymbol AnyRefClass
15
def scalaUnitConstr = scalaDot(tpnme.Unit) setSymbol UnitClass
16
def productConstr = scalaDot(tpnme.Product) setSymbol ProductRootClass
17
def serializableConstr = scalaDot(tpnme.Serializable) setSymbol SerializableClass
19
def scalaFunctionConstr(argtpes: List[Tree], restpe: Tree, abstractFun: Boolean = false): Tree = {
20
val cls = if (abstractFun)
21
mkAttributedRef(AbstractFunctionClass(argtpes.length))
23
mkAttributedRef(FunctionClass(argtpes.length))
24
AppliedTypeTree(cls, argtpes :+ restpe)
27
/** A creator for method calls, e.g. fn[T1, T2, ...](v1, v2, ...)
28
* There are a number of variations.
30
* @param receiver symbol of the method receiver
31
* @param methodName name of the method to call
32
* @param targs type arguments (if Nil, no TypeApply node will be generated)
33
* @param args value arguments
34
* @return the newly created trees.
36
def mkMethodCall(receiver: Symbol, methodName: Name, targs: List[Type], args: List[Tree]): Tree =
37
mkMethodCall(Select(mkAttributedRef(receiver), methodName), targs, args)
38
def mkMethodCall(method: Symbol, targs: List[Type], args: List[Tree]): Tree =
39
mkMethodCall(mkAttributedRef(method), targs, args)
40
def mkMethodCall(method: Symbol, args: List[Tree]): Tree =
41
mkMethodCall(method, Nil, args)
42
def mkMethodCall(target: Tree, args: List[Tree]): Tree =
43
mkMethodCall(target, Nil, args)
44
def mkMethodCall(receiver: Symbol, methodName: Name, args: List[Tree]): Tree =
45
mkMethodCall(receiver, methodName, Nil, args)
46
def mkMethodCall(receiver: Tree, method: Symbol, targs: List[Type], args: List[Tree]): Tree =
47
mkMethodCall(Select(receiver, method), targs, args)
49
def mkMethodCall(target: Tree, targs: List[Type], args: List[Tree]): Tree =
50
Apply(mkTypeApply(target, targs map TypeTree), args)
52
def mkNullaryCall(method: Symbol, targs: List[Type]): Tree =
53
mkTypeApply(mkAttributedRef(method), targs map TypeTree)
55
/** Builds a reference to value whose type is given stable prefix.
56
* The type must be suitable for this. For example, it
57
* must not be a TypeRef pointing to an abstract type variable.
59
def mkAttributedQualifier(tpe: Type): Tree =
60
mkAttributedQualifier(tpe, NoSymbol)
62
/** Builds a reference to value whose type is given stable prefix.
63
* If the type is unsuitable, e.g. it is a TypeRef for an
64
* abstract type variable, then an Ident will be made using
65
* termSym as the Ident's symbol. In that case, termSym must
68
def mkAttributedQualifier(tpe: Type, termSym: Symbol): Tree = {
69
def failMessage = "mkAttributedQualifier(" + tpe + ", " + termSym + ")"
73
case ThisType(clazz) =>
74
if (clazz.isEffectiveRoot) EmptyTree
75
else mkAttributedThis(clazz)
76
case SingleType(pre, sym) =>
77
mkApplyIfNeeded(mkAttributedStableRef(pre, sym))
78
case TypeRef(pre, sym, args) =>
81
} else if (sym.isModuleClass) {
82
mkApplyIfNeeded(mkAttributedRef(pre, sym.sourceModule))
83
} else if (sym.isModule || sym.isClass) {
84
assert(phase.erasedTypes, failMessage)
86
} else if (sym.isType) {
87
assert(termSym != NoSymbol, failMessage)
88
mkAttributedIdent(termSym) setType tpe
90
mkAttributedRef(pre, sym)
93
case ConstantType(value) =>
94
Literal(value) setType tpe
96
case AnnotatedType(_, atp, _) =>
97
mkAttributedQualifier(atp)
99
case RefinedType(parents, _) =>
100
// I am unclear whether this is reachable, but
101
// the following implementation looks logical -Lex
102
val firstStable = parents.find(_.isStable)
103
assert(!firstStable.isEmpty, failMessage + " parents = " + parents)
104
mkAttributedQualifier(firstStable.get)
107
abort("bad qualifier received: " + failMessage)
110
/** If this is a reference to a method with an empty
111
* parameter list, wrap it in an apply.
113
def mkApplyIfNeeded(qual: Tree) = qual.tpe match {
114
case MethodType(Nil, restpe) => atPos(qual.pos)(Apply(qual, Nil) setType restpe)
118
/** Builds a reference to given symbol with given stable prefix. */
119
def mkAttributedRef(pre: Type, sym: Symbol): Tree = {
120
val qual = mkAttributedQualifier(pre)
122
case EmptyTree => mkAttributedIdent(sym)
123
case This(clazz) if qual.symbol.isEffectiveRoot => mkAttributedIdent(sym)
124
case _ => mkAttributedSelect(qual, sym)
128
/** Builds a reference to given symbol. */
129
def mkAttributedRef(sym: Symbol): Tree =
130
if (sym.owner.isClass) mkAttributedRef(sym.owner.thisType, sym)
131
else mkAttributedIdent(sym)
133
/** Builds an untyped reference to given symbol. */
134
def mkUnattributedRef(sym: Symbol): Tree =
135
if (sym.owner.isClass) Select(This(sym.owner), sym)
138
/** Replaces tree type with a stable type if possible */
139
def stabilize(tree: Tree): Tree = {
140
for(tp <- stableTypeFor(tree)) tree.tpe = tp
144
/** Computes stable type for a tree if possible */
145
def stableTypeFor(tree: Tree): Option[Type] = tree match {
146
case This(_) if tree.symbol != null && !tree.symbol.isError =>
147
Some(ThisType(tree.symbol))
148
case Ident(_) if tree.symbol.isStable =>
149
Some(singleType(tree.symbol.owner.thisType, tree.symbol))
150
case Select(qual, _) if ((tree.symbol ne null) && (qual.tpe ne null)) && // turned assert into guard for #4064
151
tree.symbol.isStable && qual.tpe.isStable =>
152
Some(singleType(qual.tpe, tree.symbol))
157
/** Builds a reference with stable type to given symbol */
158
def mkAttributedStableRef(pre: Type, sym: Symbol): Tree =
159
stabilize(mkAttributedRef(pre, sym))
161
def mkAttributedStableRef(sym: Symbol): Tree =
162
stabilize(mkAttributedRef(sym))
164
def mkAttributedThis(sym: Symbol): Tree =
165
This(sym.name.toTypeName) setSymbol sym setType sym.thisType
167
def mkAttributedIdent(sym: Symbol): Tree =
168
Ident(sym.name) setSymbol sym setType sym.tpe
170
def mkAttributedSelect(qual: Tree, sym: Symbol): Tree = {
171
// Tests involving the repl fail without the .isEmptyPackage condition.
172
if (qual.symbol != null && (qual.symbol.isEffectiveRoot || qual.symbol.isEmptyPackage))
173
mkAttributedIdent(sym)
175
// Have to recognize anytime a selection is made on a package
176
// so it can be rewritten to foo.bar.`package`.name rather than
177
// foo.bar.name if name is in the package object.
178
// TODO - factor out the common logic between this and
179
// the Typers method "isInPackageObject", used in typedIdent.
181
if (qual.tpe ne null) qual.tpe.typeSymbol
182
else if (qual.symbol ne null) qual.symbol
185
val needsPackageQualifier = (
188
&& !sym.isDefinedInPackage
191
if (needsPackageQualifier) {
192
// The owner of a symbol which requires package qualification may be the
193
// package object iself, but it also could be any superclass of the package
194
// object. In the latter case, we must go through the qualifier's info
195
// to obtain the right symbol.
196
val packageObject = if (sym.owner.isModuleClass) sym.owner.sourceModule else qual.tpe member nme.PACKAGE
197
Select(qual, nme.PACKAGE) setSymbol packageObject setType singleType(qual.tpe, packageObject)
201
val tree = Select(pkgQualifier, sym)
202
if (pkgQualifier.tpe == null) tree
203
else tree setType (qual.tpe memberType sym)
207
/** Builds a type application node if args.nonEmpty, returns fun otherwise. */
208
def mkTypeApply(fun: Tree, targs: List[Tree]): Tree =
209
if (targs.isEmpty) fun else TypeApply(fun, targs)
210
def mkTypeApply(target: Tree, method: Symbol, targs: List[Type]): Tree =
211
mkTypeApply(Select(target, method), targs map TypeTree)
212
def mkAttributedTypeApply(target: Tree, method: Symbol, targs: List[Type]): Tree =
213
mkTypeApply(mkAttributedSelect(target, method), targs map TypeTree)
215
private def mkSingleTypeApply(value: Tree, tpe: Type, what: Symbol, wrapInApply: Boolean) = {
216
val tapp = mkAttributedTypeApply(value, what, tpe.normalize :: Nil)
217
if (wrapInApply) Apply(tapp, Nil) else tapp
219
private def typeTestSymbol(any: Boolean) = if (any) Any_isInstanceOf else Object_isInstanceOf
220
private def typeCastSymbol(any: Boolean) = if (any) Any_asInstanceOf else Object_asInstanceOf
222
/** Builds an instance test with given value and type. */
223
def mkIsInstanceOf(value: Tree, tpe: Type, any: Boolean = true, wrapInApply: Boolean = true): Tree =
224
mkSingleTypeApply(value, tpe, typeTestSymbol(any), wrapInApply)
226
/** Builds a cast with given value and type. */
227
def mkAsInstanceOf(value: Tree, tpe: Type, any: Boolean = true, wrapInApply: Boolean = true): Tree =
228
mkSingleTypeApply(value, tpe, typeCastSymbol(any), wrapInApply)
230
/** Cast `tree` to `pt`, unless tpe is a subtype of pt, or pt is Unit. */
231
def maybeMkAsInstanceOf(tree: Tree, pt: Type, tpe: Type, beforeRefChecks: Boolean = false): Tree =
232
if ((pt == UnitClass.tpe) || (tpe <:< pt)) tree
233
else atPos(tree.pos)(mkAsInstanceOf(tree, pt, any = true, wrapInApply = !beforeRefChecks))
235
/** Apparently we smuggle a Type around as a Literal(Constant(tp))
236
* and the implementation of Constant#tpe is such that x.tpe becomes
237
* ClassType(value.asInstanceOf[Type]), i.e. java.lang.Class[Type].
238
* Can't find any docs on how/why it's done this way. See ticket
239
* SI-490 for some interesting comments from lauri alanko suggesting
240
* that the type given by classOf[T] is too strong and should be
241
* weakened so as not to suggest that classOf[List[String]] is any
242
* different from classOf[List[Int]].
244
* !!! See deconstMap in Erasure for one bug this encoding has induced:
245
* I would be very surprised if there aren't more.
247
def mkClassOf(tp: Type): Tree =
248
Literal(Constant(tp)) setType ConstantType(Constant(tp))
250
/** Builds a list with given head and tail. */
251
def mkNewCons(head: Tree, tail: Tree): Tree =
252
New(Apply(mkAttributedRef(ConsClass), List(head, tail)))
254
/** Builds a list with given head and tail. */
255
def mkNil: Tree = mkAttributedRef(NilModule)
257
/** Builds a tree representing an undefined local, as in
259
* which is appropriate to the given Type.
261
def mkZero(tp: Type): Tree = tp.typeSymbol match {
262
case NothingClass => mkMethodCall(Predef_???, Nil) setType NothingClass.tpe
263
case _ => Literal(mkConstantZero(tp)) setType tp
266
def mkConstantZero(tp: Type): Constant = tp.typeSymbol match {
267
case UnitClass => Constant(())
268
case BooleanClass => Constant(false)
269
case FloatClass => Constant(0.0f)
270
case DoubleClass => Constant(0.0d)
271
case ByteClass => Constant(0.toByte)
272
case ShortClass => Constant(0.toShort)
273
case IntClass => Constant(0)
274
case LongClass => Constant(0L)
275
case CharClass => Constant(0.toChar)
276
case _ => Constant(null)
279
/** Builds a tuple */
280
def mkTuple(elems: List[Tree]): Tree =
281
if (elems.isEmpty) Literal(Constant())
283
Select(mkAttributedRef(TupleClass(elems.length).caseModule), nme.apply),
287
def mkAnd(tree1: Tree, tree2: Tree): Tree =
288
Apply(Select(tree1, Boolean_and), List(tree2))
291
def mkOr(tree1: Tree, tree2: Tree): Tree =
292
Apply(Select(tree1, Boolean_or), List(tree2))
294
def mkRuntimeUniverseRef: Tree = {
295
assert(ReflectRuntimeUniverse != NoSymbol)
296
mkAttributedRef(ReflectRuntimeUniverse) setType singleType(ReflectRuntimeUniverse.owner.thisPrefix, ReflectRuntimeUniverse)