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/Symbols.scala | 275 ++++++++++++++++++++++++++++++++ 1 file changed, 275 insertions(+) create mode 100644 src/dotty/tools/dotc/core/Symbols.scala (limited to 'src/dotty/tools/dotc/core/Symbols.scala') diff --git a/src/dotty/tools/dotc/core/Symbols.scala b/src/dotty/tools/dotc/core/Symbols.scala new file mode 100644 index 000000000..52cc29603 --- /dev/null +++ b/src/dotty/tools/dotc/core/Symbols.scala @@ -0,0 +1,275 @@ +package dotty.tools.dotc +package core + +import Periods._ +import DenotationTransformers._ +import Names._ +import java.lang.AssertionError +import Decorators._ +import Symbols._ +import Contexts._ +import Denotations._ +import Types._ +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: RefType): Symbol = ref match { + case ref: SymRef => ref.symbol + case OverloadedType(variants) => relink(variants(refType.signature)) + } + 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 refType(implicit ctx: Context): SymRef = SymRef(owner.thisType, this) + + // 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): Long = 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 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: Long)(implicit ctx: Context): Boolean = (flags & required) != 0 + def hasAllFlags(required: Long)(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 + + override def deref(implicit ctx: Context): ClassDenotation = ??? + + 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 + } +} \ No newline at end of file -- cgit v1.2.3