package scala.tools.nsc
package symtab
trait Scopes {
self: SymbolTable =>
class ScopeEntry(val sym: Symbol, val owner: Scope) {
var tail: ScopeEntry = null
var next: ScopeEntry = null
override def hashCode(): Int = sym.name.start
override def toString(): String = sym.toString()
}
private def newScopeEntry(sym: Symbol, owner: Scope): ScopeEntry = {
val e = new ScopeEntry(sym, owner)
e.next = owner.elems
owner.elems = e
e
}
class Scope(initElems: ScopeEntry) extends AbsScope {
var elems: ScopeEntry = initElems
private var nestinglevel = 0
private var hashtable: Array[ScopeEntry] = null
private var elemsCache: List[Symbol] = null
private val HASHSIZE = 0x80
private val HASHMASK = 0x7f
private val MIN_HASH = 8
if (size >= MIN_HASH) createHash()
def this() = this(null: ScopeEntry)
def this(base: Scope) = {
this(base.elems)
nestinglevel = base.nestinglevel + 1
}
def this(decls: List[Symbol]) = {
this()
decls foreach enter
}
def cloneScope: Scope = {
val clone = new Scope()
this.toList foreach (clone enter _)
clone
}
override def isEmpty: Boolean = elems eq null
override def size: Int = {
var s = 0
var e = elems
while (e ne null) {
s += 1
e = e.next
}
s
}
def enter(e: ScopeEntry) {
elemsCache = null
if (hashtable ne null) {
val i = e.sym.name.start & HASHMASK
elems.tail = hashtable(i)
hashtable(i) = elems
} else if (size >= MIN_HASH) {
createHash()
}
}
def enter(sym: Symbol): Symbol = { enter(newScopeEntry(sym, this)); sym }
def enterUnique(sym: Symbol) {
assert(lookup(sym.name) == NoSymbol)
enter(sym)
}
private def createHash() {
hashtable = new Array[ScopeEntry](HASHSIZE)
enterInHash(elems)
}
private def enterInHash(e: ScopeEntry) {
if (e ne null) {
enterInHash(e.next)
val i = e.sym.name.start & HASHMASK
e.tail = hashtable(i)
hashtable(i) = e
}
}
def rehash(sym: Symbol, newname: Name) {
if (hashtable ne null) {
val index = sym.name.start & HASHMASK
var e1 = hashtable(index)
var e: ScopeEntry = null
if (e1 != null) {
if (e1.sym == sym) {
hashtable(index) = e1.tail
e = e1
} else {
while (e1.tail != null && e1.tail.sym != sym) e1 = e1.tail
if (e1.tail != null) {
e = e1.tail
e1.tail = e.tail
}
}
}
if (e != null) {
val newindex = newname.start & HASHMASK
e.tail = hashtable(newindex)
hashtable(newindex) = e
}
}
}
def unlink(e: ScopeEntry) {
if (elems == e) {
elems = e.next
} else {
var e1 = elems
while (e1.next != e) e1 = e1.next
e1.next = e.next
}
if (hashtable ne null) {
val index = e.sym.name.start & HASHMASK
var e1 = hashtable(index)
if (e1 == e) {
hashtable(index) = e.tail
} else {
while (e1.tail != e) e1 = e1.tail;
e1.tail = e.tail
}
}
elemsCache = null
}
def unlink(sym: Symbol) {
var e = lookupEntry(sym.name)
while (e ne null) {
if (e.sym == sym) unlink(e);
e = lookupNextEntry(e)
}
}
def lookup(name: Name): Symbol = {
val e = lookupEntry(name)
if (e eq null) NoSymbol else e.sym
}
def lookupAll(name: Name): Iterator[Symbol] = new Iterator[Symbol] {
var e = lookupEntry(name)
def hasNext: Boolean = e ne null
def next: Symbol = { val r = e.sym; e = lookupNextEntry(e); r }
}
def lookupEntry(name: Name): ScopeEntry = {
var e: ScopeEntry = null
if (hashtable ne null) {
e = hashtable(name.start & HASHMASK)
while ((e ne null) && e.sym.name != name) {
e = e.tail
}
} else {
e = elems
while ((e ne null) && e.sym.name != name) {
e = e.next
}
}
e
}
def lookupNextEntry(entry: ScopeEntry): ScopeEntry = {
var e = entry
if (hashtable ne null)
do { e = e.tail } while ((e ne null) && e.sym.name != entry.sym.name)
else
do { e = e.next } while ((e ne null) && e.sym.name != entry.sym.name);
e
}
override def toList: List[Symbol] = {
if (elemsCache eq null) {
elemsCache = Nil
var e = elems
while ((e ne null) && e.owner == this) {
elemsCache = e.sym :: elemsCache
e = e.next
}
}
elemsCache
}
def nestingLevel = nestinglevel
def iterator: Iterator[Symbol] = toList.iterator
override def foreach[U](p: Symbol => U): Unit = toList foreach p
override def filter(p: Symbol => Boolean): Scope =
if (!(toList forall p)) new Scope(toList filter p) else this
override def mkString(start: String, sep: String, end: String) =
toList.map(_.defString).mkString(start, sep, end)
override def toString(): String = mkString("Scope{\n ", ";\n ", "\n}")
}
def newScope: Scope = new Scope
object EmptyScope extends Scope {
override def enter(e: ScopeEntry) {
abort("EmptyScope.enter")
}
}
class ErrorScope(owner: Symbol) extends Scope(null: ScopeEntry)
}