4
import scala.collection.mutable.WeakHashMap
5
import scala.ref.WeakReference
7
// SI-6241: move importers to a mirror
8
trait Importers extends api.Importers { self: SymbolTable =>
10
def mkImporter(from0: api.Universe): Importer { val from: from0.type } = (
14
val reverse = this.asInstanceOf[from.Importer{ val from: self.type }]
15
def importSymbol(sym: from.Symbol) = sym.asInstanceOf[self.Symbol]
16
def importType(tpe: from.Type) = tpe.asInstanceOf[self.Type]
17
def importTree(tree: from.Tree) = tree.asInstanceOf[self.Tree]
18
def importPosition(pos: from.Position) = pos.asInstanceOf[self.Position]
21
// todo. fix this loophole
22
assert(from0.isInstanceOf[SymbolTable], "`from` should be an instance of scala.reflect.internal.SymbolTable")
23
new StandardImporter { val from = from0.asInstanceOf[SymbolTable] }
25
).asInstanceOf[Importer { val from: from0.type }]
27
abstract class StandardImporter extends Importer {
31
protected lazy val symMap = new Cache[from.Symbol, Symbol]()
32
protected lazy val tpeMap = new Cache[from.Type, Type]()
33
protected class Cache[K <: AnyRef, V <: AnyRef] extends WeakHashMap[K, WeakReference[V]] {
34
def weakGet(key: K): Option[V] = this get key flatMap WeakReference.unapply
35
def weakUpdate(key: K, value: V) = this.update(key, WeakReference(value))
38
// fixups and maps prevent stackoverflows in importer
41
lazy val fixups = scala.collection.mutable.MutableList[Function0[Unit]]()
42
def addFixup(fixup: => Unit): Unit = fixups += (() => fixup)
43
def tryFixup(): Unit = {
44
if (pendingSyms == 0 && pendingTpes == 0) {
45
val fixups = this.fixups.toList
47
fixups foreach { _() }
51
object reverse extends from.StandardImporter {
52
val from: self.type = self
53
// FIXME this and reverse should be constantly kept in sync
54
// not just synced once upon the first usage of reverse
55
for ((fromsym, WeakReference(mysym)) <- StandardImporter.this.symMap) symMap += ((mysym, WeakReference(fromsym)))
56
for ((fromtpe, WeakReference(mytpe)) <- StandardImporter.this.tpeMap) tpeMap += ((mytpe, WeakReference(fromtpe)))
59
// todo. careful import of positions
60
def importPosition(pos: from.Position): Position =
61
pos.asInstanceOf[Position]
63
def importSymbol(sym0: from.Symbol): Symbol = {
64
def doImport(sym: from.Symbol): Symbol =
65
symMap weakGet sym match {
66
case Some(result) => result
68
val myowner = importSymbol(sym.owner)
69
val mypos = importPosition(sym.pos)
70
val myname = importName(sym.name).toTermName
71
val myflags = sym.flags
72
def linkReferenced(mysym: TermSymbol, x: from.TermSymbol, op: from.Symbol => Symbol): Symbol = {
73
symMap.weakUpdate(x, mysym)
74
mysym.referenced = op(x.referenced)
77
val mysym = sym match {
78
case x: from.MethodSymbol =>
79
linkReferenced(myowner.newMethod(myname, mypos, myflags), x, importSymbol)
80
case x: from.ModuleSymbol =>
81
linkReferenced(myowner.newModuleSymbol(myname, mypos, myflags), x, importSymbol)
82
case x: from.FreeTermSymbol =>
83
newFreeTermSymbol(importName(x.name).toTermName, x.value, x.flags, x.origin) setInfo importType(x.info)
84
case x: from.FreeTypeSymbol =>
85
newFreeTypeSymbol(importName(x.name).toTypeName, x.flags, x.origin)
86
case x: from.TermSymbol =>
87
linkReferenced(myowner.newValue(myname, mypos, myflags), x, importSymbol)
88
case x: from.TypeSkolem =>
89
val origin = x.unpackLocation match {
91
case y: from.Tree => importTree(y)
92
case y: from.Symbol => importSymbol(y)
94
myowner.newTypeSkolemSymbol(myname.toTypeName, origin, mypos, myflags)
95
case x: from.ModuleClassSymbol =>
96
val mysym = myowner.newModuleClass(myname.toTypeName, mypos, myflags)
97
symMap.weakUpdate(x, mysym)
98
mysym.sourceModule = importSymbol(x.sourceModule)
100
case x: from.ClassSymbol =>
101
val mysym = myowner.newClassSymbol(myname.toTypeName, mypos, myflags)
102
symMap.weakUpdate(x, mysym)
103
if (sym.thisSym != sym) {
104
mysym.typeOfThis = importType(sym.typeOfThis)
105
mysym.thisSym setName importName(sym.thisSym.name)
108
case x: from.TypeSymbol =>
109
myowner.newTypeSymbol(myname.toTypeName, mypos, myflags)
111
symMap.weakUpdate(sym, mysym)
112
mysym setFlag Flags.LOCKED
114
val mytypeParams = sym.typeParams map importSymbol
115
new LazyPolyType(mytypeParams) with FlagAgnosticCompleter {
116
override def complete(s: Symbol) {
117
val result = sym.info match {
118
case from.PolyType(_, res) => res
119
case result => result
121
s setInfo GenPolyType(mytypeParams, importType(result))
122
s setAnnotations (sym.annotations map importAnnotationInfo)
126
mysym resetFlag Flags.LOCKED
129
def importOrRelink: Symbol = {
130
val sym = sym0 // makes sym visible in the debugger
133
else if (sym == from.NoSymbol)
136
rootMirror.RootClass // !!! replace with actual mirror when we move importers to the mirror
139
val owner = sym.owner
140
var scope = if (owner.isClass && !owner.isRefinementClass) owner.info else from.NoType
141
var existing = scope.decl(name)
142
if (sym.isModuleClass)
143
existing = existing.moduleClass
145
if (!existing.exists) scope = from.NoType
147
val myname = importName(name)
148
val myowner = importSymbol(owner)
149
val myscope = if (scope != from.NoType && !(myowner hasFlag Flags.LOCKED)) myowner.info else NoType
150
var myexisting = if (myscope != NoType) myowner.info.decl(myname) else NoSymbol // cannot load myexisting in general case, because it creates cycles for methods
151
if (sym.isModuleClass)
152
myexisting = importSymbol(sym.sourceModule).moduleClass
154
if (!sym.isOverloaded && myexisting.isOverloaded) {
157
val localCopy = doImport(sym)
158
myexisting filter (_.tpe matches localCopy.tpe)
160
myexisting filter (!_.isMethod)
162
assert(!myexisting.isOverloaded,
163
"import failure: cannot determine unique overloaded method alternative from\n "+
164
(myexisting.alternatives map (_.defString) mkString "\n")+"\n that matches "+sym+":"+sym.tpe)
168
if (sym.isOverloaded) {
169
myowner.newOverloaded(myowner.thisType, sym.alternatives map importSymbol)
170
} else if (sym.isTypeParameter && sym.paramPos >= 0 && !(myowner hasFlag Flags.LOCKED)) {
171
assert(myowner.typeParams.length > sym.paramPos,
172
"import failure: cannot determine parameter "+sym+" (#"+sym.paramPos+") in "+
173
myowner+typeParamsString(myowner.rawInfo)+"\n original symbol was: "+
174
sym.owner+from.typeParamsString(sym.owner.info))
175
myowner.typeParams(sym.paramPos)
177
if (myexisting != NoSymbol) {
180
val mysym = doImport(sym)
182
if (myscope != NoType) {
183
assert(myowner.info.decls.lookup(myname) == NoSymbol, myname+" "+myowner.info.decl(myname)+" "+myexisting)
184
myowner.info.decls enter mysym
194
} // end importOrRelink
197
symMap.weakGet(sym) match {
198
case Some(result) => result
202
val result = importOrRelink
203
symMap.weakUpdate(sym, result)
212
def importType(tpe: from.Type): Type = {
213
def doImport(tpe: from.Type): Type = tpe match {
214
case from.TypeRef(pre, sym, args) =>
215
TypeRef(importType(pre), importSymbol(sym), args map importType)
216
case from.ThisType(clazz) =>
217
ThisType(importSymbol(clazz))
218
case from.SingleType(pre, sym) =>
219
SingleType(importType(pre), importSymbol(sym))
220
case from.MethodType(params, restpe) =>
221
MethodType(params map importSymbol, importType(restpe))
222
case from.PolyType(tparams, restpe) =>
223
PolyType(tparams map importSymbol, importType(restpe))
224
case from.NullaryMethodType(restpe) =>
225
NullaryMethodType(importType(restpe))
226
case from.ConstantType(constant @ from.Constant(_)) =>
227
ConstantType(importConstant(constant))
228
case from.SuperType(thistpe, supertpe) =>
229
SuperType(importType(thistpe), importType(supertpe))
230
case from.TypeBounds(lo, hi) =>
231
TypeBounds(importType(lo), importType(hi))
232
case from.BoundedWildcardType(bounds) =>
233
BoundedWildcardType(importTypeBounds(bounds))
234
case from.ClassInfoType(parents, decls, clazz) =>
235
val myclazz = importSymbol(clazz)
236
val myscope = if (myclazz.isPackageClass) newPackageScope(myclazz) else newScope
237
val myclazzTpe = ClassInfoType(parents map importType, myscope, myclazz)
238
myclazz setInfo GenPolyType(myclazz.typeParams, myclazzTpe) // needed so that newly created symbols find their scope
239
decls foreach importSymbol // will enter itself into myclazz
241
case from.RefinedType(parents, decls) =>
242
RefinedType(parents map importType, importScope(decls), importSymbol(tpe.typeSymbol))
243
case from.ExistentialType(tparams, restpe) =>
244
newExistentialType(tparams map importSymbol, importType(restpe))
245
case from.OverloadedType(pre, alts) =>
246
OverloadedType(importType(pre), alts map importSymbol)
247
case from.AntiPolyType(pre, targs) =>
248
AntiPolyType(importType(pre), targs map importType)
249
case x: from.TypeVar =>
250
TypeVar(importType(x.origin), importTypeConstraint(x.constr), x.typeArgs map importType, x.params map importSymbol)
251
case from.NotNullType(tpe) =>
252
NotNullType(importType(tpe))
253
case from.AnnotatedType(annots, tpe, selfsym) =>
254
AnnotatedType(annots map importAnnotationInfo, importType(tpe), importSymbol(selfsym))
255
case from.ErrorType =>
257
case from.WildcardType =>
261
case from.NoPrefix =>
267
def importOrRelink: Type =
270
tpeMap.weakGet(tpe) match {
271
case Some(result) => result
275
val result = importOrRelink
276
tpeMap.weakUpdate(tpe, result)
285
def importTypeBounds(bounds: from.TypeBounds) = importType(bounds).asInstanceOf[TypeBounds]
287
def importAnnotationInfo(ann: from.AnnotationInfo): AnnotationInfo = {
288
val atp1 = importType(ann.atp)
289
val args1 = ann.args map importTree
290
val assocs1 = ann.assocs map { case (name, arg) => (importName(name), importAnnotArg(arg)) }
291
val original1 = importTree(ann.original)
292
AnnotationInfo(atp1, args1, assocs1) setOriginal original1
295
def importAnnotArg(arg: from.ClassfileAnnotArg): ClassfileAnnotArg = arg match {
296
case from.LiteralAnnotArg(constant @ from.Constant(_)) =>
297
LiteralAnnotArg(importConstant(constant))
298
case from.ArrayAnnotArg(args) =>
299
ArrayAnnotArg(args map importAnnotArg)
300
case from.ScalaSigBytes(bytes) =>
302
case from.NestedAnnotArg(annInfo) =>
303
NestedAnnotArg(importAnnotationInfo(annInfo))
306
def importTypeConstraint(constr: from.TypeConstraint): TypeConstraint = {
307
val result = new TypeConstraint(constr.loBounds map importType, constr.hiBounds map importType)
308
result.inst = importType(constr.inst)
312
// !!! todo: override to cater for PackageScopes
313
def importScope(decls: from.Scope): Scope =
314
newScopeWith(decls.toList map importSymbol: _*)
316
def importName(name: from.Name): Name =
317
if (name.isTypeName) newTypeName(name.toString) else newTermName(name.toString)
318
def importTypeName(name: from.TypeName): TypeName = importName(name).toTypeName
319
def importTermName(name: from.TermName): TermName = importName(name).toTermName
321
def importModifiers(mods: from.Modifiers): Modifiers =
322
new Modifiers(mods.flags, importName(mods.privateWithin), mods.annotations map importTree)
324
def importImportSelector(sel: from.ImportSelector): ImportSelector =
325
new ImportSelector(importName(sel.name), sel.namePos, if (sel.rename != null) importName(sel.rename) else null, sel.renamePos)
327
def importTree(tree: from.Tree): Tree = {
328
val mytree = tree match {
329
case from.ClassDef(mods, name, tparams, impl) =>
330
new ClassDef(importModifiers(mods), importName(name).toTypeName, tparams map importTypeDef, importTemplate(impl))
331
case from.PackageDef(pid, stats) =>
332
new PackageDef(importRefTree(pid), stats map importTree)
333
case from.ModuleDef(mods, name, impl) =>
334
new ModuleDef(importModifiers(mods), importName(name).toTermName, importTemplate(impl))
335
case from.emptyValDef =>
337
case from.ValDef(mods, name, tpt, rhs) =>
338
new ValDef(importModifiers(mods), importName(name).toTermName, importTree(tpt), importTree(rhs))
339
case from.DefDef(mods, name, tparams, vparamss, tpt, rhs) =>
340
new DefDef(importModifiers(mods), importName(name).toTermName, tparams map importTypeDef, mmap(vparamss)(importValDef), importTree(tpt), importTree(rhs))
341
case from.TypeDef(mods, name, tparams, rhs) =>
342
new TypeDef(importModifiers(mods), importName(name).toTypeName, tparams map importTypeDef, importTree(rhs))
343
case from.LabelDef(name, params, rhs) =>
344
new LabelDef(importName(name).toTermName, params map importIdent, importTree(rhs))
345
case from.Import(expr, selectors) =>
346
new Import(importTree(expr), selectors map importImportSelector)
347
case from.Template(parents, self, body) =>
348
new Template(parents map importTree, importValDef(self), body map importTree)
349
case from.Block(stats, expr) =>
350
new Block(stats map importTree, importTree(expr))
351
case from.CaseDef(pat, guard, body) =>
352
new CaseDef(importTree(pat), importTree(guard), importTree(body))
353
case from.Alternative(trees) =>
354
new Alternative(trees map importTree)
355
case from.Star(elem) =>
356
new Star(importTree(elem))
357
case from.Bind(name, body) =>
358
new Bind(importName(name), importTree(body))
359
case from.UnApply(fun, args) =>
360
new UnApply(importTree(fun), args map importTree)
361
case from.ArrayValue(elemtpt ,elems) =>
362
new ArrayValue(importTree(elemtpt), elems map importTree)
363
case from.Function(vparams, body) =>
364
new Function(vparams map importValDef, importTree(body))
365
case from.Assign(lhs, rhs) =>
366
new Assign(importTree(lhs), importTree(rhs))
367
case from.AssignOrNamedArg(lhs, rhs) =>
368
new AssignOrNamedArg(importTree(lhs), importTree(rhs))
369
case from.If(cond, thenp, elsep) =>
370
new If(importTree(cond), importTree(thenp), importTree(elsep))
371
case from.Match(selector, cases) =>
372
new Match(importTree(selector), cases map importCaseDef)
373
case from.Return(expr) =>
374
new Return(importTree(expr))
375
case from.Try(block, catches, finalizer) =>
376
new Try(importTree(block), catches map importCaseDef, importTree(finalizer))
377
case from.Throw(expr) =>
378
new Throw(importTree(expr))
379
case from.New(tpt) =>
380
new New(importTree(tpt))
381
case from.Typed(expr, tpt) =>
382
new Typed(importTree(expr), importTree(tpt))
383
case from.TypeApply(fun, args) =>
384
new TypeApply(importTree(fun), args map importTree)
385
case from.Apply(fun, args) => tree match {
386
case _: from.ApplyToImplicitArgs =>
387
new ApplyToImplicitArgs(importTree(fun), args map importTree)
388
case _: from.ApplyImplicitView =>
389
new ApplyImplicitView(importTree(fun), args map importTree)
391
new Apply(importTree(fun), args map importTree)
393
case from.ApplyDynamic(qual, args) =>
394
new ApplyDynamic(importTree(qual), args map importTree)
395
case from.Super(qual, mix) =>
396
new Super(importTree(qual), importTypeName(mix))
397
case from.This(qual) =>
398
new This(importName(qual).toTypeName)
399
case from.Select(qual, name) =>
400
new Select(importTree(qual), importName(name))
401
case from.Ident(name) =>
402
new Ident(importName(name))
403
case from.ReferenceToBoxed(ident) =>
404
new ReferenceToBoxed(importTree(ident) match { case ident: Ident => ident })
405
case from.Literal(constant @ from.Constant(_)) =>
406
new Literal(importConstant(constant))
407
case from.TypeTree() =>
409
case from.Annotated(annot, arg) =>
410
new Annotated(importTree(annot), importTree(arg))
411
case from.SingletonTypeTree(ref) =>
412
new SingletonTypeTree(importTree(ref))
413
case from.SelectFromTypeTree(qual, name) =>
414
new SelectFromTypeTree(importTree(qual), importName(name).toTypeName)
415
case from.CompoundTypeTree(templ) =>
416
new CompoundTypeTree(importTemplate(templ))
417
case from.AppliedTypeTree(tpt, args) =>
418
new AppliedTypeTree(importTree(tpt), args map importTree)
419
case from.TypeBoundsTree(lo, hi) =>
420
new TypeBoundsTree(importTree(lo), importTree(hi))
421
case from.ExistentialTypeTree(tpt, whereClauses) =>
422
new ExistentialTypeTree(importTree(tpt), whereClauses map importTree)
423
case from.EmptyTree =>
429
if (mytree != null) {
430
val mysym = if (tree.hasSymbol) importSymbol(tree.symbol) else NoSymbol
431
val mytpe = importType(tree.tpe)
434
case mytt: TypeTree =>
435
val tt = tree.asInstanceOf[from.TypeTree]
436
if (mytree.hasSymbol) mytt.symbol = mysym
437
if (tt.wasEmpty) mytt.defineType(mytpe) else mytt.setType(mytpe)
438
if (tt.original != null) mytt.setOriginal(importTree(tt.original))
440
if (mytree.hasSymbol) mytree.symbol = importSymbol(tree.symbol)
441
mytree.tpe = importType(tree.tpe)
446
// we have to be careful with position import as some shared trees
447
// like EmptyTree, emptyValDef don't support position assignment
448
if (tree.pos != NoPosition)
449
mytree.setPos(importPosition(tree.pos))
454
def importValDef(tree: from.ValDef): ValDef = importTree(tree).asInstanceOf[ValDef]
455
def importTypeDef(tree: from.TypeDef): TypeDef = importTree(tree).asInstanceOf[TypeDef]
456
def importTemplate(tree: from.Template): Template = importTree(tree).asInstanceOf[Template]
457
def importRefTree(tree: from.RefTree): RefTree = importTree(tree).asInstanceOf[RefTree]
458
def importIdent(tree: from.Ident): Ident = importTree(tree).asInstanceOf[Ident]
459
def importCaseDef(tree: from.CaseDef): CaseDef = importTree(tree).asInstanceOf[CaseDef]
460
def importConstant(constant: from.Constant): Constant = new Constant(constant.tag match {
461
case ClazzTag => importType(constant.value.asInstanceOf[from.Type])
462
case EnumTag => importSymbol(constant.value.asInstanceOf[from.Symbol])
463
case _ => constant.value