From ca5652cc5a74f00277ce942a001fa6e931ee3728 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Tue, 28 Mar 2017 22:25:09 +0200 Subject: Make freshName semantic --- compiler/src/dotty/tools/dotc/ast/Desugar.scala | 10 +- compiler/src/dotty/tools/dotc/ast/tpd.scala | 3 +- compiler/src/dotty/tools/dotc/core/Contexts.scala | 3 - .../src/dotty/tools/dotc/core/Denotations.scala | 4 +- .../src/dotty/tools/dotc/core/NameExtractors.scala | 138 ++++++++++++++------- compiler/src/dotty/tools/dotc/core/NameOps.scala | 27 ++-- compiler/src/dotty/tools/dotc/core/Names.scala | 23 ++-- compiler/src/dotty/tools/dotc/core/StdNames.scala | 15 +-- .../src/dotty/tools/dotc/core/SymDenotations.scala | 6 +- compiler/src/dotty/tools/dotc/core/Symbols.scala | 3 +- compiler/src/dotty/tools/dotc/core/Types.scala | 8 +- .../dotty/tools/dotc/core/tasty/NameBuffer.scala | 34 +++-- .../dotty/tools/dotc/core/tasty/TastyFormat.scala | 3 +- .../tools/dotc/core/tasty/TastyUnpickler.scala | 10 +- .../src/dotty/tools/dotc/parsing/Parsers.scala | 7 +- .../dotty/tools/dotc/printing/PlainPrinter.scala | 2 +- .../dotty/tools/dotc/transform/CapturedVars.scala | 3 +- .../src/dotty/tools/dotc/transform/LazyVals.scala | 14 ++- .../src/dotty/tools/dotc/transform/LiftTry.scala | 3 +- .../dotty/tools/dotc/transform/MoveStatics.scala | 1 + .../tools/dotc/transform/NonLocalReturns.scala | 3 +- .../tools/dotc/transform/PatternMatcher.scala | 24 ++-- .../src/dotty/tools/dotc/transform/TailRec.scala | 37 +++--- .../tools/dotc/transform/TryCatchPatterns.scala | 3 +- .../src/dotty/tools/dotc/typer/EtaExpansion.scala | 9 +- compiler/src/dotty/tools/dotc/typer/Inliner.scala | 4 +- .../src/dotty/tools/dotc/typer/ProtoTypes.scala | 3 +- .../dotty/tools/dotc/util/FreshNameCreator.scala | 17 +-- 28 files changed, 244 insertions(+), 173 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/ast/Desugar.scala b/compiler/src/dotty/tools/dotc/ast/Desugar.scala index e2679ef56..3671ccb73 100644 --- a/compiler/src/dotty/tools/dotc/ast/Desugar.scala +++ b/compiler/src/dotty/tools/dotc/ast/Desugar.scala @@ -6,6 +6,7 @@ import core._ import util.Positions._, Types._, Contexts._, Constants._, Names._, NameOps._, Flags._ import SymDenotations._, Symbols._, StdNames._, Annotations._, Trees._ import Decorators._ +import NameExtractors.{UniqueName, EvidenceParamName} import language.higherKinds import typer.FrontEnd import collection.mutable.ListBuffer @@ -128,7 +129,7 @@ object desugar { def makeImplicitParameters(tpts: List[Tree], forPrimaryConstructor: Boolean)(implicit ctx: Context) = for (tpt <- tpts) yield { val paramFlags: FlagSet = if (forPrimaryConstructor) PrivateLocalParamAccessor else Param - val epname = ctx.freshName(nme.EVIDENCE_PARAM_PREFIX).toTermName + val epname = EvidenceParamName.fresh() ValDef(epname, tpt, EmptyTree).withFlags(paramFlags | Implicit) } @@ -230,7 +231,7 @@ object desugar { private def evidenceParams(meth: DefDef)(implicit ctx: Context): List[ValDef] = meth.vparamss.reverse match { case (vparams @ (vparam :: _)) :: _ if vparam.mods is Implicit => - vparams.dropWhile(!_.name.startsWith(nme.EVIDENCE_PARAM_PREFIX)) + vparams.dropWhile(!_.name.is(EvidenceParamName)) case _ => Nil } @@ -635,7 +636,6 @@ object desugar { case (named, tpt) :: Nil => derivedValDef(original, named, tpt, matchExpr, mods) case _ => - val tmpName = ctx.freshName().toTermName val patMods = mods & Lazy | Synthetic | (if (ctx.owner.isClass) PrivateLocal else EmptyFlags) val firstDef = @@ -810,7 +810,7 @@ object desugar { val selectPos = Position(left.pos.start, op.pos.end, op.pos.start) Apply(Select(left, op.name).withPos(selectPos), args) } else { - val x = ctx.freshName().toTermName + val x = UniqueName.fresh() val selectPos = Position(op.pos.start, right.pos.end, op.pos.start) new InfixOpBlock( ValDef(x, TypeTree(), left).withMods(synthetic), @@ -888,7 +888,7 @@ object desugar { case id: Ident if isVarPattern(id) && id.name != nme.WILDCARD => (id, id) case Typed(id: Ident, _) if isVarPattern(id) && id.name != nme.WILDCARD => (pat, id) case _ => - val name = ctx.freshName().toTermName + val name = UniqueName.fresh() (Bind(name, pat), Ident(name)) } diff --git a/compiler/src/dotty/tools/dotc/ast/tpd.scala b/compiler/src/dotty/tools/dotc/ast/tpd.scala index ff66c8c8e..e4c6dd679 100644 --- a/compiler/src/dotty/tools/dotc/ast/tpd.scala +++ b/compiler/src/dotty/tools/dotc/ast/tpd.scala @@ -12,6 +12,7 @@ import Denotations._, Decorators._, DenotTransformers._ import collection.mutable import util.{Property, SourceFile, NoSource} import typer.ErrorReporting._ +import NameExtractors.TempResultName import scala.annotation.tailrec import scala.io.Codec @@ -897,7 +898,7 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo { def evalOnce(tree: Tree)(within: Tree => Tree)(implicit ctx: Context) = { if (isIdempotentExpr(tree)) within(tree) else { - val vdef = SyntheticValDef(ctx.freshName("ev$").toTermName, tree) + val vdef = SyntheticValDef(TempResultName.fresh(), tree) Block(vdef :: Nil, within(Ident(vdef.namedType))) } } diff --git a/compiler/src/dotty/tools/dotc/core/Contexts.scala b/compiler/src/dotty/tools/dotc/core/Contexts.scala index 8707b66f9..c80ad876a 100644 --- a/compiler/src/dotty/tools/dotc/core/Contexts.scala +++ b/compiler/src/dotty/tools/dotc/core/Contexts.scala @@ -174,9 +174,6 @@ object Contexts { protected def freshNames_=(freshNames: FreshNameCreator) = _freshNames = freshNames def freshNames: FreshNameCreator = _freshNames - def freshName(prefix: String = ""): String = freshNames.newName(prefix) - def freshName(prefix: Name): String = freshName(prefix.toString) - /** A map in which more contextual properties can be stored */ private var _moreProperties: Map[Key[Any], Any] = _ protected def moreProperties_=(moreProperties: Map[Key[Any], Any]) = _moreProperties = moreProperties diff --git a/compiler/src/dotty/tools/dotc/core/Denotations.scala b/compiler/src/dotty/tools/dotc/core/Denotations.scala index 60a506291..42837122a 100644 --- a/compiler/src/dotty/tools/dotc/core/Denotations.scala +++ b/compiler/src/dotty/tools/dotc/core/Denotations.scala @@ -1193,8 +1193,8 @@ object Denotations { recur(underlying, n => wrap(ModuleClassName(n))) case QualifiedName(prefix, selector) => select(recur(prefix), wrap(selector)) - case AnyQualifiedName(prefix, info) => - recur(prefix, n => wrap(info.mkString(n).toTermName)) + case qn @ AnyQualifiedName(prefix, _) => + recur(prefix, n => wrap(qn.info.mkString(n).toTermName)) case path: SimpleTermName => def recurSimple(len: Int, wrap: TermName => Name): Denotation = { val point = path.lastIndexOf('.', len - 1) diff --git a/compiler/src/dotty/tools/dotc/core/NameExtractors.scala b/compiler/src/dotty/tools/dotc/core/NameExtractors.scala index 2c5f5c164..1439ce002 100644 --- a/compiler/src/dotty/tools/dotc/core/NameExtractors.scala +++ b/compiler/src/dotty/tools/dotc/core/NameExtractors.scala @@ -8,33 +8,38 @@ import StdNames._ import util.DotClass import tasty.TastyFormat._ import Decorators._ +import Contexts.Context import collection.mutable object NameExtractors { - @sharable private val extractors = new mutable.HashMap[Int, ClassifiedNameExtractor] + @sharable private val simpleExtractors = new mutable.HashMap[Int, ClassifiedNameExtractor] + @sharable private val uniqueExtractors = new mutable.HashMap[String, UniqueNameExtractor] + @sharable private val qualifiedExtractors = new mutable.HashMap[String, QualifiedNameExtractor] abstract class NameInfo extends DotClass { - def tag: Int - def definesNewName: Boolean = false + def extractor: NameExtractor def mkString(underlying: TermName): String def map(f: SimpleTermName => SimpleTermName): NameInfo = this } - val simpleTermNameInfo = new NameInfo { - def tag = UTF8 - def mkString(underlying: TermName): String = unsupported("mkString") - } - abstract class NameExtractor(val tag: Int) extends DotClass { self => - def mkString(underlying: TermName, info: ThisInfo): String - def infoString: String type ThisInfo <: Info class Info extends NameInfo { this: ThisInfo => - def tag = self.tag + def extractor = self def mkString(underlying: TermName) = self.mkString(underlying, this) override def toString = infoString } + def definesNewName = false + def mkString(underlying: TermName, info: ThisInfo): String + def infoString: String + } + + object SimpleTermNameExtractor extends NameExtractor(UTF8) { self => + type ThisInfo = Info + val info = new Info + def mkString(underlying: TermName, info: ThisInfo) = unsupported("mkString") + def infoString = unsupported("infoString") } abstract class ClassifiedNameExtractor(tag: Int, val infoString: String) extends NameExtractor(tag) { @@ -46,15 +51,17 @@ object NameExtractors { case DerivedTermName(underlying, `info`) => Some(underlying) case _ => None } - extractors(tag) = this + simpleExtractors(tag) = this } - class PrefixNameExtractor(tag: Int, prefix: String, infoString: String) extends ClassifiedNameExtractor(tag, infoString) { + class PrefixNameExtractor(tag: Int, prefix: String, optInfoString: String = "") + extends ClassifiedNameExtractor(tag, if (optInfoString.isEmpty) s"Prefix $prefix" else optInfoString) { def mkString(underlying: TermName, info: ThisInfo) = underlying.mapLast(n => termName(prefix + n.toString)).toString } - class SuffixNameExtractor(tag: Int, suffix: String, infoString: String) extends ClassifiedNameExtractor(tag, infoString) { + class SuffixNameExtractor(tag: Int, suffix: String, optInfoString: String = "") + extends ClassifiedNameExtractor(tag, if (optInfoString.isEmpty) s"Suffix $suffix" else optInfoString) { def mkString(underlying: TermName, info: ThisInfo) = underlying.toString ++ suffix } @@ -62,10 +69,10 @@ object NameExtractors { val name: SimpleTermName } - abstract class QualifiedNameExtractor(tag: Int, val separator: String, val infoString: String) extends NameExtractor(tag) { + class QualifiedNameExtractor(tag: Int, val separator: String) + extends NameExtractor(tag) { type ThisInfo = QualInfo case class QualInfo(val name: SimpleTermName) extends Info with QualifiedInfo { - override def definesNewName = true override def map(f: SimpleTermName => SimpleTermName): NameInfo = new QualInfo(f(name)) override def toString = s"$infoString $name" } @@ -75,26 +82,32 @@ object NameExtractors { case DerivedTermName(qual, info: this.QualInfo) => Some((qual, info.name)) case _ => None } + + override def definesNewName = true + def mkString(underlying: TermName, info: ThisInfo) = s"$underlying$separator${info.name}" + def infoString = s"Qualified $separator" + + qualifiedExtractors(separator) = this } object AnyQualifiedName { - def unapply(name: DerivedTermName): Option[(TermName, QualifiedInfo)] = name match { + def unapply(name: DerivedTermName): Option[(TermName, SimpleTermName)] = name match { case DerivedTermName(qual, info: QualifiedInfo) => - Some((name.underlying, info)) + Some((name.underlying, info.name)) case _ => None } } trait NumberedInfo { def num: Int + def extractor: NameExtractor } abstract class NumberedNameExtractor(tag: Int, val infoString: String) extends NameExtractor(tag) { self => type ThisInfo = NumberedInfo case class NumberedInfo(val num: Int) extends Info with NameExtractors.NumberedInfo { - override def definesNewName = self.definesNewName override def toString = s"$infoString $num" } def apply(qual: TermName, num: Int) = @@ -103,20 +116,66 @@ object NameExtractors { case DerivedTermName(underlying, info: this.NumberedInfo) => Some((underlying, info.num)) case _ => None } - def definesNewName = false } - class UniqueNameExtractor(sep: String) extends NumberedNameExtractor(UNIQUE, "Unique") { - val separator = if (sep.isEmpty) "$" else sep - override def definesNewName = !sep.isEmpty - def mkString(underlying: TermName, info: ThisInfo) = - underlying.toString + separator + info.num + case class UniqueNameExtractor(val separator: String) + extends NumberedNameExtractor(UNIQUE, s"Unique $separator") { + override def definesNewName = true + def mkString(underlying: TermName, info: ThisInfo) = { + val safePrefix = str.sanitize(underlying.toString + separator) + safePrefix + info.num + } + + def fresh(prefix: TermName = EmptyTermName)(implicit ctx: Context): TermName = + ctx.freshNames.newName(prefix, this) + + uniqueExtractors(separator) = this + } + + object AnyUniqueName { + def unapply(name: DerivedTermName): Option[(TermName, String, Int)] = name match { + case DerivedTermName(qual, info: NumberedInfo) => + info.extractor match { + case unique: UniqueNameExtractor => Some((qual, unique.separator, info.num)) + case _ => None + } + case _ => None + } } - object QualifiedName extends QualifiedNameExtractor(QUALIFIED, ".", "Qualified") - object FlattenedName extends QualifiedNameExtractor(FLATTENED, "$", "Flattened") - object ExpandedName extends QualifiedNameExtractor(EXPANDED, str.EXPAND_SEPARATOR, "Expanded") - object TraitSetterName extends QualifiedNameExtractor(TRAITSETTER, str.TRAIT_SETTER_SEPARATOR, "TraitSetter") + val QualifiedName = new QualifiedNameExtractor(QUALIFIED, ".") + val FlattenedName = new QualifiedNameExtractor(FLATTENED, "$") + val ExpandedName = new QualifiedNameExtractor(EXPANDED, str.EXPAND_SEPARATOR) + val TraitSetterName = new QualifiedNameExtractor(TRAITSETTER, str.TRAIT_SETTER_SEPARATOR) + + val UniqueName = new UniqueNameExtractor("$") { + override def mkString(underlying: TermName, info: ThisInfo) = + if (underlying.isEmpty) "$" + info.num + "$" else super.mkString(underlying, info) + } + + val InlineAccessorName = new UniqueNameExtractor("$_inlineAccessor_$") + val TempResultName = new UniqueNameExtractor("ev$") + val EvidenceParamName = new UniqueNameExtractor("evidence$") + val DepParamName = new UniqueNameExtractor("") + val LazyImplicitName = new UniqueNameExtractor("$_lazy_implicit_$") + val LazyLocalName = new UniqueNameExtractor("$lzy") + val LazyLocalInitName = new UniqueNameExtractor("$lzyINIT") + val LazyFieldOffsetName = new UniqueNameExtractor("$OFFSET") + val LazyBitMapName = new UniqueNameExtractor(nme.BITMAP_PREFIX.toString) + val NonLocalReturnKeyName = new UniqueNameExtractor("nonLocalReturnKey") + val WildcardParamName = new UniqueNameExtractor("_$") + val TailLabelName = new UniqueNameExtractor("tailLabel") + val ExceptionBinderName = new UniqueNameExtractor("ex") + val SkolemName = new UniqueNameExtractor("?") + val LiftedTreeName = new UniqueNameExtractor("liftedTree") + + val PatMatStdBinderName = new UniqueNameExtractor("x") + val PatMatPiName = new UniqueNameExtractor("pi") // FIXME: explain what this is + val PatMatPName = new UniqueNameExtractor("p") // FIXME: explain what this is + val PatMatOName = new UniqueNameExtractor("o") // FIXME: explain what this is + val PatMatCaseName = new UniqueNameExtractor("case") + val PatMatMatchFailName = new UniqueNameExtractor("matchFail") + val PatMatSelectorName = new UniqueNameExtractor("selector") object DefaultGetterName extends NumberedNameExtractor(DEFAULTGETTER, "DefaultGetter") { def mkString(underlying: TermName, info: ThisInfo) = { @@ -133,12 +192,11 @@ object NameExtractors { } } - val SuperAccessorName = new PrefixNameExtractor(SUPERACCESSOR, str.SUPER_PREFIX, "SuperAccessor") - val InitializerName = new PrefixNameExtractor(INITIALIZER, str.INITIALIZER_PREFIX, "Initializer") - val ShadowedName = new PrefixNameExtractor(SHADOWED, str.SHADOWED_PREFIX, "Shadowed") - val LocalDummyName = new PrefixNameExtractor(LOCALDUMMY, str.LOCAL_DUMMY_PREFIX, "LocalDummy") - val AvoidClashName = new SuffixNameExtractor(AVOIDCLASH, str.AVOID_CLASH_SUFFIX, "AvoidClash") - val ModuleClassName = new SuffixNameExtractor(OBJECTCLASS, "$", "ModuleClass") + val SuperAccessorName = new PrefixNameExtractor(SUPERACCESSOR, "super$") + val InitializerName = new PrefixNameExtractor(INITIALIZER, "initial$") + val ShadowedName = new PrefixNameExtractor(SHADOWED, "(shadowed)") + val AvoidClashName = new SuffixNameExtractor(AVOIDCLASH, "$_avoid_name_clash_$") + val ModuleClassName = new SuffixNameExtractor(OBJECTCLASS, "$", optInfoString = "ModuleClass") object SignedName extends NameExtractor(63) { @@ -159,11 +217,7 @@ object NameExtractors { def infoString: String = "Signed" } - def extractorOfTag(tag: Int) = extractors(tag) - - val separatorToQualified: Map[String, QualifiedNameExtractor] = - Map("." -> QualifiedName, - "$" -> FlattenedName, - str.EXPAND_SEPARATOR -> ExpandedName, - str.TRAIT_SETTER_SEPARATOR -> TraitSetterName) + def simpleExtractorOfTag : collection.Map[Int, ClassifiedNameExtractor] = simpleExtractors + def qualifiedExtractorOfSeparator: collection.Map[String, QualifiedNameExtractor] = qualifiedExtractors + def uniqueExtractorOfSeparator : collection.Map[String, UniqueNameExtractor] = uniqueExtractors } \ No newline at end of file diff --git a/compiler/src/dotty/tools/dotc/core/NameOps.scala b/compiler/src/dotty/tools/dotc/core/NameOps.scala index 031cda1bd..6f2c75313 100644 --- a/compiler/src/dotty/tools/dotc/core/NameOps.scala +++ b/compiler/src/dotty/tools/dotc/core/NameOps.scala @@ -71,9 +71,7 @@ object NameOps { def isModuleVarName(name: Name): Boolean = name.stripAnonNumberSuffix endsWith MODULE_VAR_SUFFIX def isSelectorName = name.startsWith(" ") && name.tail.forall(_.isDigit) - def isLazyLocal = name.endsWith(nme.LAZY_LOCAL) def isOuterSelect = name.endsWith(nme.OUTER_SELECT) - def isInlineAccessor = name.startsWith(nme.INLINE_ACCESSOR_PREFIX) /** Is name a variable name? */ def isVariableName: Boolean = name.length > 0 && { @@ -112,16 +110,16 @@ object NameOps { def moduleClassName: TypeName = name.derived(ModuleClassName).toTypeName /** Convert this module class name to corresponding source module name */ - def sourceModuleName: TermName = stripModuleClassSuffix.toTermName + def sourceModuleName: TermName = name.toTermName.exclude(ModuleClassName) /** If name ends in module class suffix, drop it */ def stripModuleClassSuffix: Name = name.exclude(ModuleClassName) /** If flags is a ModuleClass but not a Package, add module class suffix */ - def adjustIfModuleClass(flags: Flags.FlagSet): N = { + def adjustIfModuleClass(flags: Flags.FlagSet): N = likeTyped { if (flags is (ModuleClass, butNot = Package)) name.asTypeName.moduleClassName - else likeTyped(name.toTermName.exclude(AvoidClashName)) - }.asInstanceOf[N] + else name.toTermName.exclude(AvoidClashName) + } /** The superaccessor for method with given name */ def superName: TermName = SuperAccessorName(name.toTermName) @@ -138,7 +136,7 @@ object NameOps { def expandedName(prefix: Name, separator: Name = nme.EXPAND_SEPARATOR): N = likeTyped { def qualify(name: SimpleTermName) = - separatorToQualified(separator.toString)(prefix.toTermName, name) + qualifiedExtractorOfSeparator(separator.toString)(prefix.toTermName, name) name rewrite { case name: SimpleTermName => qualify(name) @@ -220,6 +218,13 @@ object NameOps { } */ + def freshened(implicit ctx: Context): N = likeTyped { + name.toTermName match { + case ModuleClassName(original) => ModuleClassName(original.freshened) + case name => UniqueName.fresh(name) + } + } + def unmangleClassName: N = if (name.isSimple && name.isTypeName) if (name.endsWith(MODULE_SUFFIX) && !tpnme.falseModuleClassNames.contains(name.asTypeName)) @@ -504,14 +509,6 @@ object NameOps { case name => name } - def lazyLocalName = name ++ nme.LAZY_LOCAL - def nonLazyName = { - assert(name.isLazyLocal) - name.dropRight(nme.LAZY_LOCAL.length) - } - - def inlineAccessorName = nme.INLINE_ACCESSOR_PREFIX ++ name ++ "$" - def unmangleMethodName: TermName = if (name.isSimple) { val idx = name.defaultGetterIndexOfMangled diff --git a/compiler/src/dotty/tools/dotc/core/Names.scala b/compiler/src/dotty/tools/dotc/core/Names.scala index 81429a8d9..e4ebe61c2 100644 --- a/compiler/src/dotty/tools/dotc/core/Names.scala +++ b/compiler/src/dotty/tools/dotc/core/Names.scala @@ -130,7 +130,7 @@ object Names { def likeKinded(name: Name): TermName = name.toTermName - def info: NameInfo = simpleTermNameInfo + def info: NameInfo = SimpleTermNameExtractor.info def underlying: TermName = unsupported("underlying") @sharable private var derivedNames: AnyRef /* SimpleMap | j.u.HashMap */ = @@ -174,9 +174,10 @@ object Names { * name as underlying name. */ def derived(info: NameInfo): TermName = { - val ownTag = this.info.tag - if (ownTag < info.tag || info.definesNewName) add(info) - else if (ownTag > info.tag) rewrap(underlying.derived(info)) + val thisKind = this.info.extractor + val thatKind = info.extractor + if (thisKind.tag < thatKind.tag || thatKind.definesNewName) add(info) + else if (thisKind.tag > thatKind.tag) rewrap(underlying.derived(info)) else { assert(info == this.info) this @@ -184,16 +185,16 @@ object Names { } def exclude(kind: NameExtractor): TermName = { - val ownTag = this.info.tag - if (ownTag < kind.tag || info.definesNewName) this - else if (ownTag > kind.tag) rewrap(underlying.exclude(kind)) + val thisKind = this.info.extractor + if (thisKind.tag < kind.tag || thisKind.definesNewName) this + else if (thisKind.tag > kind.tag) rewrap(underlying.exclude(kind)) else underlying } def is(kind: NameExtractor): Boolean = { - val ownTag = this.info.tag - ownTag == kind.tag || - !info.definesNewName && ownTag > kind.tag && underlying.is(kind) + val thisKind = this.info.extractor + thisKind == kind || + !thisKind.definesNewName && thisKind.tag > kind.tag && underlying.is(kind) } override def hashCode = System.identityHashCode(this) @@ -511,7 +512,7 @@ object Names { implicit val NameOrdering: Ordering[Name] = new Ordering[Name] { private def compareInfos(x: NameInfo, y: NameInfo): Int = - if (x.tag != y.tag) x.tag - y.tag + if (x.extractor.tag != y.extractor.tag) x.extractor.tag - y.extractor.tag else x match { case x: QualifiedInfo => y match { diff --git a/compiler/src/dotty/tools/dotc/core/StdNames.scala b/compiler/src/dotty/tools/dotc/core/StdNames.scala index 09e808c7d..598d55650 100644 --- a/compiler/src/dotty/tools/dotc/core/StdNames.scala +++ b/compiler/src/dotty/tools/dotc/core/StdNames.scala @@ -22,7 +22,8 @@ object StdNames { val INITIALIZER_PREFIX = "initial$" val SHADOWED_PREFIX = "(shadowed)" val AVOID_CLASH_SUFFIX = "$_avoid_name_clash_$" - val LOCAL_DUMMY_PREFIX = "_" // owner of local blocks + + def sanitize(str: String) = str.replaceAll("""[<>]""", """\$""") } abstract class DefinedNames[N <: Name] { @@ -96,7 +97,7 @@ object StdNames { val ANON_CLASS: N = "$anon" val ANON_FUN: N = "$anonfun" - val BITMAP_PREFIX: N = "bitmap$" + val BITMAP_PREFIX: N = "bitmap$" // @darkdimius: $bitmap? Also, the next 4 names are unused. val BITMAP_NORMAL: N = BITMAP_PREFIX // initialization bitmap for public/protected lazy vals val BITMAP_TRANSIENT: N = BITMAP_PREFIX + "trans$" // initialization bitmap for transient lazy vals val BITMAP_CHECKINIT: N = BITMAP_PREFIX + "init$" // initialization bitmap for checkinit values @@ -106,13 +107,10 @@ object StdNames { val DO_WHILE_PREFIX: N = "doWhile$" val EMPTY: N = "" val EMPTY_PACKAGE: N = Names.EMPTY_PACKAGE.toString - val EVIDENCE_PARAM_PREFIX: N = "evidence$" - val DEP_PARAM_PREFIX = "" val EXCEPTION_RESULT_PREFIX: N = "exceptionResult" val EXPAND_SEPARATOR: N = str.EXPAND_SEPARATOR val IMPL_CLASS_SUFFIX: N = "$class" val IMPORT: N = "" - val INLINE_ACCESSOR_PREFIX = "$inlineAccessor$" val INTERPRETER_IMPORT_WRAPPER: N = "$iw" val INTERPRETER_LINE_PREFIX: N = "line" val INTERPRETER_VAR_PREFIX: N = "res" @@ -121,7 +119,6 @@ object StdNames { val MODULE_SUFFIX: N = NameTransformer.MODULE_SUFFIX_STRING val MODULE_VAR_SUFFIX: N = "$module" val NAME_JOIN: N = NameTransformer.NAME_JOIN_STRING - val USCORE_PARAM_PREFIX: N = "_$" val OPS_PACKAGE: N = "" val OVERLOADED: N = "" val PACKAGE: N = "package" @@ -139,9 +136,6 @@ object StdNames { val COMPANION_CLASS_METHOD: N = "companion$class" val TRAIT_SETTER_SEPARATOR: N = str.TRAIT_SETTER_SEPARATOR val DIRECT_SUFFIX: N = "$direct" - val LAZY_IMPLICIT_PREFIX: N = "$lazy_implicit$" - val DOLLAR_VALUES: N = "$values" - val DOLLAR_NEW: N = "$new" // value types (and AnyRef) are all used as terms as well // as (at least) arguments to the @specialize annotation. @@ -249,8 +243,6 @@ object StdNames { val EVT2U: N = "evt2u$" val EQEQ_LOCAL_VAR: N = "eqEqTemp$" val FAKE_LOCAL_THIS: N = "this$" - val LAZY_LOCAL: N = "$lzy" - val LAZY_LOCAL_INIT: N = "$lzyINIT" val LAZY_FIELD_OFFSET: N = "OFFSET$" val LAZY_SLOW_SUFFIX: N = "$lzycompute" val LOCAL_SUFFIX: N = "$$local" @@ -448,7 +440,6 @@ object StdNames { val lang: N = "lang" val length: N = "length" val lengthCompare: N = "lengthCompare" - val liftedTree: N = "liftedTree" val `macro` : N = "macro" val macroThis : N = "_this" val macroContext : N = "c" diff --git a/compiler/src/dotty/tools/dotc/core/SymDenotations.scala b/compiler/src/dotty/tools/dotc/core/SymDenotations.scala index eb16b2188..5e5a5df2d 100644 --- a/compiler/src/dotty/tools/dotc/core/SymDenotations.scala +++ b/compiler/src/dotty/tools/dotc/core/SymDenotations.scala @@ -406,14 +406,14 @@ object SymDenotations { } var prefix = encl.fullNameSeparated(separator) val fn = - if (separatorToQualified.contains(sep)) { + if (qualifiedExtractorOfSeparator.contains(sep)) { if (sep == "$") // duplicate scalac's behavior: don't write a double '$$' for module class members. prefix = prefix.exclude(ModuleClassName) name rewrite { case n: SimpleTermName => val n1 = if (filler.isEmpty) n else termName(filler ++ n) - separatorToQualified(sep)(prefix.toTermName, n1) + qualifiedExtractorOfSeparator(sep)(prefix.toTermName, n1) } } else { @@ -1541,7 +1541,7 @@ object SymDenotations { !(this is Frozen) || (scope ne this.unforcedDecls) || sym.hasAnnotation(defn.ScalaStaticAnnot) || - sym.name.isInlineAccessor || + sym.name.is(InlineAccessorName) || isUsecase, i"trying to enter $sym in $this, frozen = ${this is Frozen}") scope.enter(sym) diff --git a/compiler/src/dotty/tools/dotc/core/Symbols.scala b/compiler/src/dotty/tools/dotc/core/Symbols.scala index 95ff1cb75..69d6e8db3 100644 --- a/compiler/src/dotty/tools/dotc/core/Symbols.scala +++ b/compiler/src/dotty/tools/dotc/core/Symbols.scala @@ -19,6 +19,7 @@ import util.Positions._ import DenotTransformers._ import StdNames._ import NameOps._ +import NameExtractors.LazyImplicitName import ast.tpd.Tree import ast.TreeTypeMap import Constants.Constant @@ -260,7 +261,7 @@ trait Symbols { this: Context => /** Create a synthetic lazy implicit value */ def newLazyImplicit(info: Type) = - newSymbol(owner, freshName(nme.LAZY_IMPLICIT_PREFIX).toTermName, Lazy, info) + newSymbol(owner, LazyImplicitName.fresh(), Lazy, info) /** Create a symbol representing a selftype declaration for class `cls`. */ def newSelfSym(cls: ClassSymbol, name: TermName = nme.WILDCARD, selfInfo: Type = NoType): TermSymbol = diff --git a/compiler/src/dotty/tools/dotc/core/Types.scala b/compiler/src/dotty/tools/dotc/core/Types.scala index b2502ee94..3f5a30922 100644 --- a/compiler/src/dotty/tools/dotc/core/Types.scala +++ b/compiler/src/dotty/tools/dotc/core/Types.scala @@ -7,7 +7,7 @@ import Symbols._ import Flags._ import Names._ import StdNames._, NameOps._ -import NameExtractors.ShadowedName +import NameExtractors.{ShadowedName, SkolemName} import Scopes._ import Constants._ import Contexts._ @@ -3001,9 +3001,9 @@ object Types { override def hashCode: Int = identityHash override def equals(that: Any) = this eq that.asInstanceOf[AnyRef] - private var myRepr: String = null - def repr(implicit ctx: Context) = { - if (myRepr == null) myRepr = ctx.freshName("?") + private var myRepr: Name = null + def repr(implicit ctx: Context): Name = { + if (myRepr == null) myRepr = SkolemName.fresh() myRepr } diff --git a/compiler/src/dotty/tools/dotc/core/tasty/NameBuffer.scala b/compiler/src/dotty/tools/dotc/core/tasty/NameBuffer.scala index df43eabb2..2fd078bef 100644 --- a/compiler/src/dotty/tools/dotc/core/tasty/NameBuffer.scala +++ b/compiler/src/dotty/tools/dotc/core/tasty/NameBuffer.scala @@ -26,10 +26,13 @@ class NameBuffer extends TastyBuffer(10000) { name1 match { case SignedName(original, Signature(params, result)) => nameIndex(original); nameIndex(result); params.foreach(nameIndex) - case AnyQualifiedName(prefix, info) => - nameIndex(prefix); nameIndex(info.name) - case DerivedTermName(prefix, _) => - nameIndex(prefix) + case AnyQualifiedName(prefix, name) => + nameIndex(prefix); nameIndex(name) + case AnyUniqueName(original, separator, num) => + nameIndex(separator.toTermName) + if (original.nonEmpty) nameIndex(original) + case DerivedTermName(original, _) => + nameIndex(original) case _ => } val ref = NameRef(nameRefs.size) @@ -50,7 +53,8 @@ class NameBuffer extends TastyBuffer(10000) { def writeNameRef(name: Name): Unit = writeNameRef(nameRefs(name.toTermName)) def pickleNameContents(name: Name): Unit = { - writeByte(name.toTermName.info.tag) + val tag = name.toTermName.info.extractor.tag + writeByte(tag) name.toTermName match { case name: SimpleTermName => val bytes = @@ -58,17 +62,23 @@ class NameBuffer extends TastyBuffer(10000) { else Codec.toUTF8(chrs, name.start, name.length) writeNat(bytes.length) writeBytes(bytes, bytes.length) - case AnyQualifiedName(prefix, info) => - withLength { writeNameRef(prefix); writeNameRef(info.name) } - case SignedName(original, Signature(params, result)) => - withLength( - { writeNameRef(original); writeNameRef(result); params.foreach(writeNameRef) }, - if ((params.length + 2) * maxIndexWidth <= maxNumInByte) 1 else 2) + case AnyQualifiedName(prefix, name) => + withLength { writeNameRef(prefix); writeNameRef(name) } + case AnyUniqueName(original, separator, num) => + withLength { + writeNameRef(separator.toTermName) + writeNat(num) + if (original.nonEmpty) writeNameRef(original) + } case DefaultGetterName(method, paramNumber) => withLength { writeNameRef(method); writeNat(paramNumber) } case VariantName(original, sign) => withLength { writeNameRef(original); writeNat(sign + 1) } - case DerivedTermName(original, info) => + case SignedName(original, Signature(params, result)) => + withLength( + { writeNameRef(original); writeNameRef(result); params.foreach(writeNameRef) }, + if ((params.length + 2) * maxIndexWidth <= maxNumInByte) 1 else 2) + case DerivedTermName(original, _) => withLength { writeNameRef(original) } } } diff --git a/compiler/src/dotty/tools/dotc/core/tasty/TastyFormat.scala b/compiler/src/dotty/tools/dotc/core/tasty/TastyFormat.scala index d0fee04df..18d4a6344 100644 --- a/compiler/src/dotty/tools/dotc/core/tasty/TastyFormat.scala +++ b/compiler/src/dotty/tools/dotc/core/tasty/TastyFormat.scala @@ -33,11 +33,11 @@ Macro-format: QUALIFIED Length qualified_NameRef selector_NameRef SIGNED Length original_NameRef resultSig_NameRef paramSig_NameRef* EXPANDED Length original_NameRef + UNIQUE Length separator_NameRef num_Nat original_NameRef? OBJECTCLASS Length module_NameRef SUPERACCESSOR Length accessed_NameRef DEFAULTGETTER Length method_NameRef paramNumber_Nat SHADOWED Length original_NameRef - MANGLED Length mangle_NameRef name_NameRef ... NameRef = Nat // ordinal number of name in name table, starting from 1. @@ -231,7 +231,6 @@ object TastyFormat { final val SUPERACCESSOR = 20 final val INITIALIZER = 21 final val SHADOWED = 22 - final val LOCALDUMMY = 23 final val AVOIDCLASH = 27 final val OBJECTCLASS = 29 diff --git a/compiler/src/dotty/tools/dotc/core/tasty/TastyUnpickler.scala b/compiler/src/dotty/tools/dotc/core/tasty/TastyUnpickler.scala index 7ebf3a2ea..756b7db5c 100644 --- a/compiler/src/dotty/tools/dotc/core/tasty/TastyUnpickler.scala +++ b/compiler/src/dotty/tools/dotc/core/tasty/TastyUnpickler.scala @@ -5,7 +5,7 @@ package tasty import scala.collection.mutable import TastyFormat._ import TastyBuffer.NameRef -import Names.{Name, TermName, termName} +import Names.{Name, TermName, termName, EmptyTermName} import NameExtractors._ import java.util.UUID @@ -55,6 +55,12 @@ class TastyUnpickler(reader: TastyReader) { FlattenedName(readName(), readName().asSimpleName) case EXPANDED => ExpandedName(readName(), readName().asSimpleName) + case UNIQUE => + val separator = readName().toString + val num = readNat() + val originals = until(end)(readName()) + val original = if (originals.isEmpty) EmptyTermName else originals.head + uniqueExtractorOfSeparator(separator)(original, num) case DEFAULTGETTER => DefaultGetterName(readName(), readNat()) case VARIANT => @@ -67,7 +73,7 @@ class TastyUnpickler(reader: TastyReader) { if (sig == Signature.NotAMethod) sig = Signature.NotAMethod SignedName(original, sig) case _ => - extractorOfTag(tag)(readName()) + simpleExtractorOfTag(tag)(readName()) } assert(currentAddr == end, s"bad name $result $start $currentAddr $end") result diff --git a/compiler/src/dotty/tools/dotc/parsing/Parsers.scala b/compiler/src/dotty/tools/dotc/parsing/Parsers.scala index 3e3673e5e..d0451dd60 100644 --- a/compiler/src/dotty/tools/dotc/parsing/Parsers.scala +++ b/compiler/src/dotty/tools/dotc/parsing/Parsers.scala @@ -12,6 +12,7 @@ import core._ import Flags._ import Contexts._ import Names._ +import NameExtractors.WildcardParamName import ast.{Positioned, Trees, untpd} import ast.Trees._ import Decorators._ @@ -1168,7 +1169,7 @@ object Parsers { def bindingName(): TermName = if (in.token == USCORE) { in.nextToken() - ctx.freshName(nme.USCORE_PARAM_PREFIX).toTermName + WildcardParamName.fresh() } else ident() @@ -1224,7 +1225,7 @@ object Parsers { path(thisOK = true) case USCORE => val start = in.skipToken() - val pname = ctx.freshName(nme.USCORE_PARAM_PREFIX).toTermName + val pname = WildcardParamName.fresh() val param = ValDef(pname, TypeTree(), EmptyTree).withFlags(SyntheticTermParam) .withPos(Position(start)) placeholderParams = param :: placeholderParams @@ -1705,7 +1706,7 @@ object Parsers { if (isConcreteOwner || in.token != USCORE) ident().toTypeName else { in.nextToken() - ctx.freshName(nme.USCORE_PARAM_PREFIX).toTypeName + WildcardParamName.fresh().toTypeName } val hkparams = typeParamClauseOpt(ParamOwner.TypeParam) val bounds = diff --git a/compiler/src/dotty/tools/dotc/printing/PlainPrinter.scala b/compiler/src/dotty/tools/dotc/printing/PlainPrinter.scala index 20e657ce7..ec9257acf 100644 --- a/compiler/src/dotty/tools/dotc/printing/PlainPrinter.scala +++ b/compiler/src/dotty/tools/dotc/printing/PlainPrinter.scala @@ -264,7 +264,7 @@ class PlainPrinter(_ctx: Context) extends Printer { if (idx >= 0) selfRecName(idx + 1) else "{...}.this" // TODO move underlying type to an addendum, e.g. ... z3 ... where z3: ... case tp: SkolemType => - if (homogenizedView) toText(tp.info) else tp.repr + if (homogenizedView) toText(tp.info) else toText(tp.repr) } } diff --git a/compiler/src/dotty/tools/dotc/transform/CapturedVars.scala b/compiler/src/dotty/tools/dotc/transform/CapturedVars.scala index cd05589c3..368250cdf 100644 --- a/compiler/src/dotty/tools/dotc/transform/CapturedVars.scala +++ b/compiler/src/dotty/tools/dotc/transform/CapturedVars.scala @@ -12,6 +12,7 @@ import core.SymDenotations._ import core.StdNames.nme import core.Names._ import core.NameOps._ +import core.NameExtractors.TempResultName import ast.Trees._ import SymUtils._ import collection.{ mutable, immutable } @@ -138,7 +139,7 @@ class CapturedVars extends MiniPhase with IdentityDenotTransformer { thisTransfo val Select(_, nme.elem) = qual recur(qual) case Select(_, nme.elem) if refInfo.boxedRefClasses.contains(lhs.symbol.maybeOwner) => - val tempDef = transformFollowing(SyntheticValDef(ctx.freshName("ev$").toTermName, tree.rhs)) + val tempDef = transformFollowing(SyntheticValDef(TempResultName.fresh(), tree.rhs)) transformFollowing(Block(tempDef :: Nil, cpy.Assign(tree)(lhs, ref(tempDef.symbol)))) case _ => tree diff --git a/compiler/src/dotty/tools/dotc/transform/LazyVals.scala b/compiler/src/dotty/tools/dotc/transform/LazyVals.scala index 2035fb04b..357baa3df 100644 --- a/compiler/src/dotty/tools/dotc/transform/LazyVals.scala +++ b/compiler/src/dotty/tools/dotc/transform/LazyVals.scala @@ -10,6 +10,7 @@ import Contexts._ import Symbols._ import Decorators._ import NameOps._ +import NameExtractors._ import StdNames.nme import rewrite.Rewrites.patch import util.Positions.Position @@ -106,7 +107,7 @@ class LazyVals extends MiniPhaseTransform with IdentityDenotTransformer { */ def transformSyntheticModule(tree: ValOrDefDef)(implicit ctx: Context) = { val sym = tree.symbol - val holderSymbol = ctx.newSymbol(sym.owner, sym.asTerm.name.lazyLocalName, + val holderSymbol = ctx.newSymbol(sym.owner, LazyLocalName.fresh(sym.asTerm.name), Flags.Synthetic, sym.info.widen.resultType).enteredAfter(this) val field = ValDef(holderSymbol, tree.rhs.changeOwnerAfter(sym, holderSymbol, this)) val getter = DefDef(sym.asTerm, ref(holderSymbol)) @@ -119,8 +120,9 @@ class LazyVals extends MiniPhaseTransform with IdentityDenotTransformer { */ def transformLocalDef(x: ValOrDefDef)(implicit ctx: Context) = { val valueInitter = x.rhs - val holderName = ctx.freshName(x.name.asTermName.lazyLocalName).toTermName - val initName = ctx.freshName(x.name ++ StdNames.nme.LAZY_LOCAL_INIT).toTermName + val xname = x.name.asTermName + val holderName = LazyLocalName.fresh(xname) + val initName = LazyLocalInitName.fresh(xname) val tpe = x.tpe.widen.resultType.widen val holderType = @@ -211,7 +213,7 @@ class LazyVals extends MiniPhaseTransform with IdentityDenotTransformer { val claz = x.symbol.owner.asClass val tpe = x.tpe.widen.resultType.widen assert(!(x.symbol is Flags.Mutable)) - val containerName = ctx.freshName(x.name.asTermName.lazyLocalName).toTermName + val containerName = LazyLocalName.fresh(x.name.asTermName) val containerSymbol = ctx.newSymbol(claz, containerName, x.symbol.flags &~ containerFlagsMask | containerFlags | Flags.Private, tpe, coord = x.symbol.coord @@ -223,7 +225,7 @@ class LazyVals extends MiniPhaseTransform with IdentityDenotTransformer { Thicket(containerTree, slowPath) } else { - val flagName = ctx.freshName(x.name ++ StdNames.nme.BITMAP_PREFIX).toTermName + val flagName = LazyBitMapName.fresh(x.name.asTermName) val flagSymbol = ctx.newSymbol(x.symbol.owner, flagName, containerFlags | Flags.Private, defn.BooleanType).enteredAfter(this) val flag = ValDef(flagSymbol, Literal(Constants.Constant(false))) val slowPath = DefDef(x.symbol.asTerm, mkNonThreadSafeDef(ref(containerSymbol), ref(flagSymbol), x.rhs)) @@ -376,7 +378,7 @@ class LazyVals extends MiniPhaseTransform with IdentityDenotTransformer { appendOffsetDefs += (claz -> new OffsetInfo(List(offsetTree), ord)) } - val containerName = ctx.freshName(x.name.asTermName.lazyLocalName).toTermName + val containerName = LazyLocalName.fresh(x.name.asTermName) val containerSymbol = ctx.newSymbol(claz, containerName, x.symbol.flags &~ containerFlagsMask | containerFlags, tpe, coord = x.symbol.coord).enteredAfter(this) val containerTree = ValDef(containerSymbol, defaultValue(tpe)) diff --git a/compiler/src/dotty/tools/dotc/transform/LiftTry.scala b/compiler/src/dotty/tools/dotc/transform/LiftTry.scala index d01195614..61554f5ce 100644 --- a/compiler/src/dotty/tools/dotc/transform/LiftTry.scala +++ b/compiler/src/dotty/tools/dotc/transform/LiftTry.scala @@ -8,6 +8,7 @@ import core.Contexts._ import core.Types._ import core.Flags._ import core.Decorators._ +import core.NameExtractors.LiftedTreeName import NonLocalReturns._ /** Lifts try's that might be executed on non-empty expression stacks @@ -56,7 +57,7 @@ class LiftTry extends MiniPhase with IdentityDenotTransformer { thisTransform => if (needLift) { ctx.debuglog(i"lifting tree at ${tree.pos}, current owner = ${ctx.owner}") val fn = ctx.newSymbol( - ctx.owner, ctx.freshName("liftedTree").toTermName, Synthetic | Method, + ctx.owner, LiftedTreeName.fresh(), Synthetic | Method, MethodType(Nil, tree.tpe.widenIfUnstable), coord = tree.pos) tree.changeOwnerAfter(ctx.owner, fn, thisTransform) Block(DefDef(fn, tree) :: Nil, ref(fn).appliedToNone) diff --git a/compiler/src/dotty/tools/dotc/transform/MoveStatics.scala b/compiler/src/dotty/tools/dotc/transform/MoveStatics.scala index b0ee0930d..652320639 100644 --- a/compiler/src/dotty/tools/dotc/transform/MoveStatics.scala +++ b/compiler/src/dotty/tools/dotc/transform/MoveStatics.scala @@ -55,6 +55,7 @@ class MoveStatics extends MiniPhaseTransform with SymTransformer { thisTransform } def move(module: TypeDef, companion: TypeDef): List[Tree] = { + assert(companion ne module) if (!module.symbol.is(Flags.Module)) move(companion, module) else { val allMembers = diff --git a/compiler/src/dotty/tools/dotc/transform/NonLocalReturns.scala b/compiler/src/dotty/tools/dotc/transform/NonLocalReturns.scala index 7680e283e..945504743 100644 --- a/compiler/src/dotty/tools/dotc/transform/NonLocalReturns.scala +++ b/compiler/src/dotty/tools/dotc/transform/NonLocalReturns.scala @@ -5,6 +5,7 @@ import core._ import Contexts._, Symbols._, Types._, Flags._, Decorators._, StdNames._, Constants._, Phases._ import TreeTransforms._ import ast.Trees._ +import NameExtractors.NonLocalReturnKeyName import collection.mutable object NonLocalReturns { @@ -38,7 +39,7 @@ class NonLocalReturns extends MiniPhaseTransform { thisTransformer => private def nonLocalReturnKey(meth: Symbol)(implicit ctx: Context) = nonLocalReturnKeys.getOrElseUpdate(meth, ctx.newSymbol( - meth, ctx.freshName("nonLocalReturnKey").toTermName, Synthetic, defn.ObjectType, coord = meth.pos)) + meth, NonLocalReturnKeyName.fresh(), Synthetic, defn.ObjectType, coord = meth.pos)) /** Generate a non-local return throw with given return expression from given method. * I.e. for the method's non-local return key, generate: diff --git a/compiler/src/dotty/tools/dotc/transform/PatternMatcher.scala b/compiler/src/dotty/tools/dotc/transform/PatternMatcher.scala index dbc7666f7..f93eac0a2 100644 --- a/compiler/src/dotty/tools/dotc/transform/PatternMatcher.scala +++ b/compiler/src/dotty/tools/dotc/transform/PatternMatcher.scala @@ -11,6 +11,7 @@ import core.Symbols._ import core.Types._ import core.Constants._ import core.StdNames._ +import core.NameExtractors._ import dotty.tools.dotc.ast.{untpd, TreeTypeMap, tpd} import dotty.tools.dotc.core import dotty.tools.dotc.core.DenotTransformers.DenotTransformer @@ -70,16 +71,14 @@ class PatternMatcher extends MiniPhaseTransform with DenotTransformer { class OptimizingMatchTranslator extends MatchOptimizer/*(val typer: analyzer.Typer)*/ with MatchTranslator trait CodegenCore { - private var ctr = 0 // left for debugging // assert(owner ne null); assert(owner ne NoSymbol) - def freshSym(pos: Position, tp: Type = NoType, prefix: String = "x", owner: Symbol = ctx.owner) = { - ctr += 1 - ctx.newSymbol(owner, ctx.freshName(prefix + ctr).toTermName, Flags.Synthetic | Flags.Case, tp, coord = pos) + def freshSym(pos: Position, tp: Type = NoType, unique: UniqueNameExtractor = PatMatStdBinderName, owner: Symbol = ctx.owner) = { + ctx.newSymbol(owner, unique.fresh(), Flags.Synthetic | Flags.Case, tp, coord = pos) } - def newSynthCaseLabel(name: String, tpe: Type, owner: Symbol = ctx.owner) = - ctx.newSymbol(owner, ctx.freshName(name).toTermName, Flags.Label | Flags.Synthetic | Flags.Method, tpe).asTerm + def newSynthCaseLabel(unique: UniqueNameExtractor, tpe: Type, owner: Symbol = ctx.owner) = + ctx.newSymbol(owner, unique.fresh(), Flags.Label | Flags.Synthetic | Flags.Method, tpe).asTerm //NoSymbol.newLabel(freshName(name), NoPosition) setFlag treeInfo.SYNTH_CASE_FLAGS // codegen relevant to the structure of the translation (how extractors are combined) @@ -189,7 +188,8 @@ class PatternMatcher extends MiniPhaseTransform with DenotTransformer { //NoSymbol.newValueParameter(newTermName("x"), NoPosition, newFlags = SYNTHETIC) setInfo restpe.withoutAnnotations - val caseSyms: List[TermSymbol] = cases.scanLeft(ctx.owner.asTerm)((curOwner, nextTree) => newSynthCaseLabel(ctx.freshName("case"), MethodType(Nil, restpe), curOwner)).tail + val caseSyms: List[TermSymbol] = cases.scanLeft(ctx.owner.asTerm)((curOwner, nextTree) => + newSynthCaseLabel(PatMatCaseName, MethodType(Nil, restpe), curOwner)).tail // must compute catchAll after caseLabels (side-effects nextCase) // catchAll.isEmpty iff no synthetic default case needed (the (last) user-defined case is a default) @@ -197,7 +197,7 @@ class PatternMatcher extends MiniPhaseTransform with DenotTransformer { val catchAllDef = matchFailGen.map { _(scrutSym) } .getOrElse(Throw(New(defn.MatchErrorType, List(ref(scrutSym))))) - val matchFail = newSynthCaseLabel(ctx.freshName("matchFail"), MethodType(Nil, restpe)) + val matchFail = newSynthCaseLabel(PatMatMatchFailName, MethodType(Nil, restpe)) val catchAllDefBody = DefDef(matchFail, catchAllDef) val nextCases = (caseSyms.tail ::: List(matchFail)).map(ref(_).ensureApplied) @@ -249,7 +249,7 @@ class PatternMatcher extends MiniPhaseTransform with DenotTransformer { val isEmptyDenot = extractorMember(prev.tpe, nme.isEmpty) assert(getDenot.exists && isEmptyDenot.exists, i"${prev.tpe}") - val tmpSym = freshSym(prev.pos, prev.tpe, "o") + val tmpSym = freshSym(prev.pos, prev.tpe, PatMatOName) val prevValue = ref(tmpSym).select(getDenot.symbol).ensureApplied Block( @@ -1056,9 +1056,9 @@ class PatternMatcher extends MiniPhaseTransform with DenotTransformer { } def newBoundTree(tree: Tree, pt: Type): BoundTree = tree match { - case SymbolBound(sym, Typed(subpat, tpe)) => BoundTree(freshSym(tree.pos, pt, prefix = "pi"), tree) + case SymbolBound(sym, Typed(subpat, tpe)) => BoundTree(freshSym(tree.pos, pt, PatMatPiName), tree) case SymbolBound(sym, expr) => BoundTree(sym, expr) - case _ => BoundTree(freshSym(tree.pos, pt, prefix = "p"), tree) + case _ => BoundTree(freshSym(tree.pos, pt, PatMatPName), tree) } final case class BoundTree(binder: Symbol, tree: Tree) { @@ -1204,7 +1204,7 @@ class PatternMatcher extends MiniPhaseTransform with DenotTransformer { val selectorTp = sel.tpe.widen.deAnonymize/*withoutAnnotations*/ - val selectorSym = freshSym(sel.pos, selectorTp, "selector") + val selectorSym = freshSym(sel.pos, selectorTp, PatMatSelectorName) val (nonSyntheticCases, defaultOverride) = cases match { case init :+ last if isSyntheticDefaultCase(last) => (init, Some(((scrut: Symbol) => last.body))) diff --git a/compiler/src/dotty/tools/dotc/transform/TailRec.scala b/compiler/src/dotty/tools/dotc/transform/TailRec.scala index 8a695bf22..87e9c1013 100644 --- a/compiler/src/dotty/tools/dotc/transform/TailRec.scala +++ b/compiler/src/dotty/tools/dotc/transform/TailRec.scala @@ -1,16 +1,17 @@ -package dotty.tools.dotc.transform - -import dotty.tools.dotc.ast.Trees._ -import dotty.tools.dotc.ast.{TreeTypeMap, tpd} -import dotty.tools.dotc.core.Contexts.Context -import dotty.tools.dotc.core.Decorators._ -import dotty.tools.dotc.core.DenotTransformers.DenotTransformer -import dotty.tools.dotc.core.Denotations.SingleDenotation -import dotty.tools.dotc.core.Symbols._ -import dotty.tools.dotc.core.Types._ -import dotty.tools.dotc.core._ -import dotty.tools.dotc.transform.TailRec._ -import dotty.tools.dotc.transform.TreeTransforms.{MiniPhaseTransform, TransformerInfo} +package dotty.tools.dotc +package transform + +import ast.Trees._ +import ast.{TreeTypeMap, tpd} +import core._ +import Contexts.Context +import Decorators._ +import DenotTransformers.DenotTransformer +import Denotations.SingleDenotation +import Symbols._ +import Types._ +import NameExtractors.TailLabelName +import TreeTransforms.{MiniPhaseTransform, TransformerInfo} /** * A Tail Rec Transformer @@ -62,6 +63,7 @@ import dotty.tools.dotc.transform.TreeTransforms.{MiniPhaseTransform, Transforme *

*/ class TailRec extends MiniPhaseTransform with DenotTransformer with FullParameterization { thisTransform => + import TailRec._ import dotty.tools.dotc.ast.tpd._ @@ -70,7 +72,6 @@ class TailRec extends MiniPhaseTransform with DenotTransformer with FullParamete override def phaseName: String = "tailrec" override def treeTransformPhase = thisTransform // TODO Make sure tailrec runs at next phase. - final val labelPrefix = "tailLabel" final val labelFlags = Flags.Synthetic | Flags.Label /** Symbols of methods that have @tailrec annotatios inside */ @@ -87,12 +88,12 @@ class TailRec extends MiniPhaseTransform with DenotTransformer with FullParamete tree } - private def mkLabel(method: Symbol, abstractOverClass: Boolean)(implicit c: Context): TermSymbol = { - val name = c.freshName(labelPrefix) + private def mkLabel(method: Symbol, abstractOverClass: Boolean)(implicit ctx: Context): TermSymbol = { + val name = TailLabelName.fresh() if (method.owner.isClass) - c.newSymbol(method, name.toTermName, labelFlags, fullyParameterizedType(method.info, method.enclosingClass.asClass, abstractOverClass, liftThisType = false)) - else c.newSymbol(method, name.toTermName, labelFlags, method.info) + ctx.newSymbol(method, name.toTermName, labelFlags, fullyParameterizedType(method.info, method.enclosingClass.asClass, abstractOverClass, liftThisType = false)) + else ctx.newSymbol(method, name.toTermName, labelFlags, method.info) } override def transformDefDef(tree: tpd.DefDef)(implicit ctx: Context, info: TransformerInfo): tpd.Tree = { diff --git a/compiler/src/dotty/tools/dotc/transform/TryCatchPatterns.scala b/compiler/src/dotty/tools/dotc/transform/TryCatchPatterns.scala index 9a6ecef51..a651c0c74 100644 --- a/compiler/src/dotty/tools/dotc/transform/TryCatchPatterns.scala +++ b/compiler/src/dotty/tools/dotc/transform/TryCatchPatterns.scala @@ -5,6 +5,7 @@ import core.Symbols._ import core.StdNames._ import ast.Trees._ import core.Types._ +import core.NameExtractors.ExceptionBinderName import dotty.tools.dotc.core.Decorators._ import dotty.tools.dotc.core.Flags import dotty.tools.dotc.core.Contexts.Context @@ -83,7 +84,7 @@ class TryCatchPatterns extends MiniPhaseTransform { implicit ctx: Context, info: TransformerInfo): Option[CaseDef] = { if (patternMatchCases.isEmpty) None else { - val exName = ctx.freshName("ex").toTermName + val exName = ExceptionBinderName.fresh() val fallbackSelector = ctx.newSymbol(ctx.owner, exName, Flags.Synthetic | Flags.Case, defn.ThrowableType, coord = pos) val sel = Ident(fallbackSelector.termRef).withPos(pos) diff --git a/compiler/src/dotty/tools/dotc/typer/EtaExpansion.scala b/compiler/src/dotty/tools/dotc/typer/EtaExpansion.scala index 5aee0fd54..3f3a0cce3 100644 --- a/compiler/src/dotty/tools/dotc/typer/EtaExpansion.scala +++ b/compiler/src/dotty/tools/dotc/typer/EtaExpansion.scala @@ -12,6 +12,7 @@ import Symbols._ import Decorators._ import Names._ import StdNames._ +import NameExtractors.UniqueName import Trees._ import Inferencing._ import util.Positions._ @@ -21,10 +22,10 @@ object EtaExpansion { import tpd._ - private def lift(defs: mutable.ListBuffer[Tree], expr: Tree, prefix: String = "")(implicit ctx: Context): Tree = + private def lift(defs: mutable.ListBuffer[Tree], expr: Tree, prefix: TermName = EmptyTermName)(implicit ctx: Context): Tree = if (isPureExpr(expr)) expr else { - val name = ctx.freshName(prefix).toTermName + val name = UniqueName.fresh(prefix) val liftedType = fullyDefinedType(expr.tpe.widen, "lifted expression", expr.pos) val sym = ctx.newSymbol(ctx.owner, name, EmptyFlags, liftedType, coord = positionCoord(expr.pos)) defs += ValDef(sym, expr) @@ -48,7 +49,7 @@ object EtaExpansion { } /** Lift a function argument, stripping any NamedArg wrapper */ - def liftArg(defs: mutable.ListBuffer[Tree], arg: Tree, prefix: String = "")(implicit ctx: Context): Tree = + def liftArg(defs: mutable.ListBuffer[Tree], arg: Tree, prefix: TermName = EmptyTermName)(implicit ctx: Context): Tree = arg match { case arg @ NamedArg(name, arg1) => cpy.NamedArg(arg)(name, lift(defs, arg1, prefix)) case arg => lift(defs, arg, prefix) @@ -62,7 +63,7 @@ object EtaExpansion { case mt: MethodType => (args, mt.paramNames, mt.paramInfos).zipped map { (arg, name, tp) => if (tp.isInstanceOf[ExprType]) arg - else liftArg(defs, arg, if (name contains '$') "" else name.toString + "$") + else liftArg(defs, arg, if (name contains '$') EmptyTermName else name) } case _ => args map (liftArg(defs, _)) diff --git a/compiler/src/dotty/tools/dotc/typer/Inliner.scala b/compiler/src/dotty/tools/dotc/typer/Inliner.scala index f6d65fbb9..ad65af98c 100644 --- a/compiler/src/dotty/tools/dotc/typer/Inliner.scala +++ b/compiler/src/dotty/tools/dotc/typer/Inliner.scala @@ -15,6 +15,7 @@ import StdNames.nme import Contexts.Context import Names.{Name, TermName} import NameOps._ +import NameExtractors.InlineAccessorName import SymDenotations.SymDenotation import Annotations._ import transform.ExplicitOuter @@ -49,8 +50,7 @@ object Inliner { sym.is(AccessFlags) || sym.privateWithin.exists /** The name of the next accessor to be generated */ - def accessorName(implicit ctx: Context) = - ctx.freshNames.newName(inlineMethod.name.asTermName.inlineAccessorName.toString) + def accessorName(implicit ctx: Context) = InlineAccessorName.fresh(inlineMethod.name.asTermName) /** A fresh accessor symbol. * diff --git a/compiler/src/dotty/tools/dotc/typer/ProtoTypes.scala b/compiler/src/dotty/tools/dotc/typer/ProtoTypes.scala index ab342dc17..03357fee3 100644 --- a/compiler/src/dotty/tools/dotc/typer/ProtoTypes.scala +++ b/compiler/src/dotty/tools/dotc/typer/ProtoTypes.scala @@ -5,6 +5,7 @@ package typer import core._ import ast._ import Contexts._, Types._, Flags._, Denotations._, Names._, StdNames._, NameOps._, Symbols._ +import NameExtractors.DepParamName import Trees._ import Constants._ import Scopes._ @@ -401,7 +402,7 @@ object ProtoTypes { /** Create a new TypeParamRef that represents a dependent method parameter singleton */ def newDepTypeParamRef(tp: Type)(implicit ctx: Context): TypeParamRef = { - val poly = PolyType(ctx.freshName(nme.DEP_PARAM_PREFIX).toTypeName :: Nil)( + val poly = PolyType(DepParamName.fresh().toTypeName :: Nil)( pt => TypeBounds.upper(AndType(tp, defn.SingletonType)) :: Nil, pt => defn.AnyType) ctx.typeComparer.addToConstraint(poly, Nil) diff --git a/compiler/src/dotty/tools/dotc/util/FreshNameCreator.scala b/compiler/src/dotty/tools/dotc/util/FreshNameCreator.scala index 8892a570e..529e30f05 100644 --- a/compiler/src/dotty/tools/dotc/util/FreshNameCreator.scala +++ b/compiler/src/dotty/tools/dotc/util/FreshNameCreator.scala @@ -3,9 +3,12 @@ package dotc package util import scala.collection.mutable +import core.Names.TermName +import core.NameExtractors.UniqueNameExtractor +import core.StdNames.str -trait FreshNameCreator { - def newName(prefix: String = ""): String +abstract class FreshNameCreator { + def newName(prefix: TermName, unique: UniqueNameExtractor): TermName } object FreshNameCreator { @@ -18,11 +21,11 @@ object FreshNameCreator { * that the returned name has never been returned by a previous * call to this function (provided the prefix does not end in a digit). */ - def newName(prefix: String): String = { - val safePrefix = prefix.replaceAll("""[<>]""", """\$""") - counters(safePrefix) += 1 - val counter = counters(safePrefix) - if (prefix.isEmpty) "$" + counter + "$" else safePrefix + counter + def newName(prefix: TermName, unique: UniqueNameExtractor): TermName = { + val key = str.sanitize(prefix.toString + unique.separator) + counters(key) += 1 + val counter = counters(key) + prefix.derived(unique.NumberedInfo(counter)) } } } -- cgit v1.2.3