From 145bab8190f904c9ee2df820491043436b2fdf36 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Sun, 16 Dec 2012 17:39:54 +0100 Subject: Implemented baseClasses and baseTypes (2). Refactored RefinedType and ClassInfoType. --- src/dotty/tools/dotc/core/Contexts.scala | 1 + src/dotty/tools/dotc/core/Denotations.scala | 107 +++++++++++++++++++++------- src/dotty/tools/dotc/core/DotClass.scala | 8 +++ src/dotty/tools/dotc/core/References.scala | 38 +++++----- src/dotty/tools/dotc/core/Scopes.scala | 12 ++++ 5 files changed, 121 insertions(+), 45 deletions(-) create mode 100644 src/dotty/tools/dotc/core/DotClass.scala (limited to 'src') diff --git a/src/dotty/tools/dotc/core/Contexts.scala b/src/dotty/tools/dotc/core/Contexts.scala index b13594f0b..d1f307861 100644 --- a/src/dotty/tools/dotc/core/Contexts.scala +++ b/src/dotty/tools/dotc/core/Contexts.scala @@ -17,6 +17,7 @@ object Contexts { val period: Period def names: NameTable def phase: Phase = ??? + def stableInterval: Interval = ??? } diff --git a/src/dotty/tools/dotc/core/Denotations.scala b/src/dotty/tools/dotc/core/Denotations.scala index 7f2eb0924..d7904d977 100644 --- a/src/dotty/tools/dotc/core/Denotations.scala +++ b/src/dotty/tools/dotc/core/Denotations.scala @@ -106,12 +106,10 @@ object Denotations { def newNameFilter: FingerPrint = new Array[Long](DefinedNamesWords) } - class ClassDenotation(parents: List[Type], decls: Scope) extends Denotation { + class ClassDenotation(val parents: List[Type], val decls: Scope, clazz: ClassSymbol) extends Denotation { import NameFilter._ - lazy val baseClasses: List[ClassSymbol] = ??? - private var memberCacheVar: LRU8Cache[Name, RefSet] = null private def memberCache: LRU8Cache[Name, RefSet] = { @@ -121,19 +119,45 @@ object Denotations { def thisType: Type = ??? - private var superClassBitsCache: BitSet = null - - private def computeSuperClassBits(implicit ctx: Context): BitSet = { - val b = BitSet.newBuilder - for (bc <- baseClasses) b += bc.superId - val bits = ctx.root.uniqueBits.findEntryOrUpdate(b.result()) - superClassBitsCache = bits - bits + 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 = { - val bits = superClassBitsCache - if (bits != null) bits else computeSuperClassBits + if (superClassBitsVar == null) computeSuperClassBits + superClassBitsVar + } + + def baseClasses(implicit ctx: Context): List[ClassSymbol] = { + if (baseClassesVar == null) computeSuperClassBits + baseClassesVar } /** Is this class a subclass of `clazz`? */ @@ -192,21 +216,11 @@ object Denotations { if (fp != null) fp else computeDefinedFingerPrint } - final def declsNamed(name: Name)(implicit ctx: Context): RefSet = { - var syms: RefSet = NoRef - var e = decls lookupEntry name - while (e != null) { - syms = syms union e.sym.thisRef - e = decls lookupNextEntry e - } - syms - } - final def memberRefsNamed(name: Name)(implicit ctx: Context): RefSet = { var refs: RefSet = memberCache lookup name if (refs == null) { if (containsName(definedFingerPrint, name)) { - val ownRefs = declsNamed(name) + val ownRefs = decls.refsNamed(name) refs = ownRefs var ps = parents val ownType = thisType @@ -227,6 +241,51 @@ object Denotations { } 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 tp: NamedType => + val sym = tp.symbol + val bt = baseTypeOf(tp.info) + if (sym.isClass) bt.substThis(sym.asClass, tp.prefix) + else bt + case AppliedType(tycon, args) => + baseTypeOf(tycon).subst(tycon.typeParams, args) + case AndType(tp1, tp2) => + baseTypeOf(tp1) & baseTypeOf(tp2) + case OrType(tp1, tp2) => + baseTypeOf(tp1) | baseTypeOf(tp2) + case tp @ ClassInfoType(clazz) => + def reduce(bt: Type, ps: List[Type]): Type = ps match { + case p :: ps1 => reduce(bt & baseTypeOf(p), ps1) + case _ => bt + } + reduce(NoType, tp.parents) + case tp: TypeProxy => + baseTypeOf(tp.underlying) + } + + if (clazz.isStatic && clazz.typeParams.isEmpty) clazz.tpe + 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) + } + } } object NoDenotation extends Denotation { diff --git a/src/dotty/tools/dotc/core/DotClass.scala b/src/dotty/tools/dotc/core/DotClass.scala new file mode 100644 index 000000000..fee7d5ac3 --- /dev/null +++ b/src/dotty/tools/dotc/core/DotClass.scala @@ -0,0 +1,8 @@ +package dotty.tools.dotc.core + +class DotClass { + + def unsupported(methodName: String): Nothing = + throw new UnsupportedOperationException(s"$getClass.$methodName") + +} \ No newline at end of file diff --git a/src/dotty/tools/dotc/core/References.scala b/src/dotty/tools/dotc/core/References.scala index 0922a2e2e..046fc24a7 100644 --- a/src/dotty/tools/dotc/core/References.scala +++ b/src/dotty/tools/dotc/core/References.scala @@ -83,8 +83,6 @@ object References { def exists: Boolean = true - def isValid(implicit ctx: Context): Boolean - /** Form a reference by conjoining with reference `that` */ def & (that: Reference)(implicit ctx: Context): Reference = if (this eq that) this @@ -111,7 +109,7 @@ object References { val SymRef(sym2, info2) = ref2 def isEligible(sym1: Symbol, sym2: Symbol) = if (sym1.isType) !sym1.isClass - else sym1.isConcrete || sym2.isDeferred + else sym1.isConcrete || sym2.isDeferred || !sym2.exists def normalize(info: Type) = if (isType) info.bounds else info val sym1Eligible = isEligible(sym1, sym2) @@ -165,7 +163,6 @@ object References { case class OverloadedRef(ref1: Reference, ref2: Reference) extends Reference { def derivedOverloadedRef(r1: Reference, r2: Reference) = if ((r1 eq ref1) && (r2 eq ref2)) this else OverloadedRef(r1, r2) - def isValid(implicit ctx: Context) = ref1.isValid && ref2.isValid } abstract case class SymRef(override val symbol: Symbol, @@ -191,12 +188,13 @@ object References { // ------ RefSet ops ---------------------------------------------- + def toRef(implicit ctx: Context) = this def containsSig(sig: Signature)(implicit ctx: Context) = signature == sig def filter(p: Symbol => Boolean)(implicit ctx: Context): RefSet = if (p(symbol)) this else NoRef - def filterDisjoint(syms: RefSet)(implicit ctx: Context): RefSet = - if (syms.containsSig(signature)) NoRef else this + def filterDisjoint(refs: RefSet)(implicit ctx: Context): RefSet = + if (refs.containsSig(signature)) NoRef else this def filterExcluded(flags: FlagSet)(implicit ctx: Context): RefSet = if (symbol.hasFlag(flags)) NoRef else this def filterAccessibleFrom(pre: Type)(implicit ctx: Context): RefSet = @@ -208,32 +206,29 @@ object References { class UniqueSymRef(symbol: Symbol, info: Type)(implicit ctx: Context) extends SymRef(symbol, info) { private val denot = symbol.deref private val runid = ctx.runId - def isValid(implicit ctx: Context) = ctx.runId == runid && (symbol.deref eq denot) override protected def copy(s: Symbol, i: Type): SymRef = new UniqueSymRef(s, i) } class JointSymRef(symbol: Symbol, info: Type)(implicit ctx: Context) extends SymRef(symbol, info) { private val period = ctx.period - def isValid(implicit ctx: Context) = ctx.period == period override protected def copy(s: Symbol, i: Type): SymRef = new JointSymRef(s, i) } object ErrorRef extends SymRef(NoSymbol, NoType) { - def isValid(implicit ctx: Context): Boolean = true } object NoRef extends SymRef(NoSymbol, NoType) { override def exists = false - def isValid(implicit ctx: Context): Boolean = true } // --------------- RefSets ------------------------------------------------- trait RefSet { def exists: Boolean + def toRef(implicit ctx: Context): Reference def containsSig(sig: Signature)(implicit ctx: Context): Boolean def filter(p: Symbol => Boolean)(implicit ctx: Context): RefSet - def filterDisjoint(syms: RefSet)(implicit ctx: Context): RefSet + def filterDisjoint(refs: RefSet)(implicit ctx: Context): RefSet def filterExcluded(flags: FlagSet)(implicit ctx: Context): RefSet def filterAccessibleFrom(pre: Type)(implicit ctx: Context): RefSet def asSeenFrom(pre: Type, owner: Symbol)(implicit ctx: Context): RefSet @@ -243,26 +238,27 @@ object References { else RefUnion(this, that) } - case class RefUnion(syms1: RefSet, syms2: RefSet) extends RefSet { - assert(syms1.exists && !syms2.exists) + case class RefUnion(refs1: RefSet, refs2: RefSet) extends RefSet { + assert(refs1.exists && !refs2.exists) private def derivedUnion(s1: RefSet, s2: RefSet) = if (!s1.exists) s2 else if (!s2.exists) s1 - else if ((s1 eq syms2) && (s2 eq syms2)) this + else if ((s1 eq refs2) && (s2 eq refs2)) this else new RefUnion(s1, s2) def exists = true + def toRef(implicit ctx: Context) = refs1.toRef & refs2.toRef def containsSig(sig: Signature)(implicit ctx: Context) = - (syms1 containsSig sig) || (syms2 containsSig sig) + (refs1 containsSig sig) || (refs2 containsSig sig) def filter(p: Symbol => Boolean)(implicit ctx: Context) = - derivedUnion(syms1 filter p, syms2 filter p) - def filterDisjoint(syms: RefSet)(implicit ctx: Context): RefSet = - derivedUnion(syms1 filterDisjoint syms, syms2 filterDisjoint syms) + derivedUnion(refs1 filter p, refs2 filter p) + def filterDisjoint(refs: RefSet)(implicit ctx: Context): RefSet = + derivedUnion(refs1 filterDisjoint refs, refs2 filterDisjoint refs) def filterExcluded(flags: FlagSet)(implicit ctx: Context): RefSet = - derivedUnion(syms1 filterExcluded flags, syms2 filterExcluded flags) + derivedUnion(refs1 filterExcluded flags, refs2 filterExcluded flags) def filterAccessibleFrom(pre: Type)(implicit ctx: Context): RefSet = - derivedUnion(syms1 filterAccessibleFrom pre, syms2 filterAccessibleFrom pre) + derivedUnion(refs1 filterAccessibleFrom pre, refs2 filterAccessibleFrom pre) def asSeenFrom(pre: Type, owner: Symbol)(implicit ctx: Context): RefSet = - derivedUnion(syms1.asSeenFrom(pre, owner), syms2.asSeenFrom(pre, owner)) + derivedUnion(refs1.asSeenFrom(pre, owner), refs2.asSeenFrom(pre, owner)) } } diff --git a/src/dotty/tools/dotc/core/Scopes.scala b/src/dotty/tools/dotc/core/Scopes.scala index cc50e9072..e3d3c29ce 100644 --- a/src/dotty/tools/dotc/core/Scopes.scala +++ b/src/dotty/tools/dotc/core/Scopes.scala @@ -11,6 +11,7 @@ import Names._ import Periods._ import Decorators._ import Contexts._ +import References._ object Scopes { @@ -193,6 +194,17 @@ object Scopes { def next(): Symbol = { val r = e.sym; e = lookupNextEntry(e); r } } + /** The reference set of all the symbols with given name in this scope */ + def refsNamed(name: Name)(implicit ctx: Context): RefSet = { + var syms: RefSet = NoRef + var e = lookupEntry(name) + while (e != null) { + syms = syms union e.sym.thisRef + 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 -- cgit v1.2.3