aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2014-07-05 19:20:47 +0200
committerMartin Odersky <odersky@gmail.com>2014-07-17 11:02:00 +0200
commit1fdc188af5b8b34b1a54555dc48e6f2ccb3294c8 (patch)
treea3b03731dbd176ababe950c42c769649c18932a3
parent30013465f45b9085b044b7abec36d7bd8d3b1b2b (diff)
downloaddotty-1fdc188af5b8b34b1a54555dc48e6f2ccb3294c8.tar.gz
dotty-1fdc188af5b8b34b1a54555dc48e6f2ccb3294c8.tar.bz2
dotty-1fdc188af5b8b34b1a54555dc48e6f2ccb3294c8.zip
New micro phase: Literalize
Convert expressions with constant types to Literals.
-rw-r--r--src/dotty/tools/dotc/Compiler.scala3
-rw-r--r--src/dotty/tools/dotc/transform/Literalize.scala65
2 files changed, 67 insertions, 1 deletions
diff --git a/src/dotty/tools/dotc/Compiler.scala b/src/dotty/tools/dotc/Compiler.scala
index d202f3a52..b51f383f7 100644
--- a/src/dotty/tools/dotc/Compiler.scala
+++ b/src/dotty/tools/dotc/Compiler.scala
@@ -28,7 +28,8 @@ class Compiler {
new Splitter),
List(new Nullarify,
new TypeTestsCasts,
- new InterceptedMethods),
+ new InterceptedMethods,
+ new Literalize),
List(new Erasure),
List(new UncurryTreeTransform
/* , new Constructors */)
diff --git a/src/dotty/tools/dotc/transform/Literalize.scala b/src/dotty/tools/dotc/transform/Literalize.scala
new file mode 100644
index 000000000..14ce8fd05
--- /dev/null
+++ b/src/dotty/tools/dotc/transform/Literalize.scala
@@ -0,0 +1,65 @@
+package dotty.tools.dotc
+package transform
+
+import TreeTransforms._
+import core.DenotTransformers._
+import core.Symbols._
+import core.Contexts._
+import core.Types._
+import core.Flags._
+import core.Decorators._
+import core.StdNames.nme
+import ast.Trees._
+
+/** This phase rewrites idempotent expressions with constant types to Literals.
+ * The constant types are eliminated by erasure, so we need to keep
+ * the info about constantness in the trees.
+ */
+class Literalize extends TreeTransform {
+ import ast.tpd._
+
+ override def name: String = "literalize"
+
+ /** Note: Demanding idempotency instead of purity is strictly speaking too loose.
+ * Example
+ *
+ * object O { final val x = 42; println("43") }
+ * O.x
+ *
+ * Strictly speaking we can't replace `O.x` with `42`. But this would make
+ * most expressions non-constant. Maybe we can change the spec to accept this
+ * kind of eliding behavior. Or else enforce true purity in the compiler.
+ * The choice will be affected by what we will do with `inline` and with
+ * Singleton type bounds (see SIP 23). Presumably
+ *
+ * object O1 { val x: Singleton = 42; println("43") }
+ * object O2 { inline val x = 42; println("43") }
+ *
+ * should behave differently.
+ *
+ * O1.x should have the same effect as { println("43"; 42 }
+ *
+ * whereas
+ *
+ * O2.x = 42
+ *
+ * Revisit this issue once we have implemented `inline`. Then we can demand
+ * purity of the prefix unless the selection goes to an inline val.
+ */
+ def literalize(tree: Tree)(implicit ctx: Context): Tree = tree.tpe match {
+ case ConstantType(value) if isIdempotentExpr(tree) => Literal(value)
+ case _ => tree
+ }
+
+ override def transformIdent(tree: Ident)(implicit ctx: Context, info: TransformerInfo): Tree =
+ literalize(tree)
+
+ override def transformSelect(tree: Select)(implicit ctx: Context, info: TransformerInfo): Tree =
+ literalize(tree)
+
+ override def transformApply(tree: Apply)(implicit ctx: Context, info: TransformerInfo): Tree =
+ literalize(tree)
+
+ override def transformTypeApply(tree: TypeApply)(implicit ctx: Context, info: TransformerInfo): Tree =
+ literalize(tree)
+} \ No newline at end of file