forked from scala/scala3
/
NameKinds.scala
394 lines (335 loc) · 16.2 KB
/
NameKinds.scala
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
package dotty.tools
package dotc
package core
import Names._
import NameOps._
import StdNames._
import util.DotClass
import tasty.TastyFormat._
import Decorators._
import Contexts.Context
import collection.mutable
/** Defines possible kinds of NameInfo of a derived name */
object NameKinds {
// These are sharable since all NameKinds are created eagerly at the start of the program
// before any concurrent threads are forked. for this to work, NameKinds should never
// be created lazily or in modules that start running after compilers are forked.
@sharable private val simpleNameKinds = new mutable.HashMap[Int, ClassifiedNameKind]
@sharable private val qualifiedNameKinds = new mutable.HashMap[Int, QualifiedNameKind]
@sharable private val numberedNameKinds = new mutable.HashMap[Int, NumberedNameKind]
@sharable private val uniqueNameKinds = new mutable.HashMap[String, UniqueNameKind]
/** A class for the info stored in a derived name */
abstract class NameInfo extends DotClass {
def kind: NameKind
def mkString(underlying: TermName): String
def map(f: SimpleName => SimpleName): NameInfo = this
}
/** An abstract base class of classes that define the kind of a derived name info */
abstract class NameKind(val tag: Int) extends DotClass { self =>
/** The info class defined by this kind */
type ThisInfo <: Info
/** A simple info type; some subclasses of Kind define more refined versions */
class Info extends NameInfo { this: ThisInfo =>
def kind = self
def mkString(underlying: TermName) = self.mkString(underlying, this)
override def toString = infoString
}
/** Does this kind define logically a new name (respectively qualified name)?
* Tested by the `rewrite` and `collect` combinators of class `Name`.
*/
def definesNewName = false
def definesQualifiedName = false
/** Unmangle simple name `name` into a name of this kind, or return
* original name if this is not possible.
*/
def unmangle(name: SimpleName): TermName = name
/** Turn a name of this kind consisting of an `underlying` prefix
* and the given `info` into a string. Used to turn structured into
* simple name.
*/
def mkString(underlying: TermName, info: ThisInfo): String
/** A string used for displaying the structure of a name */
def infoString: String
}
object SimpleNameKind extends NameKind(UTF8) { self =>
type ThisInfo = Info
val info = new Info
def mkString(underlying: TermName, info: ThisInfo) = unsupported("mkString")
def infoString = unsupported("infoString")
}
/** The kind of names that add a simple classification to an underlying name.
*/
abstract class ClassifiedNameKind(tag: Int, val infoString: String) extends NameKind(tag) {
type ThisInfo = Info
val info = new Info
/** Build a new name of this kind from an underlying name */
def apply(underlying: TermName) = underlying.derived(info)
/** Extractor operation for names of this kind */
def unapply(name: DerivedName): Option[TermName] = name match {
case DerivedName(underlying, `info`) => Some(underlying)
case _ => None
}
simpleNameKinds(tag) = this
}
/** The kind of names that get formed by adding a prefix to an underlying name */
class PrefixNameKind(tag: Int, prefix: String, optInfoString: String = "")
extends ClassifiedNameKind(tag, if (optInfoString.isEmpty) s"Prefix $prefix" else optInfoString) {
def mkString(underlying: TermName, info: ThisInfo) =
underlying.qualToString(_.mangledString, n => prefix + n.mangled.toString)
override def unmangle(name: SimpleName): TermName =
if (name.startsWith(prefix)) apply(name.drop(prefix.length).asSimpleName)
else name
}
/** The kind of names that get formed by appending a suffix to an underlying name */
class SuffixNameKind(tag: Int, suffix: String, optInfoString: String = "")
extends ClassifiedNameKind(tag, if (optInfoString.isEmpty) s"Suffix $suffix" else optInfoString) {
def mkString(underlying: TermName, info: ThisInfo) =
underlying.qualToString(_.mangledString, n => n.mangled.toString + suffix)
override def unmangle(name: SimpleName): TermName =
if (name.endsWith(suffix)) apply(name.take(name.length - suffix.length).asSimpleName)
else name
}
/** A base trait for infos that define an additional selector name */
trait QualifiedInfo extends NameInfo {
val name: SimpleName
}
/** The kind of qualified names, consisting of an underlying name as a prefix,
* followed by a separator, followed by a simple selector name.
*
* A qualified names always constitutes a new name, different from its underlying name.
*/
class QualifiedNameKind(tag: Int, val separator: String)
extends NameKind(tag) {
type ThisInfo = QualInfo
case class QualInfo(name: SimpleName) extends Info with QualifiedInfo {
override def map(f: SimpleName => SimpleName): NameInfo = new QualInfo(f(name))
override def toString = s"$infoString $name"
}
def apply(qual: TermName, name: SimpleName): TermName =
qual.derived(new QualInfo(name))
/** Overloaded version used only for ExpandedName and TraitSetterName.
* Needed because the suffix of an expanded name may itself be expanded.
* For example, look at javap of scala.App.initCode
*/
def apply(qual: TermName, name: TermName): TermName = name rewrite {
case name: SimpleName => apply(qual, name)
case AnyQualifiedName(_, _) => apply(qual, name.toSimpleName)
}
def unapply(name: DerivedName): Option[(TermName, SimpleName)] = name match {
case DerivedName(qual, info: this.QualInfo) => Some((qual, info.name))
case _ => None
}
override def definesNewName = true
override def definesQualifiedName = true
def mkString(underlying: TermName, info: ThisInfo) =
s"$underlying$separator${info.name}"
def infoString = s"Qualified $separator"
qualifiedNameKinds(tag) = this
}
/** An extractor for qualified names of an arbitrary kind */
object AnyQualifiedName {
def unapply(name: DerivedName): Option[(TermName, SimpleName)] = name match {
case DerivedName(qual, info: QualifiedInfo) =>
Some((name.underlying, info.name))
case _ => None
}
}
/** A base trait for infos that contain a number */
trait NumberedInfo extends NameInfo {
def num: Int
}
/** The kind of numbered names consisting of an underlying name and a number */
abstract class NumberedNameKind(tag: Int, val infoString: String) extends NameKind(tag) { self =>
type ThisInfo = NumberedInfo
case class NumberedInfo(val num: Int) extends Info with NameKinds.NumberedInfo {
override def toString = s"$infoString $num"
}
def apply(qual: TermName, num: Int) =
qual.derived(new NumberedInfo(num))
def unapply(name: DerivedName): Option[(TermName, Int)] = name match {
case DerivedName(underlying, info: this.NumberedInfo) => Some((underlying, info.num))
case _ => None
}
protected def skipSeparatorAndNum(name: SimpleName, separator: String): Int = {
var i = name.length
while (i > 0 && name(i - 1).isDigit) i -= 1
if (i > separator.length && i < name.length &&
name.slice(i - separator.length, i).toString == separator) i
else -1
}
numberedNameKinds(tag) = this
}
/** An extractor for numbered names of arbitrary kind */
object AnyNumberedName {
def unapply(name: DerivedName): Option[(TermName, Int)] = name match {
case DerivedName(qual, info: NumberedInfo) => Some((qual, info.num))
case _ => None
}
}
/** The kind of unique names that consist of an underlying name (can be empty),
* a separator indicating the class of unique name, and a unique number.
*
* A unique names always constitutes a new name, different from its underlying name.
*/
case class UniqueNameKind(val separator: String)
extends NumberedNameKind(UNIQUE, s"Unique $separator") {
override def definesNewName = true
def mkString(underlying: TermName, info: ThisInfo) = {
val safePrefix = str.sanitize(underlying.toString) + separator
safePrefix + info.num
}
/** Generate fresh unique name of this kind with given prefix name */
def fresh(prefix: TermName = EmptyTermName)(implicit ctx: Context): TermName =
ctx.freshNames.newName(prefix, this)
uniqueNameKinds(separator) = this
}
/** An extractor for unique names of arbitrary kind */
object AnyUniqueName {
def unapply(name: DerivedName): Option[(TermName, String, Int)] = name match {
case DerivedName(qual, info: NumberedInfo) =>
info.kind match {
case unique: UniqueNameKind => Some((qual, unique.separator, info.num))
case _ => None
}
case _ => None
}
}
/** Names of the form `prefix . name` */
val QualifiedName = new QualifiedNameKind(QUALIFIED, ".")
/** Names of the form `prefix $ name` that are constructed as a result of flattening */
val FlatName = new QualifiedNameKind(FLATTENED, "$")
/** Names of the form `prefix $ name` that are prefixes of expanded names */
val ExpandPrefixName = new QualifiedNameKind(EXPANDPREFIX, "$")
/** Expanded names of the form `prefix $$ name`. */
val ExpandedName = new QualifiedNameKind(EXPANDED, str.EXPAND_SEPARATOR) {
private val FalseSuper = termName("$$super")
private val FalseSuperLength = FalseSuper.length
override def unmangle(name: SimpleName): TermName = {
var i = name.lastIndexOfSlice(str.EXPAND_SEPARATOR)
if (i < 0) name
else {
// Hack to make super accessors from traits work. They would otherwise fail because of #765
// The problem is that in `x$$super$$plus` the expansion prefix needs to be `x`
// instead of `x$$super`.
if (i > FalseSuperLength && name.slice(i - FalseSuperLength, i) == FalseSuper)
i -= FalseSuper.length
apply(name.take(i).asTermName, name.drop(i + str.EXPAND_SEPARATOR.length).asSimpleName)
}
}
}
/** Expanded names of the form `prefix $_setter_$ name`. These only occur in Scala2. */
val TraitSetterName = new QualifiedNameKind(TRAITSETTER, str.TRAIT_SETTER_SEPARATOR)
/** Unique names of the form `prefix $ n` or `$ n $` */
val UniqueName = new UniqueNameKind("$") {
override def mkString(underlying: TermName, info: ThisInfo) =
if (underlying.isEmpty) "$" + info.num + "$" else super.mkString(underlying, info)
}
/** Other unique names */
val InlineAccessorName = new UniqueNameKind("$_inlineAccessor_$")
val TempResultName = new UniqueNameKind("ev$")
val EvidenceParamName = new UniqueNameKind("evidence$")
val DepParamName = new UniqueNameKind("(param)")
val LazyImplicitName = new UniqueNameKind("$_lazy_implicit_$")
val LazyLocalName = new UniqueNameKind("$lzy")
val LazyLocalInitName = new UniqueNameKind("$lzyINIT")
val LazyFieldOffsetName = new UniqueNameKind("$OFFSET")
val LazyBitMapName = new UniqueNameKind(nme.BITMAP_PREFIX.toString)
val NonLocalReturnKeyName = new UniqueNameKind("nonLocalReturnKey")
val WildcardParamName = new UniqueNameKind("_$")
val TailLabelName = new UniqueNameKind("tailLabel")
val ExceptionBinderName = new UniqueNameKind("ex")
val SkolemName = new UniqueNameKind("?")
val LiftedTreeName = new UniqueNameKind("liftedTree")
val SuperArgName = new UniqueNameKind("$superArg$")
/** A kind of unique extension methods; Unlike other unique names, these can be
* unmangled.
*/
val UniqueExtMethName = new UniqueNameKind("$extension") {
override def unmangle(name: SimpleName): TermName = {
val i = skipSeparatorAndNum(name, separator)
if (i > 0) {
val index = name.drop(i).toString.toInt
val original = name.take(i - separator.length).asTermName
apply(original, index)
}
else name
}
}
/** Kinds of unique names generated by the pattern matcher */
val PatMatStdBinderName = new UniqueNameKind("x")
val PatMatPiName = new UniqueNameKind("pi") // FIXME: explain what this is
val PatMatPName = new UniqueNameKind("p") // FIXME: explain what this is
val PatMatOName = new UniqueNameKind("o") // FIXME: explain what this is
val PatMatCaseName = new UniqueNameKind("case")
val PatMatMatchFailName = new UniqueNameKind("matchFail")
val PatMatSelectorName = new UniqueNameKind("selector")
val LocalOptInlineLocalObj = new UniqueNameKind("ilo")
/** The kind of names of default argument getters */
val DefaultGetterName = new NumberedNameKind(DEFAULTGETTER, "DefaultGetter") {
def mkString(underlying: TermName, info: ThisInfo) = {
val prefix = if (underlying.isConstructorName) nme.DEFAULT_GETTER_INIT else underlying
prefix.toString + str.DEFAULT_GETTER + (info.num + 1)
}
// TODO: Reduce code duplication with UniqueExtMethName
override def unmangle(name: SimpleName): TermName = {
val i = skipSeparatorAndNum(name, str.DEFAULT_GETTER)
if (i > 0) {
val index = name.drop(i).toString.toInt - 1
var original = name.take(i - str.DEFAULT_GETTER.length).asTermName
if (original == nme.DEFAULT_GETTER_INIT) original = nme.CONSTRUCTOR
apply(original, index)
}
else name
}
}
/** The kind of names that also encode a variance: 0 for contravariance, 1 for covariance. */
val VariantName = new NumberedNameKind(VARIANT, "Variant") {
def mkString(underlying: TermName, info: ThisInfo) = "-+"(info.num).toString + underlying
}
/** Names of the form N_<outer>. Emitted by inliner, replaced by outer path
* in ExplicitOuter.
*/
val OuterSelectName = new NumberedNameKind(OUTERSELECT, "OuterSelect") {
def mkString(underlying: TermName, info: ThisInfo) = {
assert(underlying.isEmpty)
info.num + "_<outer>"
}
}
val SuperAccessorName = new PrefixNameKind(SUPERACCESSOR, "super$")
val InitializerName = new PrefixNameKind(INITIALIZER, "initial$")
val ProtectedAccessorName = new PrefixNameKind(PROTECTEDACCESSOR, "protected$")
val ProtectedSetterName = new PrefixNameKind(PROTECTEDSETTER, "protected$set") // dubious encoding, kept for Scala2 compatibility
val AvoidClashName = new SuffixNameKind(AVOIDCLASH, "$_avoid_name_clash_$")
val DirectMethodName = new SuffixNameKind(DIRECT, "$direct") { override def definesNewName = true }
val FieldName = new SuffixNameKind(FIELD, "$$local") {
override def mkString(underlying: TermName, info: ThisInfo) = underlying.toString
}
val ExtMethName = new SuffixNameKind(EXTMETH, "$extension")
val ModuleVarName = new SuffixNameKind(OBJECTVAR, "$module")
val ModuleClassName = new SuffixNameKind(OBJECTCLASS, "$", optInfoString = "ModuleClass")
val ImplMethName = new SuffixNameKind(IMPLMETH, "$")
val AdaptedClosureName = new SuffixNameKind(ADAPTEDCLOSURE, "$adapted") { override def definesNewName = true }
/** A name together with a signature. Used in Tasty trees. */
object SignedName extends NameKind(SIGNED) {
case class SignedInfo(sig: Signature) extends Info {
assert(sig ne Signature.NotAMethod)
override def toString = s"$infoString $sig"
}
type ThisInfo = SignedInfo
def apply(qual: TermName, sig: Signature) =
qual.derived(new SignedInfo(sig))
def unapply(name: DerivedName): Option[(TermName, Signature)] = name match {
case DerivedName(underlying, info: SignedInfo) => Some((underlying, info.sig))
case _ => None
}
def mkString(underlying: TermName, info: ThisInfo): String = s"$underlying[with sig ${info.sig}]"
def infoString: String = "Signed"
}
/** Possible name kinds of a method that comes from Scala2 pickling info. */
val Scala2MethodNameKinds: List[NameKind] =
List(DefaultGetterName, ExtMethName, UniqueExtMethName, ProtectedAccessorName, ProtectedSetterName)
def simpleNameKindOfTag : collection.Map[Int, ClassifiedNameKind] = simpleNameKinds
def qualifiedNameKindOfTag : collection.Map[Int, QualifiedNameKind] = qualifiedNameKinds
def numberedNameKindOfTag : collection.Map[Int, NumberedNameKind] = numberedNameKinds
def uniqueNameKindOfSeparator: collection.Map[String, UniqueNameKind] = uniqueNameKinds
}