aboutsummaryrefslogtreecommitdiff
path: root/src/dotty/tools/dotc/core/References.scala
diff options
context:
space:
mode:
Diffstat (limited to 'src/dotty/tools/dotc/core/References.scala')
-rw-r--r--src/dotty/tools/dotc/core/References.scala135
1 files changed, 103 insertions, 32 deletions
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
}