From 868a6a1025781eeac3eb884040639119542b3f49 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Mon, 3 Apr 2017 17:35:21 +0200 Subject: Make extension method names semantic --- compiler/src/dotty/tools/dotc/core/NameKinds.scala | 33 ++++++++++++++++------ .../dotty/tools/dotc/core/tasty/TastyFormat.scala | 1 + .../tools/dotc/transform/ExtensionMethods.scala | 5 ++-- 3 files changed, 29 insertions(+), 10 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/core/NameKinds.scala b/compiler/src/dotty/tools/dotc/core/NameKinds.scala index 8ea19bed2..cda6e0c83 100644 --- a/compiler/src/dotty/tools/dotc/core/NameKinds.scala +++ b/compiler/src/dotty/tools/dotc/core/NameKinds.scala @@ -132,6 +132,13 @@ object NameKinds { 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 + } } case class UniqueNameKind(val separator: String) @@ -205,6 +212,18 @@ object NameKinds { 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 @@ -218,15 +237,12 @@ object NameKinds { val prefix = if (underlying.isConstructorName) nme.DEFAULT_GETTER_INIT else underlying prefix.toString + str.DEFAULT_GETTER + (info.num + 1) } - - private val dgLen = str.DEFAULT_GETTER.length - + // TODO: Reduce code duplication with UniqueExtMethName override def unmangle(name: SimpleTermName): TermName = { - var i = name.length - while (i > 0 && name(i - 1).isDigit) i -= 1 - if (i > dgLen && i < name.length && name.slice(i - dgLen, i) == nme.DEFAULT_GETTER) { + val i = skipSeparatorAndNum(name, str.DEFAULT_GETTER) + if (i > 0) { val index = name.drop(i).toString.toInt - 1 - var original = name.take(i - dgLen).asTermName + var original = name.take(i - str.DEFAULT_GETTER.length).asTermName if (original == nme.DEFAULT_GETTER_INIT) original = Names.CONSTRUCTOR apply(original, index) } @@ -260,6 +276,7 @@ object NameKinds { 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") @@ -283,7 +300,7 @@ object NameKinds { } val Scala2MethodNameKinds: List[NameKind] = - List(DefaultGetterName, ProtectedAccessorName, ProtectedSetterName) + List(DefaultGetterName, ExtMethName, UniqueExtMethName, ProtectedAccessorName, ProtectedSetterName) def simpleNameKindOfTag : collection.Map[Int, ClassifiedNameKind] = simpleNameKinds def qualifiedNameKindOfTag : collection.Map[Int, QualifiedNameKind] = qualifiedNameKinds diff --git a/compiler/src/dotty/tools/dotc/core/tasty/TastyFormat.scala b/compiler/src/dotty/tools/dotc/core/tasty/TastyFormat.scala index 68c5bf10e..f03e279c6 100644 --- a/compiler/src/dotty/tools/dotc/core/tasty/TastyFormat.scala +++ b/compiler/src/dotty/tools/dotc/core/tasty/TastyFormat.scala @@ -240,6 +240,7 @@ object TastyFormat { final val DIRECT = 31 final val FIELD = 32 final val SETTER = 33 + final val EXTMETH = 34 final val OBJECTVAR = 39 final val OBJECTCLASS = 40 diff --git a/compiler/src/dotty/tools/dotc/transform/ExtensionMethods.scala b/compiler/src/dotty/tools/dotc/transform/ExtensionMethods.scala index 64474cecd..61f32edae 100644 --- a/compiler/src/dotty/tools/dotc/transform/ExtensionMethods.scala +++ b/compiler/src/dotty/tools/dotc/transform/ExtensionMethods.scala @@ -16,6 +16,7 @@ import Types._, Contexts._, Constants._, Names._, NameOps._, Flags._, DenotTrans import SymDenotations._, Symbols._, StdNames._, Annotations._, Trees._, Scopes._, Denotations._ import TypeErasure.{ valueErasure, ErasedValueType } import TypeUtils._ +import NameKinds.{ExtMethName, UniqueExtMethName} import util.Positions._ import Decorators._ import SymUtils._ @@ -206,11 +207,11 @@ object ExtensionMethods { val alts = decl.alternatives val index = alts indexOf imeth.denot assert(index >= 0, alts + " does not contain " + imeth) - def altName(index: Int) = (imeth.name + "$extension" + index).toTermName + def altName(index: Int) = UniqueExtMethName(imeth.name.asTermName, index) altName(index) #:: ((0 until alts.length).toStream filter (index != _) map altName) case decl => assert(decl.exists, imeth.name + " not found in " + imeth.owner + "'s decls: " + imeth.owner.info.decls) - Stream((imeth.name + "$extension").toTermName) + Stream(ExtMethName(imeth.name.asTermName)) } } -- cgit v1.2.3