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
108
109
110
111
|
package scala.reflect.reify
package codegen
trait Symbols {
self: Reifier =>
import mirror._
import definitions._
import treeInfo._
/** 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 == RootPackage)
Select(mirrorSelect(nme.definitions), nme.RootPackage)
else if (sym == RootClass)
Select(mirrorSelect(nme.definitions), nme.RootClass)
else if (sym == EmptyPackage)
Select(mirrorSelect(nme.definitions), nme.EmptyPackage)
else if (sym == EmptyPackageClass)
Select(mirrorSelect(nme.definitions), nme.EmptyPackageClass)
else if (sym.isModuleClass)
Select(reify(sym.sourceModule), 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
mirrorCall(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)
mirrorCall(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)
mirrorCall(nme.selectOverloadedMethod, rowner, rname, reify(index))
} else
mirrorCall(nme.selectTerm, rowner, rname)
}
} 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))
}
}
}
def reifyFreeTerm(sym: Symbol, value: Tree): Tree =
locallyReified get sym match {
case Some(reified) =>
reified
case None =>
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))))
} else {
locallyReify(sym, mirrorCall(nme.newFreeTerm, reify(sym.name.toString), reify(sym.tpe), value, reify(origin(sym))))
}
}
def reifyFreeType(sym: Symbol, value: Tree): Tree =
locallyReified get sym match {
case Some(reified) =>
reified
case None =>
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))))
}
import scala.collection.mutable._
private val localReifications = ArrayBuffer[ValDef]()
private val locallyReified = Map[Symbol, Tree]()
def symbolTable: List[ValDef] = localReifications.toList
def symbolTable_=(newSymbolTable: List[ValDef]): Unit = {
localReifications.clear()
locallyReified.clear()
newSymbolTable foreach {
case freedef @ FreeDef(_, name, binding, _) =>
if (!(locallyReified contains binding.symbol)) {
localReifications += freedef
locallyReified(binding.symbol) = Ident(name)
}
}
}
private def locallyReify(sym: Symbol, 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)
locallyReified(sym) = Ident(name)
locallyReified(sym)
}
}
|