Skip to content

Commit 10ebd17

Browse files
committed
Make freshName semantic
1 parent 063e47c commit 10ebd17

28 files changed

+244
-175
lines changed

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

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import core._
66
import util.Positions._, Types._, Contexts._, Constants._, Names._, NameOps._, Flags._
77
import SymDenotations._, Symbols._, StdNames._, Annotations._, Trees._
88
import Decorators._
9+
import NameExtractors.{UniqueName, EvidenceParamName}
910
import language.higherKinds
1011
import typer.FrontEnd
1112
import collection.mutable.ListBuffer
@@ -127,7 +128,7 @@ object desugar {
127128
def makeImplicitParameters(tpts: List[Tree], forPrimaryConstructor: Boolean)(implicit ctx: Context) =
128129
for (tpt <- tpts) yield {
129130
val paramFlags: FlagSet = if (forPrimaryConstructor) PrivateLocalParamAccessor else Param
130-
val epname = ctx.freshName(nme.EVIDENCE_PARAM_PREFIX).toTermName
131+
val epname = EvidenceParamName.fresh()
131132
ValDef(epname, tpt, EmptyTree).withFlags(paramFlags | Implicit)
132133
}
133134

@@ -229,7 +230,7 @@ object desugar {
229230
private def evidenceParams(meth: DefDef)(implicit ctx: Context): List[ValDef] =
230231
meth.vparamss.reverse match {
231232
case (vparams @ (vparam :: _)) :: _ if vparam.mods is Implicit =>
232-
vparams.dropWhile(!_.name.startsWith(nme.EVIDENCE_PARAM_PREFIX))
233+
vparams.dropWhile(!_.name.is(EvidenceParamName))
233234
case _ =>
234235
Nil
235236
}
@@ -585,7 +586,7 @@ object desugar {
585586
case (named, tpt) :: Nil =>
586587
derivedValDef(original, named, tpt, matchExpr, mods)
587588
case _ =>
588-
val tmpName = ctx.freshName().toTermName
589+
val tmpName = UniqueName.fresh()
589590
val patMods = mods & (AccessFlags | Lazy) | Synthetic
590591
val firstDef =
591592
ValDef(tmpName, TypeTree(), matchExpr)
@@ -759,7 +760,7 @@ object desugar {
759760
val selectPos = Position(left.pos.start, op.pos.end, op.pos.start)
760761
Apply(Select(left, op.name).withPos(selectPos), args)
761762
} else {
762-
val x = ctx.freshName().toTermName
763+
val x = UniqueName.fresh()
763764
val selectPos = Position(op.pos.start, right.pos.end, op.pos.start)
764765
new InfixOpBlock(
765766
ValDef(x, TypeTree(), left).withMods(synthetic),
@@ -837,7 +838,7 @@ object desugar {
837838
case id: Ident if isVarPattern(id) && id.name != nme.WILDCARD => (id, id)
838839
case Typed(id: Ident, _) if isVarPattern(id) && id.name != nme.WILDCARD => (pat, id)
839840
case _ =>
840-
val name = ctx.freshName().toTermName
841+
val name = UniqueName.fresh()
841842
(Bind(name, pat), Ident(name))
842843
}
843844

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import Denotations._, Decorators._, DenotTransformers._
1212
import collection.mutable
1313
import util.{Property, SourceFile, NoSource}
1414
import typer.ErrorReporting._
15+
import NameExtractors.TempResultName
1516

1617
import scala.annotation.tailrec
1718
import scala.io.Codec
@@ -897,7 +898,7 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo {
897898
def evalOnce(tree: Tree)(within: Tree => Tree)(implicit ctx: Context) = {
898899
if (isIdempotentExpr(tree)) within(tree)
899900
else {
900-
val vdef = SyntheticValDef(ctx.freshName("ev$").toTermName, tree)
901+
val vdef = SyntheticValDef(TempResultName.fresh(), tree)
901902
Block(vdef :: Nil, within(Ident(vdef.namedType)))
902903
}
903904
}

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

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -174,9 +174,6 @@ object Contexts {
174174
protected def freshNames_=(freshNames: FreshNameCreator) = _freshNames = freshNames
175175
def freshNames: FreshNameCreator = _freshNames
176176

177-
def freshName(prefix: String = ""): String = freshNames.newName(prefix)
178-
def freshName(prefix: Name): String = freshName(prefix.toString)
179-
180177
/** A map in which more contextual properties can be stored */
181178
private var _moreProperties: Map[Key[Any], Any] = _
182179
protected def moreProperties_=(moreProperties: Map[Key[Any], Any]) = _moreProperties = moreProperties

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1213,8 +1213,8 @@ object Denotations {
12131213
recur(underlying, n => wrap(ModuleClassName(n)))
12141214
case QualifiedName(prefix, selector) =>
12151215
select(recur(prefix), wrap(selector))
1216-
case AnyQualifiedName(prefix, info) =>
1217-
recur(prefix, n => wrap(info.mkString(n).toTermName))
1216+
case qn @ AnyQualifiedName(prefix, _) =>
1217+
recur(prefix, n => wrap(qn.info.mkString(n).toTermName))
12181218
case path: SimpleTermName =>
12191219
def recurSimple(len: Int, wrap: TermName => Name): Denotation = {
12201220
val point = path.lastIndexOf('.', len - 1)

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

Lines changed: 96 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -8,33 +8,38 @@ import StdNames._
88
import util.DotClass
99
import tasty.TastyFormat._
1010
import Decorators._
11+
import Contexts.Context
1112
import collection.mutable
1213

1314
object NameExtractors {
1415

15-
@sharable private val extractors = new mutable.HashMap[Int, ClassifiedNameExtractor]
16+
@sharable private val simpleExtractors = new mutable.HashMap[Int, ClassifiedNameExtractor]
17+
@sharable private val uniqueExtractors = new mutable.HashMap[String, UniqueNameExtractor]
18+
@sharable private val qualifiedExtractors = new mutable.HashMap[String, QualifiedNameExtractor]
1619

1720
abstract class NameInfo extends DotClass {
18-
def tag: Int
19-
def definesNewName: Boolean = false
21+
def extractor: NameExtractor
2022
def mkString(underlying: TermName): String
2123
def map(f: SimpleTermName => SimpleTermName): NameInfo = this
2224
}
2325

24-
val simpleTermNameInfo = new NameInfo {
25-
def tag = UTF8
26-
def mkString(underlying: TermName): String = unsupported("mkString")
27-
}
28-
2926
abstract class NameExtractor(val tag: Int) extends DotClass { self =>
30-
def mkString(underlying: TermName, info: ThisInfo): String
31-
def infoString: String
3227
type ThisInfo <: Info
3328
class Info extends NameInfo { this: ThisInfo =>
34-
def tag = self.tag
29+
def extractor = self
3530
def mkString(underlying: TermName) = self.mkString(underlying, this)
3631
override def toString = infoString
3732
}
33+
def definesNewName = false
34+
def mkString(underlying: TermName, info: ThisInfo): String
35+
def infoString: String
36+
}
37+
38+
object SimpleTermNameExtractor extends NameExtractor(UTF8) { self =>
39+
type ThisInfo = Info
40+
val info = new Info
41+
def mkString(underlying: TermName, info: ThisInfo) = unsupported("mkString")
42+
def infoString = unsupported("infoString")
3843
}
3944

4045
abstract class ClassifiedNameExtractor(tag: Int, val infoString: String) extends NameExtractor(tag) {
@@ -46,26 +51,28 @@ object NameExtractors {
4651
case DerivedTermName(underlying, `info`) => Some(underlying)
4752
case _ => None
4853
}
49-
extractors(tag) = this
54+
simpleExtractors(tag) = this
5055
}
5156

52-
class PrefixNameExtractor(tag: Int, prefix: String, infoString: String) extends ClassifiedNameExtractor(tag, infoString) {
57+
class PrefixNameExtractor(tag: Int, prefix: String, optInfoString: String = "")
58+
extends ClassifiedNameExtractor(tag, if (optInfoString.isEmpty) s"Prefix $prefix" else optInfoString) {
5359
def mkString(underlying: TermName, info: ThisInfo) =
5460
underlying.mapLast(n => termName(prefix + n.toString)).toString
5561
}
5662

57-
class SuffixNameExtractor(tag: Int, suffix: String, infoString: String) extends ClassifiedNameExtractor(tag, infoString) {
63+
class SuffixNameExtractor(tag: Int, suffix: String, optInfoString: String = "")
64+
extends ClassifiedNameExtractor(tag, if (optInfoString.isEmpty) s"Suffix $suffix" else optInfoString) {
5865
def mkString(underlying: TermName, info: ThisInfo) = underlying.toString ++ suffix
5966
}
6067

6168
trait QualifiedInfo extends NameInfo {
6269
val name: SimpleTermName
6370
}
6471

65-
abstract class QualifiedNameExtractor(tag: Int, val separator: String, val infoString: String) extends NameExtractor(tag) {
72+
class QualifiedNameExtractor(tag: Int, val separator: String)
73+
extends NameExtractor(tag) {
6674
type ThisInfo = QualInfo
6775
case class QualInfo(val name: SimpleTermName) extends Info with QualifiedInfo {
68-
override def definesNewName = true
6976
override def map(f: SimpleTermName => SimpleTermName): NameInfo = new QualInfo(f(name))
7077
override def toString = s"$infoString $name"
7178
}
@@ -75,26 +82,32 @@ object NameExtractors {
7582
case DerivedTermName(qual, info: this.QualInfo) => Some((qual, info.name))
7683
case _ => None
7784
}
85+
86+
override def definesNewName = true
87+
7888
def mkString(underlying: TermName, info: ThisInfo) =
7989
s"$underlying$separator${info.name}"
90+
def infoString = s"Qualified $separator"
91+
92+
qualifiedExtractors(separator) = this
8093
}
8194

8295
object AnyQualifiedName {
83-
def unapply(name: DerivedTermName): Option[(TermName, QualifiedInfo)] = name match {
96+
def unapply(name: DerivedTermName): Option[(TermName, SimpleTermName)] = name match {
8497
case DerivedTermName(qual, info: QualifiedInfo) =>
85-
Some((name.underlying, info))
98+
Some((name.underlying, info.name))
8699
case _ => None
87100
}
88101
}
89102

90103
trait NumberedInfo {
91104
def num: Int
105+
def extractor: NameExtractor
92106
}
93107

94108
abstract class NumberedNameExtractor(tag: Int, val infoString: String) extends NameExtractor(tag) { self =>
95109
type ThisInfo = NumberedInfo
96110
case class NumberedInfo(val num: Int) extends Info with NameExtractors.NumberedInfo {
97-
override def definesNewName = self.definesNewName
98111
override def toString = s"$infoString $num"
99112
}
100113
def apply(qual: TermName, num: Int) =
@@ -103,20 +116,66 @@ object NameExtractors {
103116
case DerivedTermName(underlying, info: this.NumberedInfo) => Some((underlying, info.num))
104117
case _ => None
105118
}
106-
def definesNewName = false
107119
}
108120

109-
class UniqueNameExtractor(sep: String) extends NumberedNameExtractor(UNIQUE, "Unique") {
110-
val separator = if (sep.isEmpty) "$" else sep
111-
override def definesNewName = !sep.isEmpty
112-
def mkString(underlying: TermName, info: ThisInfo) =
113-
underlying.toString + separator + info.num
121+
case class UniqueNameExtractor(val separator: String)
122+
extends NumberedNameExtractor(UNIQUE, s"Unique $separator") {
123+
override def definesNewName = true
124+
def mkString(underlying: TermName, info: ThisInfo) = {
125+
val safePrefix = str.sanitize(underlying.toString + separator)
126+
safePrefix + info.num
127+
}
128+
129+
def fresh(prefix: TermName = EmptyTermName)(implicit ctx: Context): TermName =
130+
ctx.freshNames.newName(prefix, this)
131+
132+
uniqueExtractors(separator) = this
133+
}
134+
135+
object AnyUniqueName {
136+
def unapply(name: DerivedTermName): Option[(TermName, String, Int)] = name match {
137+
case DerivedTermName(qual, info: NumberedInfo) =>
138+
info.extractor match {
139+
case unique: UniqueNameExtractor => Some((qual, unique.separator, info.num))
140+
case _ => None
141+
}
142+
case _ => None
143+
}
114144
}
115145

116-
object QualifiedName extends QualifiedNameExtractor(QUALIFIED, ".", "Qualified")
117-
object FlattenedName extends QualifiedNameExtractor(FLATTENED, "$", "Flattened")
118-
object ExpandedName extends QualifiedNameExtractor(EXPANDED, str.EXPAND_SEPARATOR, "Expanded")
119-
object TraitSetterName extends QualifiedNameExtractor(TRAITSETTER, str.TRAIT_SETTER_SEPARATOR, "TraitSetter")
146+
val QualifiedName = new QualifiedNameExtractor(QUALIFIED, ".")
147+
val FlattenedName = new QualifiedNameExtractor(FLATTENED, "$")
148+
val ExpandedName = new QualifiedNameExtractor(EXPANDED, str.EXPAND_SEPARATOR)
149+
val TraitSetterName = new QualifiedNameExtractor(TRAITSETTER, str.TRAIT_SETTER_SEPARATOR)
150+
151+
val UniqueName = new UniqueNameExtractor("$") {
152+
override def mkString(underlying: TermName, info: ThisInfo) =
153+
if (underlying.isEmpty) "$" + info.num + "$" else super.mkString(underlying, info)
154+
}
155+
156+
val InlineAccessorName = new UniqueNameExtractor("$_inlineAccessor_$")
157+
val TempResultName = new UniqueNameExtractor("ev$")
158+
val EvidenceParamName = new UniqueNameExtractor("evidence$")
159+
val DepParamName = new UniqueNameExtractor("<param>")
160+
val LazyImplicitName = new UniqueNameExtractor("$_lazy_implicit_$")
161+
val LazyLocalName = new UniqueNameExtractor("$lzy")
162+
val LazyLocalInitName = new UniqueNameExtractor("$lzyINIT")
163+
val LazyFieldOffsetName = new UniqueNameExtractor("$OFFSET")
164+
val LazyBitMapName = new UniqueNameExtractor(nme.BITMAP_PREFIX.toString)
165+
val NonLocalReturnKeyName = new UniqueNameExtractor("nonLocalReturnKey")
166+
val WildcardParamName = new UniqueNameExtractor("_$")
167+
val TailLabelName = new UniqueNameExtractor("tailLabel")
168+
val ExceptionBinderName = new UniqueNameExtractor("ex")
169+
val SkolemName = new UniqueNameExtractor("?")
170+
val LiftedTreeName = new UniqueNameExtractor("liftedTree")
171+
172+
val PatMatStdBinderName = new UniqueNameExtractor("x")
173+
val PatMatPiName = new UniqueNameExtractor("pi") // FIXME: explain what this is
174+
val PatMatPName = new UniqueNameExtractor("p") // FIXME: explain what this is
175+
val PatMatOName = new UniqueNameExtractor("o") // FIXME: explain what this is
176+
val PatMatCaseName = new UniqueNameExtractor("case")
177+
val PatMatMatchFailName = new UniqueNameExtractor("matchFail")
178+
val PatMatSelectorName = new UniqueNameExtractor("selector")
120179

121180
object DefaultGetterName extends NumberedNameExtractor(DEFAULTGETTER, "DefaultGetter") {
122181
def mkString(underlying: TermName, info: ThisInfo) = {
@@ -133,12 +192,11 @@ object NameExtractors {
133192
}
134193
}
135194

136-
val SuperAccessorName = new PrefixNameExtractor(SUPERACCESSOR, str.SUPER_PREFIX, "SuperAccessor")
137-
val InitializerName = new PrefixNameExtractor(INITIALIZER, str.INITIALIZER_PREFIX, "Initializer")
138-
val ShadowedName = new PrefixNameExtractor(SHADOWED, str.SHADOWED_PREFIX, "Shadowed")
139-
val LocalDummyName = new PrefixNameExtractor(LOCALDUMMY, str.LOCAL_DUMMY_PREFIX, "LocalDummy")
140-
val AvoidClashName = new SuffixNameExtractor(AVOIDCLASH, str.AVOID_CLASH_SUFFIX, "AvoidClash")
141-
val ModuleClassName = new SuffixNameExtractor(OBJECTCLASS, "$", "ModuleClass")
195+
val SuperAccessorName = new PrefixNameExtractor(SUPERACCESSOR, "super$")
196+
val InitializerName = new PrefixNameExtractor(INITIALIZER, "initial$")
197+
val ShadowedName = new PrefixNameExtractor(SHADOWED, "(shadowed)")
198+
val AvoidClashName = new SuffixNameExtractor(AVOIDCLASH, "$_avoid_name_clash_$")
199+
val ModuleClassName = new SuffixNameExtractor(OBJECTCLASS, "$", optInfoString = "ModuleClass")
142200

143201
object SignedName extends NameExtractor(63) {
144202

@@ -159,11 +217,7 @@ object NameExtractors {
159217
def infoString: String = "Signed"
160218
}
161219

162-
def extractorOfTag(tag: Int) = extractors(tag)
163-
164-
val separatorToQualified: Map[String, QualifiedNameExtractor] =
165-
Map("." -> QualifiedName,
166-
"$" -> FlattenedName,
167-
str.EXPAND_SEPARATOR -> ExpandedName,
168-
str.TRAIT_SETTER_SEPARATOR -> TraitSetterName)
220+
def simpleExtractorOfTag : collection.Map[Int, ClassifiedNameExtractor] = simpleExtractors
221+
def qualifiedExtractorOfSeparator: collection.Map[String, QualifiedNameExtractor] = qualifiedExtractors
222+
def uniqueExtractorOfSeparator : collection.Map[String, UniqueNameExtractor] = uniqueExtractors
169223
}

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

Lines changed: 11 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -71,9 +71,7 @@ object NameOps {
7171
def isModuleVarName(name: Name): Boolean =
7272
name.stripAnonNumberSuffix endsWith MODULE_VAR_SUFFIX
7373
def isSelectorName = name.startsWith(" ") && name.tail.forall(_.isDigit)
74-
def isLazyLocal = name.endsWith(nme.LAZY_LOCAL)
7574
def isOuterSelect = name.endsWith(nme.OUTER_SELECT)
76-
def isInlineAccessor = name.startsWith(nme.INLINE_ACCESSOR_PREFIX)
7775

7876
/** Is name a variable name? */
7977
def isVariableName: Boolean = name.length > 0 && {
@@ -112,16 +110,16 @@ object NameOps {
112110
def moduleClassName: TypeName = name.derived(ModuleClassName).toTypeName
113111

114112
/** Convert this module class name to corresponding source module name */
115-
def sourceModuleName: TermName = stripModuleClassSuffix.toTermName
113+
def sourceModuleName: TermName = name.toTermName.exclude(ModuleClassName)
116114

117115
/** If name ends in module class suffix, drop it */
118116
def stripModuleClassSuffix: Name = name.exclude(ModuleClassName)
119117

120118
/** If flags is a ModuleClass but not a Package, add module class suffix */
121-
def adjustIfModuleClass(flags: Flags.FlagSet): N = {
119+
def adjustIfModuleClass(flags: Flags.FlagSet): N = likeTyped {
122120
if (flags is (ModuleClass, butNot = Package)) name.asTypeName.moduleClassName
123-
else likeTyped(name.toTermName.exclude(AvoidClashName))
124-
}.asInstanceOf[N]
121+
else name.toTermName.exclude(AvoidClashName)
122+
}
125123

126124
/** The superaccessor for method with given name */
127125
def superName: TermName = SuperAccessorName(name.toTermName)
@@ -138,7 +136,7 @@ object NameOps {
138136
def expandedName(prefix: Name, separator: Name = nme.EXPAND_SEPARATOR): N =
139137
likeTyped {
140138
def qualify(name: SimpleTermName) =
141-
separatorToQualified(separator.toString)(prefix.toTermName, name)
139+
qualifiedExtractorOfSeparator(separator.toString)(prefix.toTermName, name)
142140
name rewrite {
143141
case name: SimpleTermName =>
144142
qualify(name)
@@ -189,10 +187,12 @@ object NameOps {
189187

190188
def directName: N = likeTyped(name ++ DIRECT_SUFFIX)
191189

192-
def freshened(implicit ctx: Context): N =
193-
likeTyped(
194-
if (name.is(ModuleClassName)) name.stripModuleClassSuffix.freshened.moduleClassName
195-
else likeTyped(ctx.freshName(name ++ NameTransformer.NAME_JOIN_STRING)))
190+
def freshened(implicit ctx: Context): N = likeTyped {
191+
name.toTermName match {
192+
case ModuleClassName(original) => ModuleClassName(original.freshened)
193+
case name => UniqueName.fresh(name)
194+
}
195+
}
196196

197197
def unmangleClassName: N =
198198
if (name.isSimple && name.isTypeName)
@@ -478,14 +478,6 @@ object NameOps {
478478
case name => name
479479
}
480480

481-
def lazyLocalName = name ++ nme.LAZY_LOCAL
482-
def nonLazyName = {
483-
assert(name.isLazyLocal)
484-
name.dropRight(nme.LAZY_LOCAL.length)
485-
}
486-
487-
def inlineAccessorName = nme.INLINE_ACCESSOR_PREFIX ++ name ++ "$"
488-
489481
def unmangleMethodName: TermName =
490482
if (name.isSimple) {
491483
val idx = name.defaultGetterIndexOfMangled

0 commit comments

Comments
 (0)