summaryrefslogtreecommitdiff
path: root/sources/scala/tools/nsc/transform/OverridingPairs.scala
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2005-09-20 17:45:45 +0000
committerMartin Odersky <odersky@gmail.com>2005-09-20 17:45:45 +0000
commit3761cb4b3a1c03f5daa2fac28d19f6f398072ffe (patch)
treeaf915e38284d71f68b9986f7050e0aa5555345f0 /sources/scala/tools/nsc/transform/OverridingPairs.scala
parenta2231f55a00c96ecf670e0f02ed026c0ff956ecc (diff)
downloadscala-3761cb4b3a1c03f5daa2fac28d19f6f398072ffe.tar.gz
scala-3761cb4b3a1c03f5daa2fac28d19f6f398072ffe.tar.bz2
scala-3761cb4b3a1c03f5daa2fac28d19f6f398072ffe.zip
*** empty log message ***
Diffstat (limited to 'sources/scala/tools/nsc/transform/OverridingPairs.scala')
-rwxr-xr-xsources/scala/tools/nsc/transform/OverridingPairs.scala126
1 files changed, 126 insertions, 0 deletions
diff --git a/sources/scala/tools/nsc/transform/OverridingPairs.scala b/sources/scala/tools/nsc/transform/OverridingPairs.scala
new file mode 100755
index 0000000000..2830fed9f5
--- /dev/null
+++ b/sources/scala/tools/nsc/transform/OverridingPairs.scala
@@ -0,0 +1,126 @@
+/* NSC -- new scala compiler
+ * Copyright 2005 LAMP/EPFL
+ * @author
+ */
+// $Id$
+package scala.tools.nsc.transform;
+
+import util.HashSet;
+import collection.mutable.HashMap;
+import symtab.Flags._;
+
+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 hasFlag LOCAL);
+
+ 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 = new Scope;
+ { def fillDecls(bcs: List[Symbol], deferredflag: int): unit =
+ if (!bcs.isEmpty) {
+ fillDecls(bcs.tail, deferredflag);
+ var e = bcs.head.info.decls.elems;
+ while (e != 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 = _;
+
+ def hasNext: boolean = curEntry != null;
+
+ def next: unit =
+ if (curEntry != null) {
+ overriding = curEntry.sym;
+ if (nextEntry != null) {
+ do {
+ nextEntry = decls.lookupNextEntry(nextEntry);
+ } while (nextEntry != null &&
+ ((nextEntry.sym hasFlag PRIVATE) ||
+ (overriding.owner == nextEntry.sym.owner) ||
+ (hasCommonParent(overriding, nextEntry.sym)) ||
+ (!matches(overriding, nextEntry.sym)) ||
+ (overriding hasFlag LOCAL)))
+ }
+ if (nextEntry != null) {
+ overridden = nextEntry.sym;
+ //System.out.println("yield: " + overriding + overriding.locationString + " / " + overridden + overridden.locationString);//DEBUG
+ visited addEntry nextEntry
+ } else {
+ do {
+ curEntry = curEntry.next
+ } while (curEntry != null && (visited contains curEntry));
+ nextEntry = curEntry;
+ next
+ }
+ }
+
+ next
+ }
+}
+