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
}
}