aboutsummaryrefslogtreecommitdiff
path: root/src/dotty/tools/dotc/transform/ClassOf.scala
diff options
context:
space:
mode:
Diffstat (limited to 'src/dotty/tools/dotc/transform/ClassOf.scala')
-rw-r--r--src/dotty/tools/dotc/transform/ClassOf.scala53
1 files changed, 53 insertions, 0 deletions
diff --git a/src/dotty/tools/dotc/transform/ClassOf.scala b/src/dotty/tools/dotc/transform/ClassOf.scala
new file mode 100644
index 000000000..4d6bf2dc9
--- /dev/null
+++ b/src/dotty/tools/dotc/transform/ClassOf.scala
@@ -0,0 +1,53 @@
+package dotty.tools.dotc
+package transform
+
+import ast.tpd
+import core.Constants.Constant
+import core.Contexts.Context
+import core.StdNames.nme
+import core.Symbols.TermSymbol
+import core.TypeErasure
+import TreeTransforms.{MiniPhaseTransform, TransformerInfo, TreeTransform}
+
+/** Rewrite `classOf` calls as follow:
+ *
+ * For every primitive class C whose boxed class is called B:
+ * classOf[C] -> B.TYPE
+ * For every non-primitive class D:
+ * classOf[D] -> Literal(Constant(erasure(D)))
+ */
+class ClassOf extends MiniPhaseTransform {
+ import tpd._
+
+ override def phaseName: String = "classOf"
+
+ private var classOfMethod: TermSymbol = _
+
+ override def prepareForUnit(tree: tpd.Tree)(implicit ctx: Context): TreeTransform = {
+ val predefModule = ctx.definitions.ScalaPredefModule
+ classOfMethod = ctx.requiredMethod(predefModule.moduleClass.asClass, nme.classOf)
+ this
+ }
+
+ override def transformTypeApply(tree: TypeApply)(implicit ctx: Context, info: TransformerInfo): Tree = {
+ if (tree.symbol eq classOfMethod) {
+ val tp = tree.args.head.tpe
+ val defn = ctx.definitions
+ val claz = tp.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 _ => Literal(Constant(TypeErasure.erasure(tp)))
+ }
+ } else tree
+ }
+}