From b43de54be5c4d91762d8dc6a4ce7b612935639f9 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Thu, 17 Jan 2013 09:54:05 +0100 Subject: Completed period-tracking in named types. Made Denotation a subtype of symblic referenced and generalized denotation versioning to referenced versioning. --- src/dotty/tools/dotc/core/Denotations.scala | 25 ++---- src/dotty/tools/dotc/core/References.scala | 135 +++++++++++++++++++++------- src/dotty/tools/dotc/core/Scopes.scala | 2 +- src/dotty/tools/dotc/core/Symbols.scala | 66 +++----------- src/dotty/tools/dotc/core/Types.scala | 9 +- 5 files changed, 124 insertions(+), 113 deletions(-) (limited to 'src/dotty') diff --git a/src/dotty/tools/dotc/core/Denotations.scala b/src/dotty/tools/dotc/core/Denotations.scala index 0882a9343..8aae7d644 100644 --- a/src/dotty/tools/dotc/core/Denotations.scala +++ b/src/dotty/tools/dotc/core/Denotations.scala @@ -2,30 +2,16 @@ package dotty.tools.dotc package core import Periods._, Contexts._, Symbols._, References._, Names._ -import Types._, Flags._, Decorators._ +import Types._, Flags._, Decorators._, Transformers._ import Scopes.Scope import collection.mutable import collection.immutable.BitSet object Denotations { - abstract class Denotation { + abstract class Denotation extends SymRef { - /** The validity interval of this symbol */ - var validFor: Period = 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 d = nextInRun - while (d.validFor.code > this.validFor.code) d = d.nextInRun - d - } + def symbol: Symbol = ??? def owner: Symbol = ??? @@ -57,9 +43,6 @@ object Denotations { * interval starting in FirstPhaseId. */ - /** is this symbol a type? */ - def isType: Boolean = false - /** is this symbol a class? */ def isClass: Boolean = false @@ -70,6 +53,8 @@ object Denotations { def isError: Boolean = false def withType(tp: Type): Denotation = ??? + + override protected def copy(s: Symbol, i: Type): SymRef = new UniqueSymRef(s, i, validFor) } object NameFilter { diff --git a/src/dotty/tools/dotc/core/References.scala b/src/dotty/tools/dotc/core/References.scala index bd640ed1d..d102edc77 100644 --- a/src/dotty/tools/dotc/core/References.scala +++ b/src/dotty/tools/dotc/core/References.scala @@ -7,18 +7,18 @@ import Names.Name import Names.TypeName import Symbols.NoSymbol import Symbols.Symbol -import Types._, Periods._, Flags._ +import Types._, Periods._, Flags._, Transformers._ -/** Classes that implement references and sets of references +/** Classes that implement referenced items and sets of them */ object References { - /** The signature of a reference. - * Overloaded references with the same name are distinguished by + /** The signature of a referenced. + * Overloaded referenceds with the same name are distinguished by * their signatures. A signature is a list of the fully qualified names * of the type symbols of the erasure of the parameters of the - * reference. For instance a reference to the definition + * referenced. For instance a referenced definition * * def f(x: Int)(y: List[String]): String * @@ -33,24 +33,24 @@ object References { */ val NullSignature = List(Names.EmptyTypeName) - /** A reference is the result of resolving a name (either simple identifier or select) - * during a given period interval. + /** A referenced is the result of resolving + * a name (either simple identifier or select) during a given period. * - * Reference has two subclasses: OverloadedRef and SymRef. + * Referenced has two subclasses: OverloadedRefd and SymRefd. * - * A SymRef refers to a `symbol` and a type (`info`) that the symbol has - * when referred through this reference. + * A SymRefd refers to a `symbol` and a type (`info`) that the symbol has + * when seen from the reference. * - * References (`SymRef`s) can be combined with `&` and `|`. + * References can be combined with `&` and `|`. * & is conjunction, | is disjunction. * * `&` will create an overloaded reference from two * non-overloaded references if their signatures differ. * Analogously `|` of two references with different signatures will give - * an empty reference `NoRef`. + * an empty reference `NoRefd`. * - * A reference might refer to `NoSymbol`. This is the case if the reference - * was produced from a disjunction of two references with different symbols + * A referenced might refer to `NoSymbol`. This is the case if the referenced + * was produced from a disjunction of two referenceds with different symbols * and there was no common symbol in a superclass that could substitute for * both symbols. Here is an example: * @@ -61,7 +61,7 @@ object References { * val x: A | B = if (???) new A else new B * val y = x.f * - * Then the reference of `y` is `SymRef(NoSymbol, A | B)`. + * Then the referenced of `y` is `SymRef(NoSymbol, A | B)`. */ abstract class Reference extends DotClass { @@ -74,6 +74,9 @@ object References { /** The interval during which this reference is valid */ def validFor: Period + /** The previous reference */ + def prev: Reference = ??? + /** Is this a reference to a type symbol? */ def isType: Boolean = false @@ -83,10 +86,8 @@ object References { /** Resolve overloaded reference to pick the one with the given signature */ def atSignature(sig: Signature): Reference - /** This reference at given phase */ - def atPhase(pid: PhaseId)(implicit ctx: Context): Reference = { - ??? - } + /** The variant of this reference that's current in the given context. */ + def current(implicit ctx: Context): Reference def exists: Boolean = true @@ -98,7 +99,7 @@ object References { else if (!this.exists) that else if (!that.exists) this else that match { - case that @ SymRef(sym2, info2) => + case that: SymRef => val r = mergeRef(this, that) if (r ne NoRef) r else OverloadedRef(this, that) case that @ OverloadedRef(ref1, ref2) => @@ -112,15 +113,18 @@ object References { case ref1 @ OverloadedRef(ref11, ref12) => val r1 = mergeRef(ref11, ref2) if (r1 ne NoRef) r1 else mergeRef(ref12, ref2) - case ref1 @ SymRef(sym1, info1) => + case ref1: SymRef => if (ref1 eq ref2) ref1 else if (ref1.signature == ref2.signature) { - val SymRef(sym2, info2) = ref2 def isEligible(sym1: Symbol, sym2: Symbol) = if (sym1.isType) !sym1.isClass else sym1.isConcrete || sym2.isDeferred || !sym2.exists def normalize(info: Type) = if (isType) info.bounds else info + val sym1 = ref1.symbol + val info1 = ref1.info + val sym2 = ref2.symbol + val info2 = ref2.info val sym1Eligible = isEligible(sym1, sym2) val sym2Eligible = isEligible(sym2, sym1) val bounds1 = normalize(info1) @@ -184,10 +188,12 @@ object References { def atSignature(sig: Signature): Reference = ref1.atSignature(sig) orElse ref2.atSignature(sig) def validFor = ref1.validFor & ref2.validFor + def current(implicit ctx: Context): Reference = + derivedOverloadedRef(ref1.current, ref2.current) } - abstract case class SymRef(override val symbol: Symbol, - override val info: Type) extends Reference with RefSet { + abstract class SymRef extends Reference with RefSet { + override def isType = symbol.isType override def signature: Signature = { def sig(tp: Type): Signature = tp match { @@ -210,6 +216,62 @@ object References { def atSignature(sig: Signature): Reference = if (sig == signature) this else NoRef + // ------ Transformations ----------------------------------------- + + var validFor: Period = Nowhere + + /** The next SymRef in this run, with wrap-around from last to first. */ + var nextInRun: SymRef = this + + /** The version of this SymRef that was valid in the first phase + * of this run. + */ + def initial: SymRef = { + var current = nextInRun + while (current.validFor.code > this.validFor.code) current = current.nextInRun + current + } + + def current(implicit ctx: Context): SymRef = { + val currentPeriod = ctx.period + val valid = validFor + var current = this + if (currentPeriod.code > valid.code) { + // search for containing period as long as nextInRun increases. + var next = nextInRun + while (next.validFor.code > valid.code && + !(next.validFor contains currentPeriod)) { + current = next + next = next.nextInRun + } + if (next.validFor.code > valid.code) { + // in this case, containsPeriod(next.validFor, currentPeriod) + current = next + } else { + // not found, current points to highest existing variant + var startPid = current.validFor.lastPhaseId + 1 + val trans = ctx.root.transformersFor(current) + val endPid = trans.nextTransformer(startPid + 1).phaseId - 1 + next = trans.nextTransformer(startPid) transform current + if (next eq current) + startPid = current.validFor.firstPhaseId + else { + current.nextInRun = next + current = next + } + current.validFor = Period(currentPeriod.runId, startPid, endPid) + } + } else { + // currentPeriod < valid; in this case a version must exist + do { + current = current.nextInRun + } while (!(current.validFor contains currentPeriod)) + } + current + } + + def asDenotation = asInstanceOf[Denotation] + // ------ RefSet ops ---------------------------------------------- def toRef(implicit ctx: Context) = this @@ -227,21 +289,30 @@ object References { derivedSymRef(symbol, info.asSeenFrom(pre, owner)) } - class UniqueSymRef(symbol: Symbol, info: Type)(implicit ctx: Context) extends SymRef(symbol, info) { - val validFor = symbol.deref.validFor - override protected def copy(s: Symbol, i: Type): SymRef = new UniqueSymRef(s, i) + class UniqueSymRef(val symbol: Symbol, + val info: Type, + initValidFor: Period) extends SymRef { + validFor = initValidFor + override protected def copy(s: Symbol, i: Type): SymRef = new UniqueSymRef(s, i, validFor) } - class JointSymRef(symbol: Symbol, info: Type, override val validFor: Period)(implicit ctx: Context) extends SymRef(symbol, info) { + class JointSymRef(val symbol: Symbol, + val info: Type, + initValidFor: Period) extends SymRef { + validFor = initValidFor override protected def copy(s: Symbol, i: Type): SymRef = new JointSymRef(s, i, validFor) } - class ErrorRef(implicit ctx: Context) extends SymRef(NoSymbol, NoType) { - def validFor = Period.allInRun(ctx.runId) + class ErrorRef(implicit ctx: Context) extends SymRef { + val symbol = NoSymbol + val info = NoType + validFor = Period.allInRun(ctx.runId) } - object NoRef extends SymRef(NoSymbol, NoType) { - def validFor = Nowhere + object NoRef extends SymRef { + val symbol = NoSymbol + val info = NoType + validFor = Nowhere override def exists = false } diff --git a/src/dotty/tools/dotc/core/Scopes.scala b/src/dotty/tools/dotc/core/Scopes.scala index e3d3c29ce..7a827ccf1 100644 --- a/src/dotty/tools/dotc/core/Scopes.scala +++ b/src/dotty/tools/dotc/core/Scopes.scala @@ -199,7 +199,7 @@ object Scopes { var syms: RefSet = NoRef var e = lookupEntry(name) while (e != null) { - syms = syms union e.sym.thisRef + syms = syms union e.sym.deref e = lookupNextEntry(e) } syms diff --git a/src/dotty/tools/dotc/core/Symbols.scala b/src/dotty/tools/dotc/core/Symbols.scala index 8ce7bfa64..3f14fd37b 100644 --- a/src/dotty/tools/dotc/core/Symbols.scala +++ b/src/dotty/tools/dotc/core/Symbols.scala @@ -2,7 +2,7 @@ package dotty.tools.dotc package core import Periods._ -import DenotationTransformers._ +import Transformers._ import Names._ import Flags._ import java.lang.AssertionError @@ -11,7 +11,7 @@ import Symbols._ import Contexts._ import Denotations._ import Types._ -import References.{Reference, SymRef, UniqueSymRef, OverloadedRef} +import References.{Reference, SymRef, OverloadedRef} import collection.mutable object Symbols { @@ -70,74 +70,32 @@ object Symbols { */ def deref(implicit ctx: Context): Denotation = { val denot = lastDenot - if (denot != null && (denot.validFor contains 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 { + if (denot == null) loadDenot + else { val currentPeriod = ctx.period val valid = denot.validFor - val currentRunId = currentPeriod.runId - val validRunId = valid.runId - if (currentRunId != validRunId) { - reloadDenot - } else if (currentPeriod.code > valid.code) { - // search for containing interval as long as nextInRun - // increases. - var nextDenot = denot.nextInRun - while (nextDenot.validFor.code > valid.code && !(nextDenot.validFor contains currentPeriod)) { - denot = nextDenot - nextDenot = nextDenot.nextInRun - } - if (nextDenot.validFor.code > valid.code) { - // in this case, containsPeriod(nextDenot.valid, currentPeriod) - denot = nextDenot - } else { - // not found, denot points to highest existing variant - var startPid = denot.validFor.lastPhaseId + 1 - val endPid = ctx.root.nextTransformer(startPid + 1).phaseId - 1 - nextDenot = ctx.root.nextTransformer(startPid) transform denot - if (nextDenot eq denot) - startPid = denot.validFor.firstPhaseId - else { - denot.nextInRun = nextDenot - denot = nextDenot - } - denot.validFor = Period(currentRunId, startPid, endPid) - } - } else { - // currentPeriod < valid; in this case a denotation must exist - do { - denot = denot.nextInRun - } while (!(denot.validFor contains currentPeriod)) - } + if (valid contains currentPeriod) denot + else if (valid.runId != currentPeriod.runId) reloadDenot + else denot.current.asDenotation } - denot } /** * Get loaded denotation if lastDenot points to a denotation from - * a different run. + * a different run. !!! needed? */ private def reloadDenot(implicit ctx: Context): Denotation = { - val initDenot = lastDenot.initial + val initDenot = lastDenot.initial.asDenotation val newSym: Symbol = ctx.atPhase(FirstPhaseId) { implicit ctx => initDenot.owner.info.decl(initDenot.name) - .atSignature(thisRef.signature).symbol + .atSignature(deref.signature).symbol } if (newSym eq this) { // no change, change validity var d = initDenot do { d.validFor = Period(ctx.runId, d.validFor.firstPhaseId, d.validFor.lastPhaseId) - d = d.nextInRun + d = d.nextInRun.asDenotation } while (d ne initDenot) } newSym.deref @@ -146,8 +104,6 @@ object Symbols { 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 diff --git a/src/dotty/tools/dotc/core/Types.scala b/src/dotty/tools/dotc/core/Types.scala index 98f63a5b0..3c5530bb0 100644 --- a/src/dotty/tools/dotc/core/Types.scala +++ b/src/dotty/tools/dotc/core/Types.scala @@ -528,13 +528,12 @@ object Types { val thisPeriod = ctx.period referenceVar = if (validPeriods.runId == thisPeriod.runId) - referenceVar.atPhase(ctx.period.phaseId) + referenceVar.current //val ref @ SymRef(clazz: ClassSymbol, _) = referenceVar //ref.derivedSymRef(clazz, ClassInfo(prefix, clazz.deref)) else if (thisPeriod.phaseId > name.lastIntroPhaseId) - ctx.atPhase(name.lastIntroPhaseId)(prefix.member(name)(_)) - .atPhase(thisPeriod.phaseId) - else + ctx.atPhase(name.lastIntroPhaseId)(prefix.member(name)(_)).current + else prefix.member(name) if (checkPrefix(referenceVar.symbol) && !prefix.isLegalPrefix) throw new MalformedType(prefix, referenceVar.symbol) @@ -567,7 +566,7 @@ object Types { protected val fixedSym: Symbol override def symbol(implicit ctx: Context): Symbol = fixedSym override def info(implicit ctx: Context): Type = fixedSym.info - override def reference(implicit ctx: Context): Reference = new UniqueSymRef(fixedSym, info) + override def reference(implicit ctx: Context): Reference = fixedSym.deref } final class TermRefNoPrefix(val fixedSym: TermSymbol)(implicit ctx: Context) -- cgit v1.2.3