aboutsummaryrefslogtreecommitdiff
path: root/compiler/src/dotty/tools/dotc/core/NameKinds.scala
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/src/dotty/tools/dotc/core/NameKinds.scala')
-rw-r--r--compiler/src/dotty/tools/dotc/core/NameKinds.scala317
1 files changed, 317 insertions, 0 deletions
diff --git a/compiler/src/dotty/tools/dotc/core/NameKinds.scala b/compiler/src/dotty/tools/dotc/core/NameKinds.scala
new file mode 100644
index 000000000..0f08e4701
--- /dev/null
+++ b/compiler/src/dotty/tools/dotc/core/NameKinds.scala
@@ -0,0 +1,317 @@
+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
+
+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 uniqueNameKinds = new mutable.HashMap[String, UniqueNameKind]
+
+ abstract class NameInfo extends DotClass {
+ def kind: NameKind
+ def mkString(underlying: TermName): String
+ def map(f: SimpleTermName => SimpleTermName): NameInfo = this
+ }
+
+ abstract class NameKind(val tag: Int) extends DotClass { self =>
+ type ThisInfo <: Info
+ class Info extends NameInfo { this: ThisInfo =>
+ def kind = self
+ def mkString(underlying: TermName) = self.mkString(underlying, this)
+ override def toString = infoString
+ }
+ def definesNewName = false
+ def unmangle(name: SimpleTermName): TermName = name
+ def mkString(underlying: TermName, info: ThisInfo): String
+ def infoString: String
+ }
+
+ object SimpleTermNameKind extends NameKind(UTF8) { self =>
+ type ThisInfo = Info
+ val info = new Info
+ def mkString(underlying: TermName, info: ThisInfo) = unsupported("mkString")
+ def infoString = unsupported("infoString")
+ }
+
+ abstract class ClassifiedNameKind(tag: Int, val infoString: String) extends NameKind(tag) {
+ type ThisInfo = Info
+ val info = new Info
+ def apply(qual: TermName) =
+ qual.derived(info)
+ def unapply(name: DerivedTermName): Option[TermName] = name match {
+ case DerivedTermName(underlying, `info`) => Some(underlying)
+ case _ => None
+ }
+ simpleNameKinds(tag) = this
+ }
+
+ 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.mapLast(n => termName(prefix + n.toString)).toString
+ override def unmangle(name: SimpleTermName): TermName =
+ if (name.startsWith(prefix)) apply(name.drop(prefix.length).asSimpleName)
+ else 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.toString ++ suffix
+ override def unmangle(name: SimpleTermName): TermName =
+ if (name.endsWith(suffix)) apply(name.take(name.length - suffix.length).asSimpleName)
+ else name
+ }
+
+ trait QualifiedInfo extends NameInfo {
+ val name: SimpleTermName
+ }
+
+ class QualifiedNameKind(tag: Int, val separator: String)
+ extends NameKind(tag) {
+ type ThisInfo = QualInfo
+ case class QualInfo(val name: SimpleTermName) extends Info with QualifiedInfo {
+ override def map(f: SimpleTermName => SimpleTermName): NameInfo = new QualInfo(f(name))
+ override def toString = s"$infoString $name"
+ }
+ def apply(qual: TermName, name: SimpleTermName): 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: SimpleTermName => apply(qual, name)
+ case AnyQualifiedName(_, _) => apply(qual, name.toSimpleName)
+ }
+
+ def unapply(name: DerivedTermName): Option[(TermName, SimpleTermName)] = name match {
+ 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"
+
+ qualifiedNameKinds(tag) = this
+ }
+
+ object AnyQualifiedName {
+ def unapply(name: DerivedTermName): Option[(TermName, SimpleTermName)] = name match {
+ case DerivedTermName(qual, info: QualifiedInfo) =>
+ Some((name.underlying, info.name))
+ case _ => None
+ }
+ }
+
+ trait NumberedInfo extends NameInfo {
+ def num: Int
+ }
+
+ 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: DerivedTermName): Option[(TermName, Int)] = name match {
+ case DerivedTermName(underlying, info: this.NumberedInfo) => Some((underlying, info.num))
+ case _ => None
+ }
+ protected def skipSeparatorAndNum(name: SimpleTermName, 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
+ }
+ }
+
+ object AnyNumberedName {
+ def unapply(name: DerivedTermName): Option[(TermName, Int)] = name match {
+ case DerivedTermName(qual, info: NumberedInfo) => Some((qual, info.num))
+ case _ => None
+ }
+ }
+
+ 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
+ }
+
+ def fresh(prefix: TermName = EmptyTermName)(implicit ctx: Context): TermName =
+ ctx.freshNames.newName(prefix, this)
+
+ uniqueNameKinds(separator) = this
+ }
+
+ object AnyUniqueName {
+ def unapply(name: DerivedTermName): Option[(TermName, String, Int)] = name match {
+ case DerivedTermName(qual, info: NumberedInfo) =>
+ info.kind match {
+ case unique: UniqueNameKind => Some((qual, unique.separator, info.num))
+ case _ => None
+ }
+ case _ => None
+ }
+ }
+
+ val QualifiedName = new QualifiedNameKind(QUALIFIED, ".")
+ val FlatName = new QualifiedNameKind(FLATTENED, "$")
+ val ExpandPrefixName = new QualifiedNameKind(EXPANDPREFIX, "$")
+
+ val ExpandedName = new QualifiedNameKind(EXPANDED, str.EXPAND_SEPARATOR) {
+ private val FalseSuper = termName("$$super")
+ private val FalseSuperLength = FalseSuper.length
+
+ override def unmangle(name: SimpleTermName): 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)
+ }
+ }
+ }
+
+ val TraitSetterName = new QualifiedNameKind(TRAITSETTER, str.TRAIT_SETTER_SEPARATOR)
+
+ val UniqueName = new UniqueNameKind("$") {
+ override def mkString(underlying: TermName, info: ThisInfo) =
+ if (underlying.isEmpty) "$" + info.num + "$" else super.mkString(underlying, info)
+ }
+
+ 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 UniqueExtMethName = new UniqueNameKind("$extension") {
+ override def unmangle(name: SimpleTermName): TermName = {
+ val i = skipSeparatorAndNum(name, separator)
+ if (i > 0) {
+ val index = name.drop(i).toString.toInt
+ var original = name.take(i - separator.length).asTermName
+ apply(original, index)
+ }
+ else name
+ }
+ }
+
+ 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")
+
+ object DefaultGetterName extends 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: SimpleTermName): 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 = Names.CONSTRUCTOR
+ apply(original, index)
+ }
+ else name
+ }
+ }
+
+ object VariantName extends NumberedNameKind(VARIANT, "Variant") {
+ val varianceToPrefix = Map(-1 -> '-', 0 -> '=', 1 -> '+')
+ def mkString(underlying: TermName, info: ThisInfo) = {
+ varianceToPrefix(info.num).toString + underlying
+ }
+ }
+
+ /** Names of the form N_<outer>. Emitted by inliner, replaced by outer path
+ * in ExplicitOuter.
+ */
+ object OuterSelectName extends 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 ShadowedName = new PrefixNameKind(SHADOWED, "(shadowed)")
+ 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 DirectName = new SuffixNameKind(DIRECT, "$direct")
+ val FieldName = new SuffixNameKind(FIELD, "$$local")
+ val ExtMethName = new SuffixNameKind(EXTMETH, "$extension")
+ val ModuleVarName = new SuffixNameKind(OBJECTVAR, "$module")
+ val ModuleClassName = new SuffixNameKind(OBJECTCLASS, "$", optInfoString = "ModuleClass")
+
+ object SignedName extends NameKind(63) {
+
+ /** @param parts resultSig followed by paramsSig */
+ case class SignedInfo(sig: Signature) extends Info {
+ override def toString = s"$infoString $sig"
+ }
+ type ThisInfo = SignedInfo
+
+ def apply(qual: TermName, sig: Signature) =
+ qual.derived(new SignedInfo(sig))
+ def unapply(name: DerivedTermName): Option[(TermName, Signature)] = name match {
+ case DerivedTermName(underlying, info: SignedInfo) => Some((underlying, info.sig))
+ case _ => None
+ }
+
+ def mkString(underlying: TermName, info: ThisInfo): String = unsupported("mkString")
+ def infoString: String = "Signed"
+ }
+
+ 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 uniqueNameKindOfSeparator: collection.Map[String, UniqueNameKind] = uniqueNameKinds
+} \ No newline at end of file