Skip to content

Commit 22f8013

Browse files
committed
Polish and document NameKinds
1 parent 24065e2 commit 22f8013

File tree

6 files changed

+94
-33
lines changed

6 files changed

+94
-33
lines changed

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

Lines changed: 76 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ object NameKinds {
1919
// be created lazily or in modules that start running after compilers are forked.
2020
@sharable private val simpleNameKinds = new mutable.HashMap[Int, ClassifiedNameKind]
2121
@sharable private val qualifiedNameKinds = new mutable.HashMap[Int, QualifiedNameKind]
22+
@sharable private val numberedNameKinds = new mutable.HashMap[Int, NumberedNameKind]
2223
@sharable private val uniqueNameKinds = new mutable.HashMap[String, UniqueNameKind]
2324

2425
/** A class for the info stored in a derived name */
@@ -28,39 +29,65 @@ object NameKinds {
2829
def map(f: SimpleName => SimpleName): NameInfo = this
2930
}
3031

31-
/** The kind of a derived name info */
32+
/** An abstract base class of classes that define the kind of a derived name info */
3233
abstract class NameKind(val tag: Int) extends DotClass { self =>
34+
35+
/** The info class defined by this kind */
3336
type ThisInfo <: Info
37+
38+
/** A simple info type; some subclasses of Kind define more refined versions */
3439
class Info extends NameInfo { this: ThisInfo =>
3540
def kind = self
3641
def mkString(underlying: TermName) = self.mkString(underlying, this)
3742
override def toString = infoString
3843
}
44+
45+
/** Does this kind define logically a new name? Tested by the `rewrite` and `collect`
46+
* combinators of names.
47+
*/
3948
def definesNewName = false
49+
50+
/** Unmangle simple name `name` into a name of this kind, or return
51+
* original name if this is not possible.
52+
*/
4053
def unmangle(name: SimpleName): TermName = name
54+
55+
/** Turn a name of this kind consisting of an `underlying` prefix
56+
* and the given `info` into a string.
57+
*/
4158
def mkString(underlying: TermName, info: ThisInfo): String
59+
60+
/** A string used for displaying the structure of a name */
4261
def infoString: String
4362
}
4463

64+
/** The kind of SimpleNames */
4565
object SimpleNameKind extends NameKind(UTF8) { self =>
4666
type ThisInfo = Info
4767
val info = new Info
4868
def mkString(underlying: TermName, info: ThisInfo) = unsupported("mkString")
4969
def infoString = unsupported("infoString")
5070
}
5171

72+
/** The kind of names that add a simple classification to an underlying name.
73+
*/
5274
abstract class ClassifiedNameKind(tag: Int, val infoString: String) extends NameKind(tag) {
5375
type ThisInfo = Info
5476
val info = new Info
55-
def apply(qual: TermName) =
56-
qual.derived(info)
77+
78+
/** Build a new name of this kind from an underlying name */
79+
def apply(underlying: TermName) = underlying.derived(info)
80+
81+
/** Extractor operation for names of this kind */
5782
def unapply(name: DerivedName): Option[TermName] = name match {
5883
case DerivedName(underlying, `info`) => Some(underlying)
5984
case _ => None
6085
}
86+
6187
simpleNameKinds(tag) = this
6288
}
6389

90+
/** The kind of names that get formed by adding a prefix to an underlying name */
6491
class PrefixNameKind(tag: Int, prefix: String, optInfoString: String = "")
6592
extends ClassifiedNameKind(tag, if (optInfoString.isEmpty) s"Prefix $prefix" else optInfoString) {
6693
def mkString(underlying: TermName, info: ThisInfo) =
@@ -70,6 +97,7 @@ object NameKinds {
7097
else name
7198
}
7299

100+
/** The kind of names that get formed by appending a suffix to an underlying name */
73101
class SuffixNameKind(tag: Int, suffix: String, optInfoString: String = "")
74102
extends ClassifiedNameKind(tag, if (optInfoString.isEmpty) s"Suffix $suffix" else optInfoString) {
75103
def mkString(underlying: TermName, info: ThisInfo) = underlying.toString ++ suffix
@@ -78,17 +106,24 @@ object NameKinds {
78106
else name
79107
}
80108

109+
/** A base trait for infos that define an additional selector name */
81110
trait QualifiedInfo extends NameInfo {
82111
val name: SimpleName
83112
}
84113

114+
/** The kind of qualified names, consisting of an underlying name as a prefix,
115+
* followed by a separator, followed by a simple selector name.
116+
*
117+
* A qualified names always constitutes a new name, different from its underlying name.
118+
*/
85119
class QualifiedNameKind(tag: Int, val separator: String)
86120
extends NameKind(tag) {
87121
type ThisInfo = QualInfo
88122
case class QualInfo(val name: SimpleName) extends Info with QualifiedInfo {
89123
override def map(f: SimpleName => SimpleName): NameInfo = new QualInfo(f(name))
90124
override def toString = s"$infoString $name"
91125
}
126+
92127
def apply(qual: TermName, name: SimpleName): TermName =
93128
qual.derived(new QualInfo(name))
94129

@@ -110,11 +145,13 @@ object NameKinds {
110145

111146
def mkString(underlying: TermName, info: ThisInfo) =
112147
s"$underlying$separator${info.name}"
148+
113149
def infoString = s"Qualified $separator"
114150

115151
qualifiedNameKinds(tag) = this
116152
}
117153

154+
/** An extractor for qualified names of an arbitrary kind */
118155
object AnyQualifiedName {
119156
def unapply(name: DerivedName): Option[(TermName, SimpleName)] = name match {
120157
case DerivedName(qual, info: QualifiedInfo) =>
@@ -123,10 +160,12 @@ object NameKinds {
123160
}
124161
}
125162

163+
/** A base trait for infos that contain a number */
126164
trait NumberedInfo extends NameInfo {
127165
def num: Int
128166
}
129167

168+
/** The kind of numbered names consisting of an underlying name and a number */
130169
abstract class NumberedNameKind(tag: Int, val infoString: String) extends NameKind(tag) { self =>
131170
type ThisInfo = NumberedInfo
132171
case class NumberedInfo(val num: Int) extends Info with NameKinds.NumberedInfo {
@@ -145,29 +184,40 @@ object NameKinds {
145184
name.slice(i - separator.length, i).toString == separator) i
146185
else -1
147186
}
187+
188+
numberedNameKinds(tag) = this
148189
}
149190

191+
/** An extractor for numbered names of arbitrary kind */
150192
object AnyNumberedName {
151193
def unapply(name: DerivedName): Option[(TermName, Int)] = name match {
152194
case DerivedName(qual, info: NumberedInfo) => Some((qual, info.num))
153195
case _ => None
154196
}
155197
}
156198

199+
/** The kind of unique names that consist of an underlying name (can be empty),
200+
* a separator indicating the class of unique name, and a unique number.
201+
*
202+
* A unique names always constitutes a new name, different from its underlying name.
203+
*/
157204
case class UniqueNameKind(val separator: String)
158205
extends NumberedNameKind(UNIQUE, s"Unique $separator") {
159206
override def definesNewName = true
207+
160208
def mkString(underlying: TermName, info: ThisInfo) = {
161209
val safePrefix = str.sanitize(underlying.toString + separator)
162210
safePrefix + info.num
163211
}
164212

213+
/** Generate fresh unique name of this kind with given prefix name */
165214
def fresh(prefix: TermName = EmptyTermName)(implicit ctx: Context): TermName =
166215
ctx.freshNames.newName(prefix, this)
167216

168217
uniqueNameKinds(separator) = this
169218
}
170219

220+
/** An extractor for unique names of arbitrary kind */
171221
object AnyUniqueName {
172222
def unapply(name: DerivedName): Option[(TermName, String, Int)] = name match {
173223
case DerivedName(qual, info: NumberedInfo) =>
@@ -179,10 +229,16 @@ object NameKinds {
179229
}
180230
}
181231

182-
val QualifiedName = new QualifiedNameKind(QUALIFIED, ".")
183-
val FlatName = new QualifiedNameKind(FLATTENED, "$")
184-
val ExpandPrefixName = new QualifiedNameKind(EXPANDPREFIX, "$")
232+
/** Names of the form `prefix . name` */
233+
val QualifiedName = new QualifiedNameKind(QUALIFIED, ".")
234+
235+
/** Names of the form `prefix $ name` that are constructed as a result of flattening */
236+
val FlatName = new QualifiedNameKind(FLATTENED, "$")
237+
238+
/** Names of the form `prefix $ name` that are prefixes of expanded names */
239+
val ExpandPrefixName = new QualifiedNameKind(EXPANDPREFIX, "$")
185240

241+
/** Expanded names of the form `prefix $$ name`. */
186242
val ExpandedName = new QualifiedNameKind(EXPANDED, str.EXPAND_SEPARATOR) {
187243
private val FalseSuper = termName("$$super")
188244
private val FalseSuperLength = FalseSuper.length
@@ -202,13 +258,16 @@ object NameKinds {
202258
}
203259
}
204260

205-
val TraitSetterName = new QualifiedNameKind(TRAITSETTER, str.TRAIT_SETTER_SEPARATOR)
261+
/** Expanded names of the form `prefix $_setter_$ name`. These only occur in Scala2. */
262+
val TraitSetterName = new QualifiedNameKind(TRAITSETTER, str.TRAIT_SETTER_SEPARATOR)
206263

264+
/** Unique names of the form `prefix $ n` or `$ n $` */
207265
val UniqueName = new UniqueNameKind("$") {
208266
override def mkString(underlying: TermName, info: ThisInfo) =
209267
if (underlying.isEmpty) "$" + info.num + "$" else super.mkString(underlying, info)
210268
}
211269

270+
/** Other unique names */
212271
val InlineAccessorName = new UniqueNameKind("$_inlineAccessor_$")
213272
val TempResultName = new UniqueNameKind("ev$")
214273
val EvidenceParamName = new UniqueNameKind("evidence$")
@@ -225,6 +284,9 @@ object NameKinds {
225284
val SkolemName = new UniqueNameKind("?")
226285
val LiftedTreeName = new UniqueNameKind("liftedTree")
227286

287+
/** A kind of unique extension methods; Unlike other unique names, these can be
288+
* unmangled.
289+
*/
228290
val UniqueExtMethName = new UniqueNameKind("$extension") {
229291
override def unmangle(name: SimpleName): TermName = {
230292
val i = skipSeparatorAndNum(name, separator)
@@ -237,6 +299,7 @@ object NameKinds {
237299
}
238300
}
239301

302+
/** Kinds of unique names generated by the pattern matcher */
240303
val PatMatStdBinderName = new UniqueNameKind("x")
241304
val PatMatPiName = new UniqueNameKind("pi") // FIXME: explain what this is
242305
val PatMatPName = new UniqueNameKind("p") // FIXME: explain what this is
@@ -245,6 +308,7 @@ object NameKinds {
245308
val PatMatMatchFailName = new UniqueNameKind("matchFail")
246309
val PatMatSelectorName = new UniqueNameKind("selector")
247310

311+
/** The kind of names of default argument getters */
248312
object DefaultGetterName extends NumberedNameKind(DEFAULTGETTER, "DefaultGetter") {
249313
def mkString(underlying: TermName, info: ThisInfo) = {
250314
val prefix = if (underlying.isConstructorName) nme.DEFAULT_GETTER_INIT else underlying
@@ -263,11 +327,9 @@ object NameKinds {
263327
}
264328
}
265329

330+
/** The kind of names that also encode a variance: 0 for contravariance, 1 for covariance. */
266331
object VariantName extends NumberedNameKind(VARIANT, "Variant") {
267-
val varianceToPrefix = Map(-1 -> '-', 0 -> '=', 1 -> '+')
268-
def mkString(underlying: TermName, info: ThisInfo) = {
269-
varianceToPrefix(info.num).toString + underlying
270-
}
332+
def mkString(underlying: TermName, info: ThisInfo) = "-+"(info.num).toString + underlying
271333
}
272334

273335
/** Names of the form N_<outer>. Emitted by inliner, replaced by outer path
@@ -292,9 +354,9 @@ object NameKinds {
292354
val ModuleVarName = new SuffixNameKind(OBJECTVAR, "$module")
293355
val ModuleClassName = new SuffixNameKind(OBJECTCLASS, "$", optInfoString = "ModuleClass")
294356

357+
/** A name together with a signature. Used in Tasty trees. */
295358
object SignedName extends NameKind(63) {
296359

297-
/** @param parts resultSig followed by paramsSig */
298360
case class SignedInfo(sig: Signature) extends Info {
299361
override def toString = s"$infoString $sig"
300362
}
@@ -311,10 +373,12 @@ object NameKinds {
311373
def infoString: String = "Signed"
312374
}
313375

376+
/** Possible name kinds of a method that comes from Scala2 pickling info. */
314377
val Scala2MethodNameKinds: List[NameKind] =
315378
List(DefaultGetterName, ExtMethName, UniqueExtMethName, ProtectedAccessorName, ProtectedSetterName)
316379

317380
def simpleNameKindOfTag : collection.Map[Int, ClassifiedNameKind] = simpleNameKinds
318381
def qualifiedNameKindOfTag : collection.Map[Int, QualifiedNameKind] = qualifiedNameKinds
382+
def numberedNameKindOfTag : collection.Map[Int, NumberedNameKind] = numberedNameKinds
319383
def uniqueNameKindOfSeparator: collection.Map[String, UniqueNameKind] = uniqueNameKinds
320384
}

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

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -128,15 +128,24 @@ object NameOps {
128128

129129
def errorName: N = likeSpaced(name ++ nme.ERROR)
130130

131+
/** Map variance value -1, +1 to 0, 1 */
132+
private def varianceToNat(v: Int) = (v + 1) / 2
133+
134+
/** Map 0, 1 to variance value -1, +1 */
135+
private def natToVariance(n: Int) = n * 2 - 1
131136

132137
/** Name with variance prefix: `+` for covariant, `-` for contravariant */
133-
def withVariance(v: Int): N =
134-
likeSpaced { VariantName(name.exclude(VariantName).toTermName, v) }
138+
def withVariance(v: Int): N = {
139+
val underlying = name.exclude(VariantName)
140+
likeSpaced(
141+
if (v == 0) underlying
142+
else VariantName(underlying.toTermName, varianceToNat(v)))
143+
}
135144

136145
/** The variance as implied by the variance prefix, or 0 if there is
137146
* no variance prefix.
138147
*/
139-
def variance = name.collect { case VariantName(_, n) => n }.getOrElse(0)
148+
def variance = name.collect { case VariantName(_, n) => natToVariance(n) }.getOrElse(0)
140149

141150
def freshened(implicit ctx: Context): N = likeSpaced {
142151
name.toTermName match {

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

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -84,13 +84,15 @@ object Names {
8484
}
8585

8686
/** Apply rewrite rule given by `f` to some part of this name, skipping and rewrapping
87-
* other decorators. Stops at first qualified name that's encountered.
87+
* other decorators.
88+
* Stops at derived names whose kind has `definesNewName = true`.
8889
* If `f` does not apply to any part, return name unchanged.
8990
*/
9091
def rewrite(f: PartialFunction[Name, Name]): ThisName
9192

9293
/** If partial function `f` is defined for some part of this name, apply it
93-
* in a Some, otherwise None. Stops at first qualified name that's encountered.
94+
* in a Some, otherwise None.
95+
* Stops at derived names whose kind has `definesNewName = true`.
9496
*/
9597
def collect[T](f: PartialFunction[Name, T]): Option[T]
9698

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

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -34,14 +34,6 @@ import scala.annotation.tailrec
3434
case class Signature(paramsSig: List[TypeName], resSig: TypeName) {
3535
import Signature._
3636

37-
/* FIXME does not compile under dotty, we get a missing param error
38-
def checkUnqual(name: TypeName) = name mapParts { part =>
39-
assert(!part.contains('.'), name)
40-
part
41-
}
42-
paramsSig.foreach(checkUnqual)
43-
checkUnqual(resSig)
44-
*/
4537
/** Two names are consistent if they are the same or one of them is tpnme.Uninstantiated */
4638
private def consistent(name1: TypeName, name2: TypeName) =
4739
name1 == name2 || name1 == tpnme.Uninstantiated || name2 == tpnme.Uninstantiated

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

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,8 +70,6 @@ class NameBuffer extends TastyBuffer(10000) {
7070
writeNat(num)
7171
if (!original.isEmpty) writeNameRef(original)
7272
}
73-
case VariantName(original, sign) =>
74-
withLength { writeNameRef(original); writeNat(sign + 1) }
7573
case AnyNumberedName(original, num) =>
7674
withLength { writeNameRef(original); writeNat(num) }
7775
case SignedName(original, Signature(params, result)) =>

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

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -57,12 +57,8 @@ class TastyUnpickler(reader: TastyReader) {
5757
val originals = until(end)(readName())
5858
val original = if (originals.isEmpty) EmptyTermName else originals.head
5959
uniqueNameKindOfSeparator(separator)(original, num)
60-
case DEFAULTGETTER =>
61-
DefaultGetterName(readName(), readNat())
62-
case VARIANT =>
63-
VariantName(readName(), readNat() - 1)
64-
case OUTERSELECT =>
65-
OuterSelectName(readName(), readNat())
60+
case DEFAULTGETTER | VARIANT | OUTERSELECT =>
61+
numberedNameKindOfTag(tag)(readName(), readNat())
6662
case SIGNED =>
6763
val original = readName()
6864
val result = readName().toTypeName

0 commit comments

Comments
 (0)