diff options
Diffstat (limited to 'compiler/src/dotty/tools/dotc/core/Scopes.scala')
-rw-r--r-- | compiler/src/dotty/tools/dotc/core/Scopes.scala | 73 |
1 files changed, 44 insertions, 29 deletions
diff --git a/compiler/src/dotty/tools/dotc/core/Scopes.scala b/compiler/src/dotty/tools/dotc/core/Scopes.scala index 6090079e5..205798474 100644 --- a/compiler/src/dotty/tools/dotc/core/Scopes.scala +++ b/compiler/src/dotty/tools/dotc/core/Scopes.scala @@ -32,7 +32,7 @@ object Scopes { * This value must be a power of two, so that the index of an element can * be computed as element.hashCode & (hashTable.length - 1) */ - private final val MinHash = 8 + final val MinHashedScopeSize = 8 /** The maximal permissible number of recursions when creating * a hashtable @@ -60,7 +60,7 @@ object Scopes { * or to delete them. These methods are provided by subclass * MutableScope. */ - abstract class Scope extends DotClass with printing.Showable with Iterable[Symbol] { + abstract class Scope extends DotClass with printing.Showable { /** The last scope-entry from which all others are reachable via `prev` */ private[dotc] def lastEntry: ScopeEntry @@ -76,18 +76,37 @@ object Scopes { /** The symbols in this scope in the order they were entered; * inherited from outer ones first. */ - def toList: List[Symbol] + def toList(implicit ctx: Context): List[Symbol] /** Return all symbols as an iterator in the order they were entered in this scope. */ - def iterator: Iterator[Symbol] = toList.iterator + def iterator(implicit ctx: Context): Iterator[Symbol] = toList.iterator + + /** Is the scope empty? */ + def isEmpty: Boolean = lastEntry eq null + + def foreach[U](p: Symbol => U)(implicit ctx: Context): Unit = toList foreach p + + def filter(p: Symbol => Boolean)(implicit ctx: Context): List[Symbol] = { + ensureComplete() + var syms: List[Symbol] = Nil + var e = lastEntry + while ((e ne null) && e.owner == this) { + val sym = e.sym + if (p(sym)) syms = sym :: syms + e = e.prev + } + syms + } + + def find(p: Symbol => Boolean)(implicit ctx: Context): Symbol = filter(p) match { + case sym :: _ => sym + case _ => NoSymbol + } /** Returns a new mutable scope with the same content as this one. */ def cloneScope(implicit ctx: Context): MutableScope - /** Is the scope empty? */ - override def isEmpty: Boolean = lastEntry eq null - /** Lookup a symbol entry matching given name. */ def lookupEntry(name: Name)(implicit ctx: Context): ScopeEntry @@ -144,6 +163,12 @@ object Scopes { final def toText(printer: Printer): Text = printer.toText(this) def checkConsistent()(implicit ctx: Context) = () + + /** Ensure that all elements of this scope have been entered. + * Overridden by SymbolLoaders.PackageLoader#PackageScope, where it + * makes sure that all names with `$`'s have been added. + */ + protected def ensureComplete()(implicit ctx: Context): Unit = () } /** A subclass of Scope that defines methods for entering and @@ -155,9 +180,10 @@ object Scopes { class MutableScope protected[Scopes](initElems: ScopeEntry, initSize: Int, val nestingLevel: Int = 0) extends Scope { + /** Scope shares elements with `base` */ protected[Scopes] def this(base: Scope)(implicit ctx: Context) = { this(base.lastEntry, base.size, base.nestingLevel + 1) - ensureCapacity(MinHash)(ctx) // WTH? it seems the implicit is not in scope for a secondary constructor call. + ensureCapacity(MinHashedScopeSize)(ctx) // WTH? it seems the implicit is not in scope for a secondary constructor call. } def this() = this(null, 0, 0) @@ -178,6 +204,8 @@ object Scopes { */ private var elemsCache: List[Symbol] = null + protected def newScopeLikeThis() = new MutableScope() + /** Clone scope, taking care not to force the denotations of any symbols in the scope. */ def cloneScope(implicit ctx: Context): MutableScope = { @@ -187,7 +215,7 @@ object Scopes { entries += e e = e.prev } - val scope = newScope + val scope = newScopeLikeThis() for (i <- entries.length - 1 to 0 by -1) { val e = entries(i) scope.newScopeEntry(e.name, e.sym) @@ -197,7 +225,7 @@ object Scopes { /** create and enter a scope entry with given name and symbol */ protected def newScopeEntry(name: Name, sym: Symbol)(implicit ctx: Context): ScopeEntry = { - ensureCapacity(if (hashTable ne null) hashTable.length else MinHash) + ensureCapacity(if (hashTable ne null) hashTable.length else MinHashedScopeSize) val e = new ScopeEntry(name, sym, this) e.prev = lastEntry lastEntry = e @@ -338,8 +366,9 @@ object Scopes { /** Returns all symbols as a list in the order they were entered in this scope. * Does _not_ include the elements of inherited scopes. */ - override final def toList: List[Symbol] = { + override final def toList(implicit ctx: Context): List[Symbol] = { if (elemsCache eq null) { + ensureComplete() elemsCache = Nil var e = lastEntry while ((e ne null) && e.owner == this) { @@ -351,6 +380,7 @@ object Scopes { } override def implicitDecls(implicit ctx: Context): List[TermRef] = { + ensureComplete() var irefs = new mutable.ListBuffer[TermRef] var e = lastEntry while (e ne null) { @@ -365,25 +395,13 @@ object Scopes { /** Vanilla scope - symbols are stored in declaration order. */ - final def sorted: List[Symbol] = toList - - override def foreach[U](p: Symbol => U): Unit = toList foreach p - - override def filter(p: Symbol => Boolean): List[Symbol] = { - var syms: List[Symbol] = Nil - var e = lastEntry - while ((e ne null) && e.owner == this) { - val sym = e.sym - if (p(sym)) syms = sym :: syms - e = e.prev - } - syms - } + final def sorted(implicit ctx: Context): List[Symbol] = toList override def openForMutations: MutableScope = this /** Check that all symbols in this scope are in their correct hashtable buckets. */ override def checkConsistent()(implicit ctx: Context) = { + ensureComplete() var e = lastEntry while (e != null) { var e1 = lookupEntry(e.name) @@ -407,9 +425,6 @@ object Scopes { scope } - /** Create new scope for the members of package `pkg` */ - def newPackageScope(pkgClass: Symbol): MutableScope = newScope - /** Transform scope of members of `owner` using operation `op` * This is overridden by the reflective compiler to avoid creating new scopes for packages */ @@ -425,7 +440,7 @@ object Scopes { override private[dotc] def lastEntry = null override def size = 0 override def nestingLevel = 0 - override def toList = Nil + override def toList(implicit ctx: Context) = Nil override def cloneScope(implicit ctx: Context): MutableScope = unsupported("cloneScope") override def lookupEntry(name: Name)(implicit ctx: Context): ScopeEntry = null override def lookupNextEntry(entry: ScopeEntry)(implicit ctx: Context): ScopeEntry = null |