diff options
author | Eugene Burmako <burmako@epfl.ch> | 2011-11-28 15:02:48 +0000 |
---|---|---|
committer | Eugene Burmako <burmako@epfl.ch> | 2011-11-28 15:02:48 +0000 |
commit | 88ab6441739811243f15d668c8c23a2b6481b7eb (patch) | |
tree | 02c5dac49cc62fda2ccb474d52bf7457fb78671b /src/compiler | |
parent | f69d3e34dd165eb0f3242fcba3e6bbdc3d61e5d1 (diff) | |
download | scala-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.
Diffstat (limited to 'src/compiler')
-rw-r--r-- | src/compiler/scala/reflect/internal/Flags.scala | 10 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/settings/ScalaSettings.scala | 2 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/transform/LiftCode.scala | 57 |
3 files changed, 68 insertions, 1 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 |