|
|
package dotty.tools.dotc
package core
import Periods._
import DenotationTransformers._
import Names._
import Flags._
import java.lang.AssertionError
import Decorators._
import Symbols._
import Contexts._
import Denotations._
import Types._
import References.{Reference, SymRef, UniqueSymRef, OverloadedRef}
import collection.mutable
trait Symbols { self: Context =>
import Symbols._
// Infrastructure to assign unique superclass idents to class symbols that are superclasses of
// some other class
private final val InitialSuperIdsSize = 4096
/** A map from a superclass id to the class that has it */
private var classOfId = Array.ofDim[ClassSymbol](InitialSuperIdsSize)
/** A map from a superclass to its superclass id */
private val superIdOfClass = new mutable.HashMap[ClassSymbol, Int]
/** The last allocate superclass id */
private var lastSuperId = -1
/** Allocate and return next free superclass id */
private def nextSuperId: Int = { lastSuperId += 1; lastSuperId }
}
object Symbols {
/**
* A SymRef is a period-dependent reference to a denotation.
* Given a period, its `deref` method resolves to a Symbol.
*/
abstract class Symbol {
def overriddenSymbol(inclass: ClassSymbol)(implicit ctx: Context): Symbol =
if (owner isSubClass inclass) ???
else NoSymbol
def isProtected: Boolean = ???
def isStable: Boolean = ???
def accessBoundary: ClassSymbol = ???
def isContainedIn(boundary: ClassSymbol) = ???
def baseClasses: List[ClassSymbol] = ???
def exists = true
def orElse(that: => Symbol) = if (exists) this else that
/** A isAbove B iff A can always be used instead of B
*/
def isAbove(that: Symbol)(implicit ctx: Context): Boolean =
(that.owner isSubClass this.owner) &&
(this isAsAccessible that)
/** A isBelow B iff the reference A & B can always be simplified to A
*/
def isBelow(that: Symbol)(implicit ctx: Context): Boolean =
(this.owner isSubClass that.owner) ||
(this isAsAccessible that)
def isAsAccessible(that: Symbol)(implicit ctx: Context): Boolean =
!this.isProtected && !that.isProtected && // protected members are incomparable
(that.accessBoundary isContainedIn this.accessBoundary) &&
this.isStable || !that.isStable
/** Set the denotation of this symbol.
*/
def setDenotation(denot: Denotation) =
lastDenot = denot
/** The last denotation of this symbol */
protected[this] var lastDenot: Denotation = null
/** Load denotation of this symbol */
protected def loadDenot(implicit ctx: Context): Denotation
/** The denotation of this symbol
*/
def deref(implicit ctx: Context): Denotation = {
val denot = lastDenot
if (denot != null && containsPeriod(denot.valid, ctx.period))
denot
else
trackedDenot
}
/** Get referenced denotation if lastDenot points to a different instance */
private def trackedDenot(implicit ctx: Context): Denotation = {
var denot = lastDenot
if (denot == null) {
denot = loadDenot
} else {
val currentPeriod = ctx.period
val valid = denot.valid
val currentRunId = runIdOf(currentPeriod)
val validRunId = runIdOf(valid)
if (currentRunId != validRunId) {
reloadDenot
} else if (currentPeriod > valid) {
// search for containing interval as long as nextInRun
// increases.
var nextDenot = denot.nextInRun
while (nextDenot.valid > valid && !containsPeriod(nextDenot.valid, currentPeriod)) {
denot = nextDenot
nextDenot = nextDenot.nextInRun
}
if (nextDenot.valid > valid) {
// in this case, containsPeriod(nextDenot.valid, currentPeriod)
denot = nextDenot
} else {
// not found, denot points to highest existing variant
var startPid = lastPhaseIdOf(denot.valid) + 1
val endPid = ctx.root.nextTransformer(startPid + 1).phaseId - 1
nextDenot = ctx.root.nextTransformer(startPid) transform denot
if (nextDenot eq denot)
startPid = firstPhaseIdOf(denot.valid)
else {
denot.nextInRun = nextDenot
denot = nextDenot
}
denot.valid = intervalOf(currentRunId, startPid, endPid)
}
} else {
// currentPeriod < valid; in this case a denotation must exist
do {
denot = denot.nextInRun
} while (!containsPeriod(denot.valid, currentPeriod))
}
}
denot
}
/**
* Get loaded denotation if lastDenot points to a denotation from
* a different run.
*/
private def reloadDenot(implicit ctx: Context): Denotation = {
val initDenot = lastDenot.initial
val newSym: Symbol =
ctx.atPhase(FirstPhaseId) { implicit ctx =>
def relink(ref: Reference): Symbol = ref match {
case ref: SymRef =>
if (ref.signature == thisRef.signature) ref.symbol else NoSymbol
case ref @ OverloadedRef(ref1, ref2) =>
relink(ref1) orElse relink(ref2)
}
relink(initDenot.owner.info.decl(initDenot.name))
}
if (newSym eq this) { // no change, change validity
var d = initDenot
do {
d.valid = intervalOf(ctx.runId, firstPhaseIdOf(d.valid), lastPhaseIdOf(d.valid))
d = d.nextInRun
} while (d ne initDenot)
}
newSym.deref
}
def isType: Boolean
def isTerm = !isType
def thisRef(implicit ctx: Context): SymRef = new UniqueSymRef(this, info)
// forwarders for sym methods
def owner(implicit ctx: Context): Symbol = deref.owner
def name(implicit ctx: Context): Name = deref.name
def flags(implicit ctx: Context): FlagSet = deref.flags
def info(implicit ctx: Context): Type = deref.info
def tpe(implicit ctx: Context): Type = info
def prefix(implicit ctx: Context) = owner.thisType
def allOverriddenSymbols: Iterator[Symbol] = ???
def isAsAccessibleAs(other: Symbol): Boolean = ???
def isAccessibleFrom(pre: Type)(implicit ctx: Context): Boolean = ???
def locationString: String = ???
def locatedFullString: String = ???
def defString: String = ???
def typeParams: List[TypeSymbol] = ???
def thisType: Type = ???
def isStaticMono = isStatic && typeParams.isEmpty
def isPackageClass: Boolean = ???
def isRoot: Boolean = ???
def moduleClass: Symbol = ???
def cloneSymbol: Symbol = ???
def asTerm: TermSymbol = ???
def asType: TypeSymbol = ???
def asClass: ClassSymbol = ???
def isStatic: Boolean = ???
def isTypeParameter: Boolean = ???
def isOverridable: Boolean = ???
def isCovariant: Boolean = ???
def isContravariant: Boolean = ???
def isSkolem: Boolean = ???
def isDeferred: Boolean = ???
def isConcrete = !isDeferred
def isJava: Boolean = ???
def isSubClass(that: Symbol): Boolean = ???
def isNonBottomSubClass(that: Symbol): Boolean = ???
def isProperSubClass(that: Symbol): Boolean =
(this ne that) && (this isSubClass that)
def isAbstractType: Boolean = ???
def newAbstractType(name: TypeName, info: TypeBounds): TypeSymbol = ???
def newAbstractTerm(name: TermName, tpe: Type): TypeSymbol = ???
def isClass: Boolean = false
def isMethod(implicit ctx: Context): Boolean = deref.isMethod
def hasFlag(required: FlagSet)(implicit ctx: Context): Boolean = (flags & required) != Flags.Empty
def hasAllFlags(required: FlagSet)(implicit ctx: Context): Boolean = (flags & required) == flags
}
abstract class TermSymbol extends Symbol {
def name: TermName
def isType = true
}
trait RefinementSymbol extends Symbol {
override def deref(implicit ctx: Context) = lastDenot
}
abstract class RefinementTermSymbol extends TermSymbol with RefinementSymbol
abstract class RefinementTypeSymbol extends TypeSymbol with RefinementSymbol
abstract class TypeSymbol extends Symbol {
def name: TypeName
def isType = false
}
abstract class ClassSymbol extends TypeSymbol {
override def isClass = true
private var superIdHint: Int = -1
def typeOfThis(implicit ctx: Context): Type = ???
/** The unique, densely packed identifier of this class symbol. Should be called
* only if class is a super class of some other class.
*/
def superId(implicit ctx: Context): Int = {
val hint = superIdHint
val rctx = ctx.root
if (hint >= 0 && hint <= rctx.lastSuperId && (rctx.classOfId(hint) eq this)) hint
else {
val id = rctx.superIdOfClass get this match {
case Some(id) =>
id
case None =>
val id = rctx.nextSuperId
rctx.superIdOfClass(this) = id
rctx.classOfId(id) = this
id
}
superIdHint = id
id
}
}
}
object NoSymbol extends Symbol {
def loadDenot(implicit ctx: Context): Denotation = NoDenotation
override def exists = false
def isType = false
}
}
|