1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
|
/* NSC -- new Scala compiler
* Copyright 2005-2006 LAMP/EPFL
* @author Martin Odersky
*/
// $Id$
package scala.tools.nsc.transform
import symtab._
import Flags._
import scala.tools.nsc.util.Position
import scala.collection.mutable.{ListBuffer, HashMap}
abstract class CleanUp extends Transform {
import global._
import definitions._
import posAssigner.atPos
/** the following two members override abstract members in Transform */
val phaseName: String = "cleanup"
protected def newTransformer(unit: CompilationUnit): Transformer =
new CleanUpTransformer(unit)
class CleanUpTransformer(unit: CompilationUnit) extends Transformer {
private val newDefs = new ListBuffer[Tree]
private val classConstantMeth = new HashMap[String, Symbol]
// a map from the symbols of the Scala primitive types to the symbols
// of the modules of the Java box classes
private val javaBoxClassModule = new HashMap[Symbol, Symbol]
if (!forMSIL) {
javaBoxClassModule(UnitClass) = getModule("java.lang.Void")
javaBoxClassModule(BooleanClass) = getModule("java.lang.Boolean")
javaBoxClassModule(ByteClass) = getModule("java.lang.Byte")
javaBoxClassModule(ShortClass) = getModule("java.lang.Short")
javaBoxClassModule(IntClass) = getModule("java.lang.Integer")
javaBoxClassModule(CharClass) = getModule("java.lang.Character")
javaBoxClassModule(LongClass) = getModule("java.lang.Long")
javaBoxClassModule(FloatClass) = getModule("java.lang.Float")
javaBoxClassModule(DoubleClass) = getModule("java.lang.Double")
}
private var localTyper: analyzer.Typer = null;
private def freshClassConstantMethName() = unit.fresh.newName("class$Method")
private def freshClassConstantVarName() = unit.fresh.newName("class$Cache")
private def classConstantMethod(pos: Position, sig: String): Symbol = classConstantMeth.get(sig) match {
case Some(meth) =>
meth
case None =>
val forName = getMember(ClassClass.linkedModuleOfClass, nme.forName)
val owner = currentOwner.enclClass
val cvar = owner.newVariable(pos, freshClassConstantVarName())
.setFlag(PRIVATE | STATIC | MUTABLE | SYNTHETIC).setInfo(ClassClass.tpe)
owner.info.decls.enter(cvar)
val cdef =
localTyper.typed {
atPos(pos) {
ValDef(cvar, Literal(Constant(null)))
}
}
val meth = owner.newMethod(pos, freshClassConstantMethName())
.setFlag(PRIVATE | STATIC | SYNTHETIC).setInfo(MethodType(List(), ClassClass.tpe))
owner.info.decls.enter(meth)
val mdef =
localTyper.typed {
atPos(pos) {
DefDef(meth, vparamss =>
gen.mkCached(
cvar,
Apply(
gen.mkAttributedRef(forName), List(Literal(sig)))))
}
}
newDefs.append(cdef, mdef);
classConstantMeth.update(sig, meth)
meth
}
override def transformUnit(unit: CompilationUnit) =
if (settings.target.value != "jvm-1.5" && !forMSIL) {
unit.body = transform(unit.body)
}
override def transform(tree: Tree): Tree = tree match {
case Template(parents, body) =>
classConstantMeth.clear
newDefs.clear
localTyper = typer.atOwner(tree, currentOwner)
val body1 = transformTrees(body)
copy.Template(tree, parents, newDefs.toList ::: body1)
case Literal(c) if (c.tag == ClassTag) =>
val tpe = c.typeValue
atPos(tree.pos) {
localTyper.typed {
if (isValueClass(tpe.symbol))
Select(gen.mkAttributedRef(javaBoxClassModule(tpe.symbol)), "TYPE")
else
Apply(
gen.mkAttributedRef(classConstantMethod(tree.pos, signature(tpe))),
List())
}
}
case _ =>
super.transform(tree)
}
} // CleanUpTransformer
}
|