summaryrefslogtreecommitdiff
path: root/src/compiler/scala/reflect/reify/codegen/Symbols.scala
diff options
context:
space:
mode:
Diffstat (limited to 'src/compiler/scala/reflect/reify/codegen/Symbols.scala')
-rw-r--r--src/compiler/scala/reflect/reify/codegen/Symbols.scala114
1 files changed, 90 insertions, 24 deletions
diff --git a/src/compiler/scala/reflect/reify/codegen/Symbols.scala b/src/compiler/scala/reflect/reify/codegen/Symbols.scala
index 3328f5e402..2fc0002838 100644
--- a/src/compiler/scala/reflect/reify/codegen/Symbols.scala
+++ b/src/compiler/scala/reflect/reify/codegen/Symbols.scala
@@ -46,13 +46,8 @@ trait Symbols {
}
} else {
// todo. make sure that free methods and free local defs work correctly
- if (sym.isTerm) {
- if (reifyDebug) println("Free term" + (if (sym.isCapturedVariable) " (captured)" else "") + ": " + sym)
- reifyFreeTerm(sym, Ident(sym))
- } else {
- if (reifyDebug) println("Free type: " + sym)
- reifyFreeType(sym, Ident(sym))
- }
+ if (sym.isTerm) reifyFreeTerm(sym, Ident(sym))
+ else reifyFreeType(sym, Ident(sym))
}
}
@@ -61,13 +56,16 @@ trait Symbols {
case Some(reified) =>
reified
case None =>
+ if (reifyDebug) println("Free term" + (if (sym.isCapturedVariable) " (captured)" else "") + ": " + sym + "(" + sym.accurateKindString + ")")
+ var name = newTermName(nme.MIRROR_FREE_PREFIX + sym.name)
+ if (sym.isType) name = name.append(nme.MIRROR_FREE_THIS_SUFFIX)
if (sym.isCapturedVariable) {
assert(value.isInstanceOf[Ident], showRaw(value))
val capturedTpe = capturedVariableType(sym)
val capturedValue = referenceCapturedVariable(sym)
- locallyReify(sym, mirrorCall(nme.newFreeTerm, reify(sym.name.toString), reify(capturedTpe), capturedValue, reify(origin(sym))))
+ locallyReify(sym, name, mirrorCall(nme.newFreeTerm, reify(sym.name.toString), reify(capturedTpe), capturedValue, reify(origin(sym))))
} else {
- locallyReify(sym, mirrorCall(nme.newFreeTerm, reify(sym.name.toString), reify(sym.tpe), value, reify(origin(sym))))
+ locallyReify(sym, name, mirrorCall(nme.newFreeTerm, reify(sym.name.toString), reify(sym.tpe), value, reify(origin(sym))))
}
}
@@ -76,36 +74,104 @@ trait Symbols {
case Some(reified) =>
reified
case None =>
+ if (reifyDebug) println("Free type: %s (%s)".format(sym, sym.accurateKindString))
+ var name = newTermName(nme.MIRROR_FREE_PREFIX + sym.name)
val phantomTypeTag = Apply(TypeApply(Select(Ident(nme.MIRROR_SHORT), nme.TypeTag), List(value)), List(Literal(Constant(null))))
// todo. implement info reification for free types: type bounds, HK-arity, whatever else that can be useful
- locallyReify(sym, mirrorCall(nme.newFreeType, reify(sym.name.toString), reify(sym.info), phantomTypeTag, reify(origin(sym))))
+ locallyReify(sym, name, mirrorCall(nme.newFreeType, reify(sym.name.toString), reify(sym.info), phantomTypeTag, reify(origin(sym))))
+ }
+
+ def reifySymDef(sym: Symbol): Tree =
+ locallyReified get sym match {
+ case Some(reified) =>
+ reified
+ case None =>
+ if (reifyDebug) println("Sym def: %s (%s)".format(sym, sym.accurateKindString))
+ assert(!sym.isLocatable, sym) // if this assertion fires, then tough type reification needs to be rethought
+ sym.owner.ownersIterator find (!_.isLocatable) foreach reifySymDef
+ var name = newTermName(nme.MIRROR_SYMDEF_PREFIX + sym.name)
+ locallyReify(sym, name, Apply(Select(reify(sym.owner), nme.newNestedSymbol), List(reify(sym.name), reify(sym.pos), reify(sym.flags), reify(sym.isClass))))
}
+ // todo. very brittle abstraction, needs encapsulation
import scala.collection.mutable._
- private val localReifications = ArrayBuffer[ValDef]()
+ private val localReifications = ArrayBuffer[Tree]()
private val locallyReified = Map[Symbol, Tree]()
- def symbolTable: List[ValDef] = localReifications.toList
- def symbolTable_=(newSymbolTable: List[ValDef]): Unit = {
+ private var filledIn = false
+ def symbolTable: List[Tree] = { fillInSymbolTable(); localReifications.toList }
+ def symbolTable_=(newSymbolTable: List[Tree]): Unit = {
localReifications.clear()
locallyReified.clear()
+ filledIn = false
newSymbolTable foreach {
- case freedef @ FreeDef(_, name, binding, _) =>
- if (!(locallyReified contains binding.symbol)) {
- localReifications += freedef
- locallyReified(binding.symbol) = Ident(name)
+ case entry =>
+ val att = entry.attachment
+ att match {
+ case sym: Symbol =>
+ // don't duplicate reified symbols when merging inlined reifee
+ if (!(locallyReified contains sym)) {
+ val ValDef(_, name, _, _) = entry
+ localReifications += entry
+ locallyReified(sym) = Ident(name)
+ }
+ case other =>
+ // do nothing => symbol table fill-ins will be repopulated later
}
}
}
- private def locallyReify(sym: Symbol, reificode: => Tree): Tree = {
+ private def localName(name0: TermName): TermName = {
+ var name = name0.toString
+ name = name.replace(".type", "$type")
+ name = name.replace(" ", "$")
+ val fresh = typer.context.unit.fresh
+ newTermName(fresh.newName(name))
+ }
+
+ private def locallyReify(sym: Symbol, name0: TermName, reificode: => Tree): Tree = {
val reified = reificode
- val Apply(Select(_, flavor), _) = reified
- // [Eugene] name clashes are impossible, right?
- var name = newTermName(nme.MIRROR_FREE_PREFIX + sym.name)
- if (flavor == nme.newFreeTerm && sym.isType) name = name.append(nme.MIRROR_FREE_THIS_SUFFIX);
- // todo. also reify annotations for free vars
- localReifications += ValDef(NoMods, name, TypeTree(), reified)
+ val name = localName(name0)
+ // todo. tried to declare a private class here to carry an attachment, but it's path-dependent
+ // so got troubles with exchanging free variables between nested and enclosing quasiquotes
+ // attaching just Symbol isn't good either, so we need to think of a principled solution
+ val local = ValDef(NoMods, name, TypeTree(), reified) setAttachment sym
+ localReifications += local
+ filledIn = false
locallyReified(sym) = Ident(name)
locallyReified(sym)
}
+
+ /** Sets type signatures and annotations for locally reified symbols */
+ private def fillInSymbolTable() = {
+ if (!filledIn) {
+ val fillIns = new ArrayBuffer[Tree]
+ var i = 0
+ while (i < localReifications.length) {
+ // fillInSymbol might create new locallyReified symbols, that's why this is done iteratively
+ val reified = localReifications(i)
+ reified.attachment match {
+ case sym: Symbol => fillIns += fillInSymbol(sym)
+ case other => // do nothing
+ }
+ i += 1
+ }
+
+ filledIn = true
+ localReifications ++= fillIns.toList
+ }
+ }
+
+ /** Generate code to add type and annotation info to a reified symbol */
+ private def fillInSymbol(sym: Symbol): Tree = {
+ if (reifyDebug) println("Filling in: %s (%s)".format(sym, sym.accurateKindString))
+ val isFree = locallyReified(sym) match { case Ident(name) => name startsWith nme.MIRROR_FREE_PREFIX }
+ if (isFree) {
+ if (sym.annotations.isEmpty) EmptyTree
+ else Apply(Select(locallyReified(sym), nme.setAnnotations), List(reify(sym.annotations)))
+ } else {
+ val rset = Apply(Select(locallyReified(sym), nme.setTypeSignature), List(reifyType(sym.info)))
+ if (sym.annotations.isEmpty) rset
+ else Apply(Select(rset, nme.setAnnotations), List(reify(sym.annotations)))
+ }
+ }
} \ No newline at end of file