From 90962407e72d88f8f3249ade0f6bd60ff15af5ce Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Thu, 6 Dec 2012 14:06:00 +0100 Subject: Initial commit --- src/dotty/tools/dotc/core/Denotations.scala | 241 ++++++++++++++++++++++++++++ 1 file changed, 241 insertions(+) create mode 100644 src/dotty/tools/dotc/core/Denotations.scala (limited to 'src/dotty/tools/dotc/core/Denotations.scala') 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("") + override def flags: Long = 0 + override def tpe: Type = NoType + override def info: Type = NoType + } + + +} \ No newline at end of file -- cgit v1.2.3