summaryrefslogtreecommitdiff
path: root/src/compiler/scala/reflect/reify/phases/Reshape.scala
diff options
context:
space:
mode:
authorEugene Burmako <xeno.by@gmail.com>2012-06-06 14:29:05 +0200
committerEugene Burmako <xeno.by@gmail.com>2012-06-08 15:32:03 +0200
commit6355d1a0b825c99560d4ccec1a8769f7421b1a71 (patch)
tree80f448f0da11dcab9cee30f3d8fe867cd66313ed /src/compiler/scala/reflect/reify/phases/Reshape.scala
parentce67870e64afabf75363679bcee597812ad223e9 (diff)
downloadscala-6355d1a0b825c99560d4ccec1a8769f7421b1a71.tar.gz
scala-6355d1a0b825c99560d4ccec1a8769f7421b1a71.tar.bz2
scala-6355d1a0b825c99560d4ccec1a8769f7421b1a71.zip
brings reification up to speed
Along with recovering from reflection refactoring, I implemented some new features (e.g. rollback of macro expansions), and did some stabilizing refactorings (e.g. moved mutable state into a ghetto). Also used the refactoring as a chance to fix free and aux symbols. Encapsulated this notion in a symbol table class, which allowed me to address outstanding issues with symbol table inheritance and inlining.
Diffstat (limited to 'src/compiler/scala/reflect/reify/phases/Reshape.scala')
-rw-r--r--src/compiler/scala/reflect/reify/phases/Reshape.scala47
1 files changed, 43 insertions, 4 deletions
diff --git a/src/compiler/scala/reflect/reify/phases/Reshape.scala b/src/compiler/scala/reflect/reify/phases/Reshape.scala
index 4ab306a13f..2a562d81e2 100644
--- a/src/compiler/scala/reflect/reify/phases/Reshape.scala
+++ b/src/compiler/scala/reflect/reify/phases/Reshape.scala
@@ -6,15 +6,16 @@ import scala.tools.nsc.symtab.Flags._
trait Reshape {
self: Reifier =>
- import mirror._
+ import global._
import definitions._
- import treeInfo._
/**
* Rolls back certain changes that were introduced during typechecking of the reifee.
*
* These include:
+ * * Undoing macro expansions
* * Replacing type trees with TypeTree(tpe)
+ * * Reassembling CompoundTypeTrees into reifiable form
* * Transforming Modifiers.annotations into Symbol.annotations
* * Transforming Annotated annotations into AnnotatedType annotations
* * Transforming Annotated(annot, expr) into Typed(expr, TypeTree(Annotated(annot, _))
@@ -23,7 +24,8 @@ trait Reshape {
val reshape = new Transformer {
var currentSymbol: Symbol = NoSymbol
- override def transform(tree: Tree) = {
+ override def transform(tree0: Tree) = {
+ val tree = undoMacroExpansion(tree0)
currentSymbol = tree.symbol
val preTyper = tree match {
@@ -31,8 +33,13 @@ trait Reshape {
tree
case tt @ TypeTree() =>
toPreTyperTypeTree(tt)
+ case ctt @ CompoundTypeTree(_) =>
+ toPreTyperCompoundTypeTree(ctt)
case toa @ TypedOrAnnotated(_) =>
toPreTyperTypedOrAnnotated(toa)
+ case ta @ TypeApply(_, _) if isCrossStageTypeBearer(ta) =>
+ if (reifyDebug) println("cross-stage type bearer, retaining: " + tree)
+ ta
case ta @ TypeApply(hk, ts) =>
val discard = ts collect { case tt: TypeTree => tt } exists isDiscarded
if (reifyDebug && discard) println("discarding TypeApply: " + tree)
@@ -85,6 +92,29 @@ trait Reshape {
super.transform(preTyper)
}
+ private def undoMacroExpansion(tree: Tree): Tree =
+ tree.attachments.get[MacroExpansionAttachment] match {
+ case Some(MacroExpansionAttachment(original)) =>
+ original match {
+ // this hack is necessary until I fix implicit macros
+ // so far tag materialization is implemented by sneaky macros hidden in scala-compiler.jar
+ // hence we cannot reify references to them, because noone will be able to see them later
+ // when implicit macros are fixed, these sneaky macros will move to corresponding companion objects
+ // of, say, ClassTag or TypeTag
+ case Apply(TypeApply(_, List(tt)), _) if original.symbol == MacroInternal_materializeArrayTag =>
+ gen.mkNullaryCall(Predef_implicitly, List(appliedType(ArrayTagClass, tt.tpe)))
+ case Apply(TypeApply(_, List(tt)), _) if original.symbol == MacroInternal_materializeClassTag =>
+ gen.mkNullaryCall(Predef_implicitly, List(appliedType(ClassTagClass, tt.tpe)))
+ case Apply(TypeApply(_, List(tt)), List(pre)) if original.symbol == MacroInternal_materializeTypeTag =>
+ gen.mkNullaryCall(Predef_implicitly, List(typeRef(pre.tpe, TypeTagClass, List(tt.tpe))))
+ case Apply(TypeApply(_, List(tt)), List(pre)) if original.symbol == MacroInternal_materializeConcreteTypeTag =>
+ gen.mkNullaryCall(Predef_implicitly, List(typeRef(pre.tpe, ConcreteTypeTagClass, List(tt.tpe))))
+ case _ =>
+ original
+ }
+ case _ => tree
+ }
+
override def transformModifiers(mods: Modifiers) = {
val mods1 = toPreTyperModifiers(mods, currentSymbol)
super.transformModifiers(mods1)
@@ -130,6 +160,7 @@ trait Reshape {
* Suddenly I found out that in certain contexts original trees do not contain symbols, but are just parser trees.
* To the moment I know only one such situation: typedAnnotations does not typecheck the annotation in-place, but rather creates new trees and typechecks them, so the original remains symless.
* Thus we apply a workaround for that in typedAnnotated. I hope this will be the only workaround in this department.
+ * upd. There are also problems with CompoundTypeTrees. I had to use attachments to retain necessary information.
*
* upd. Recently I went ahead and started using original for all TypeTrees, regardless of whether they refer to local symbols or not.
* As a result, ``reifyType'' is never called directly by tree reification (and, wow, it seems to work great!).
@@ -137,7 +168,7 @@ trait Reshape {
*/
private def isDiscarded(tt: TypeTree) = tt.original == null
private def toPreTyperTypeTree(tt: TypeTree): Tree = {
- if (tt.original != null) {
+ if (!isDiscarded(tt)) {
// here we rely on the fact that the originals that reach this point
// have all necessary symbols attached to them (i.e. that they can be recompiled in any lexical context)
// if this assumption fails, please, don't be quick to add postprocessing here (like I did before)
@@ -154,6 +185,14 @@ trait Reshape {
}
}
+ private def toPreTyperCompoundTypeTree(ctt: CompoundTypeTree): Tree = {
+ val CompoundTypeTree(tmpl @ Template(parents, self, stats)) = ctt
+ assert(self eq emptyValDef, self)
+ val att = tmpl.attachments.get[CompoundTypeTreeOriginalAttachment]
+ val CompoundTypeTreeOriginalAttachment(parents1, stats1) = att.getOrElse(CompoundTypeTreeOriginalAttachment(parents, stats))
+ CompoundTypeTree(Template(parents1, self, stats1))
+ }
+
private def toPreTyperTypedOrAnnotated(tree: Tree): Tree = tree match {
case ty @ Typed(expr1, tt @ TypeTree()) =>
if (reifyDebug) println("reify typed: " + tree)