
scala.reflect.reify.phases.Calculate.scala Maven / Gradle / Ivy
The newest version!
/*
* Scala (https://www.scala-lang.org)
*
* Copyright EPFL and Lightbend, Inc. dba Akka
*
* Licensed under Apache License 2.0
* (http://www.apache.org/licenses/LICENSE-2.0).
*
* See the NOTICE file distributed with this work for
* additional information regarding copyright ownership.
*/
package scala.reflect.reify
package phases
trait Calculate {
self: Reifier =>
import global._
implicit class RichCalculateSymbol(sym: Symbol) {
def metalevel: Int = {
assert(sym != null && sym != NoSymbol, "Missing symbol")
localSymbols.getOrElse(sym, 0)
}
def isLocalToReifee = (localSymbols contains sym) // todo. how do I account for local skolems?
}
implicit class RichCalculateType(tpe: Type) {
def isLocalToReifee = tpe != null && (tpe exists (tp => (localSymbols contains tp.typeSymbol) || (localSymbols contains tp.termSymbol)))
}
private def localSymbols: Map[Symbol, Int] = state.localSymbols // set of all symbols that are local to the tree to be reified
private def localSymbols_=(value: Map[Symbol, Int]): Unit = state.localSymbols = value
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))
else
localSymbols += (sym -> metalevel)
}
/**
* Merely traverses the target and records symbols local to the reifee 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")
tree.symbol match { case termSymbol: TermSymbol => bindRelatedSymbol(termSymbol.referenced, "referenced") case _ => }
tree match { case labelDef: LabelDef => labelDef.params.foreach(param => bindRelatedSymbol(param.symbol, "labelParam")) case _ => }
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)
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy