aboutsummaryrefslogtreecommitdiff
path: root/src/dotty/tools/dotc/core/Denotations.scala
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2012-12-06 14:06:00 +0100
committerMartin Odersky <odersky@gmail.com>2012-12-06 14:06:00 +0100
commit90962407e72d88f8f3249ade0f6bd60ff15af5ce (patch)
tree6b2fc0ba13bad7c4532ebf1df39b0b2f5d7e70b6 /src/dotty/tools/dotc/core/Denotations.scala
parent2308509d2651ee78e1122b5d61b798c984c96c4d (diff)
downloaddotty-90962407e72d88f8f3249ade0f6bd60ff15af5ce.tar.gz
dotty-90962407e72d88f8f3249ade0f6bd60ff15af5ce.tar.bz2
dotty-90962407e72d88f8f3249ade0f6bd60ff15af5ce.zip
Initial commit
Diffstat (limited to 'src/dotty/tools/dotc/core/Denotations.scala')
-rw-r--r--src/dotty/tools/dotc/core/Denotations.scala241
1 files changed, 241 insertions, 0 deletions
diff --git a/src/dotty/tools/dotc/core/Denotations.scala b/src/dotty/tools/dotc/core/Denotations.scala
new file mode 100644
index 000000000..aa3768a99
--- /dev/null
+++ b/src/dotty/tools/dotc/core/Denotations.scala
@@ -0,0 +1,241 @@
+package dotty.tools.dotc
+package core
+
+import Periods._, Contexts._, Symbols._, RefSets._, Names._
+import Types._, Flags._, Decorators._
+import Scopes.Scope
+import collection.immutable.BitSet
+import collection.mutable
+import util.LRU8Cache
+
+trait Denotations { self: Context =>
+
+ /** A set for hash consing superclass bitsets */
+ private val uniqueBits = new util.HashSet[BitSet]("superbits", 1024)
+
+}
+
+object Denotations {
+
+ abstract class Denotation {
+
+ /** The validity interval of this symbol */
+ var valid: Interval = Nowhere
+
+ /** The next instance of this symbol in the same run */
+ private[core] var nextInRun: Denotation = this
+
+ /**
+ * The version of this symbol that was valid in the first phase
+ * of this run
+ */
+ def initial: Denotation = {
+ var sym = nextInRun
+ while (sym.valid > this.valid) sym = sym.nextInRun
+ sym
+ }
+
+ def owner: Symbol = ???
+
+ def name: Name = ???
+
+ def flags: Long = ???
+
+ def setFlag(flag: Long): Unit = ???
+
+ def tpe: Type = ???
+
+ def info: Type = ???
+
+ /* Validity and instance handling:
+ *
+ * Symbols have an interval of validity, defined
+ * by their `valid` fields.
+ *
+ * There may be several symbols with different validity
+ * representing the same underlying symbol at different phases.
+ * These are called a "flock". Flock members are generated by
+ * @see SymRef.trackSym. Flock members are connected in a ring
+ * with their `nextInFlock` fields.
+ *
+ * There are the following invariants converning flock members
+ *
+ * 1) validity intervals must be non-overlapping
+ * 2) the union of all validity intervals must be a contiguous
+ * interval starting in FirstPhaseId.
+ */
+
+ /** is this symbol a type? */
+ def isType: Boolean = false
+
+ /** is this symbol a class? */
+ def isClass: Boolean = false
+
+ /** is this symbol a method? */
+ def isMethod: Boolean = false
+
+ /** is this symbol the result of an erroneous definition? */
+ def isError: Boolean = false
+
+ def asClass: ClassDenotation = ???
+
+ def withType(tp: Type): Denotation = ???
+ }
+
+ object NameFilter {
+ final val WordSizeLog = 6
+ final val DefinedNamesWords = 16
+ final val DefinedNamesSize = DefinedNamesWords << WordSizeLog
+ final val DefinedNamesMask = DefinedNamesSize - 1
+
+ type FingerPrint = Array[Long]
+
+ def includeName(bits: FingerPrint, name: Name): Unit = {
+ val hash = name.start & DefinedNamesMask
+ bits(hash >> 6) |= (1 << hash)
+ }
+
+ def includeFingerPrint(bits1: FingerPrint, bits2: FingerPrint): Unit =
+ for (i <- 0 until DefinedNamesWords) bits1(i) |= bits2(i)
+
+ def containsName(bits: FingerPrint, name: Name): Boolean = {
+ val hash = name.start & DefinedNamesMask
+ (bits(hash >> 6) & (1 << hash)) != 0
+ }
+
+ def newNameFilter: FingerPrint = new Array[Long](DefinedNamesWords)
+ }
+
+ class ClassDenotation(parents: List[Type], decls: Scope) extends Denotation {
+
+ import NameFilter._
+
+ lazy val baseClasses: List[ClassSymbol] = ???
+
+ private var memberCacheVar: LRU8Cache[Name, RefSet] = null
+
+ private def memberCache: LRU8Cache[Name, RefSet] = {
+ if (memberCacheVar == null) memberCacheVar = new LRU8Cache
+ memberCacheVar
+ }
+
+ 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
+ }
+
+ def superClassBits(implicit ctx: Context): BitSet = {
+ val bits = superClassBitsCache
+ if (bits != null) bits else computeSuperClassBits
+ }
+
+ /** 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, name)
+ e = e.prev
+ }
+ var ps = parents
+ while (ps.nonEmpty) {
+ val parent = ps.head.typeSymbol.asClass.deref
+ includeFingerPrint(bits, parent.definedFingerPrint)
+ parent setFlag Frozen
+ 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((flags & Frozen) == 0)
+ 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((flags & Frozen) == 0)
+ 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 declsNamed(name: Name)(implicit ctx: Context): RefSet = {
+ var syms: RefSet = NoType
+ var e = decls lookupEntry name
+ while (e != null) {
+ syms = syms union e.sym.refType
+ 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)
+ refs = ownRefs
+ var ps = parents
+ val ownType = thisType
+ while (ps.nonEmpty) {
+ val parentSym = ps.head.typeSymbol.asClass
+ val parent = parentSym.deref
+ refs = refs union
+ parent.memberRefsNamed(name)
+ .filterExcluded(Flags.Private)
+ .seenFrom(thisType, parentSym)
+ .filterDisjoint(ownRefs)
+ ps = ps.tail
+ }
+ } else {
+ refs = NoType
+ }
+ memberCache enter (name, refs)
+ }
+ refs
+ }
+ }
+
+ object NoDenotation extends Denotation {
+ override def owner: Symbol = throw new AssertionError("NoDenotation.owner")
+ override def name: Name = BootNameTable.newTermName("<none>")
+ override def flags: Long = 0
+ override def tpe: Type = NoType
+ override def info: Type = NoType
+ }
+
+
+} \ No newline at end of file