diff options
author | Dmitry Petrashko <dark@d-d.me> | 2015-07-27 23:26:26 +0200 |
---|---|---|
committer | Dmitry Petrashko <dark@d-d.me> | 2015-07-27 23:26:26 +0200 |
commit | 056e1246c9dc365bd37627923b999a80a57ca0f9 (patch) | |
tree | 28d95f59b223290c035ed2f716840c19f6b73872 | |
parent | cf17b73cc02daf514f6d5499fd7a5562fc93349e (diff) | |
parent | d24c6945963198566cd8e97e6bcacf6ebe2127dc (diff) | |
download | dotty-056e1246c9dc365bd37627923b999a80a57ca0f9.tar.gz dotty-056e1246c9dc365bd37627923b999a80a57ca0f9.tar.bz2 dotty-056e1246c9dc365bd37627923b999a80a57ca0f9.zip |
Merge pull request #734 from alexander-myltsev/add-getclass
Implement getClass
-rw-r--r-- | src/dotty/tools/dotc/Compiler.scala | 3 | ||||
-rw-r--r-- | src/dotty/tools/dotc/transform/GetClass.scala | 49 | ||||
-rw-r--r-- | tests/run/getclass.check | 26 | ||||
-rw-r--r-- | tests/run/getclass.scala | 41 |
4 files changed, 118 insertions, 1 deletions
diff --git a/src/dotty/tools/dotc/Compiler.scala b/src/dotty/tools/dotc/Compiler.scala index 75b790861..76cf10428 100644 --- a/src/dotty/tools/dotc/Compiler.scala +++ b/src/dotty/tools/dotc/Compiler.scala @@ -70,7 +70,8 @@ class Compiler { new LinkScala2ImplClasses, new CapturedVars, // capturedVars has a transformUnit: no phases should introduce local mutable vars here new Constructors, - new FunctionalInterfaces), + new FunctionalInterfaces, + new GetClass), // getClass transformation should be applied to specialized methods List(new LambdaLift, // in this mini-phase block scopes are incorrect. No phases that rely on scopes should be here new ElimStaticThis, new Flatten, 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(_ != '/')) + } +} |