summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEugene Burmako <burmako@epfl.ch>2011-11-28 15:02:48 +0000
committerEugene Burmako <burmako@epfl.ch>2011-11-28 15:02:48 +0000
commit88ab6441739811243f15d668c8c23a2b6481b7eb (patch)
tree02c5dac49cc62fda2ccb474d52bf7457fb78671b
parentf69d3e34dd165eb0f3242fcba3e6bbdc3d61e5d1 (diff)
downloadscala-88ab6441739811243f15d668c8c23a2b6481b7eb.tar.gz
scala-88ab6441739811243f15d668c8c23a2b6481b7eb.tar.bz2
scala-88ab6441739811243f15d668c8c23a2b6481b7eb.zip
-Yreify-copypaste: the copy/pasteable mode for ...
-Yreify-copypaste: the copy/pasteable mode for reification When experimenting with macros, I've found out that it's helpful to use the reifier to find out what Scala idioms map to what Tree shapes. However, stuff emitted by -Yreify-debug is too verbose, that's why I decided to put up a human-readable dumper. To use the dumps, you need to first import the following things: import scala.reflect.api._ import scala.reflect.mirror._ import scala.reflect.api.Modifier._ import scala.reflect.internal.Flags._ The stuff is really experimental, e.g. the tension between flags and modifiers needs to be thought out and addressed. Review by odersky.
-rw-r--r--src/compiler/scala/reflect/internal/Flags.scala10
-rw-r--r--src/compiler/scala/tools/nsc/settings/ScalaSettings.scala2
-rw-r--r--src/compiler/scala/tools/nsc/transform/LiftCode.scala57
-rw-r--r--src/library/scala/reflect/api/Modifier.scala4
4 files changed, 70 insertions, 3 deletions
diff --git a/src/compiler/scala/reflect/internal/Flags.scala b/src/compiler/scala/reflect/internal/Flags.scala
index b95042341a..8366c6d63a 100644
--- a/src/compiler/scala/reflect/internal/Flags.scala
+++ b/src/compiler/scala/reflect/internal/Flags.scala
@@ -458,6 +458,7 @@ class Flags extends ModifierFlags {
case Modifier.interface => INTERFACE
case Modifier.mutable => MUTABLE
case Modifier.parameter => PARAM
+ case Modifier.`macro` => MACRO
case Modifier.covariant => COVARIANT
case Modifier.contravariant => CONTRAVARIANT
case Modifier.preSuper => PRESUPER
@@ -471,6 +472,15 @@ class Flags extends ModifierFlags {
case Modifier.paramAccessor => PARAMACCESSOR
case Modifier.bynameParameter => BYNAMEPARAM
}
+
+ def flagsOfModifiers(mods: List[Modifier.Value]): Long =
+ (mods :\ 0L) { (mod, curr) => curr | flagOfModifier(mod) }
+
+ def modifierOfFlag(flag: Long): Option[Modifier.Value] =
+ Modifier.values find { mod => flagOfModifier(mod) == flag }
+
+ def modifiersOfFlags(flags: Long): List[Modifier.Value] =
+ pickledListOrder map (mask => modifierOfFlag(flags & mask)) flatMap { mod => mod }
}
object Flags extends Flags { }
diff --git a/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala b/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala
index b15f338938..6be15e4e98 100644
--- a/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala
+++ b/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala
@@ -159,6 +159,8 @@ trait ScalaSettings extends AbsScalaSettings
val Ytyperdebug = BooleanSetting ("-Ytyper-debug", "Trace all type assignments.")
val Yinferdebug = BooleanSetting ("-Yinfer-debug", "Trace type inference and implicit search.")
val Ypmatdebug = BooleanSetting ("-Ypmat-debug", "Trace all pattern matcher activity.")
+ val Yreifycopypaste =
+ BooleanSetting ("-Yreify-copypaste", "Dump the reified trees in copypasteable representation.")
val Yreifydebug = BooleanSetting ("-Yreify-debug", "Trace reification actions.")
val Yreplsync = BooleanSetting ("-Yrepl-sync", "Do not use asynchronous code for repl startup")
val Yrepldebug = BooleanSetting ("-Yrepl-debug", "Trace all repl activity.") .
diff --git a/src/compiler/scala/tools/nsc/transform/LiftCode.scala b/src/compiler/scala/tools/nsc/transform/LiftCode.scala
index f55fe4f75e..b395f9095e 100644
--- a/src/compiler/scala/tools/nsc/transform/LiftCode.scala
+++ b/src/compiler/scala/tools/nsc/transform/LiftCode.scala
@@ -57,6 +57,59 @@ abstract class LiftCode extends Transform with TypingTransformers {
val reifyDebug = settings.Yreifydebug.value
val debugTrace = util.trace when reifyDebug
+ val reifyCopypaste = settings.Yreifycopypaste.value
+ def printCopypaste(tree: Tree) {
+ import scala.reflect.api.Modifier
+ import scala.reflect.api.Modifier._
+
+ def copypasteModifier(mod: Modifier.Value): String = mod match {
+ case mod @ (
+ `protected` | `private` | `override` |
+ `abstract` | `final` | `sealed` |
+ `implicit` | `lazy` | `macro` |
+ `case` | `trait`) => "`" + mod.toString + "`"
+ case mod => mod.toString
+ }
+
+ for (line <- (tree.toString.split(Properties.lineSeparator) drop 2 dropRight 1)) {
+ var s = line.trim
+ s = s.replace("$mr.", "")
+ s = s.replace(".apply", "")
+ s = s.replace("scala.collection.immutable.", "")
+ s = "List\\[List\\[.*?\\].*?\\]".r.replaceAllIn(s, "List")
+ s = "List\\[.*?\\]".r.replaceAllIn(s, "List")
+ s = s.replace("immutable.this.Nil", "List()")
+ s = s.replace("modifiersFromInternalFlags", "Modifiers")
+ s = s.replace("Modifiers(0L, newTypeName(\"\"), List())", "Modifiers()")
+ s = """Modifiers\((\d+)L, newTypeName\("(.*?)"\), List\((.*?)\)\)""".r.replaceAllIn(s, m => {
+ val buf = new StringBuffer()
+
+ val flags = m.group(1).toLong
+ var s_flags = Flags.modifiersOfFlags(flags) map copypasteModifier
+ buf.append("Set(" + s_flags.mkString(", ") + ")")
+
+ var privateWithin = m.group(2)
+ buf.append(", " + "newTypeName(\"" + privateWithin + "\")")
+
+ var annotations = m.group(3)
+ buf.append(", " + "List(" + annotations + ")")
+
+ var s = buf.toString
+ if (s.endsWith(", Map()")) s = s.substring(0, s.length - ", Map()".length)
+ if (s.endsWith(", newTypeName(\"\")")) s = s.substring(0, s.length - ", newTypeName(\"\")".length)
+ if (s.endsWith("Set()")) s = s.substring(0, s.length - "Set()".length)
+ "Modifiers(" + s + ")"
+ })
+ s = """setInternalFlags\((\d+)L\)""".r.replaceAllIn(s, m => {
+ val flags = m.group(1).toLong
+ val mods = Flags.modifiersOfFlags(flags) map copypasteModifier
+ "setInternalFlags(flagsOfModifiers(List(" + mods.mkString(", ") + ")))"
+ })
+
+ println(s)
+ }
+ }
+
/** Set of mutable local variables that are free in some inner method. */
private val freeMutableVars: mutable.Set[Symbol] = new mutable.HashSet
private val converted: mutable.Set[Symbol] = new mutable.HashSet // debug
@@ -79,7 +132,9 @@ abstract class LiftCode extends Transform with TypingTransformers {
try {
printTypings = reifyDebug
debugTrace("transformed = ") {
- localTyper.typedPos(tree.pos)(codify(super.transform(tree)))
+ val result = localTyper.typedPos(tree.pos)(codify(super.transform(tree)))
+ if (reifyCopypaste) printCopypaste(result)
+ result
}
} finally printTypings = saved
case ValDef(mods, name, tpt, rhs) if (freeMutableVars(sym)) => // box mutable variables that are accessed from a local closure
diff --git a/src/library/scala/reflect/api/Modifier.scala b/src/library/scala/reflect/api/Modifier.scala
index 5992e658c6..8569b103cf 100644
--- a/src/library/scala/reflect/api/Modifier.scala
+++ b/src/library/scala/reflect/api/Modifier.scala
@@ -3,9 +3,9 @@ package scala.reflect.api
object Modifier extends Enumeration {
val `protected`, `private`, `override`, `abstract`, `final`,
- `sealed`, `implicit`, `lazy`, `case`, `trait`,
+ `sealed`, `implicit`, `lazy`, `macro`, `case`, `trait`,
deferred, interface, mutable, parameter, covariant, contravariant,
preSuper, abstractOverride, local, java, static, caseAccessor,
defaultParameter, defaultInit, paramAccessor, bynameParameter = Value
-} \ No newline at end of file
+}