aboutsummaryrefslogtreecommitdiff
path: root/src/dotty/tools/dotc/core/Denotations.scala
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2012-12-22 18:13:35 +0100
committerMartin Odersky <odersky@gmail.com>2012-12-22 18:13:35 +0100
commit39ab8822039706b88373954a7e39919938d79f6f (patch)
tree2d23e004ccae345357135474303290c7a56c66c8 /src/dotty/tools/dotc/core/Denotations.scala
parent78f0d5a0e0ea477087385277d217d9300c018aa0 (diff)
downloaddotty-39ab8822039706b88373954a7e39919938d79f6f.tar.gz
dotty-39ab8822039706b88373954a7e39919938d79f6f.tar.bz2
dotty-39ab8822039706b88373954a7e39919938d79f6f.zip
Refactored ClassInfoType content back to Denotation. Created separate ClassInfo type, which combines
a prefix with a ClassInfo denotation. That leads to better regularity elsewhere, because now taking the info of a TypeRef will not lose information: If the info is a TypeBounds, the prefix is already taken account in it, and for ClassInfo we now record it explicitly.
Diffstat (limited to 'src/dotty/tools/dotc/core/Denotations.scala')
-rw-r--r--src/dotty/tools/dotc/core/Denotations.scala227
1 files changed, 225 insertions, 2 deletions
diff --git a/src/dotty/tools/dotc/core/Denotations.scala b/src/dotty/tools/dotc/core/Denotations.scala
index 8126ad117..a1ad814ba 100644
--- a/src/dotty/tools/dotc/core/Denotations.scala
+++ b/src/dotty/tools/dotc/core/Denotations.scala
@@ -5,9 +5,12 @@ import Periods._, Contexts._, Symbols._, References._, Names._
import Types._, Flags._, Decorators._
import Scopes.Scope
import collection.mutable
+import collection.immutable.BitSet
trait Denotations { self: Context =>
+ /** A set for hash consing superclass bitsets */
+ private val uniqueBits = new util.HashSet[BitSet]("superbits", 1024)
}
@@ -100,6 +103,228 @@ object Denotations {
def newNameFilter: FingerPrint = new Array[Long](DefinedNamesWords)
}
+ class ClassDenotation(val parents: List[Type], val decls: Scope, val clazz: ClassSymbol) extends Denotation {
+ import NameFilter._
+ import util.LRU8Cache
+
+ def typeParams: List[TypeSymbol] = ???
+
+ private var memberCacheVar: LRU8Cache[Name, RefSet] = null
+
+ private def memberCache: LRU8Cache[Name, RefSet] = {
+ if (memberCacheVar == null) memberCacheVar = new LRU8Cache
+ memberCacheVar
+ }
+
+ private var thisTypeCache: ThisType = null
+
+ def thisType(implicit ctx: Context): Type = {
+ if (thisTypeCache == null)
+ thisTypeCache = ThisType(clazz)
+ thisTypeCache
+ }
+
+ private var typeConstructorCache: Type = null
+
+ def typeConstructor(implicit ctx: Context): Type = {
+ if (typeConstructorCache == null)
+ typeConstructorCache = NamedType(thisType, clazz.name)
+ typeConstructorCache
+ }
+
+ private var typeTemplateCache: Type = null
+
+ def typeTemplate(implicit ctx: Context): Type = {
+ if (typeTemplateCache == null)
+ AppliedType.make(typeConstructor, typeParams map (_.typeConstructor))
+ typeTemplateCache
+ }
+
+ private var baseClassesVar: List[ClassSymbol] = null
+ private var superClassBitsVar: BitSet = null
+
+ private def computeSuperClassBits(implicit ctx: Context): Unit = {
+ val seen = new mutable.BitSet
+ val locked = new mutable.BitSet
+ def addBaseClasses(bcs: List[ClassSymbol], to: List[ClassSymbol])
+ : List[ClassSymbol] = bcs match {
+ case bc :: bcs1 =>
+ val id = bc.superId
+ if (seen contains id) to
+ else if (locked contains id) throw new CyclicReference(clazz)
+ else {
+ locked += id
+ val bcs1added = addBaseClasses(bcs1, to)
+ seen += id
+ if (bcs1added eq bcs1) bcs else bc :: bcs1added
+ }
+ case _ =>
+ to
+ }
+ def addParentBaseClasses(ps: List[Type], to: List[ClassSymbol]): List[ClassSymbol] = ps match {
+ case p :: ps1 =>
+ addBaseClasses(p.baseClasses, addParentBaseClasses(ps1, to))
+ case _ =>
+ to
+ }
+ baseClassesVar = clazz :: addParentBaseClasses(parents, Nil)
+ superClassBitsVar = ctx.root.uniqueBits.findEntryOrUpdate(seen.toImmutable)
+ }
+
+ def superClassBits(implicit ctx: Context): BitSet = {
+ if (superClassBitsVar == null) computeSuperClassBits
+ superClassBitsVar
+ }
+
+ def baseClasses(implicit ctx: Context): List[ClassSymbol] = {
+ if (baseClassesVar == null) computeSuperClassBits
+ baseClassesVar
+ }
+
+ /** Is this class a subclass of `clazz`? */
+ final def isSubClass(clazz: ClassSymbol)(implicit ctx: Context): Boolean = {
+ superClassBits contains clazz.superId
+ }
+
+ private var definedFingerPrintCache: FingerPrint = null
+
+ private def computeDefinedFingerPrint(implicit ctx: Context): FingerPrint = {
+ var bits = newNameFilter
+ var e = decls.lastEntry
+ while (e != null) {
+ includeName(bits, clazz.name)
+ e = e.prev
+ }
+ var ps = parents
+ while (ps.nonEmpty) {
+ val parent = ps.head.typeSymbol
+ parent.deref match {
+ case classd: ClassDenotation =>
+ includeFingerPrint(bits, classd.definedFingerPrint)
+ parent.deref setFlag Frozen
+ case _ =>
+ }
+ ps = ps.tail
+ }
+ definedFingerPrintCache = bits
+ bits
+ }
+
+ /** Enter a symbol in current scope.
+ * Note: We require that this does not happen after the first time
+ * someone does a findMember on a subclass.
+ */
+ def enter(sym: Symbol)(implicit ctx: Context) = {
+ require((clazz.flags & Frozen) == Flags.Empty)
+ decls enter sym
+ if (definedFingerPrintCache != null)
+ includeName(definedFingerPrintCache, sym.name)
+ if (memberCacheVar != null)
+ memberCache invalidate sym.name
+ }
+
+ /** Delete symbol from current scope.
+ * Note: We require that this does not happen after the first time
+ * someone does a findMember on a subclass.
+ */
+ def delete(sym: Symbol)(implicit ctx: Context) = {
+ require((clazz.flags & Frozen) == Flags.Empty)
+ decls unlink sym
+ if (definedFingerPrintCache != null)
+ computeDefinedFingerPrint
+ if (memberCacheVar != null)
+ memberCache invalidate sym.name
+ }
+
+ def definedFingerPrint(implicit ctx: Context): FingerPrint = {
+ val fp = definedFingerPrintCache
+ if (fp != null) fp else computeDefinedFingerPrint
+ }
+
+ final def memberRefsNamed(name: Name)(implicit ctx: Context): RefSet = {
+ var refs: RefSet = memberCache lookup name
+ if (refs == null) {
+ if (containsName(definedFingerPrint, name)) {
+ val ownRefs = decls.refsNamed(name)
+ refs = ownRefs
+ var ps = parents
+ while (ps.nonEmpty) {
+ val parentSym = ps.head.typeSymbol
+ parentSym.deref match {
+ case parentd: ClassDenotation =>
+ refs = refs union
+ parentd.memberRefsNamed(name)
+ .filterExcluded(Flags.Private)
+ .asSeenFrom(thisType, parentSym)
+ .filterDisjoint(ownRefs)
+ case _ =>
+ }
+ }
+ } else {
+ refs = NoRef
+ }
+ memberCache enter (name, refs)
+ }
+ refs
+ }
+
+ private var baseTypeCache: java.util.HashMap[UniqueType, Type] = null
+
+ final def baseTypeOf(tp: Type)(implicit ctx: Context): Type = {
+
+ def computeBaseTypeOf(tp: Type): Type = tp match {
+ case AppliedType(tycon, args) =>
+ baseTypeOf(tycon).subst(tycon.typeParams, args)
+ case tp: TypeProxy =>
+ baseTypeOf(tp.underlying)
+ case AndType(tp1, tp2) =>
+ baseTypeOf(tp1) & baseTypeOf(tp2)
+ case OrType(tp1, tp2) =>
+ baseTypeOf(tp1) | baseTypeOf(tp2)
+ case tp @ ClassInfo(pre, classd) =>
+ def reduce(bt: Type, ps: List[Type]): Type = ps match {
+ case p :: ps1 => reduce(bt & baseTypeOf(p), ps1)
+ case _ => bt
+ }
+ if (classd.clazz == clazz) tp.typeTemplate
+ else reduce(NoType, classd.parents).substThis(classd.clazz, tp.prefix)
+ }
+
+ if (clazz.isStatic && clazz.typeParams.isEmpty) clazz.typeConstructor
+ else tp match {
+ case tp: UniqueType =>
+ if (baseTypeCache == null)
+ baseTypeCache = new java.util.HashMap[UniqueType, Type]
+ var basetp = baseTypeCache get tp
+ if (basetp == null) {
+ baseTypeCache.put(tp, NoType)
+ basetp = computeBaseTypeOf(tp)
+ baseTypeCache.put(tp, basetp)
+ } else if (basetp == NoType) {
+ throw new CyclicReference(clazz)
+ }
+ basetp
+ case _ =>
+ computeBaseTypeOf(tp)
+ }
+ }
+
+ private var memberNamesCache: Map[NameFilter, Set[Name]] = Map()
+
+ def memberNames(pre: Type, filter: NameFilter)(implicit ctx: Context): Set[Name] =
+ memberNamesCache get filter match {
+ case Some(names) =>
+ names
+ case _ =>
+ val inheritedNames = (parents flatMap (_.memberNames(thisType, filter))).toSet
+ val ownNames = decls.iterator map (_.name)
+ val candidates = inheritedNames ++ ownNames
+ val names = candidates filter (filter(thisType, _))
+ memberNamesCache += (filter -> names)
+ names
+ }
+ }
+
object NoDenotation extends Denotation {
override def owner: Symbol = throw new AssertionError("NoDenotation.owner")
override def name: Name = BootNameTable.newTermName("<none>")
@@ -107,6 +332,4 @@ object Denotations {
override def tpe: Type = NoType
override def info: Type = NoType
}
-
-
} \ No newline at end of file