~ubuntu-branches/debian/sid/scala/sid

« back to all changes in this revision

Viewing changes to src/reflect/scala/reflect/internal/TreeGen.scala

  • Committer: Package Import Robot
  • Author(s): Emmanuel Bourg, Mehdi Dogguy, Lucas Satabin, Frank S. Thomas, Emmanuel Bourg
  • Date: 2015-06-05 23:52:59 UTC
  • mfrom: (1.2.11)
  • Revision ID: package-import@ubuntu.com-20150605235259-wk00vgk83dh8o19g
Tags: 2.10.5-1
* Team upload.

[ Mehdi Dogguy ]
* New upstream release (Closes: #744278).

[ Lucas Satabin ]
* Update patches
* Update the clean target
* Update paths of elements to install
* Update watch file

[ Frank S. Thomas ]
* Remove myself from Uploaders.

[ Emmanuel Bourg ]
* The package has been adopted by the Java Team (Closes: #754935)
* Patched the build to avoid downloading libraries from the Internet
* Replaced the minified JavaScript files with unobfuscated ones
* No longer build scala-partest.jar until diffutils is packaged or replaced
* debian/watch: Fixed the versions matched (x.y.z instead of x.y.z..z)
* debian/rules:
  - Added the missing get-orig-source target (Closes: #724704)
  - Improved the clean target
* debian/control:
  - Build depend on scala (>= 2.10) and bnd
  - Use canonical URLs for the Vcs-* fields
  - Standards-Version updated to 3.9.6 (no changes)
* Switch to debhelper level 9

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
package scala.reflect
 
2
package internal
 
3
 
 
4
abstract class TreeGen extends macros.TreeBuilder {
 
5
  val global: SymbolTable
 
6
 
 
7
  import global._
 
8
  import definitions._
 
9
 
 
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
 
18
 
 
19
  def scalaFunctionConstr(argtpes: List[Tree], restpe: Tree, abstractFun: Boolean = false): Tree = {
 
20
    val cls = if (abstractFun)
 
21
      mkAttributedRef(AbstractFunctionClass(argtpes.length))
 
22
    else
 
23
      mkAttributedRef(FunctionClass(argtpes.length))
 
24
    AppliedTypeTree(cls, argtpes :+ restpe)
 
25
  }
 
26
 
 
27
  /** A creator for method calls, e.g. fn[T1, T2, ...](v1, v2, ...)
 
28
   *  There are a number of variations.
 
29
   *
 
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.
 
35
   */
 
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)
 
48
 
 
49
  def mkMethodCall(target: Tree, targs: List[Type], args: List[Tree]): Tree =
 
50
    Apply(mkTypeApply(target, targs map TypeTree), args)
 
51
 
 
52
  def mkNullaryCall(method: Symbol, targs: List[Type]): Tree =
 
53
    mkTypeApply(mkAttributedRef(method), targs map TypeTree)
 
54
 
 
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.
 
58
   */
 
59
  def mkAttributedQualifier(tpe: Type): Tree =
 
60
    mkAttributedQualifier(tpe, NoSymbol)
 
61
 
 
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
 
66
   *  not be NoSymbol.
 
67
   */
 
68
  def mkAttributedQualifier(tpe: Type, termSym: Symbol): Tree = {
 
69
    def failMessage = "mkAttributedQualifier(" + tpe + ", " + termSym + ")"
 
70
    tpe match {
 
71
      case NoPrefix =>
 
72
        EmptyTree
 
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) =>
 
79
        if (sym.isRoot) {
 
80
          mkAttributedThis(sym)
 
81
        } else if (sym.isModuleClass) {
 
82
          mkApplyIfNeeded(mkAttributedRef(pre, sym.sourceModule))
 
83
        } else if (sym.isModule || sym.isClass) {
 
84
          assert(phase.erasedTypes, failMessage)
 
85
          mkAttributedThis(sym)
 
86
        } else if (sym.isType) {
 
87
          assert(termSym != NoSymbol, failMessage)
 
88
          mkAttributedIdent(termSym) setType tpe
 
89
        } else {
 
90
          mkAttributedRef(pre, sym)
 
91
        }
 
92
 
 
93
      case ConstantType(value) =>
 
94
        Literal(value) setType tpe
 
95
 
 
96
      case AnnotatedType(_, atp, _) =>
 
97
        mkAttributedQualifier(atp)
 
98
 
 
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)
 
105
 
 
106
      case _ =>
 
107
        abort("bad qualifier received: " + failMessage)
 
108
    }
 
109
  }
 
110
  /** If this is a reference to a method with an empty
 
111
   *  parameter list, wrap it in an apply.
 
112
   */
 
113
  def mkApplyIfNeeded(qual: Tree) = qual.tpe match {
 
114
    case MethodType(Nil, restpe) => atPos(qual.pos)(Apply(qual, Nil) setType restpe)
 
115
    case _                       => qual
 
116
  }
 
117
 
 
118
  /** Builds a reference to given symbol with given stable prefix. */
 
119
  def mkAttributedRef(pre: Type, sym: Symbol): Tree = {
 
120
    val qual = mkAttributedQualifier(pre)
 
121
    qual match {
 
122
      case EmptyTree                                  => mkAttributedIdent(sym)
 
123
      case This(clazz) if qual.symbol.isEffectiveRoot => mkAttributedIdent(sym)
 
124
      case _                                          => mkAttributedSelect(qual, sym)
 
125
    }
 
126
  }
 
127
 
 
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)
 
132
 
 
133
  /** Builds an untyped reference to given symbol. */
 
134
  def mkUnattributedRef(sym: Symbol): Tree =
 
135
    if (sym.owner.isClass) Select(This(sym.owner), sym)
 
136
    else Ident(sym)
 
137
 
 
138
  /** Replaces tree type with a stable type if possible */
 
139
  def stabilize(tree: Tree): Tree = {
 
140
    for(tp <- stableTypeFor(tree)) tree.tpe = tp
 
141
    tree
 
142
  }
 
143
 
 
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))
 
153
    case _ =>
 
154
      None
 
155
  }
 
156
 
 
157
  /** Builds a reference with stable type to given symbol */
 
158
  def mkAttributedStableRef(pre: Type, sym: Symbol): Tree =
 
159
    stabilize(mkAttributedRef(pre, sym))
 
160
 
 
161
  def mkAttributedStableRef(sym: Symbol): Tree =
 
162
    stabilize(mkAttributedRef(sym))
 
163
 
 
164
  def mkAttributedThis(sym: Symbol): Tree =
 
165
    This(sym.name.toTypeName) setSymbol sym setType sym.thisType
 
166
 
 
167
  def mkAttributedIdent(sym: Symbol): Tree =
 
168
    Ident(sym.name) setSymbol sym setType sym.tpe
 
169
 
 
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)
 
174
    else {
 
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.
 
180
      val qualsym = (
 
181
        if (qual.tpe ne null) qual.tpe.typeSymbol
 
182
        else if (qual.symbol ne null) qual.symbol
 
183
        else NoSymbol
 
184
      )
 
185
      val needsPackageQualifier = (
 
186
           (sym ne null)
 
187
        && qualsym.isPackage
 
188
        && !sym.isDefinedInPackage
 
189
      )
 
190
      val pkgQualifier =
 
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)
 
198
        }
 
199
        else qual
 
200
 
 
201
      val tree = Select(pkgQualifier, sym)
 
202
      if (pkgQualifier.tpe == null) tree
 
203
      else tree setType (qual.tpe memberType sym)
 
204
    }
 
205
  }
 
206
 
 
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)
 
214
 
 
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
 
218
  }
 
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
 
221
 
 
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)
 
225
 
 
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)
 
229
 
 
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))
 
234
 
 
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]].
 
243
   *
 
244
   *  !!! See deconstMap in Erasure for one bug this encoding has induced:
 
245
   *  I would be very surprised if there aren't more.
 
246
   */
 
247
  def mkClassOf(tp: Type): Tree =
 
248
    Literal(Constant(tp)) setType ConstantType(Constant(tp))
 
249
 
 
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)))
 
253
 
 
254
  /** Builds a list with given head and tail. */
 
255
  def mkNil: Tree = mkAttributedRef(NilModule)
 
256
 
 
257
  /** Builds a tree representing an undefined local, as in
 
258
   *    var x: T = _
 
259
   *  which is appropriate to the given Type.
 
260
   */
 
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
 
264
  }
 
265
 
 
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)
 
277
  }
 
278
 
 
279
  /** Builds a tuple */
 
280
  def mkTuple(elems: List[Tree]): Tree =
 
281
    if (elems.isEmpty) Literal(Constant())
 
282
    else Apply(
 
283
      Select(mkAttributedRef(TupleClass(elems.length).caseModule), nme.apply),
 
284
      elems)
 
285
 
 
286
  // tree1 AND tree2
 
287
  def mkAnd(tree1: Tree, tree2: Tree): Tree =
 
288
    Apply(Select(tree1, Boolean_and), List(tree2))
 
289
 
 
290
  // tree1 OR tree2
 
291
  def mkOr(tree1: Tree, tree2: Tree): Tree =
 
292
    Apply(Select(tree1, Boolean_or), List(tree2))
 
293
 
 
294
  def mkRuntimeUniverseRef: Tree = {
 
295
    assert(ReflectRuntimeUniverse != NoSymbol)
 
296
    mkAttributedRef(ReflectRuntimeUniverse) setType singleType(ReflectRuntimeUniverse.owner.thisPrefix, ReflectRuntimeUniverse)
 
297
  }
 
298
}