diff options
Diffstat (limited to 'src/compiler/scala/reflect/reify/phases/Calculate.scala')
-rw-r--r-- | src/compiler/scala/reflect/reify/phases/Calculate.scala | 61 |
1 files changed, 61 insertions, 0 deletions
diff --git a/src/compiler/scala/reflect/reify/phases/Calculate.scala b/src/compiler/scala/reflect/reify/phases/Calculate.scala new file mode 100644 index 0000000000..59a36f0ba4 --- /dev/null +++ b/src/compiler/scala/reflect/reify/phases/Calculate.scala @@ -0,0 +1,61 @@ +package scala.reflect.reify +package phases + +trait Calculate { + self: Reifier => + + import mirror._ + import definitions._ + import treeInfo._ + + implicit def sym2richSym(sym: Symbol): RichSymbol = new RichSymbol(sym) + class RichSymbol(sym: Symbol) { + def metalevel: Int = { assert(sym != NoSymbol); localSymbols.getOrElse(sym, 0) } + def isLocalToReifee = (localSymbols contains sym) // [Eugene] how do I account for local skolems? + } + + implicit def tpe2richTpe(tpe: Type): RichType = new RichType(tpe) + class RichType(tpe: Type) { + def isLocalToReifee = tpe != null && (tpe exists (tp => (localSymbols contains tp.typeSymbol) || (localSymbols contains tp.termSymbol))) + } + + private var localSymbols = collection.mutable.Map[Symbol, Int]() // set of all symbols that are local to the tree to be reified + private def registerLocalSymbol(sym: Symbol, metalevel: Int): Unit = + if (sym != null && sym != NoSymbol) { + if (localSymbols contains sym) + assert(localSymbols(sym) == metalevel, "metalevel mismatch: expected %s, actual %s".format(localSymbols(sym), metalevel)) + localSymbols(sym) = metalevel + } + + /** + * Merely traverses the reifiee and records local symbols along with their metalevels. + */ + val calculate = new Traverser { + // see the explanation of metalevels in ``Metalevels'' + var currMetalevel = 1 + + override def traverse(tree: Tree): Unit = tree match { + case TreeSplice(_) => + currMetalevel -= 1 + try super.traverse(tree) + finally currMetalevel += 1 + case tree if tree.isDef => + if (reifyDebug) println("boundSym: %s of type %s".format(tree.symbol, (tree.productIterator.toList collect { case tt: TypeTree => tt } headOption).getOrElse(TypeTree(tree.tpe)))) + registerLocalSymbol(tree.symbol, currMetalevel) + + bindRelatedSymbol(tree.symbol.sourceModule, "sourceModule") + bindRelatedSymbol(tree.symbol.moduleClass, "moduleClass") + bindRelatedSymbol(tree.symbol.companionClass, "companionClass") + bindRelatedSymbol(tree.symbol.companionModule, "companionModule") + Some(tree.symbol) collect { case termSymbol: TermSymbol => bindRelatedSymbol(termSymbol.referenced, "referenced") } + def bindRelatedSymbol(related: Symbol, name: String): Unit = + if (related != null && related != NoSymbol) { + if (reifyDebug) println("boundSym (" + name + "): " + related) + registerLocalSymbol(related, currMetalevel) + } + super.traverse(tree) + case _ => + super.traverse(tree) + } + } +}
\ No newline at end of file |