Skip to content

Commit 056e124

Browse files
committed
Merge pull request #734 from alexander-myltsev/add-getclass
Implement getClass
2 parents cf17b73 + d24c694 commit 056e124

File tree

4 files changed

+118
-1
lines changed

4 files changed

+118
-1
lines changed

src/dotty/tools/dotc/Compiler.scala

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,8 @@ class Compiler {
7070
new LinkScala2ImplClasses,
7171
new CapturedVars, // capturedVars has a transformUnit: no phases should introduce local mutable vars here
7272
new Constructors,
73-
new FunctionalInterfaces),
73+
new FunctionalInterfaces,
74+
new GetClass), // getClass transformation should be applied to specialized methods
7475
List(new LambdaLift, // in this mini-phase block scopes are incorrect. No phases that rely on scopes should be here
7576
new ElimStaticThis,
7677
new Flatten,
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
package dotty.tools.dotc
2+
package transform
3+
4+
import ast.tpd
5+
import core.Contexts.Context
6+
import core.StdNames.nme
7+
import core.Symbols.TermSymbol
8+
import core.Phases.Phase
9+
import TreeTransforms.{MiniPhaseTransform, TransformerInfo}
10+
11+
/** Rewrite `getClass` calls as follow:
12+
*
13+
* For every instance of primitive class C whose boxed class is called B:
14+
* instanceC.getClass -> B.TYPE
15+
* For every instance of non-primitive class D:
16+
* instanceD.getClass -> instanceD.getClass
17+
*/
18+
class GetClass extends MiniPhaseTransform {
19+
import tpd._
20+
21+
override def phaseName: String = "getClass"
22+
23+
override def runsAfter: Set[Class[_ <: Phase]] = Set(classOf[Erasure])
24+
25+
override def transformApply(tree: Apply)(implicit ctx: Context, info: TransformerInfo): Tree = {
26+
import ast.Trees._
27+
28+
tree match {
29+
case Apply(Select(qual, nme.getClass_), Nil) =>
30+
val defn = ctx.definitions
31+
val claz = qual.tpe.classSymbol
32+
33+
def TYPE(module: TermSymbol) = ref(module).select(nme.TYPE_).ensureConforms(tree.tpe)
34+
claz match {
35+
case defn.BooleanClass => TYPE(defn.BoxedBooleanModule)
36+
case defn.ByteClass => TYPE(defn.BoxedByteModule)
37+
case defn.ShortClass => TYPE(defn.BoxedShortModule)
38+
case defn.CharClass => TYPE(defn.BoxedCharModule)
39+
case defn.IntClass => TYPE(defn.BoxedIntModule)
40+
case defn.LongClass => TYPE(defn.BoxedLongModule)
41+
case defn.FloatClass => TYPE(defn.BoxedFloatModule)
42+
case defn.DoubleClass => TYPE(defn.BoxedDoubleModule)
43+
case defn.UnitClass => TYPE(defn.BoxedVoidModule)
44+
case _ => tree
45+
}
46+
case _ => tree
47+
}
48+
}
49+
}

tests/run/getclass.check

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
Value types:
2+
void
3+
boolean
4+
byte
5+
short
6+
char
7+
int
8+
long
9+
float
10+
double
11+
12+
Class types:
13+
class SomeClass
14+
class ValueClass
15+
class scala.collection.immutable.$colon$colon
16+
class scala.Tuple2
17+
18+
Arrays:
19+
class [Lscala.runtime.BoxedUnit;
20+
class [I
21+
class [D
22+
class [Lscala.collection.immutable.List;
23+
24+
Functions:
25+
class Test$$$Lambda$1
26+
class Test$$$Lambda$2

tests/run/getclass.scala

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
class ValueClass(val i: Integer) extends AnyVal
2+
class SomeClass
3+
4+
object Test {
5+
def main(args: Array[String]): Unit = {
6+
val cls: Predef.Class[_] = new SomeClass().getClass
7+
val valCls: Predef.Class[_] = new ValueClass(1).getClass
8+
val iCls: Class[Int] = 1.getClass
9+
val f1: Function2[Int, Int, Unit] = (a: Int, b: Int) => println(a + b)
10+
val f2: Function1[Int, Boolean] = (a: Int) => a % 2 == 0
11+
12+
println("Value types:")
13+
println(().getClass)
14+
println(true.getClass)
15+
println(1.asInstanceOf[Byte].getClass)
16+
println(1.asInstanceOf[Short].getClass)
17+
println('a'.getClass)
18+
println(1.getClass)
19+
println(1L.getClass)
20+
println(1f.getClass)
21+
println(1d.getClass)
22+
23+
println("\nClass types:")
24+
println(new SomeClass().getClass)
25+
println(new ValueClass(1).getClass)
26+
println(List(Array(1f)).getClass)
27+
println(("a", Map(1 -> "b")).getClass)
28+
29+
println("\nArrays:")
30+
println(Array(()).getClass)
31+
println(Array(1).getClass)
32+
println(Array(1d).getClass)
33+
println(Array(List("1")).getClass)
34+
35+
println("\nFunctions:")
36+
// FunctionN.getClass.toString has form of "class Test$$$Lambda$N/1349414238",
37+
// but number (1349414238) depends on environment
38+
println(f1.getClass.toString.takeWhile(_ != '/'))
39+
println(f2.getClass.toString.takeWhile(_ != '/'))
40+
}
41+
}

0 commit comments

Comments
 (0)