Skip to content

Commit e8a3d7d

Browse files
committed
Handle expansion and flattening
1 parent dd3f0db commit e8a3d7d

File tree

12 files changed

+131
-49
lines changed

12 files changed

+131
-49
lines changed

compiler/src/dotty/tools/dotc/ast/Trees.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -316,7 +316,7 @@ object Trees {
316316
def namePos =
317317
if (pos.exists)
318318
if (rawMods.is(Synthetic)) Position(pos.point, pos.point)
319-
else Position(pos.point, pos.point + name.stripModuleClassSuffix.length, pos.point)
319+
else Position(pos.point, pos.point + name.stripModuleClassSuffix.lastPart.length, pos.point)
320320
else pos
321321
}
322322

compiler/src/dotty/tools/dotc/core/Denotations.scala

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1210,8 +1210,10 @@ object Denotations {
12101210
recur(path.toTermName, n => wrap(n.toTypeName))
12111211
case DerivedTermName(prefix, NameInfo.ModuleClass) =>
12121212
recur(prefix, n => wrap(n.derived(NameInfo.ModuleClass)))
1213-
case DerivedTermName(prefix, NameInfo.Qualified(selector, ".")) =>
1213+
case DerivedTermName(prefix, NameInfo.Select(selector)) =>
12141214
select(recur(prefix), wrap(selector))
1215+
case DerivedTermName(prefix, qual: NameInfo.Qualified) =>
1216+
recur(prefix, n => wrap(n ++ qual.separator ++ qual.name))
12151217
case path: SimpleTermName =>
12161218
def recurSimple(len: Int, wrap: Name => Name): Denotation = {
12171219
val point = path.lastIndexOf('.', len - 1)

compiler/src/dotty/tools/dotc/core/NameInfos.scala

Lines changed: 34 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package dotty.tools.dotc
22
package core
33

44
import Names._
5+
import StdNames._
56

67
/** Additional info associated with a name. At a minimum its kind and
78
* a way to turn it into a string.
@@ -20,6 +21,12 @@ object NameInfo {
2021
val QualifiedKind = 1
2122
val ModuleClassKind = 2
2223

24+
val qualifier: Map[String, SimpleTermName => Qualified] =
25+
Map("." -> Select,
26+
"$" -> Flatten,
27+
str.EXPAND_SEPARATOR -> Expand,
28+
str.TRAIT_SETTER_SEPARATOR -> TraitSetter)
29+
2330
def definesNewName(kind: Kind) = kind <= QualifiedKind
2431

2532
/** TermNames have the lowest possible kind */
@@ -28,11 +35,35 @@ object NameInfo {
2835
def mkString(underlying: TermName) = underlying.toString // will cause an unsupported exception
2936
}
3037

31-
case class Qualified(name: SimpleTermName, separator: String) extends NameInfo {
38+
trait Qualified extends NameInfo {
39+
def name: SimpleTermName
40+
def separator: String
41+
def newLikeThis(name: SimpleTermName): Qualified // TODO: should use copy instead after bootstrap
42+
3243
def kind = QualifiedKind
44+
override def map(f: SimpleTermName => SimpleTermName): NameInfo = newLikeThis(f(name))
3345
def mkString(underlying: TermName) = s"$underlying$separator$name"
34-
override def map(f: SimpleTermName => SimpleTermName): NameInfo = Qualified(f(name), separator)
35-
override def toString = s"Qualified($name, $separator)"
46+
override def toString = s"$getClass($name)"
47+
}
48+
49+
case class Select(val name: SimpleTermName) extends Qualified {
50+
def separator = "."
51+
def newLikeThis(name: SimpleTermName) = Select(name)
52+
}
53+
54+
case class Flatten(val name: SimpleTermName) extends Qualified {
55+
def separator = "$"
56+
def newLikeThis(name: SimpleTermName) = Flatten(name)
57+
}
58+
59+
case class Expand(val name: SimpleTermName) extends Qualified {
60+
def separator = str.EXPAND_SEPARATOR
61+
def newLikeThis(name: SimpleTermName) = Expand(name)
62+
}
63+
64+
case class TraitSetter(val name: SimpleTermName) extends Qualified {
65+
def separator = nme.TRAIT_SETTER_SEPARATOR.toString
66+
def newLikeThis(name: SimpleTermName) = TraitSetter(name)
3667
}
3768

3869
val ModuleClass = new NameInfo {

compiler/src/dotty/tools/dotc/core/NameOps.scala

Lines changed: 29 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -162,30 +162,46 @@ object NameOps {
162162
/** The expanded name of `name` relative to `basename` with given `separator`
163163
*/
164164
def expandedName(prefix: Name, separator: Name = nme.EXPAND_SEPARATOR): N =
165-
name.likeKinded(prefix ++ separator ++ name).asInstanceOf[N]
165+
likeTyped(
166+
if (Config.semanticNames)
167+
prefix.derived(NameInfo.qualifier(separator.toString)(name.asSimpleName))
168+
else prefix ++ separator ++ name)
166169

167170
def expandedName(prefix: Name): N = expandedName(prefix, nme.EXPAND_SEPARATOR)
168171

169-
/** Revert the expanded name. Note: This currently gives incorrect results
172+
/** Revert the expanded name.
173+
* Note: This currently gives incorrect results
170174
* if the normal name contains `nme.EXPAND_SEPARATOR`, i.e. two consecutive '$'
171175
* signs. This can happen for instance if a super accessor is paired with
172176
* an encoded name, e.g. super$$plus$eq. See #765.
173177
*/
174-
def unexpandedName: N = {
175-
var idx = name.lastIndexOfSlice(nme.EXPAND_SEPARATOR)
178+
def unexpandedName: N = likeTyped {
179+
if (Config.semanticNames)
180+
name.rewrite {
181+
case DerivedTermName(_, NameInfo.Expand(unexp)) => unexp
182+
}
183+
else {
184+
var idx = name.lastIndexOfSlice(nme.EXPAND_SEPARATOR)
176185

177-
// Hack to make super accessors from traits work. They would otherwise fail because of #765
178-
// TODO: drop this once we have more robust name handling
179-
if (idx > FalseSuperLength && name.slice(idx - FalseSuperLength, idx) == FalseSuper)
180-
idx -= FalseSuper.length
186+
// Hack to make super accessors from traits work. They would otherwise fail because of #765
187+
// TODO: drop this once we have more robust name handling
188+
if (idx > FalseSuperLength && name.slice(idx - FalseSuperLength, idx) == FalseSuper)
189+
idx -= FalseSuper.length
181190

182-
if (idx < 0) name else (name drop (idx + nme.EXPAND_SEPARATOR.length)).asInstanceOf[N]
191+
if (idx < 0) name else (name drop (idx + nme.EXPAND_SEPARATOR.length))
192+
}
183193
}
184194

185-
def expandedPrefix: N = {
186-
val idx = name.lastIndexOfSlice(nme.EXPAND_SEPARATOR)
187-
assert(idx >= 0)
188-
name.take(idx).asInstanceOf[N]
195+
def expandedPrefix: N = likeTyped {
196+
if (Config.semanticNames)
197+
name.rewrite {
198+
case DerivedTermName(prefix, NameInfo.Expand(_)) => prefix
199+
}
200+
else {
201+
val idx = name.lastIndexOfSlice(nme.EXPAND_SEPARATOR)
202+
assert(idx >= 0)
203+
name.take(idx)
204+
}
189205
}
190206

191207
def shadowedName: N = likeTyped(nme.SHADOWED ++ name)

compiler/src/dotty/tools/dotc/core/Names.scala

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -65,13 +65,12 @@ object Names {
6565
def isSimple: Boolean
6666
def asSimpleName: SimpleTermName
6767
def toSimpleName: SimpleTermName
68-
def mapSimpleCore(f: SimpleTermName => Name): ThisName
68+
def rewrite(f: PartialFunction[Name, Name]): ThisName
6969

7070
/** A name of the same kind as this name and with same characters as given `name` */
7171
def likeKinded(name: Name): ThisName
7272

7373
def derived(info: NameInfo): ThisName
74-
def select(name: SimpleTermName, sep: String) = derived(NameInfo.Qualified(name, sep))
7574
def exclude(kind: NameInfo.Kind): ThisName
7675
def is(kind: NameInfo.Kind): Boolean
7776
def debugString: String
@@ -99,6 +98,8 @@ object Names {
9998
def startsWith(name: Name): Boolean = startsWith(name.toString)
10099
def endsWith(str: String): Boolean = lastPart.endsWith(str)
101100
def endsWith(name: Name): Boolean = endsWith(name.toString)
101+
def lastIndexOfSlice(str: String): Int = lastPart.toString.lastIndexOfSlice(str)
102+
def lastIndexOfSlice(name: Name): Int = lastIndexOfSlice(name.toString)
102103

103104
override def equals(that: Any) = this eq that.asInstanceOf[AnyRef]
104105
}
@@ -231,7 +232,7 @@ object Names {
231232
def isSimple = true
232233
def asSimpleName = this
233234
def toSimpleName = this
234-
def mapSimpleCore(f: SimpleTermName => Name): TermName = likeKinded(f(this))
235+
def rewrite(f: PartialFunction[Name, Name]): ThisName = likeKinded(f(this))
235236

236237
def encode: SimpleTermName =
237238
if (dontEncode(toTermName)) this else NameTransformer.encode(this)
@@ -272,7 +273,7 @@ object Names {
272273
def isSimple = toTermName.isSimple
273274
def asSimpleName = toTermName.asSimpleName
274275
def toSimpleName = toTermName.toSimpleName
275-
def mapSimpleCore(f: SimpleTermName => Name): TypeName = toTermName.mapSimpleCore(f).toTypeName
276+
def rewrite(f: PartialFunction[Name, Name]): ThisName = toTermName.rewrite(f).toTypeName
276277

277278
def likeKinded(name: Name): TypeName = name.toTypeName
278279

@@ -292,16 +293,13 @@ object Names {
292293
def isEmpty = false
293294
def encode: Name = underlying.encode.derived(info.map(_.encode))
294295
def decode: Name = underlying.decode.derived(info.map(_.decode))
295-
def firstPart = info match {
296-
case NameInfo.Qualified(name, _) => name
297-
case _ => underlying.firstPart
298-
}
296+
def firstPart = underlying.firstPart
299297
def lastPart = info match {
300-
case NameInfo.Qualified(name, _) => name
298+
case qual: NameInfo.Qualified => qual.name
301299
case _ => underlying.lastPart
302300
}
303301
def ++ (other: String): ThisName = info match {
304-
case NameInfo.Qualified(name, sep) => underlying.select(name ++ other, sep)
302+
case qual: NameInfo.Qualified => underlying.derived(qual.map(_ ++ other))
305303
case _ => (underlying ++ other).derived(info)
306304
}
307305
override def toString = info.mkString(underlying)
@@ -310,7 +308,13 @@ object Names {
310308
def isSimple = false
311309
def asSimpleName = throw new UnsupportedOperationException(s"$debugString is not a simple name")
312310
def toSimpleName = termName(toString)
313-
def mapSimpleCore(f: SimpleTermName => Name) = underlying.mapSimpleCore(f).derived(info)
311+
312+
def rewrite(f: PartialFunction[Name, Name]): ThisName =
313+
if (f.isDefinedAt(this)) likeKinded(f(this))
314+
else info match {
315+
case qual: NameInfo.Qualified => this
316+
case _ => underlying.rewrite(f).derived(info)
317+
}
314318
}
315319

316320
// Nametable
@@ -470,7 +474,6 @@ object Names {
470474
def seq: WrappedString = new WrappedString(name.toString)
471475
override protected[this] def thisCollection: WrappedString = seq
472476
def indexOfSlice(name: Name): Int = indexOfSlice(name.toString)
473-
def lastIndexOfSlice(name: Name): Int = lastIndexOfSlice(name.toString)
474477
def containsSlice(name: Name): Boolean = containsSlice(name.toString)
475478
}
476479

compiler/src/dotty/tools/dotc/core/StdNames.scala

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,11 @@ object StdNames {
1515

1616
/** Base strings from which synthetic names are derived. */
1717

18+
object str {
19+
val EXPAND_SEPARATOR = "$$"
20+
val TRAIT_SETTER_SEPARATOR = "$_setter_$"
21+
}
22+
1823
abstract class DefinedNames[N <: Name] {
1924
protected implicit def fromString(s: String): N
2025
protected def fromName(name: Name): N = fromString(name.toString)
@@ -99,7 +104,7 @@ object StdNames {
99104
val EVIDENCE_PARAM_PREFIX: N = "evidence$"
100105
val DEP_PARAM_PREFIX = "<param>"
101106
val EXCEPTION_RESULT_PREFIX: N = "exceptionResult"
102-
val EXPAND_SEPARATOR: N = "$$"
107+
val EXPAND_SEPARATOR: N = str.EXPAND_SEPARATOR
103108
val IMPL_CLASS_SUFFIX: N = "$class"
104109
val IMPORT: N = "<import>"
105110
val INLINE_ACCESSOR_PREFIX = "$inlineAccessor$"
@@ -129,7 +134,7 @@ object StdNames {
129134
val INITIALIZER_PREFIX: N = "initial$"
130135
val COMPANION_MODULE_METHOD: N = "companion$module"
131136
val COMPANION_CLASS_METHOD: N = "companion$class"
132-
val TRAIT_SETTER_SEPARATOR: N = "$_setter_$"
137+
val TRAIT_SETTER_SEPARATOR: N = str.TRAIT_SETTER_SEPARATOR
133138
val DIRECT_SUFFIX: N = "$direct"
134139
val LAZY_IMPLICIT_PREFIX: N = "$lazy_implicit$"
135140

compiler/src/dotty/tools/dotc/core/SymDenotations.scala

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -406,11 +406,13 @@ object SymDenotations {
406406
}
407407
var prefix = encl.fullNameSeparated(separator)
408408
val fn =
409-
if (Config.semanticNames) {
409+
if (Config.semanticNames && NameInfo.qualifier.contains(sep)) {
410410
if (sep == "$")
411411
// duplicate scalac's behavior: don't write a double '$$' for module class members.
412412
prefix = prefix.exclude(NameInfo.ModuleClassKind)
413-
name.mapSimpleCore(prefix.select(_, sep))
413+
name rewrite {
414+
case n: SimpleTermName => prefix.derived(NameInfo.qualifier(sep)(n))
415+
}
414416
}
415417
else {
416418
if (owner.is(ModuleClass, butNot = Package) && sep == "$")

compiler/src/dotty/tools/dotc/core/tasty/NameBuffer.scala

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,13 @@ class NameBuffer extends TastyBuffer(10000) {
2929
val tname = name.toTermName match {
3030
case DerivedTermName(name1, NameInfo.ModuleClass) =>
3131
ModuleClass(nameIndex(name1, toTasty))
32-
case DerivedTermName(prefix, NameInfo.Qualified(selector, ".")) =>
33-
Qualified(nameIndex(prefix, toTasty), nameIndex(selector))
32+
case DerivedTermName(prefix, qual: NameInfo.Qualified) =>
33+
val tcon: (NameRef, NameRef) => TastyName = qual match {
34+
case _: NameInfo.Select => Qualified
35+
case _: NameInfo.Flatten => Flattened
36+
case _: NameInfo.Expand => Expanded
37+
}
38+
tcon(nameIndex(prefix, toTasty), nameIndex(qual.name))
3439
case name1 =>
3540
if (name1.isShadowedName) Shadowed(nameIndex(name1.revertShadowed, toTasty))
3641
else toTasty(name1.asSimpleName)
@@ -72,14 +77,17 @@ class NameBuffer extends TastyBuffer(10000) {
7277
case Qualified(qualified, selector) =>
7378
writeByte(QUALIFIED)
7479
withLength { writeNameRef(qualified); writeNameRef(selector) }
80+
case Flattened(qualified, selector) =>
81+
writeByte(FLATTENED)
82+
withLength { writeNameRef(qualified); writeNameRef(selector) }
83+
case Expanded(prefix, original) =>
84+
writeByte(EXPANDED)
85+
withLength { writeNameRef(prefix); writeNameRef(original) }
7586
case Signed(original, params, result) =>
7687
writeByte(SIGNED)
7788
withLength(
7889
{ writeNameRef(original); writeNameRef(result); params.foreach(writeNameRef) },
7990
if ((params.length + 2) * maxIndexWidth <= maxNumInByte) 1 else 2)
80-
case Expanded(prefix, original) =>
81-
writeByte(EXPANDED)
82-
withLength { writeNameRef(prefix); writeNameRef(original) }
8391
case ModuleClass(module) =>
8492
writeByte(OBJECTCLASS)
8593
withLength { writeNameRef(module) }

compiler/src/dotty/tools/dotc/core/tasty/TastyFormat.scala

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -221,12 +221,13 @@ object TastyFormat {
221221

222222
final val UTF8 = 1
223223
final val QUALIFIED = 2
224-
final val SIGNED = 3
224+
final val FLATTENED = 3
225225
final val EXPANDED = 4
226-
final val OBJECTCLASS = 5
227-
final val SUPERACCESSOR = 6
228-
final val DEFAULTGETTER = 7
229-
final val SHADOWED = 8
226+
final val SIGNED = 5
227+
final val OBJECTCLASS = 6
228+
final val SUPERACCESSOR = 7
229+
final val DEFAULTGETTER = 8
230+
final val SHADOWED = 9
230231

231232
// AST tags
232233

compiler/src/dotty/tools/dotc/core/tasty/TastyName.scala

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,9 @@ object TastyName {
1414

1515
case class Simple(name: SimpleTermName) extends TastyName
1616
case class Qualified(qualified: NameRef, selector: NameRef) extends TastyName
17-
case class Signed(original: NameRef, params: List[NameRef], result: NameRef) extends TastyName
1817
case class Expanded(prefix: NameRef, original: NameRef) extends TastyName
18+
case class Flattened(prefix: NameRef, original: NameRef) extends TastyName
19+
case class Signed(original: NameRef, params: List[NameRef], result: NameRef) extends TastyName
1920
case class ModuleClass(module: NameRef) extends TastyName
2021
case class SuperAccessor(accessed: NameRef) extends TastyName
2122
case class DefaultGetter(method: NameRef, num: Int) extends TastyName

compiler/src/dotty/tools/dotc/core/tasty/TastyUnpickler.scala

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,13 +45,15 @@ class TastyUnpickler(reader: TastyReader) {
4545
Simple(termName(bytes, start.index, length))
4646
case QUALIFIED =>
4747
Qualified(readNameRef(), readNameRef())
48+
case FLATTENED =>
49+
Flattened(readNameRef(), readNameRef())
50+
case EXPANDED =>
51+
Expanded(readNameRef(), readNameRef())
4852
case SIGNED =>
4953
val original = readNameRef()
5054
val result = readNameRef()
5155
val params = until(end)(readNameRef())
5256
Signed(original, params, result)
53-
case EXPANDED =>
54-
Expanded(readNameRef(), readNameRef())
5557
case OBJECTCLASS =>
5658
ModuleClass(readNameRef())
5759
case SUPERACCESSOR =>

compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import scala.collection.mutable.ListBuffer
1515
import scala.collection.{ mutable, immutable }
1616
import config.Printers.pickling
1717
import typer.Checking
18+
import config.Config
1819

1920
/** Unpickler for typed trees
2021
* @param reader the reader from which to unpickle
@@ -76,15 +77,25 @@ class TreeUnpickler(reader: TastyReader, tastyName: TastyName.Table, posUnpickle
7677

7778
def toTermName(tname: TastyName): TermName = tname match {
7879
case Simple(name) => name
79-
case Qualified(qual, name) => toTermName(qual) ++ "." ++ toTermName(name)
80+
case Qualified(qual, name) =>
81+
if (Config.semanticNames) qualTermName(qual, name, ".")
82+
else toTermName(qual) ++ "." ++ toTermName(name)
83+
case Flattened(qual, name) =>
84+
if (Config.semanticNames) qualTermName(qual, name, "$")
85+
else toTermName(qual) ++ "$" ++ toTermName(name)
86+
case Expanded(prefix, original) =>
87+
if (Config.semanticNames) qualTermName(prefix, original, str.EXPAND_SEPARATOR)
88+
else toTermName(original).expandedName(toTermName(prefix))
8089
case Signed(original, params, result) => toTermName(original)
8190
case Shadowed(original) => toTermName(original).shadowedName
82-
case Expanded(prefix, original) => toTermName(original).expandedName(toTermName(prefix))
8391
case ModuleClass(original) => toTermName(original).moduleClassName.toTermName
8492
case SuperAccessor(accessed) => toTermName(accessed).superName
8593
case DefaultGetter(meth, num) => ???
8694
}
8795

96+
private def qualTermName(qual: NameRef, name: NameRef, sep: String) =
97+
toTermName(qual).derived(NameInfo.qualifier(sep)(toTermName(name).asSimpleName))
98+
8899
def toTermName(ref: NameRef): TermName = toTermName(tastyName(ref))
89100
def toTypeName(ref: NameRef): TypeName = toTermName(ref).toTypeName
90101

0 commit comments

Comments
 (0)