Skip to content

Commit e4f1c30

Browse files
committed
Polish and document NameKinds
1 parent e3e66ef commit e4f1c30

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
@@ -16,6 +16,7 @@ object NameKinds {
1616

1717
@sharable private val simpleNameKinds = new mutable.HashMap[Int, ClassifiedNameKind]
1818
@sharable private val qualifiedNameKinds = new mutable.HashMap[Int, QualifiedNameKind]
19+
@sharable private val numberedNameKinds = new mutable.HashMap[Int, NumberedNameKind]
1920
@sharable private val uniqueNameKinds = new mutable.HashMap[String, UniqueNameKind]
2021

2122
/** A class for the info stored in a derived name */
@@ -25,39 +26,65 @@ object NameKinds {
2526
def map(f: SimpleName => SimpleName): NameInfo = this
2627
}
2728

28-
/** The kind of a derived name info */
29+
/** An abstract base class of classes that define the kind of a derived name info */
2930
abstract class NameKind(val tag: Int) extends DotClass { self =>
31+
32+
/** The info class defined by this kind */
3033
type ThisInfo <: Info
34+
35+
/** A simple info type; some subclasses of Kind define more refined versions */
3136
class Info extends NameInfo { this: ThisInfo =>
3237
def kind = self
3338
def mkString(underlying: TermName) = self.mkString(underlying, this)
3439
override def toString = infoString
3540
}
41+
42+
/** Does this kind define logically a new name? Tested by the `rewrite` and `collect`
43+
* combinators of names.
44+
*/
3645
def definesNewName = false
46+
47+
/** Unmangle simple name `name` into a name of this kind, or return
48+
* original name if this is not possible.
49+
*/
3750
def unmangle(name: SimpleName): TermName = name
51+
52+
/** Turn a name of this kind consisting of an `underlying` prefix
53+
* and the given `info` into a string.
54+
*/
3855
def mkString(underlying: TermName, info: ThisInfo): String
56+
57+
/** A string used for displaying the structure of a name */
3958
def infoString: String
4059
}
4160

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

69+
/** The kind of names that add a simple classification to an underlying name.
70+
*/
4971
abstract class ClassifiedNameKind(tag: Int, val infoString: String) extends NameKind(tag) {
5072
type ThisInfo = Info
5173
val info = new Info
52-
def apply(qual: TermName) =
53-
qual.derived(info)
74+
75+
/** Build a new name of this kind from an underlying name */
76+
def apply(underlying: TermName) = underlying.derived(info)
77+
78+
/** Extractor operation for names of this kind */
5479
def unapply(name: DerivedName): Option[TermName] = name match {
5580
case DerivedName(underlying, `info`) => Some(underlying)
5681
case _ => None
5782
}
83+
5884
simpleNameKinds(tag) = this
5985
}
6086

87+
/** The kind of names that get formed by adding a prefix to an underlying name */
6188
class PrefixNameKind(tag: Int, prefix: String, optInfoString: String = "")
6289
extends ClassifiedNameKind(tag, if (optInfoString.isEmpty) s"Prefix $prefix" else optInfoString) {
6390
def mkString(underlying: TermName, info: ThisInfo) =
@@ -67,6 +94,7 @@ object NameKinds {
6794
else name
6895
}
6996

97+
/** The kind of names that get formed by appending a suffix to an underlying name */
7098
class SuffixNameKind(tag: Int, suffix: String, optInfoString: String = "")
7199
extends ClassifiedNameKind(tag, if (optInfoString.isEmpty) s"Suffix $suffix" else optInfoString) {
72100
def mkString(underlying: TermName, info: ThisInfo) = underlying.toString ++ suffix
@@ -75,17 +103,24 @@ object NameKinds {
75103
else name
76104
}
77105

106+
/** A base trait for infos that define an additional selector name */
78107
trait QualifiedInfo extends NameInfo {
79108
val name: SimpleName
80109
}
81110

111+
/** The kind of qualified names, consisting of an underlying name as a prefix,
112+
* followed by a separator, followed by a simple selector name.
113+
*
114+
* A qualified names always constitutes a new name, different from its underlying name.
115+
*/
82116
class QualifiedNameKind(tag: Int, val separator: String)
83117
extends NameKind(tag) {
84118
type ThisInfo = QualInfo
85119
case class QualInfo(val name: SimpleName) extends Info with QualifiedInfo {
86120
override def map(f: SimpleName => SimpleName): NameInfo = new QualInfo(f(name))
87121
override def toString = s"$infoString $name"
88122
}
123+
89124
def apply(qual: TermName, name: SimpleName): TermName =
90125
qual.derived(new QualInfo(name))
91126

@@ -107,11 +142,13 @@ object NameKinds {
107142

108143
def mkString(underlying: TermName, info: ThisInfo) =
109144
s"$underlying$separator${info.name}"
145+
110146
def infoString = s"Qualified $separator"
111147

112148
qualifiedNameKinds(tag) = this
113149
}
114150

151+
/** An extractor for qualified names of an arbitrary kind */
115152
object AnyQualifiedName {
116153
def unapply(name: DerivedName): Option[(TermName, SimpleName)] = name match {
117154
case DerivedName(qual, info: QualifiedInfo) =>
@@ -120,10 +157,12 @@ object NameKinds {
120157
}
121158
}
122159

160+
/** A base trait for infos that contain a number */
123161
trait NumberedInfo extends NameInfo {
124162
def num: Int
125163
}
126164

165+
/** The kind of numbered names consisting of an underlying name and a number */
127166
abstract class NumberedNameKind(tag: Int, val infoString: String) extends NameKind(tag) { self =>
128167
type ThisInfo = NumberedInfo
129168
case class NumberedInfo(val num: Int) extends Info with NameKinds.NumberedInfo {
@@ -142,29 +181,40 @@ object NameKinds {
142181
name.slice(i - separator.length, i).toString == separator) i
143182
else -1
144183
}
184+
185+
numberedNameKinds(tag) = this
145186
}
146187

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

196+
/** The kind of unique names that consist of an underlying name (can be empty),
197+
* a separator indicating the class of unique name, and a unique number.
198+
*
199+
* A unique names always constitutes a new name, different from its underlying name.
200+
*/
154201
case class UniqueNameKind(val separator: String)
155202
extends NumberedNameKind(UNIQUE, s"Unique $separator") {
156203
override def definesNewName = true
204+
157205
def mkString(underlying: TermName, info: ThisInfo) = {
158206
val safePrefix = str.sanitize(underlying.toString + separator)
159207
safePrefix + info.num
160208
}
161209

210+
/** Generate fresh unique name of this kind with given prefix name */
162211
def fresh(prefix: TermName = EmptyTermName)(implicit ctx: Context): TermName =
163212
ctx.freshNames.newName(prefix, this)
164213

165214
uniqueNameKinds(separator) = this
166215
}
167216

217+
/** An extractor for unique names of arbitrary kind */
168218
object AnyUniqueName {
169219
def unapply(name: DerivedName): Option[(TermName, String, Int)] = name match {
170220
case DerivedName(qual, info: NumberedInfo) =>
@@ -176,10 +226,16 @@ object NameKinds {
176226
}
177227
}
178228

179-
val QualifiedName = new QualifiedNameKind(QUALIFIED, ".")
180-
val FlatName = new QualifiedNameKind(FLATTENED, "$")
181-
val ExpandPrefixName = new QualifiedNameKind(EXPANDPREFIX, "$")
229+
/** Names of the form `prefix . name` */
230+
val QualifiedName = new QualifiedNameKind(QUALIFIED, ".")
231+
232+
/** Names of the form `prefix $ name` that are constructed as a result of flattening */
233+
val FlatName = new QualifiedNameKind(FLATTENED, "$")
234+
235+
/** Names of the form `prefix $ name` that are prefixes of expanded names */
236+
val ExpandPrefixName = new QualifiedNameKind(EXPANDPREFIX, "$")
182237

238+
/** Expanded names of the form `prefix $$ name`. */
183239
val ExpandedName = new QualifiedNameKind(EXPANDED, str.EXPAND_SEPARATOR) {
184240
private val FalseSuper = termName("$$super")
185241
private val FalseSuperLength = FalseSuper.length
@@ -199,13 +255,16 @@ object NameKinds {
199255
}
200256
}
201257

202-
val TraitSetterName = new QualifiedNameKind(TRAITSETTER, str.TRAIT_SETTER_SEPARATOR)
258+
/** Expanded names of the form `prefix $_setter_$ name`. These only occur in Scala2. */
259+
val TraitSetterName = new QualifiedNameKind(TRAITSETTER, str.TRAIT_SETTER_SEPARATOR)
203260

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

267+
/** Other unique names */
209268
val InlineAccessorName = new UniqueNameKind("$_inlineAccessor_$")
210269
val TempResultName = new UniqueNameKind("ev$")
211270
val EvidenceParamName = new UniqueNameKind("evidence$")
@@ -222,6 +281,9 @@ object NameKinds {
222281
val SkolemName = new UniqueNameKind("?")
223282
val LiftedTreeName = new UniqueNameKind("liftedTree")
224283

284+
/** A kind of unique extension methods; Unlike other unique names, these can be
285+
* unmangled.
286+
*/
225287
val UniqueExtMethName = new UniqueNameKind("$extension") {
226288
override def unmangle(name: SimpleName): TermName = {
227289
val i = skipSeparatorAndNum(name, separator)
@@ -234,6 +296,7 @@ object NameKinds {
234296
}
235297
}
236298

299+
/** Kinds of unique names generated by the pattern matcher */
237300
val PatMatStdBinderName = new UniqueNameKind("x")
238301
val PatMatPiName = new UniqueNameKind("pi") // FIXME: explain what this is
239302
val PatMatPName = new UniqueNameKind("p") // FIXME: explain what this is
@@ -242,6 +305,7 @@ object NameKinds {
242305
val PatMatMatchFailName = new UniqueNameKind("matchFail")
243306
val PatMatSelectorName = new UniqueNameKind("selector")
244307

308+
/** The kind of names of default argument getters */
245309
object DefaultGetterName extends NumberedNameKind(DEFAULTGETTER, "DefaultGetter") {
246310
def mkString(underlying: TermName, info: ThisInfo) = {
247311
val prefix = if (underlying.isConstructorName) nme.DEFAULT_GETTER_INIT else underlying
@@ -260,11 +324,9 @@ object NameKinds {
260324
}
261325
}
262326

327+
/** The kind of names that also encode a variance: 0 for contravariance, 1 for covariance. */
263328
object VariantName extends NumberedNameKind(VARIANT, "Variant") {
264-
val varianceToPrefix = Map(-1 -> '-', 0 -> '=', 1 -> '+')
265-
def mkString(underlying: TermName, info: ThisInfo) = {
266-
varianceToPrefix(info.num).toString + underlying
267-
}
329+
def mkString(underlying: TermName, info: ThisInfo) = "-+"(info.num).toString + underlying
268330
}
269331

270332
/** Names of the form N_<outer>. Emitted by inliner, replaced by outer path
@@ -289,9 +351,9 @@ object NameKinds {
289351
val ModuleVarName = new SuffixNameKind(OBJECTVAR, "$module")
290352
val ModuleClassName = new SuffixNameKind(OBJECTCLASS, "$", optInfoString = "ModuleClass")
291353

354+
/** A name together with a signature. Used in Tasty trees. */
292355
object SignedName extends NameKind(63) {
293356

294-
/** @param parts resultSig followed by paramsSig */
295357
case class SignedInfo(sig: Signature) extends Info {
296358
override def toString = s"$infoString $sig"
297359
}
@@ -308,10 +370,12 @@ object NameKinds {
308370
def infoString: String = "Signed"
309371
}
310372

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

314377
def simpleNameKindOfTag : collection.Map[Int, ClassifiedNameKind] = simpleNameKinds
315378
def qualifiedNameKindOfTag : collection.Map[Int, QualifiedNameKind] = qualifiedNameKinds
379+
def numberedNameKindOfTag : collection.Map[Int, NumberedNameKind] = numberedNameKinds
316380
def uniqueNameKindOfSeparator: collection.Map[String, UniqueNameKind] = uniqueNameKinds
317381
}

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)