aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2017-03-23 23:35:17 +0100
committerMartin Odersky <odersky@gmail.com>2017-04-11 09:33:10 +0200
commita2731a8be2f3434218623c0b0ecd4078107f14a5 (patch)
tree3077df892ba46e4142cb6a38555cc7604be36222
parente2056bb62e8d4ce5806111f0c54f7331eb690f0a (diff)
downloaddotty-a2731a8be2f3434218623c0b0ecd4078107f14a5.tar.gz
dotty-a2731a8be2f3434218623c0b0ecd4078107f14a5.tar.bz2
dotty-a2731a8be2f3434218623c0b0ecd4078107f14a5.zip
Handle expansion and flattening
-rw-r--r--compiler/src/dotty/tools/dotc/ast/Trees.scala2
-rw-r--r--compiler/src/dotty/tools/dotc/core/Denotations.scala4
-rw-r--r--compiler/src/dotty/tools/dotc/core/NameInfos.scala37
-rw-r--r--compiler/src/dotty/tools/dotc/core/NameOps.scala42
-rw-r--r--compiler/src/dotty/tools/dotc/core/Names.scala27
-rw-r--r--compiler/src/dotty/tools/dotc/core/StdNames.scala9
-rw-r--r--compiler/src/dotty/tools/dotc/core/SymDenotations.scala6
-rw-r--r--compiler/src/dotty/tools/dotc/core/tasty/NameBuffer.scala18
-rw-r--r--compiler/src/dotty/tools/dotc/core/tasty/TastyFormat.scala11
-rw-r--r--compiler/src/dotty/tools/dotc/core/tasty/TastyName.scala3
-rw-r--r--compiler/src/dotty/tools/dotc/core/tasty/TastyUnpickler.scala6
-rw-r--r--compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala15
12 files changed, 131 insertions, 49 deletions
diff --git a/compiler/src/dotty/tools/dotc/ast/Trees.scala b/compiler/src/dotty/tools/dotc/ast/Trees.scala
index 20d7c1458..0ff335e40 100644
--- a/compiler/src/dotty/tools/dotc/ast/Trees.scala
+++ b/compiler/src/dotty/tools/dotc/ast/Trees.scala
@@ -316,7 +316,7 @@ object Trees {
def namePos =
if (pos.exists)
if (rawMods.is(Synthetic)) Position(pos.point, pos.point)
- else Position(pos.point, pos.point + name.stripModuleClassSuffix.length, pos.point)
+ else Position(pos.point, pos.point + name.stripModuleClassSuffix.lastPart.length, pos.point)
else pos
}
diff --git a/compiler/src/dotty/tools/dotc/core/Denotations.scala b/compiler/src/dotty/tools/dotc/core/Denotations.scala
index a679cad6f..aa0ea39a2 100644
--- a/compiler/src/dotty/tools/dotc/core/Denotations.scala
+++ b/compiler/src/dotty/tools/dotc/core/Denotations.scala
@@ -1190,8 +1190,10 @@ object Denotations {
recur(path.toTermName, n => wrap(n.toTypeName))
case DerivedTermName(prefix, NameInfo.ModuleClass) =>
recur(prefix, n => wrap(n.derived(NameInfo.ModuleClass)))
- case DerivedTermName(prefix, NameInfo.Qualified(selector, ".")) =>
+ case DerivedTermName(prefix, NameInfo.Select(selector)) =>
select(recur(prefix), wrap(selector))
+ case DerivedTermName(prefix, qual: NameInfo.Qualified) =>
+ recur(prefix, n => wrap(n ++ qual.separator ++ qual.name))
case path: SimpleTermName =>
def recurSimple(len: Int, wrap: Name => Name): Denotation = {
val point = path.lastIndexOf('.', len - 1)
diff --git a/compiler/src/dotty/tools/dotc/core/NameInfos.scala b/compiler/src/dotty/tools/dotc/core/NameInfos.scala
index e8db88f84..daaa5c4e1 100644
--- a/compiler/src/dotty/tools/dotc/core/NameInfos.scala
+++ b/compiler/src/dotty/tools/dotc/core/NameInfos.scala
@@ -2,6 +2,7 @@ package dotty.tools.dotc
package core
import Names._
+import StdNames._
/** Additional info associated with a name. At a minimum its kind and
* a way to turn it into a string.
@@ -20,6 +21,12 @@ object NameInfo {
val QualifiedKind = 1
val ModuleClassKind = 2
+ val qualifier: Map[String, SimpleTermName => Qualified] =
+ Map("." -> Select,
+ "$" -> Flatten,
+ str.EXPAND_SEPARATOR -> Expand,
+ str.TRAIT_SETTER_SEPARATOR -> TraitSetter)
+
def definesNewName(kind: Kind) = kind <= QualifiedKind
/** TermNames have the lowest possible kind */
@@ -28,11 +35,35 @@ object NameInfo {
def mkString(underlying: TermName) = underlying.toString // will cause an unsupported exception
}
- case class Qualified(name: SimpleTermName, separator: String) extends NameInfo {
+ trait Qualified extends NameInfo {
+ def name: SimpleTermName
+ def separator: String
+ def newLikeThis(name: SimpleTermName): Qualified // TODO: should use copy instead after bootstrap
+
def kind = QualifiedKind
+ override def map(f: SimpleTermName => SimpleTermName): NameInfo = newLikeThis(f(name))
def mkString(underlying: TermName) = s"$underlying$separator$name"
- override def map(f: SimpleTermName => SimpleTermName): NameInfo = Qualified(f(name), separator)
- override def toString = s"Qualified($name, $separator)"
+ override def toString = s"$getClass($name)"
+ }
+
+ case class Select(val name: SimpleTermName) extends Qualified {
+ def separator = "."
+ def newLikeThis(name: SimpleTermName) = Select(name)
+ }
+
+ case class Flatten(val name: SimpleTermName) extends Qualified {
+ def separator = "$"
+ def newLikeThis(name: SimpleTermName) = Flatten(name)
+ }
+
+ case class Expand(val name: SimpleTermName) extends Qualified {
+ def separator = str.EXPAND_SEPARATOR
+ def newLikeThis(name: SimpleTermName) = Expand(name)
+ }
+
+ case class TraitSetter(val name: SimpleTermName) extends Qualified {
+ def separator = nme.TRAIT_SETTER_SEPARATOR.toString
+ def newLikeThis(name: SimpleTermName) = TraitSetter(name)
}
val ModuleClass = new NameInfo {
diff --git a/compiler/src/dotty/tools/dotc/core/NameOps.scala b/compiler/src/dotty/tools/dotc/core/NameOps.scala
index c4d551981..65669a871 100644
--- a/compiler/src/dotty/tools/dotc/core/NameOps.scala
+++ b/compiler/src/dotty/tools/dotc/core/NameOps.scala
@@ -162,30 +162,46 @@ object NameOps {
/** The expanded name of `name` relative to `basename` with given `separator`
*/
def expandedName(prefix: Name, separator: Name = nme.EXPAND_SEPARATOR): N =
- name.likeKinded(prefix ++ separator ++ name).asInstanceOf[N]
+ likeTyped(
+ if (Config.semanticNames)
+ prefix.derived(NameInfo.qualifier(separator.toString)(name.asSimpleName))
+ else prefix ++ separator ++ name)
def expandedName(prefix: Name): N = expandedName(prefix, nme.EXPAND_SEPARATOR)
- /** Revert the expanded name. Note: This currently gives incorrect results
+ /** Revert the expanded name.
+ * Note: This currently gives incorrect results
* if the normal name contains `nme.EXPAND_SEPARATOR`, i.e. two consecutive '$'
* signs. This can happen for instance if a super accessor is paired with
* an encoded name, e.g. super$$plus$eq. See #765.
*/
- def unexpandedName: N = {
- var idx = name.lastIndexOfSlice(nme.EXPAND_SEPARATOR)
+ def unexpandedName: N = likeTyped {
+ if (Config.semanticNames)
+ name.rewrite {
+ case DerivedTermName(_, NameInfo.Expand(unexp)) => unexp
+ }
+ else {
+ var idx = name.lastIndexOfSlice(nme.EXPAND_SEPARATOR)
- // Hack to make super accessors from traits work. They would otherwise fail because of #765
- // TODO: drop this once we have more robust name handling
- if (idx > FalseSuperLength && name.slice(idx - FalseSuperLength, idx) == FalseSuper)
- idx -= FalseSuper.length
+ // Hack to make super accessors from traits work. They would otherwise fail because of #765
+ // TODO: drop this once we have more robust name handling
+ if (idx > FalseSuperLength && name.slice(idx - FalseSuperLength, idx) == FalseSuper)
+ idx -= FalseSuper.length
- if (idx < 0) name else (name drop (idx + nme.EXPAND_SEPARATOR.length)).asInstanceOf[N]
+ if (idx < 0) name else (name drop (idx + nme.EXPAND_SEPARATOR.length))
+ }
}
- def expandedPrefix: N = {
- val idx = name.lastIndexOfSlice(nme.EXPAND_SEPARATOR)
- assert(idx >= 0)
- name.take(idx).asInstanceOf[N]
+ def expandedPrefix: N = likeTyped {
+ if (Config.semanticNames)
+ name.rewrite {
+ case DerivedTermName(prefix, NameInfo.Expand(_)) => prefix
+ }
+ else {
+ val idx = name.lastIndexOfSlice(nme.EXPAND_SEPARATOR)
+ assert(idx >= 0)
+ name.take(idx)
+ }
}
def shadowedName: N = likeTyped(nme.SHADOWED ++ name)
diff --git a/compiler/src/dotty/tools/dotc/core/Names.scala b/compiler/src/dotty/tools/dotc/core/Names.scala
index ffbb097b8..84b2fab0c 100644
--- a/compiler/src/dotty/tools/dotc/core/Names.scala
+++ b/compiler/src/dotty/tools/dotc/core/Names.scala
@@ -65,13 +65,12 @@ object Names {
def isSimple: Boolean
def asSimpleName: SimpleTermName
def toSimpleName: SimpleTermName
- def mapSimpleCore(f: SimpleTermName => Name): ThisName
+ def rewrite(f: PartialFunction[Name, Name]): ThisName
/** A name of the same kind as this name and with same characters as given `name` */
def likeKinded(name: Name): ThisName
def derived(info: NameInfo): ThisName
- def select(name: SimpleTermName, sep: String) = derived(NameInfo.Qualified(name, sep))
def exclude(kind: NameInfo.Kind): ThisName
def is(kind: NameInfo.Kind): Boolean
def debugString: String
@@ -99,6 +98,8 @@ object Names {
def startsWith(name: Name): Boolean = startsWith(name.toString)
def endsWith(str: String): Boolean = lastPart.endsWith(str)
def endsWith(name: Name): Boolean = endsWith(name.toString)
+ def lastIndexOfSlice(str: String): Int = lastPart.toString.lastIndexOfSlice(str)
+ def lastIndexOfSlice(name: Name): Int = lastIndexOfSlice(name.toString)
override def equals(that: Any) = this eq that.asInstanceOf[AnyRef]
}
@@ -231,7 +232,7 @@ object Names {
def isSimple = true
def asSimpleName = this
def toSimpleName = this
- def mapSimpleCore(f: SimpleTermName => Name): TermName = likeKinded(f(this))
+ def rewrite(f: PartialFunction[Name, Name]): ThisName = likeKinded(f(this))
def encode: SimpleTermName =
if (dontEncode(toTermName)) this else NameTransformer.encode(this)
@@ -272,7 +273,7 @@ object Names {
def isSimple = toTermName.isSimple
def asSimpleName = toTermName.asSimpleName
def toSimpleName = toTermName.toSimpleName
- def mapSimpleCore(f: SimpleTermName => Name): TypeName = toTermName.mapSimpleCore(f).toTypeName
+ def rewrite(f: PartialFunction[Name, Name]): ThisName = toTermName.rewrite(f).toTypeName
def likeKinded(name: Name): TypeName = name.toTypeName
@@ -292,16 +293,13 @@ object Names {
def isEmpty = false
def encode: Name = underlying.encode.derived(info.map(_.encode))
def decode: Name = underlying.decode.derived(info.map(_.decode))
- def firstPart = info match {
- case NameInfo.Qualified(name, _) => name
- case _ => underlying.firstPart
- }
+ def firstPart = underlying.firstPart
def lastPart = info match {
- case NameInfo.Qualified(name, _) => name
+ case qual: NameInfo.Qualified => qual.name
case _ => underlying.lastPart
}
def ++ (other: String): ThisName = info match {
- case NameInfo.Qualified(name, sep) => underlying.select(name ++ other, sep)
+ case qual: NameInfo.Qualified => underlying.derived(qual.map(_ ++ other))
case _ => (underlying ++ other).derived(info)
}
override def toString = info.mkString(underlying)
@@ -310,7 +308,13 @@ object Names {
def isSimple = false
def asSimpleName = throw new UnsupportedOperationException(s"$debugString is not a simple name")
def toSimpleName = termName(toString)
- def mapSimpleCore(f: SimpleTermName => Name) = underlying.mapSimpleCore(f).derived(info)
+
+ def rewrite(f: PartialFunction[Name, Name]): ThisName =
+ if (f.isDefinedAt(this)) likeKinded(f(this))
+ else info match {
+ case qual: NameInfo.Qualified => this
+ case _ => underlying.rewrite(f).derived(info)
+ }
}
// Nametable
@@ -470,7 +474,6 @@ object Names {
def seq: WrappedString = new WrappedString(name.toString)
override protected[this] def thisCollection: WrappedString = seq
def indexOfSlice(name: Name): Int = indexOfSlice(name.toString)
- def lastIndexOfSlice(name: Name): Int = lastIndexOfSlice(name.toString)
def containsSlice(name: Name): Boolean = containsSlice(name.toString)
}
diff --git a/compiler/src/dotty/tools/dotc/core/StdNames.scala b/compiler/src/dotty/tools/dotc/core/StdNames.scala
index 56f8ca189..9e05d4bce 100644
--- a/compiler/src/dotty/tools/dotc/core/StdNames.scala
+++ b/compiler/src/dotty/tools/dotc/core/StdNames.scala
@@ -15,6 +15,11 @@ object StdNames {
/** Base strings from which synthetic names are derived. */
+ object str {
+ val EXPAND_SEPARATOR = "$$"
+ val TRAIT_SETTER_SEPARATOR = "$_setter_$"
+ }
+
abstract class DefinedNames[N <: Name] {
protected implicit def fromString(s: String): N
protected def fromName(name: Name): N = fromString(name.toString)
@@ -99,7 +104,7 @@ object StdNames {
val EVIDENCE_PARAM_PREFIX: N = "evidence$"
val DEP_PARAM_PREFIX = "<param>"
val EXCEPTION_RESULT_PREFIX: N = "exceptionResult"
- val EXPAND_SEPARATOR: N = "$$"
+ val EXPAND_SEPARATOR: N = str.EXPAND_SEPARATOR
val IMPL_CLASS_SUFFIX: N = "$class"
val IMPORT: N = "<import>"
val INLINE_ACCESSOR_PREFIX = "$inlineAccessor$"
@@ -129,7 +134,7 @@ object StdNames {
val INITIALIZER_PREFIX: N = "initial$"
val COMPANION_MODULE_METHOD: N = "companion$module"
val COMPANION_CLASS_METHOD: N = "companion$class"
- val TRAIT_SETTER_SEPARATOR: N = "$_setter_$"
+ val TRAIT_SETTER_SEPARATOR: N = str.TRAIT_SETTER_SEPARATOR
val DIRECT_SUFFIX: N = "$direct"
val LAZY_IMPLICIT_PREFIX: N = "$lazy_implicit$"
val DOLLAR_VALUES: N = "$values"
diff --git a/compiler/src/dotty/tools/dotc/core/SymDenotations.scala b/compiler/src/dotty/tools/dotc/core/SymDenotations.scala
index f671ab557..74505d811 100644
--- a/compiler/src/dotty/tools/dotc/core/SymDenotations.scala
+++ b/compiler/src/dotty/tools/dotc/core/SymDenotations.scala
@@ -411,11 +411,13 @@ object SymDenotations {
}
var prefix = encl.fullNameSeparated(separator)
val fn =
- if (Config.semanticNames) {
+ if (Config.semanticNames && NameInfo.qualifier.contains(sep)) {
if (sep == "$")
// duplicate scalac's behavior: don't write a double '$$' for module class members.
prefix = prefix.exclude(NameInfo.ModuleClassKind)
- name.mapSimpleCore(prefix.select(_, sep))
+ name rewrite {
+ case n: SimpleTermName => prefix.derived(NameInfo.qualifier(sep)(n))
+ }
}
else {
if (owner.is(ModuleClass, butNot = Package) && sep == "$")
diff --git a/compiler/src/dotty/tools/dotc/core/tasty/NameBuffer.scala b/compiler/src/dotty/tools/dotc/core/tasty/NameBuffer.scala
index f1f03dd3c..7ac505a20 100644
--- a/compiler/src/dotty/tools/dotc/core/tasty/NameBuffer.scala
+++ b/compiler/src/dotty/tools/dotc/core/tasty/NameBuffer.scala
@@ -29,8 +29,13 @@ class NameBuffer extends TastyBuffer(10000) {
val tname = name.toTermName match {
case DerivedTermName(name1, NameInfo.ModuleClass) =>
ModuleClass(nameIndex(name1, toTasty))
- case DerivedTermName(prefix, NameInfo.Qualified(selector, ".")) =>
- Qualified(nameIndex(prefix, toTasty), nameIndex(selector))
+ case DerivedTermName(prefix, qual: NameInfo.Qualified) =>
+ val tcon: (NameRef, NameRef) => TastyName = qual match {
+ case _: NameInfo.Select => Qualified
+ case _: NameInfo.Flatten => Flattened
+ case _: NameInfo.Expand => Expanded
+ }
+ tcon(nameIndex(prefix, toTasty), nameIndex(qual.name))
case name1 =>
if (name1.isShadowedName) Shadowed(nameIndex(name1.revertShadowed, toTasty))
else toTasty(name1.asSimpleName)
@@ -72,14 +77,17 @@ class NameBuffer extends TastyBuffer(10000) {
case Qualified(qualified, selector) =>
writeByte(QUALIFIED)
withLength { writeNameRef(qualified); writeNameRef(selector) }
+ case Flattened(qualified, selector) =>
+ writeByte(FLATTENED)
+ withLength { writeNameRef(qualified); writeNameRef(selector) }
+ case Expanded(prefix, original) =>
+ writeByte(EXPANDED)
+ withLength { writeNameRef(prefix); writeNameRef(original) }
case Signed(original, params, result) =>
writeByte(SIGNED)
withLength(
{ writeNameRef(original); writeNameRef(result); params.foreach(writeNameRef) },
if ((params.length + 2) * maxIndexWidth <= maxNumInByte) 1 else 2)
- case Expanded(prefix, original) =>
- writeByte(EXPANDED)
- withLength { writeNameRef(prefix); writeNameRef(original) }
case ModuleClass(module) =>
writeByte(OBJECTCLASS)
withLength { writeNameRef(module) }
diff --git a/compiler/src/dotty/tools/dotc/core/tasty/TastyFormat.scala b/compiler/src/dotty/tools/dotc/core/tasty/TastyFormat.scala
index 8b2255e94..848b7995f 100644
--- a/compiler/src/dotty/tools/dotc/core/tasty/TastyFormat.scala
+++ b/compiler/src/dotty/tools/dotc/core/tasty/TastyFormat.scala
@@ -222,12 +222,13 @@ object TastyFormat {
final val UTF8 = 1
final val QUALIFIED = 2
- final val SIGNED = 3
+ final val FLATTENED = 3
final val EXPANDED = 4
- final val OBJECTCLASS = 5
- final val SUPERACCESSOR = 6
- final val DEFAULTGETTER = 7
- final val SHADOWED = 8
+ final val SIGNED = 5
+ final val OBJECTCLASS = 6
+ final val SUPERACCESSOR = 7
+ final val DEFAULTGETTER = 8
+ final val SHADOWED = 9
// AST tags
diff --git a/compiler/src/dotty/tools/dotc/core/tasty/TastyName.scala b/compiler/src/dotty/tools/dotc/core/tasty/TastyName.scala
index da205542e..67b08a1c1 100644
--- a/compiler/src/dotty/tools/dotc/core/tasty/TastyName.scala
+++ b/compiler/src/dotty/tools/dotc/core/tasty/TastyName.scala
@@ -14,8 +14,9 @@ object TastyName {
case class Simple(name: SimpleTermName) extends TastyName
case class Qualified(qualified: NameRef, selector: NameRef) extends TastyName
- case class Signed(original: NameRef, params: List[NameRef], result: NameRef) extends TastyName
case class Expanded(prefix: NameRef, original: NameRef) extends TastyName
+ case class Flattened(prefix: NameRef, original: NameRef) extends TastyName
+ case class Signed(original: NameRef, params: List[NameRef], result: NameRef) extends TastyName
case class ModuleClass(module: NameRef) extends TastyName
case class SuperAccessor(accessed: NameRef) extends TastyName
case class DefaultGetter(method: NameRef, num: Int) extends TastyName
diff --git a/compiler/src/dotty/tools/dotc/core/tasty/TastyUnpickler.scala b/compiler/src/dotty/tools/dotc/core/tasty/TastyUnpickler.scala
index 8a1f58acd..c8c1878bc 100644
--- a/compiler/src/dotty/tools/dotc/core/tasty/TastyUnpickler.scala
+++ b/compiler/src/dotty/tools/dotc/core/tasty/TastyUnpickler.scala
@@ -45,13 +45,15 @@ class TastyUnpickler(reader: TastyReader) {
Simple(termName(bytes, start.index, length))
case QUALIFIED =>
Qualified(readNameRef(), readNameRef())
+ case FLATTENED =>
+ Flattened(readNameRef(), readNameRef())
+ case EXPANDED =>
+ Expanded(readNameRef(), readNameRef())
case SIGNED =>
val original = readNameRef()
val result = readNameRef()
val params = until(end)(readNameRef())
Signed(original, params, result)
- case EXPANDED =>
- Expanded(readNameRef(), readNameRef())
case OBJECTCLASS =>
ModuleClass(readNameRef())
case SUPERACCESSOR =>
diff --git a/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala b/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala
index a186d1ce4..06165c6f4 100644
--- a/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala
+++ b/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala
@@ -15,6 +15,7 @@ import scala.collection.mutable.ListBuffer
import scala.collection.{ mutable, immutable }
import config.Printers.pickling
import typer.Checking
+import config.Config
/** Unpickler for typed trees
* @param reader the reader from which to unpickle
@@ -76,15 +77,25 @@ class TreeUnpickler(reader: TastyReader, tastyName: TastyName.Table, posUnpickle
def toTermName(tname: TastyName): TermName = tname match {
case Simple(name) => name
- case Qualified(qual, name) => toTermName(qual) ++ "." ++ toTermName(name)
+ case Qualified(qual, name) =>
+ if (Config.semanticNames) qualTermName(qual, name, ".")
+ else toTermName(qual) ++ "." ++ toTermName(name)
+ case Flattened(qual, name) =>
+ if (Config.semanticNames) qualTermName(qual, name, "$")
+ else toTermName(qual) ++ "$" ++ toTermName(name)
+ case Expanded(prefix, original) =>
+ if (Config.semanticNames) qualTermName(prefix, original, str.EXPAND_SEPARATOR)
+ else toTermName(original).expandedName(toTermName(prefix))
case Signed(original, params, result) => toTermName(original)
case Shadowed(original) => toTermName(original).shadowedName
- case Expanded(prefix, original) => toTermName(original).expandedName(toTermName(prefix))
case ModuleClass(original) => toTermName(original).moduleClassName.toTermName
case SuperAccessor(accessed) => toTermName(accessed).superName
case DefaultGetter(meth, num) => ???
}
+ private def qualTermName(qual: NameRef, name: NameRef, sep: String) =
+ toTermName(qual).derived(NameInfo.qualifier(sep)(toTermName(name).asSimpleName))
+
def toTermName(ref: NameRef): TermName = toTermName(tastyName(ref))
def toTypeName(ref: NameRef): TypeName = toTermName(ref).toTypeName