aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexander Myltsev <alexander.myltsev@phystech.edu>2015-07-23 15:16:18 +0300
committerAlexander Myltsev <alexander.myltsev@phystech.edu>2015-07-25 17:52:40 +0300
commit2cf567b1023734d481e8511e4e3314246afef6a4 (patch)
tree4e9b2ef2a44e3d4c804504b1ad224706a2069321
parentcf17b73cc02daf514f6d5499fd7a5562fc93349e (diff)
downloaddotty-2cf567b1023734d481e8511e4e3314246afef6a4.tar.gz
dotty-2cf567b1023734d481e8511e4e3314246afef6a4.tar.bz2
dotty-2cf567b1023734d481e8511e4e3314246afef6a4.zip
Implement getClass method
-rw-r--r--src/dotty/tools/dotc/Compiler.scala1
-rw-r--r--src/dotty/tools/dotc/transform/GetClass.scala49
-rw-r--r--tests/run/getclass.check26
-rw-r--r--tests/run/getclass.scala41
4 files changed, 117 insertions, 0 deletions
diff --git a/src/dotty/tools/dotc/Compiler.scala b/src/dotty/tools/dotc/Compiler.scala
index 75b790861..a58ee907d 100644
--- a/src/dotty/tools/dotc/Compiler.scala
+++ b/src/dotty/tools/dotc/Compiler.scala
@@ -62,6 +62,7 @@ class Compiler {
new AugmentScala2Traits,
new ResolveSuper),
List(new Erasure),
+ List(new GetClass), // getClass transformation should be applied to specialized methods
List(new ElimErasedValueType,
new VCElideAllocations,
new Mixin,
diff --git a/src/dotty/tools/dotc/transform/GetClass.scala b/src/dotty/tools/dotc/transform/GetClass.scala
new file mode 100644
index 000000000..0545133da
--- /dev/null
+++ b/src/dotty/tools/dotc/transform/GetClass.scala
@@ -0,0 +1,49 @@
+package dotty.tools.dotc
+package transform
+
+import ast.tpd
+import core.Contexts.Context
+import core.StdNames.nme
+import core.Symbols.TermSymbol
+import core.Phases.Phase
+import TreeTransforms.{MiniPhaseTransform, TransformerInfo}
+
+/** Rewrite `getClass` calls as follow:
+ *
+ * For every instance of primitive class C whose boxed class is called B:
+ * instanceC.getClass -> B.TYPE
+ * For every instance of non-primitive class D:
+ * instanceD.getClass -> instanceD.getClass
+ */
+class GetClass extends MiniPhaseTransform {
+ import tpd._
+
+ override def phaseName: String = "getClass"
+
+ override def runsAfter: Set[Class[_ <: Phase]] = Set(classOf[Erasure])
+
+ override def transformApply(tree: Apply)(implicit ctx: Context, info: TransformerInfo): Tree = {
+ import ast.Trees._
+
+ tree match {
+ case Apply(Select(qual, nme.getClass_), Nil) =>
+ val defn = ctx.definitions
+ val claz = qual.tpe.classSymbol
+
+ def TYPE(module: TermSymbol) = ref(module).select(nme.TYPE_).ensureConforms(tree.tpe)
+ claz match {
+ case defn.BooleanClass => TYPE(defn.BoxedBooleanModule)
+ case defn.ByteClass => TYPE(defn.BoxedByteModule)
+ case defn.ShortClass => TYPE(defn.BoxedShortModule)
+ case defn.CharClass => TYPE(defn.BoxedCharModule)
+ case defn.IntClass => TYPE(defn.BoxedIntModule)
+ case defn.LongClass => TYPE(defn.BoxedLongModule)
+ case defn.FloatClass => TYPE(defn.BoxedFloatModule)
+ case defn.DoubleClass => TYPE(defn.BoxedDoubleModule)
+ case defn.UnitClass => TYPE(defn.BoxedVoidModule)
+ case _ => tree
+ }
+ case _ => tree
+ }
+ }
+}
diff --git a/tests/run/getclass.check b/tests/run/getclass.check
new file mode 100644
index 000000000..9d88762f4
--- /dev/null
+++ b/tests/run/getclass.check
@@ -0,0 +1,26 @@
+Value types:
+void
+boolean
+byte
+short
+char
+int
+long
+float
+double
+
+Class types:
+class SomeClass
+class ValueClass
+class scala.collection.immutable.$colon$colon
+class scala.Tuple2
+
+Arrays:
+class [Lscala.runtime.BoxedUnit;
+class [I
+class [D
+class [Lscala.collection.immutable.List;
+
+Functions:
+class Test$$$Lambda$1
+class Test$$$Lambda$2
diff --git a/tests/run/getclass.scala b/tests/run/getclass.scala
new file mode 100644
index 000000000..7e6430a53
--- /dev/null
+++ b/tests/run/getclass.scala
@@ -0,0 +1,41 @@
+class ValueClass(val i: Integer) extends AnyVal
+class SomeClass
+
+object Test {
+ def main(args: Array[String]): Unit = {
+ val cls: Predef.Class[_] = new SomeClass().getClass
+ val valCls: Predef.Class[_] = new ValueClass(1).getClass
+ val iCls: Class[Int] = 1.getClass
+ val f1: Function2[Int, Int, Unit] = (a: Int, b: Int) => println(a + b)
+ val f2: Function1[Int, Boolean] = (a: Int) => a % 2 == 0
+
+ println("Value types:")
+ println(().getClass)
+ println(true.getClass)
+ println(1.asInstanceOf[Byte].getClass)
+ println(1.asInstanceOf[Short].getClass)
+ println('a'.getClass)
+ println(1.getClass)
+ println(1L.getClass)
+ println(1f.getClass)
+ println(1d.getClass)
+
+ println("\nClass types:")
+ println(new SomeClass().getClass)
+ println(new ValueClass(1).getClass)
+ println(List(Array(1f)).getClass)
+ println(("a", Map(1 -> "b")).getClass)
+
+ println("\nArrays:")
+ println(Array(()).getClass)
+ println(Array(1).getClass)
+ println(Array(1d).getClass)
+ println(Array(List("1")).getClass)
+
+ println("\nFunctions:")
+ // FunctionN.getClass.toString has form of "class Test$$$Lambda$N/1349414238",
+ // but number (1349414238) depends on environment
+ println(f1.getClass.toString.takeWhile(_ != '/'))
+ println(f2.getClass.toString.takeWhile(_ != '/'))
+ }
+}