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
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
|
/* NSC -- new Scala compiler
* Copyright 2005-2006 LAMP/EPFL
* @author Martin Odersky
*/
// $Id$
package scala.tools.nsc.transform
import collection.mutable.HashMap
import symtab.Flags._
import util.HashSet
/** This abstract class ...
*
* @author Martin Odersky
* @version 1.0
*/
abstract class OverridingPairs {
val global: Global
import global._
class Cursor(base: Symbol) {
private val self = base.thisType
protected def exclude(sym: Symbol): boolean = sym.isConstructor || sym.isPrivateLocal
protected def parents: List[Type] = base.info.parents
protected def matches(sym1: Symbol, sym2: Symbol): boolean =
sym1.isType || (self.memberType(sym1) matches self.memberType(sym2))
private type BitSet = Array[int]
private def newBitSet(size: int): BitSet = new Array((size + 31) >> 5)
private def include(bs: BitSet, n: int): unit = {
val nshifted = n >> 5
val nmask = 1 << (n & 31)
bs(nshifted) = bs(nshifted) | nmask
}
private def intersectionContainsElementLeq(bs1: BitSet, bs2: BitSet,
n: int): boolean =
{
val nshifted = n >> 5;
val nmask = 1 << (n & 31);
((List.range(0, nshifted) exists (i => (bs1(i) & bs2(i)) != 0)) ||
((bs1(nshifted) & bs2(nshifted) & (nmask | nmask - 1)) != 0))
}
private val decls = newScope;
{ def fillDecls(bcs: List[Symbol], deferredflag: int): unit =
if (!bcs.isEmpty) {
fillDecls(bcs.tail, deferredflag)
var e = bcs.head.info.decls.elems;
while (e ne null) {
if (e.sym.getFlag(DEFERRED) == deferredflag && !exclude(e.sym))
decls enter e.sym;
e = e.next
}
}
fillDecls(base.info.baseClasses, DEFERRED)
fillDecls(base.info.baseClasses, 0)
}
private val size = base.info.baseClasses.length
private val index = new HashMap[Symbol, int]
{ var i = 0;
for (val bc <- base.info.baseClasses) {
index(bc) = i
i = i + 1
}
}
private val subParents = new Array[BitSet](size)
{ for (val i <- List.range(0, size))
subParents(i) = new BitSet(size);
for (val p <- parents) {
val pIndex = index(p.symbol)
for (val bc <- p.baseClasses) include(subParents(index(bc)), pIndex)
}
}
private def hasCommonParent(sym1: Symbol, sym2: Symbol) = {
//assert(index.get(sym1.owner) != None, "" + base + " " + sym1 + " " + sym1.owner);//DEBUG
//assert(index.get(sym2.owner) != None, "" + base + " " + sym2 + " " + sym2.owner);//DEBUG
val index1 = index(sym1.owner)
val index2 = index(sym2.owner)
val minindex = if (index1 < index2) index1 else index2
intersectionContainsElementLeq(subParents(index1), subParents(index2), minindex)
}
private val visited = new HashSet[ScopeEntry](256)
private var curEntry = decls.elems
private var nextEntry = curEntry
var overriding: Symbol = _
var overridden: Symbol = _
//@M: note that next is called once during object initialisation
def hasNext: boolean = curEntry ne null
def next: unit =
if (curEntry ne null) {
overriding = curEntry.sym
if (nextEntry ne null) {
do {
nextEntry = decls.lookupNextEntry(nextEntry);
} while ((nextEntry ne null) &&
((nextEntry.sym hasFlag PRIVATE) ||
(overriding.owner == nextEntry.sym.owner) ||
(!matches(overriding, nextEntry.sym)) ||
(hasCommonParent(overriding, nextEntry.sym)) ||
(exclude(overriding))))
}
if (nextEntry ne null) {
overridden = nextEntry.sym;
//Console.println("yield: " + overriding + overriding.locationString + " / " + overridden + overridden.locationString);//DEBUG
visited addEntry nextEntry
} else {
do {
curEntry = curEntry.next
} while ((curEntry ne null) && (visited contains curEntry));
nextEntry = curEntry
next
}
}
next //@M: ATTN! this method gets called during construction!
}
}
|