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

« back to all changes in this revision

Viewing changes to src/compiler/scala/tools/nsc/ast/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
1
/* NSC -- new Scala compiler
2
 
 * Copyright 2005-2011 LAMP/EPFL
 
2
 * Copyright 2005-2013 LAMP/EPFL
3
3
 * @author  Martin Odersky
4
4
 */
5
5
 
9
9
import scala.collection.mutable.ListBuffer
10
10
import symtab.Flags._
11
11
import symtab.SymbolTable
 
12
import scala.language.postfixOps
12
13
 
13
14
/** XXX to resolve: TreeGen only assumes global is a SymbolTable, but
14
15
 *  TreeDSL at the moment expects a Global.  Can we get by with SymbolTable?
15
16
 */
16
 
abstract class TreeGen {
17
 
  val global: SymbolTable
 
17
abstract class TreeGen extends scala.reflect.internal.TreeGen with TreeDSL {
 
18
  val global: Global
18
19
 
19
20
  import global._
20
21
  import definitions._
21
22
 
22
 
  def rootId(name: Name)          = Select(Ident(nme.ROOTPKG), name)
23
 
  def rootScalaDot(name: Name)    = Select(rootId(nme.scala_) setSymbol ScalaPackage, name)
24
 
  def scalaDot(name: Name)        = Select(Ident(nme.scala_) setSymbol ScalaPackage, name)
25
 
  def scalaAnyRefConstr           = scalaDot(tpnme.AnyRef)
26
 
  def scalaUnitConstr             = scalaDot(tpnme.Unit)
27
 
  def scalaScalaObjectConstr      = scalaDot(tpnme.ScalaObject)
28
 
  def productConstr               = scalaDot(tpnme.Product)
29
 
  def serializableConstr          = scalaDot(tpnme.Serializable)
30
 
 
31
 
  def scalaFunctionConstr(argtpes: List[Tree], restpe: Tree, abstractFun: Boolean = false): Tree = {
32
 
    val cls = if (abstractFun)
33
 
      mkAttributedRef(AbstractFunctionClass(argtpes.length))
34
 
    else
35
 
      mkAttributedRef(FunctionClass(argtpes.length))
36
 
    AppliedTypeTree(cls, argtpes :+ restpe)
37
 
  }
38
 
 
39
 
  /** Builds a reference to value whose type is given stable prefix.
40
 
   *  The type must be suitable for this.  For example, it
41
 
   *  must not be a TypeRef pointing to an abstract type variable.
42
 
   */
43
 
  def mkAttributedQualifier(tpe: Type): Tree =
44
 
    mkAttributedQualifier(tpe, NoSymbol)
45
 
 
46
 
  /** Builds a reference to value whose type is given stable prefix.
47
 
   *  If the type is unsuitable, e.g. it is a TypeRef for an
48
 
   *  abstract type variable, then an Ident will be made using
49
 
   *  termSym as the Ident's symbol.  In that case, termSym must
50
 
   *  not be NoSymbol.
51
 
   */
52
 
  def mkAttributedQualifier(tpe: Type, termSym: Symbol): Tree = tpe match {
53
 
    case NoPrefix =>
54
 
      EmptyTree
55
 
    case ThisType(clazz) =>
56
 
      if (clazz.isEffectiveRoot) EmptyTree
57
 
      else mkAttributedThis(clazz)
58
 
    case SingleType(pre, sym) =>
59
 
      applyIfNoArgs(mkAttributedStableRef(pre, sym))
60
 
    case TypeRef(pre, sym, args) =>
61
 
      if (sym.isRoot) {
62
 
        mkAttributedThis(sym)
63
 
      } else if (sym.isModuleClass) {
64
 
        applyIfNoArgs(mkAttributedRef(pre, sym.sourceModule))
65
 
      } else if (sym.isModule || sym.isClass) {
66
 
        assert(phase.erasedTypes, tpe)
67
 
        mkAttributedThis(sym)
68
 
      } else if (sym.isType) {
69
 
        assert(termSym != NoSymbol, tpe)
70
 
        mkAttributedIdent(termSym) setType tpe
71
 
      } else {
72
 
        mkAttributedRef(pre, sym)
73
 
      }
74
 
 
75
 
    case ConstantType(value) =>
76
 
      Literal(value) setType tpe
77
 
 
78
 
    case AnnotatedType(_, atp, _) =>
79
 
      mkAttributedQualifier(atp)
80
 
 
81
 
    case RefinedType(parents, _) =>
82
 
      // I am unclear whether this is reachable, but
83
 
      // the following implementation looks logical -Lex
84
 
      val firstStable = parents.find(_.isStable)
85
 
      assert(!firstStable.isEmpty, tpe)
86
 
      mkAttributedQualifier(firstStable.get)
87
 
 
88
 
    case _ =>
89
 
      abort("bad qualifier: " + tpe)
90
 
  }
91
 
  /** If this is a reference to a method with an empty
92
 
   *  parameter list, wrap it in an apply.
93
 
   */
94
 
  private def applyIfNoArgs(qual: Tree) = qual.tpe match {
95
 
    case MethodType(Nil, restpe) => Apply(qual, Nil) setType restpe
96
 
    case _                       => qual
97
 
  }
98
 
 
99
 
  /** Builds a reference to given symbol with given stable prefix. */
100
 
  def mkAttributedRef(pre: Type, sym: Symbol): Tree = {
101
 
    val qual = mkAttributedQualifier(pre)
102
 
    qual match {
103
 
      case EmptyTree                                  => mkAttributedIdent(sym)
104
 
      case This(clazz) if qual.symbol.isEffectiveRoot => mkAttributedIdent(sym)
105
 
      case _                                          => mkAttributedSelect(qual, sym)
106
 
    }
107
 
  }
108
 
 
109
 
  /** Builds a reference to given symbol. */
110
 
  def mkAttributedRef(sym: Symbol): Tree =
111
 
    if (sym.owner.isClass) mkAttributedRef(sym.owner.thisType, sym)
112
 
    else mkAttributedIdent(sym)
113
 
 
114
 
  /** Builds an untyped reference to given symbol. */
115
 
  def mkUnattributedRef(sym: Symbol): Tree =
116
 
    if (sym.owner.isClass) Select(This(sym.owner), sym)
117
 
    else Ident(sym)
118
 
 
119
 
  /** Replaces tree type with a stable type if possible */
120
 
  def stabilize(tree: Tree): Tree = {
121
 
    for(tp <- stableTypeFor(tree)) tree.tpe = tp
122
 
    tree
123
 
  }
124
 
 
125
 
  /** Computes stable type for a tree if possible */
126
 
  def stableTypeFor(tree: Tree): Option[Type] = tree match {
127
 
    case Ident(_) if tree.symbol.isStable =>
128
 
      Some(singleType(tree.symbol.owner.thisType, tree.symbol))
129
 
    case Select(qual, _) if ((tree.symbol ne null) && (qual.tpe ne null)) && // turned assert into guard for #4064
130
 
                            tree.symbol.isStable && qual.tpe.isStable =>
131
 
      Some(singleType(qual.tpe, tree.symbol))
132
 
    case _ =>
133
 
      None
134
 
  }
135
 
 
136
 
  /** Cast `tree' to type `pt' */
137
 
  def mkCast(tree: Tree, pt: Type): Tree = {
138
 
    if (settings.debug.value) log("casting " + tree + ":" + tree.tpe + " to " + pt)
139
 
    assert(!tree.tpe.isInstanceOf[MethodType], tree)
140
 
    assert(!pt.typeSymbol.isPackageClass)
141
 
    assert(!pt.typeSymbol.isPackageObjectClass)
142
 
    assert(pt eq pt.normalize, tree +" : "+ debugString(pt) +" ~>"+ debugString(pt.normalize)) //@MAT only called during erasure, which already takes care of that
143
 
    atPos(tree.pos)(mkAsInstanceOf(tree, pt, false))
144
 
  }
145
 
 
146
 
  /** Builds a reference with stable type to given symbol */
147
 
  def mkAttributedStableRef(pre: Type, sym: Symbol): Tree =
148
 
    stabilize(mkAttributedRef(pre, sym))
149
 
 
150
 
  def mkAttributedStableRef(sym: Symbol): Tree =
151
 
    stabilize(mkAttributedRef(sym))
152
 
 
153
 
  def mkAttributedThis(sym: Symbol): Tree =
154
 
    This(sym.name.toTypeName) setSymbol sym setType sym.thisType
155
 
 
156
 
  def mkAttributedIdent(sym: Symbol): Tree =
157
 
    Ident(sym.name) setSymbol sym setType sym.tpe
158
 
 
159
 
  def mkAttributedSelect(qual: Tree, sym: Symbol): Tree = {
160
 
    // Tests involving the repl fail without the .isEmptyPackage condition.
161
 
    if (qual.symbol != null && (qual.symbol.isEffectiveRoot || qual.symbol.isEmptyPackage))
162
 
      mkAttributedIdent(sym)
163
 
    else {
164
 
      val pkgQualifier =
165
 
        if (sym != null && sym.owner.isPackageObjectClass && sym.owner.owner == qual.tpe.typeSymbol) {
166
 
          val obj = sym.owner.sourceModule
167
 
          Select(qual, nme.PACKAGEkw) setSymbol obj setType singleType(qual.tpe, obj)
168
 
        }
169
 
        else qual
170
 
 
171
 
      val tree = Select(pkgQualifier, sym)
172
 
      if (pkgQualifier.tpe == null) tree
173
 
      else tree setType (qual.tpe memberType sym)
174
 
    }
175
 
  }
176
 
 
177
 
  private def mkTypeApply(value: Tree, tpe: Type, what: Symbol) =
178
 
    Apply(
179
 
      TypeApply(
180
 
        mkAttributedSelect(value, what),
181
 
        List(TypeTree(tpe.normalize))
182
 
      ),
183
 
      Nil
184
 
    )
185
 
  /** Builds an instance test with given value and type. */
186
 
  def mkIsInstanceOf(value: Tree, tpe: Type, any: Boolean = true): Tree =
187
 
    mkTypeApply(value, tpe, (if (any) Any_isInstanceOf else Object_isInstanceOf))
188
 
 
189
 
  /** Builds a cast with given value and type. */
190
 
  def mkAsInstanceOf(value: Tree, tpe: Type, any: Boolean = true): Tree =
191
 
    mkTypeApply(value, tpe, (if (any) Any_asInstanceOf else Object_asInstanceOf))
192
 
 
193
 
  /** Cast `tree' to 'pt', unless tpe is a subtype of pt, or pt is Unit.  */
194
 
  def maybeMkAsInstanceOf(tree: Tree, pt: Type, tpe: Type, beforeRefChecks: Boolean = false): Tree =
195
 
    if ((pt == UnitClass.tpe) || (tpe <:< pt)) {
196
 
      log("no need to cast from " + tpe + " to " + pt)
197
 
      tree
198
 
    } else
199
 
      atPos(tree.pos) {
200
 
        if (beforeRefChecks)
201
 
          TypeApply(mkAttributedSelect(tree, Any_asInstanceOf), List(TypeTree(pt)))
202
 
        else
203
 
          mkAsInstanceOf(tree, pt)
204
 
      }
205
 
 
206
 
  def mkClassOf(tp: Type): Tree =
207
 
    Literal(Constant(tp)) setType ConstantType(Constant(tp))// ClassType(tp)
208
 
 
209
23
  def mkCheckInit(tree: Tree): Tree = {
210
24
    val tpe =
211
25
      if (tree.tpe != null || !tree.hasSymbol) tree.tpe
218
32
      tree
219
33
  }
220
34
 
221
 
  /** Builds a list with given head and tail. */
222
 
  def mkNewCons(head: Tree, tail: Tree): Tree =
223
 
    New(Apply(mkAttributedRef(ConsClass), List(head, tail)))
224
 
 
225
 
  /** Builds a list with given head and tail. */
226
 
  def mkNil: Tree = mkAttributedRef(NilModule)
227
 
 
228
 
  /** Builds a tree representing an undefined local, as in
229
 
   *    var x: T = _
230
 
   *  which is appropriate to the given Type.
 
35
  /** Builds a fully attributed wildcard import node.
231
36
   */
232
 
  def mkZero(tp: Type): Tree = {
233
 
    val tree = tp.typeSymbol match {
234
 
      case UnitClass    => Literal(())
235
 
      case BooleanClass => Literal(false)
236
 
      case FloatClass   => Literal(0.0f)
237
 
      case DoubleClass  => Literal(0.0d)
238
 
      case ByteClass    => Literal(0.toByte)
239
 
      case ShortClass   => Literal(0.toShort)
240
 
      case IntClass     => Literal(0)
241
 
      case LongClass    => Literal(0L)
242
 
      case CharClass    => Literal(0.toChar)
243
 
      case _            =>
244
 
        if (NullClass.tpe <:< tp) Literal(null: Any)
245
 
        else abort("Cannot determine zero for " + tp)
246
 
    }
247
 
    tree setType tp
 
37
  def mkWildcardImport(pkg: Symbol): Import = {
 
38
    assert(pkg ne null, this)
 
39
    val qual = gen.mkAttributedStableRef(pkg)
 
40
    val importSym = (
 
41
      NoSymbol
 
42
        newImport NoPosition
 
43
          setFlag SYNTHETIC
 
44
          setInfo analyzer.ImportType(qual)
 
45
    )
 
46
    val importTree = (
 
47
      Import(qual, ImportSelector.wildList)
 
48
        setSymbol importSym
 
49
          setType NoType
 
50
    )
 
51
    importTree
248
52
  }
249
53
 
250
 
  /** Builds a tuple */
251
 
  def mkTuple(elems: List[Tree]): Tree =
252
 
    if (elems.isEmpty) Literal(())
253
 
    else Apply(
254
 
      Select(mkAttributedRef(TupleClass(elems.length).caseModule), nme.apply),
255
 
      elems)
256
 
 
257
 
  // tree1 AND tree2
258
 
  def mkAnd(tree1: Tree, tree2: Tree): Tree =
259
 
    Apply(Select(tree1, Boolean_and), List(tree2))
260
 
 
261
 
  // tree1 OR tree2
262
 
  def mkOr(tree1: Tree, tree2: Tree): Tree =
263
 
    Apply(Select(tree1, Boolean_or), List(tree2))
264
 
 
265
54
  // wrap the given expression in a SoftReference so it can be gc-ed
266
 
  def mkSoftRef(expr: Tree): Tree = New(TypeTree(SoftReferenceClass.tpe), List(List(expr)))
 
55
  def mkSoftRef(expr: Tree): Tree = atPos(expr.pos)(New(SoftReferenceClass.tpe, expr))
 
56
 
 
57
  // annotate the expression with @unchecked
 
58
  def mkUnchecked(expr: Tree): Tree = atPos(expr.pos) {
 
59
    // This can't be "Annotated(New(UncheckedClass), expr)" because annotations
 
60
    // are very picky about things and it crashes the compiler with "unexpected new".
 
61
    Annotated(New(scalaDot(UncheckedClass.name), ListOfNil), expr)
 
62
  }
 
63
  // if it's a Match, mark the selector unchecked; otherwise nothing.
 
64
  def mkUncheckedMatch(tree: Tree) = tree match {
 
65
    case Match(selector, cases) => atPos(tree.pos)(Match(mkUnchecked(selector), cases))
 
66
    case _                      => tree
 
67
  }
 
68
 
 
69
  def mkSynthSwitchSelector(expr: Tree): Tree = atPos(expr.pos) {
 
70
    // This can't be "Annotated(New(SwitchClass), expr)" because annotations
 
71
    // are very picky about things and it crashes the compiler with "unexpected new".
 
72
    Annotated(Ident(nme.synthSwitch), expr)
 
73
  }
 
74
 
 
75
  // TODO: would be so much nicer if we would know during match-translation (i.e., type checking)
 
76
  // whether we should emit missingCase-style apply (and isDefinedAt), instead of transforming trees post-factum
 
77
  class MatchMatcher {
 
78
    def caseMatch(orig: Tree, selector: Tree, cases: List[CaseDef], wrap: Tree => Tree): Tree = unknownTree(orig)
 
79
    def caseVirtualizedMatch(orig: Tree, _match: Tree, targs: List[Tree], scrut: Tree, matcher: Tree): Tree = unknownTree(orig)
 
80
    def caseVirtualizedMatchOpt(orig: Tree, prologue: List[Tree], cases: List[Tree], matchEndDef: Tree, wrap: Tree => Tree): Tree = unknownTree(orig)
 
81
 
 
82
    def genVirtualizedMatch(prologue: List[Tree], cases: List[Tree], matchEndDef: Tree): Tree = Block(prologue ++ cases, matchEndDef)
 
83
 
 
84
    def apply(matchExpr: Tree): Tree = matchExpr match {
 
85
      // old-style match or virtpatmat switch
 
86
      case Match(selector, cases) => // println("simple match: "+ (selector, cases) + "for:\n"+ matchExpr )
 
87
        caseMatch(matchExpr, selector, cases, identity)
 
88
      // old-style match or virtpatmat switch
 
89
      case Block((vd: ValDef) :: Nil, orig@Match(selector, cases)) => // println("block match: "+ (selector, cases, vd) + "for:\n"+ matchExpr )
 
90
        caseMatch(matchExpr, selector, cases, m => copyBlock(matchExpr, List(vd), m))
 
91
      // virtpatmat
 
92
      case Apply(Apply(TypeApply(Select(tgt, nme.runOrElse), targs), List(scrut)), List(matcher)) if opt.virtPatmat => // println("virt match: "+ (tgt, targs, scrut, matcher) + "for:\n"+ matchExpr )
 
93
        caseVirtualizedMatch(matchExpr, tgt, targs, scrut, matcher)
 
94
      // optimized version of virtpatmat
 
95
      case Block(stats, matchEndDef) if opt.virtPatmat && (stats forall treeInfo.hasSynthCaseSymbol) =>
 
96
        // the assumption is once we encounter a case, the remainder of the block will consist of cases
 
97
        // the prologue may be empty, usually it is the valdef that stores the scrut
 
98
        val (prologue, cases) = stats span (s => !s.isInstanceOf[LabelDef])
 
99
        caseVirtualizedMatchOpt(matchExpr, prologue, cases, matchEndDef, identity)
 
100
      // optimized version of virtpatmat
 
101
      case Block(outerStats, orig@Block(stats, matchEndDef)) if opt.virtPatmat && (stats forall treeInfo.hasSynthCaseSymbol) =>
 
102
        val (prologue, cases) = stats span (s => !s.isInstanceOf[LabelDef])
 
103
        caseVirtualizedMatchOpt(matchExpr, prologue, cases, matchEndDef, m => copyBlock(matchExpr, outerStats, m))
 
104
      case other =>
 
105
        unknownTree(other)
 
106
    }
 
107
 
 
108
    def unknownTree(t: Tree): Tree = throw new MatchError(t)
 
109
    def copyBlock(orig: Tree, stats: List[Tree], expr: Tree): Block = Block(stats, expr)
 
110
 
 
111
    def dropSyntheticCatchAll(cases: List[CaseDef]): List[CaseDef] =
 
112
      if (!opt.virtPatmat) cases
 
113
      else cases filter {
 
114
             case CaseDef(pat, EmptyTree, Throw(Apply(Select(New(exTpt), nme.CONSTRUCTOR), _))) if (treeInfo.isWildcardArg(pat) && (exTpt.tpe.typeSymbol eq MatchErrorClass)) => false
 
115
             case CaseDef(pat, guard, body) => true
 
116
           }
 
117
  }
267
118
 
268
119
  def mkCached(cvar: Symbol, expr: Tree): Tree = {
269
120
    val cvarRef = mkUnattributedRef(cvar)
283
134
  }
284
135
 
285
136
  def mkModuleVarDef(accessor: Symbol) = {
 
137
    val inClass    = accessor.owner.isClass
 
138
    val extraFlags = if (inClass) PrivateLocal | SYNTHETIC else 0
 
139
 
286
140
    val mval = (
287
 
      accessor.owner.newVariable(accessor.pos.focus, nme.moduleVarName(accessor.name))
288
 
      setInfo accessor.tpe.finalResultType
289
 
      setFlag (MODULEVAR)
 
141
      accessor.owner.newVariable(nme.moduleVarName(accessor.name), accessor.pos.focus, MODULEVAR | extraFlags)
 
142
        setInfo accessor.tpe.finalResultType
 
143
        addAnnotation VolatileAttr
290
144
    )
 
145
    if (inClass)
 
146
      mval.owner.info.decls enter mval
291
147
 
292
 
    mval.addAnnotation(AnnotationInfo(VolatileAttr.tpe, Nil, Nil))
293
 
    if (mval.owner.isClass) {
294
 
      mval setFlag (PRIVATE | LOCAL | SYNTHETIC)
295
 
      mval.owner.info.decls.enter(mval)
296
 
    }
297
148
    ValDef(mval)
298
149
  }
299
150
 
305
156
  def mkModuleAccessDef(accessor: Symbol, msym: Symbol) =
306
157
    DefDef(accessor, Select(This(msym.owner), msym))
307
158
 
308
 
  def newModule(accessor: Symbol, tpe: Type) =
309
 
    New(TypeTree(tpe),
310
 
        List(for (pt <- tpe.typeSymbol.primaryConstructor.info.paramTypes)
311
 
             yield This(accessor.owner.enclClass)))
 
159
  def newModule(accessor: Symbol, tpe: Type) = {
 
160
    val ps = tpe.typeSymbol.primaryConstructor.info.paramTypes
 
161
    if (ps.isEmpty) New(tpe)
 
162
    else New(tpe, This(accessor.owner.enclClass))
 
163
  }
312
164
 
313
165
  // def m: T;
314
166
  def mkModuleAccessDcl(accessor: Symbol) =
315
167
    DefDef(accessor setFlag lateDEFERRED, EmptyTree)
316
168
 
317
169
  def mkRuntimeCall(meth: Name, args: List[Tree]): Tree =
318
 
    Apply(Select(mkAttributedRef(ScalaRunTimeModule), meth), args)
 
170
    mkRuntimeCall(meth, Nil, args)
319
171
 
320
172
  def mkRuntimeCall(meth: Name, targs: List[Type], args: List[Tree]): Tree =
321
 
    Apply(TypeApply(Select(mkAttributedRef(ScalaRunTimeModule), meth), targs map TypeTree), args)
 
173
    mkMethodCall(ScalaRunTimeModule, meth, targs, args)
 
174
 
 
175
  def mkSysErrorCall(message: String): Tree =
 
176
    mkMethodCall(Sys_error, List(Literal(Constant(message))))
 
177
 
 
178
  /** A creator for a call to a scala.reflect.Manifest or ClassManifest factory method.
 
179
   *
 
180
   *  @param    full          full or partial manifest (target will be Manifest or ClassManifest)
 
181
   *  @param    constructor   name of the factory method (e.g. "classType")
 
182
   *  @param    tparg         the type argument
 
183
   *  @param    args          value arguments
 
184
   *  @return   the tree
 
185
   */
 
186
  def mkManifestFactoryCall(full: Boolean, constructor: String, tparg: Type, args: List[Tree]): Tree =
 
187
    mkMethodCall(
 
188
      if (full) FullManifestModule else PartialManifestModule,
 
189
      newTermName(constructor),
 
190
      List(tparg),
 
191
      args
 
192
    )
322
193
 
323
194
  /** Make a synchronized block on 'monitor'. */
324
195
  def mkSynchronized(monitor: Tree, body: Tree): Tree =
325
196
    Apply(Select(monitor, Object_synchronized), List(body))
326
197
 
 
198
  def mkAppliedTypeForCase(clazz: Symbol): Tree = {
 
199
    val numParams = clazz.typeParams.size
 
200
    if (clazz.typeParams.isEmpty) Ident(clazz)
 
201
    else AppliedTypeTree(Ident(clazz), 1 to numParams map (_ => Bind(tpnme.WILDCARD, EmptyTree)) toList)
 
202
  }
 
203
  def mkBindForCase(patVar: Symbol, clazz: Symbol, targs: List[Type]): Tree = {
 
204
    Bind(patVar, Typed(Ident(nme.WILDCARD),
 
205
      if (targs.isEmpty) mkAppliedTypeForCase(clazz)
 
206
      else AppliedTypeTree(Ident(clazz), targs map TypeTree)
 
207
    ))
 
208
  }
 
209
  def mkSuperSelect = Select(Super(This(tpnme.EMPTY), tpnme.EMPTY), nme.CONSTRUCTOR)
 
210
 
327
211
  def wildcardStar(tree: Tree) =
328
212
    atPos(tree.pos) { Typed(tree, Ident(tpnme.WILDCARD_STAR)) }
329
213
 
330
 
  def paramToArg(vparam: Symbol) = {
331
 
    val arg = Ident(vparam)
332
 
    if (isRepeatedParamType(vparam.tpe)) wildcardStar(arg)
333
 
    else arg
334
 
  }
335
 
 
336
 
  def paramToArg(vparam: ValDef) = {
337
 
    val arg = Ident(vparam.name)
338
 
    if (treeInfo.isRepeatedParamType(vparam.tpt)) wildcardStar(arg)
339
 
    else arg
340
 
  }
341
 
 
342
 
  /** Make forwarder to method `target', passing all parameters in `params' */
 
214
  def paramToArg(vparam: Symbol): Tree =
 
215
    paramToArg(Ident(vparam), isRepeatedParamType(vparam.tpe))
 
216
 
 
217
  def paramToArg(vparam: ValDef): Tree =
 
218
    paramToArg(Ident(vparam.name), treeInfo.isRepeatedParamType(vparam.tpt))
 
219
 
 
220
  def paramToArg(arg: Ident, isRepeatedParam: Boolean): Tree  =
 
221
    if (isRepeatedParam) wildcardStar(arg) else arg
 
222
 
 
223
  /** Make forwarder to method `target`, passing all parameters in `params` */
343
224
  def mkForwarder(target: Tree, vparamss: List[List[Symbol]]) =
344
225
    (target /: vparamss)((fn, vparams) => Apply(fn, vparams map paramToArg))
345
226
 
348
229
   *  apply the element type directly.
349
230
   */
350
231
  def mkWrapArray(tree: Tree, elemtp: Type) = {
351
 
    val sym = elemtp.typeSymbol
352
 
    val meth: Name =
353
 
      if (isValueClass(sym)) "wrap"+sym.name+"Array"
354
 
      else if ((elemtp <:< AnyRefClass.tpe) && !isPhantomClass(sym)) "wrapRefArray"
355
 
      else "genericWrapArray"
356
 
 
357
 
    if (isValueClass(sym))
358
 
      Apply(Select(mkAttributedRef(PredefModule), meth), List(tree))
359
 
    else
360
 
      Apply(TypeApply(Select(mkAttributedRef(PredefModule), meth), List(TypeTree(elemtp))), List(tree))
361
 
  }
 
232
    mkMethodCall(
 
233
      PredefModule,
 
234
      wrapArrayMethodName(elemtp),
 
235
      if (isPrimitiveValueType(elemtp)) Nil else List(elemtp),
 
236
      List(tree)
 
237
    )
 
238
  }
 
239
 
 
240
  /** Cast `tree` to type `pt` by creating
 
241
   *  one of the calls of the form
 
242
   *
 
243
   *    x.asInstanceOf[`pt`]     up to phase uncurry
 
244
   *    x.asInstanceOf[`pt`]()   if after uncurry but before erasure
 
245
   *    x.$asInstanceOf[`pt`]()  if at or after erasure
 
246
   */
 
247
  def mkCast(tree: Tree, pt: Type): Tree = {
 
248
    debuglog("casting " + tree + ":" + tree.tpe + " to " + pt + " at phase: " + phase)
 
249
    assert(!tree.tpe.isInstanceOf[MethodType], tree)
 
250
    assert(pt eq pt.normalize, tree +" : "+ debugString(pt) +" ~>"+ debugString(pt.normalize))
 
251
    atPos(tree.pos) {
 
252
      mkAsInstanceOf(tree, pt, any = !phase.next.erasedTypes, wrapInApply = isAtPhaseAfter(currentRun.uncurryPhase))
 
253
    }
 
254
  }
 
255
 
 
256
  // drop annotations generated by CPS plugin etc, since its annotationchecker rejects T @cps[U] <: Any
 
257
  // let's assume for now annotations don't affect casts, drop them there, and bring them back using the outer Typed tree
 
258
  def mkCastPreservingAnnotations(tree: Tree, pt: Type) =
 
259
    Typed(mkCast(tree, pt.withoutAnnotations.dealias), TypeTree(pt))
362
260
 
363
261
  /** Generate a cast for tree Tree representing Array with
364
262
   *  elem type elemtp to expected type pt.
365
263
   */
366
264
  def mkCastArray(tree: Tree, elemtp: Type, pt: Type) =
367
 
    if (elemtp.typeSymbol == AnyClass && isValueClass(tree.tpe.typeArgs.head.typeSymbol))
368
 
      mkCast(mkRuntimeCall("toObjectArray", List(tree)), pt)
 
265
    if (elemtp.typeSymbol == AnyClass && isPrimitiveValueType(tree.tpe.typeArgs.head))
 
266
      mkCast(mkRuntimeCall(nme.toObjectArray, List(tree)), pt)
369
267
    else
370
268
      mkCast(tree, pt)
371
269
 
 
270
  def mkZeroContravariantAfterTyper(tp: Type): Tree = {
 
271
    // contravariant -- for replacing an argument in a method call
 
272
    // must use subtyping, as otherwise we miss types like `Any with Int`
 
273
    val tree =
 
274
      if      (NullClass.tpe    <:< tp) Literal(Constant(null))
 
275
      else if (UnitClass.tpe    <:< tp) Literal(Constant())
 
276
      else if (BooleanClass.tpe <:< tp) Literal(Constant(false))
 
277
      else if (FloatClass.tpe   <:< tp) Literal(Constant(0.0f))
 
278
      else if (DoubleClass.tpe  <:< tp) Literal(Constant(0.0d))
 
279
      else if (ByteClass.tpe    <:< tp) Literal(Constant(0.toByte))
 
280
      else if (ShortClass.tpe   <:< tp) Literal(Constant(0.toShort))
 
281
      else if (IntClass.tpe     <:< tp) Literal(Constant(0))
 
282
      else if (LongClass.tpe    <:< tp) Literal(Constant(0L))
 
283
      else if (CharClass.tpe    <:< tp) Literal(Constant(0.toChar))
 
284
      else mkCast(Literal(Constant(null)), tp)
 
285
 
 
286
    tree
 
287
  }
 
288
 
372
289
  /** Translate names in Select/Ident nodes to type names.
373
290
   */
374
291
  def convertToTypeName(tree: Tree): Option[RefTree] = tree match {
384
301
    case _            => EmptyTree
385
302
  }
386
303
 
 
304
  /** Create a ValDef initialized to the given expression, setting the
 
305
   *  symbol to its packed type, and an function for creating Idents
 
306
   *  which refer to it.
 
307
   */
 
308
  private def mkPackedValDef(expr: Tree, owner: Symbol, name: Name): (ValDef, () => Ident) = {
 
309
    val packedType = typer.packedType(expr, owner)
 
310
    val sym = owner.newValue(name, expr.pos.makeTransparent, SYNTHETIC) setInfo packedType
 
311
 
 
312
    (ValDef(sym, expr), () => Ident(sym) setPos sym.pos.focus setType expr.tpe)
 
313
  }
 
314
 
387
315
  /** Used in situations where you need to access value of an expression several times
388
316
   */
389
317
  def evalOnce(expr: Tree, owner: Symbol, unit: CompilationUnit)(within: (() => Tree) => Tree): Tree = {
390
318
    var used = false
391
 
    if (treeInfo.isPureExpr(expr)) {
 
319
    if (treeInfo.isExprSafeToInline(expr)) {
392
320
      within(() => if (used) expr.duplicate else { used = true; expr })
393
 
    } else {
394
 
      val temp = owner.newValue(expr.pos.makeTransparent, unit.freshTermName("ev$"))
395
 
        .setFlag(SYNTHETIC).setInfo(expr.tpe)
396
 
      val containing = within(() => Ident(temp) setPos temp.pos.focus setType expr.tpe)
 
321
    }
 
322
    else {
 
323
      val (valDef, identFn) = mkPackedValDef(expr, owner, unit.freshTermName("ev$"))
 
324
      val containing = within(identFn)
397
325
      ensureNonOverlapping(containing, List(expr))
398
 
      Block(List(ValDef(temp, expr)), containing) setPos (containing.pos union expr.pos)
 
326
      Block(List(valDef), containing) setPos (containing.pos union expr.pos)
399
327
    }
400
328
  }
401
329
 
405
333
    val used = new Array[Boolean](exprs.length)
406
334
    var i = 0
407
335
    for (expr <- exprs) {
408
 
      if (treeInfo.isPureExpr(expr)) {
 
336
      if (treeInfo.isExprSafeToInline(expr)) {
409
337
        exprs1 += {
410
338
          val idx = i
411
339
          () => if (used(idx)) expr.duplicate else { used(idx) = true; expr }
412
340
        }
413
 
      } else {
414
 
        val temp = owner.newValue(expr.pos.makeTransparent, unit.freshTermName("ev$"))
415
 
          .setFlag(SYNTHETIC).setInfo(expr.tpe)
416
 
        vdefs += ValDef(temp, expr)
417
 
        exprs1 += (() => Ident(temp) setPos temp.pos.focus setType expr.tpe)
 
341
      }
 
342
      else {
 
343
        val (valDef, identFn) = mkPackedValDef(expr, owner, unit.freshTermName("ev$"))
 
344
        vdefs += valDef
 
345
        exprs1 += identFn
418
346
      }
419
347
      i += 1
420
348
    }
425
353
    else Block(prefix, containing) setPos (prefix.head.pos union containing.pos)
426
354
  }
427
355
 
428
 
  /** Return a double-checked locking idiom around the syncBody tree. It guards with 'cond' and
429
 
   *  synchronizez on 'clazz.this'. Additional statements can be included after initialization,
 
356
  /** Return the synchronized part of the double-checked locking idiom around the syncBody tree. It guards with `cond` and
 
357
   *  synchronizez on `clazz.this`. Additional statements can be included after initialization,
430
358
   *  (outside the synchronized block).
431
359
   *
432
360
   *  The idiom works only if the condition is using a volatile field.
433
361
   *  @see http://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html
434
362
   */
435
 
  def mkDoubleCheckedLocking(clazz: Symbol, cond: Tree, syncBody: List[Tree], stats: List[Tree]): Tree =
436
 
    mkDoubleCheckedLocking(mkAttributedThis(clazz), cond, syncBody, stats)
 
363
  def mkSynchronizedCheck(clazz: Symbol, cond: Tree, syncBody: List[Tree], stats: List[Tree]): Tree =
 
364
    mkSynchronizedCheck(mkAttributedThis(clazz), cond, syncBody, stats)
437
365
 
438
 
  def mkDoubleCheckedLocking(attrThis: Tree, cond: Tree, syncBody: List[Tree], stats: List[Tree]): Tree = {
439
 
    If(cond,
440
 
       Block(
441
 
         mkSynchronized(
442
 
           attrThis,
443
 
           If(cond, Block(syncBody: _*), EmptyTree)) ::
444
 
         stats: _*),
445
 
       EmptyTree)
446
 
  }
 
366
  def mkSynchronizedCheck(attrThis: Tree, cond: Tree, syncBody: List[Tree], stats: List[Tree]): Tree =
 
367
    Block(mkSynchronized(
 
368
      attrThis,
 
369
      If(cond, Block(syncBody: _*), EmptyTree)) ::
 
370
      stats: _*)
447
371
}