diff options
-rw-r--r-- | src/dotty/tools/dotc/core/Definitions.scala | 2 | ||||
-rw-r--r-- | src/dotty/tools/dotc/core/Scopes.scala | 168 | ||||
-rw-r--r-- | src/dotty/tools/dotc/core/SymDenotations.scala | 4 | ||||
-rw-r--r-- | src/dotty/tools/dotc/core/SymbolLoaders.scala | 4 | ||||
-rw-r--r-- | src/dotty/tools/dotc/core/Symbols.scala | 2 | ||||
-rw-r--r-- | src/dotty/tools/dotc/core/TypeOps.scala | 2 | ||||
-rw-r--r-- | src/dotty/tools/dotc/core/pickling/ClassfileParser.scala | 6 | ||||
-rw-r--r-- | src/dotty/tools/dotc/core/pickling/UnPickler.scala | 6 |
8 files changed, 112 insertions, 82 deletions
diff --git a/src/dotty/tools/dotc/core/Definitions.scala b/src/dotty/tools/dotc/core/Definitions.scala index 4af1fefa4..878cec877 100644 --- a/src/dotty/tools/dotc/core/Definitions.scala +++ b/src/dotty/tools/dotc/core/Definitions.scala @@ -25,7 +25,7 @@ class Definitions(implicit ctx: Context) { import ctx.{requiredClass, requiredModule, requiredPackage} - private def newSyntheticTypeParam(cls: ClassSymbol, scope: Scope, suffix: String = "T0") = { + private def newSyntheticTypeParam(cls: ClassSymbol, scope: MutableScope, suffix: String = "T0") = { val tname = suffix.toTypeName.expandedName(cls) val tparam = ctx.newSymbol(cls, tname, TypeParamCreationFlags, TypeBounds.empty) scope.enter(tparam) diff --git a/src/dotty/tools/dotc/core/Scopes.scala b/src/dotty/tools/dotc/core/Scopes.scala index 51e5419e6..89bdeb94b 100644 --- a/src/dotty/tools/dotc/core/Scopes.scala +++ b/src/dotty/tools/dotc/core/Scopes.scala @@ -42,12 +42,81 @@ object Scopes { override def toString: String = sym.toString } - /** Note: constructor is protected to force everyone to use the factory methods newScope or newNestedScope instead. + /** A scope contains a set of symbols. It can be an extension + * of some outer scope, from which it inherits all symbols. + * This class does not have any methods to add symbols to a scope + * or to delete them. These methods are provided by subclass + * MutableScope. + */ + abstract class Scope extends Iterable[Symbol] { + private[dotc] def lastEntry: ScopeEntry + + /** The number of symbols in this scope (including inherited ones + * from outer scopes). + */ + def size: Int + + /** The number of outer scopes from which symbols are inherited */ + def nestingLevel: Int + + /** The symbols in this scope in the order they were entered; + * inherited from outer ones first. + */ + def toList: List[Symbol] + + /** Return all symbols as an iterator in the order they were entered in this scope. + */ + def iterator: Iterator[Symbol] = toList.iterator + + /** Returns a new scope with the same content as this one. */ + def cloneScope(implicit ctx: Context): Scope + + /** 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 + + /** Lookup next entry with same name as this one */ + def lookupNextEntry(entry: ScopeEntry)(implicit ctx: Context): ScopeEntry + + /** Lookup a symbol */ + final def lookup(name: Name)(implicit ctx: Context): Symbol = { + val e = lookupEntry(name) + if (e eq null) NoSymbol else e.sym + } + + /** Returns an iterator yielding every symbol with given name in this scope. + */ + final def lookupAll(name: Name)(implicit ctx: Context): 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 } + } + + /** The denotation set of all the symbols with given name in this scope */ + final def denotsNamed(name: Name)(implicit ctx: Context): PreDenotation = { + var syms: PreDenotation = NoDenotation + var e = lookupEntry(name) + while (e != null) { + syms = syms union e.sym.denot + e = lookupNextEntry(e) + } + syms + } + + /** Cast this scope to a mutable scope */ + final def openForMutations: MutableScope = this.asInstanceOf[MutableScope] + } + + /** A subclass of Scope that defines methods for entering and + * unlinking entries. + * Note: constructor is protected to force everyone to use the factory methods newScope or newNestedScope instead. * This is necessary because when run from reflection every scope needs to have a * SynchronizedScope as mixin. */ - class Scope protected[Scopes](initElems: ScopeEntry, initSize: Int, val nestingLevel: Int = 0) - extends Iterable[Symbol] { + class MutableScope protected[Scopes](initElems: ScopeEntry, initSize: Int, val nestingLevel: Int = 0) + extends Scope { protected[Scopes] def this(base: Scope)(implicit ctx: Context) = { this(base.lastEntry, base.size, base.nestingLevel + 1) @@ -61,7 +130,7 @@ object Scopes { /** The size of the scope */ private[this] var _size = initSize - override def size = _size + override final def size = _size private def size_= (x: Int) = _size = x /** the hash table @@ -72,11 +141,7 @@ object Scopes { */ private var elemsCache: List[Symbol] = null - /** Returns a new scope with the same content as this one. */ - def cloneScope(implicit ctx: Context): Scope = newScopeWith(this.toList: _*) - - /** is the scope empty? */ - override def isEmpty: Boolean = lastEntry eq null + def cloneScope(implicit ctx: Context): MutableScope = newScopeWith(this.toList: _*) /** create and enter a scope entry */ protected def newScopeEntry(sym: Symbol)(implicit ctx: Context): ScopeEntry = { @@ -100,20 +165,14 @@ object Scopes { hashTable(i) = e } - /** enter a symbol - * - * @param sym ... - */ - def enter[T <: Symbol](sym: T)(implicit ctx: Context): T = { + /** enter a symbol in this scope. */ + final def enter[T <: Symbol](sym: T)(implicit ctx: Context): T = { newScopeEntry(sym) sym } - /** enter a symbol, asserting that no symbol with same name exists in scope - * - * @param sym ... - */ - def enterUnique(sym: Symbol)(implicit ctx: Context) { + /** enter a symbol, asserting that no symbol with same name exists in scope */ + final def enterUnique(sym: Symbol)(implicit ctx: Context) { assert(lookup(sym.name) == NoSymbol, (sym.showLocated, lookup(sym.name).showLocated)) enter(sym) } @@ -146,7 +205,7 @@ object Scopes { } /** remove entry from this scope. */ - def unlink(e: ScopeEntry)(implicit ctx: Context) { + final def unlink(e: ScopeEntry)(implicit ctx: Context) { if (lastEntry == e) { lastEntry = e.prev } else { @@ -169,7 +228,7 @@ object Scopes { } /** remove symbol from this scope */ - def unlink(sym: Symbol)(implicit ctx: Context) { + final def unlink(sym: Symbol)(implicit ctx: Context) { var e = lookupEntry(sym.name) while (e ne null) { if (e.sym == sym) unlink(e); @@ -177,41 +236,12 @@ object Scopes { } } - /** lookup a symbol - * - * @param name ... - * @return ... - */ - def lookup(name: Name)(implicit ctx: Context): Symbol = { - val e = lookupEntry(name) - if (e eq null) NoSymbol else e.sym - } - - /** Returns an iterator yielding every symbol with given name in this scope. - */ - def lookupAll(name: Name)(implicit ctx: Context): 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 } - } - - /** The denotation set of all the symbols with given name in this scope */ - def denotsNamed(name: Name)(implicit ctx: Context): PreDenotation = { - var syms: PreDenotation = NoDenotation - var e = lookupEntry(name) - while (e != null) { - syms = syms union e.sym.denot - e = lookupNextEntry(e) - } - syms - } - /** lookup a symbol entry matching given name. * @note from Martin: I believe this is a hotspot or will be one * in future versions of the type system. I have reverted the previous * change to use iterators as too costly. */ - def lookupEntry(name: Name)(implicit ctx: Context): ScopeEntry = { + override final def lookupEntry(name: Name)(implicit ctx: Context): ScopeEntry = { var e: ScopeEntry = null if (hashTable ne null) { e = hashTable(name.start & (hashTable.length - 1)) @@ -228,7 +258,7 @@ object Scopes { } /** lookup next entry with same name as this one */ - def lookupNextEntry(entry: ScopeEntry)(implicit ctx: Context): ScopeEntry = { + override final def lookupNextEntry(entry: ScopeEntry)(implicit ctx: Context): ScopeEntry = { var e = entry if (hashTable ne null) do { e = e.tail } while ((e ne null) && e.sym.name != entry.sym.name) @@ -239,7 +269,7 @@ object Scopes { /** Return all symbols as a list in the order they were entered in this scope. */ - override def toList: List[Symbol] = { + override final def toList: List[Symbol] = { if (elemsCache eq null) { elemsCache = Nil var e = lastEntry @@ -253,54 +283,54 @@ object Scopes { /** Vanilla scope - symbols are stored in declaration order. */ - def sorted: List[Symbol] = toList - - /** Return all symbols as an iterator in the order they were entered in this scope. - */ - def iterator: Iterator[Symbol] = toList.iterator + final def sorted: List[Symbol] = toList override def foreach[U](p: Symbol => U): Unit = toList foreach p - def filteredScope(p: Symbol => Boolean)(implicit ctx: Context): Scope = { + final def filteredScope(p: Symbol => Boolean)(implicit ctx: Context): MutableScope = { val unfiltered = toList val filtered = unfiltered filterConserve p if (filtered eq unfiltered) this else newScopeWith(filtered: _*) } - def show(implicit ctx: Context): String = ctx.show(this) + final def show(implicit ctx: Context): String = ctx.show(this) } /** Create a new scope */ - def newScope: Scope = new Scope() + def newScope: MutableScope = new MutableScope() /** Create a new scope nested in another one with which it shares its elements */ - def newNestedScope(outer: Scope)(implicit ctx: Context): Scope = new Scope(outer) + def newNestedScope(outer: Scope)(implicit ctx: Context): MutableScope = new MutableScope(outer) /** Create a new scope with given initial elements */ - def newScopeWith(elems: Symbol*)(implicit ctx: Context): Scope = { + def newScopeWith(elems: Symbol*)(implicit ctx: Context): MutableScope = { val scope = newScope elems foreach scope.enter scope } /** Create new scope for the members of package `pkg` */ - def newPackageScope(pkgClass: Symbol): Scope = newScope + 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 */ - def scopeTransform(owner: Symbol)(op: => Scope): Scope = op + def scopeTransform(owner: Symbol)(op: => MutableScope): MutableScope = op /** The empty scope (immutable). */ object EmptyScope extends Scope { - override def newScopeEntry(sym: Symbol)(implicit ctx: Context): ScopeEntry = { - throw new AssertionError("EmptyScope.newScopeEntry") - } + override def lastEntry = null + override def size = 0 + override def nestingLevel = 0 + override def toList = Nil + override def cloneScope(implicit ctx: Context): Scope = this + override def lookupEntry(name: Name)(implicit ctx: Context): ScopeEntry = null + override def lookupNextEntry(entry: ScopeEntry)(implicit ctx: Context): ScopeEntry = null } /** The error scope (mutable) */ - class ErrorScope(owner: Symbol) extends Scope + class ErrorScope(owner: Symbol) extends MutableScope } diff --git a/src/dotty/tools/dotc/core/SymDenotations.scala b/src/dotty/tools/dotc/core/SymDenotations.scala index 975c4d6f1..144432245 100644 --- a/src/dotty/tools/dotc/core/SymDenotations.scala +++ b/src/dotty/tools/dotc/core/SymDenotations.scala @@ -722,7 +722,7 @@ object SymDenotations { */ def enter(sym: Symbol)(implicit ctx: Context) = { require(!(this is Frozen)) - info.decls enter sym + info.decls.openForMutations.enter(sym) if (_definedFingerPrint != null) includeName(_definedFingerPrint, sym.name) if (_memberCache != null) @@ -735,7 +735,7 @@ object SymDenotations { */ def delete(sym: Symbol)(implicit ctx: Context) = { require(!(this is Frozen)) - info.decls unlink sym + info.decls.openForMutations.unlink(sym) if (_definedFingerPrint != null) computeDefinedFingerPrint if (_memberCache != null) diff --git a/src/dotty/tools/dotc/core/SymbolLoaders.scala b/src/dotty/tools/dotc/core/SymbolLoaders.scala index 59835beda..9559db68a 100644 --- a/src/dotty/tools/dotc/core/SymbolLoaders.scala +++ b/src/dotty/tools/dotc/core/SymbolLoaders.scala @@ -20,7 +20,7 @@ class SymbolLoaders { protected def enterIfNew(owner: Symbol, member: Symbol, completer: SymbolLoader)(implicit ctx: Context): Symbol = { assert(owner.info.decls.lookup(member.name) == NoSymbol, owner.fullName + "." + member.name) - owner.info.decls enter member + owner.asClass.enter(member) member } @@ -57,7 +57,7 @@ class SymbolLoaders { else if (ctx.settings.termConflict.value == "package") { ctx.warning( s"Resolving package/object name conflict in favor of package ${preExisting.fullName}. The object will be inaccessible.") - owner.info.decls.unlink(preExisting) + owner.asClass.delete(preExisting) } else { ctx.warning( s"Resolving package/object name conflict in favor of object ${preExisting.fullName}. The package will be inaccessible.") diff --git a/src/dotty/tools/dotc/core/Symbols.scala b/src/dotty/tools/dotc/core/Symbols.scala index 2491e2ff9..90b9837ca 100644 --- a/src/dotty/tools/dotc/core/Symbols.scala +++ b/src/dotty/tools/dotc/core/Symbols.scala @@ -318,7 +318,7 @@ object Symbols { def superId: Int = -1 final def entered(implicit ctx: Context): this.type = { - this.owner.info.decls.enter(this) + this.owner.asClass.enter(this) this } diff --git a/src/dotty/tools/dotc/core/TypeOps.scala b/src/dotty/tools/dotc/core/TypeOps.scala index a8c9af32d..6628aa824 100644 --- a/src/dotty/tools/dotc/core/TypeOps.scala +++ b/src/dotty/tools/dotc/core/TypeOps.scala @@ -197,7 +197,7 @@ trait TypeOps { this: Context => * to a list of typerefs, by converting all refinements to member * definitions in scope `decls`. Can add members to `decls` as a side-effect. */ - def normalizeToRefs(parents: List[Type], cls: ClassSymbol, decls: Scope): List[TypeRef] = { + def normalizeToRefs(parents: List[Type], cls: ClassSymbol, decls: MutableScope): List[TypeRef] = { var refinements = Map[TypeName, Type]() var formals = Map[TypeName, Symbol]() def normalizeToRef(tp: Type): TypeRef = tp match { diff --git a/src/dotty/tools/dotc/core/pickling/ClassfileParser.scala b/src/dotty/tools/dotc/core/pickling/ClassfileParser.scala index 685ece6cb..5fbafb431 100644 --- a/src/dotty/tools/dotc/core/pickling/ClassfileParser.scala +++ b/src/dotty/tools/dotc/core/pickling/ClassfileParser.scala @@ -26,8 +26,8 @@ class ClassfileParser( protected val staticModule: Symbol = moduleRoot.sourceModule - protected val instanceScope: Scope = newScope // the scope of all instance definitions - protected val staticScope: Scope = newScope // the scope of all static definitions + protected val instanceScope: MutableScope = newScope // the scope of all instance definitions + protected val staticScope: MutableScope = newScope // the scope of all static definitions protected var pool: ConstantPool = _ // the classfile's constant pool protected var currentClassName: Name = _ // JVM name of the current class @@ -707,7 +707,7 @@ class ClassfileParser( protected def getOwner(flags: Int): Symbol = if (isStatic(flags)) moduleRoot.symbol else classRoot.symbol - protected def getScope(flags: Int): Scope = + protected def getScope(flags: Int): MutableScope = if (isStatic(flags)) staticScope else instanceScope private def setPrivateWithin(denot: SymDenotation, jflags: Int) { diff --git a/src/dotty/tools/dotc/core/pickling/UnPickler.scala b/src/dotty/tools/dotc/core/pickling/UnPickler.scala index 9edc8cb84..55ed9b63d 100644 --- a/src/dotty/tools/dotc/core/pickling/UnPickler.scala +++ b/src/dotty/tools/dotc/core/pickling/UnPickler.scala @@ -24,7 +24,7 @@ object UnPickler { case class TempPolyType(tparams: List[Symbol], tpe: Type) extends UncachedGroundType /** Temporary type for classinfos, will be decomposed on completion of the class */ - case class TempClassInfoType(parentTypes: List[Type], decls: Scope, clazz: Symbol) extends UncachedGroundType + case class TempClassInfoType(parentTypes: List[Type], decls: MutableScope, clazz: Symbol) extends UncachedGroundType def depoly(tp: Type)(implicit ctx: Context): Type = tp match { case TempPolyType(tparams, restpe) => PolyType.fromSymbols(tparams, restpe) @@ -356,7 +356,7 @@ class UnPickler(bytes: Array[Byte], classRoot: ClassDenotation, moduleRoot: Clas isUnpickleRoot(sym) || (sym is (ModuleClass | TypeParam | Scala2Existential)) || isRefinementClass(sym))) - symScope(sym.owner) enter sym + symScope(sym.owner).openForMutations.enter(sym) sym } @@ -519,7 +519,7 @@ class UnPickler(bytes: Array[Byte], classRoot: ClassDenotation, moduleRoot: Clas } case CLASSINFOtpe => val clazz = readSymbolRef() - TempClassInfoType(until(end, readTypeRef), symScope(clazz), clazz) + TempClassInfoType(until(end, readTypeRef), symScope(clazz).openForMutations, clazz) case METHODtpe | IMPLICITMETHODtpe => val restpe = readTypeRef() val params = until(end, readSymbolRef) |