aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2012-12-16 17:39:54 +0100
committerMartin Odersky <odersky@gmail.com>2012-12-16 17:39:54 +0100
commit145bab8190f904c9ee2df820491043436b2fdf36 (patch)
tree85575bfd498b55dd4ac524cfdc9182399a691a65 /src
parent3468813082f035fef9984d480fd01e74a65028a0 (diff)
downloaddotty-145bab8190f904c9ee2df820491043436b2fdf36.tar.gz
dotty-145bab8190f904c9ee2df820491043436b2fdf36.tar.bz2
dotty-145bab8190f904c9ee2df820491043436b2fdf36.zip
Implemented baseClasses and baseTypes (2). Refactored RefinedType and ClassInfoType.
Diffstat (limited to 'src')
-rw-r--r--src/dotty/tools/dotc/core/Contexts.scala1
-rw-r--r--src/dotty/tools/dotc/core/Denotations.scala107
-rw-r--r--src/dotty/tools/dotc/core/DotClass.scala8
-rw-r--r--src/dotty/tools/dotc/core/References.scala38
-rw-r--r--src/dotty/tools/dotc/core/Scopes.scala12
5 files changed, 121 insertions, 45 deletions
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