1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
|
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(sym: Symbol): Tree = {
assert(sym != null, "sym is null")
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
}
}
|