diff options
Diffstat (limited to 'src/compiler/scala/reflect/reify/codegen/GenSymbols.scala')
-rw-r--r-- | src/compiler/scala/reflect/reify/codegen/GenSymbols.scala | 109 |
1 files changed, 109 insertions, 0 deletions
diff --git a/src/compiler/scala/reflect/reify/codegen/GenSymbols.scala b/src/compiler/scala/reflect/reify/codegen/GenSymbols.scala new file mode 100644 index 0000000000..3a98d308a7 --- /dev/null +++ b/src/compiler/scala/reflect/reify/codegen/GenSymbols.scala @@ -0,0 +1,109 @@ +package scala.reflect.reify +package codegen + +trait GenSymbols { + self: Reifier => + + import global._ + import definitions._ + + /** Symbol table of the reifee. + * + * Keeps track of auxiliary symbols that are necessary for this reification session. + * These include: + * 1) Free vars (terms, types and existentials), + * 2) Non-locatable symbols (sometimes, e.g. for RefinedTypes, we need to reify these; to do that we create their local copies in the reificode) + * 3) Non-locatable symbols that are referred by #1, #2 and #3 + * + * Exposes three main methods: + * 1) `syms` that lists symbols belonging to the table, + * 2) `symXXX` family of methods that provide information about the symbols in the table, + * 3) `encode` that renders the table into a list of trees (recursively populating #3 and setting up initialization code for #1, #2 and #3) + */ + def symtab: SymbolTable = state.symtab + + /** Reify a reference to a symbol */ + def reifySymRef(sym0: Symbol): Tree = { + assert(sym0 != null, "sym is null") + val sym = sym0.dealias + + if (sym == NoSymbol) + mirrorSelect(nme.NoSymbol) + else if (sym.isRootPackage) + mirrorMirrorSelect(nme.RootPackage) + else if (sym.isRoot) + mirrorMirrorSelect(nme.RootClass) + else if (sym.isEmptyPackage) + mirrorMirrorSelect(nme.EmptyPackage) + else if (sym.isEmptyPackageClass) + mirrorMirrorSelect(nme.EmptyPackageClass) + else if (sym.isModuleClass) + Select(Select(reify(sym.sourceModule), nme.asModuleSymbol), nme.moduleClass) + else if (sym.isLocatable) { + // [Eugene] am I doing this right? +// if (sym.isStaticOwner) { // no good for us, because it returns false for packages + if (sym.isStatic && (sym.isClass || sym.isModule)) { + val resolver = if (sym.isType) nme.staticClass else nme.staticModule + mirrorMirrorCall(resolver, reify(sym.fullName)) + } else { + if (reifyDebug) println("Locatable: %s (%s) owned by %s (%s) at %s".format(sym, sym.accurateKindString, sym.owner, sym.owner.accurateKindString, sym.owner.fullNameString)) + val rowner = reify(sym.owner) + val rname = reify(sym.name.toString) + if (sym.isType) + mirrorBuildCall(nme.selectType, rowner, rname) + else if (sym.isMethod && sym.owner.isClass && sym.owner.info.decl(sym.name).isOverloaded) { + val index = sym.owner.info.decl(sym.name).alternatives indexOf sym + assert(index >= 0, sym) + mirrorBuildCall(nme.selectOverloadedMethod, rowner, rname, reify(index)) + } else + mirrorBuildCall(nme.selectTerm, rowner, rname) + } + } else { + // todo. make sure that free methods and free local defs work correctly + if (sym.isTerm) reifyFreeTerm(sym, Ident(sym)) + else reifyFreeType(sym, Ident(sym)) + } + } + + def reifyFreeTerm(sym: Symbol, value: Tree): Tree = + reifyIntoSymtab(sym) { + if (reifyDebug) println("Free term" + (if (sym.isCapturedVariable) " (captured)" else "") + ": " + sym + "(" + sym.accurateKindString + ")") + var name = newTermName(nme.REIFY_FREE_PREFIX + sym.name) + if (sym.isType) name = name.append(nme.REIFY_FREE_THIS_SUFFIX) + if (sym.isCapturedVariable) { + assert(value.isInstanceOf[Ident], showRaw(value)) + val capturedTpe = capturedVariableType(sym) + val capturedValue = referenceCapturedVariable(sym) + (name, mirrorBuildCall(nme.newFreeTerm, reify(sym.name.toString), reify(capturedTpe), capturedValue, mirrorBuildCall(nme.flagsFromBits, reify(sym.flags)), reify(origin(sym)))) + } else { + (name, mirrorBuildCall(nme.newFreeTerm, reify(sym.name.toString), reify(sym.tpe), value, mirrorBuildCall(nme.flagsFromBits, reify(sym.flags)), reify(origin(sym)))) + } + } + + def reifyFreeType(sym: Symbol, value: Tree): Tree = + reifyIntoSymtab(sym) { + if (reifyDebug) println("Free type: %s (%s)".format(sym, sym.accurateKindString)) + var name = newTermName(nme.REIFY_FREE_PREFIX + sym.name) + val phantomTypeTag = Apply(TypeApply(Select(Ident(nme.UNIVERSE_SHORT), nme.TypeTag), List(value)), List(Literal(Constant(null)), Literal(Constant(null)))) + val flavor = if (sym.isExistential) nme.newFreeExistential else nme.newFreeType + (name, mirrorBuildCall(flavor, reify(sym.name.toString), reify(sym.info), phantomTypeTag, mirrorBuildCall(nme.flagsFromBits, reify(sym.flags)), reify(origin(sym)))) + } + + def reifySymDef(sym: Symbol): Tree = + reifyIntoSymtab(sym) { + 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.REIFY_SYMDEF_PREFIX + sym.name) + (name, mirrorBuildCall(nme.newNestedSymbol, reify(sym.owner), reify(sym.name), reify(sym.pos), mirrorBuildCall(nme.flagsFromBits, reify(sym.flags)), reify(sym.isClass))) + } + + private def reifyIntoSymtab(sym: Symbol)(reificode: => (TermName, Tree)): Tree ={ + def fromSymtab = symtab symRef sym + if (fromSymtab == EmptyTree) { + val reification = reificode + state.symtab += (sym, reification._1, reification._2) + } + fromSymtab + } +} |