aboutsummaryrefslogtreecommitdiff
path: root/compiler/src/dotty/tools/dotc/core/NameOps.scala
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2017-03-31 18:32:02 +0200
committerMartin Odersky <odersky@gmail.com>2017-04-11 09:33:12 +0200
commitb4f21c6da6b6bc1797908f1400631573b6445e31 (patch)
tree19efe5c588230059b04ef046114c30d3fd64b1f9 /compiler/src/dotty/tools/dotc/core/NameOps.scala
parent7a927ce233a8ea4b8ddc285b8a36c61ca3fdd405 (diff)
downloaddotty-b4f21c6da6b6bc1797908f1400631573b6445e31.tar.gz
dotty-b4f21c6da6b6bc1797908f1400631573b6445e31.tar.bz2
dotty-b4f21c6da6b6bc1797908f1400631573b6445e31.zip
Names are no longer Seqs
Drop Seq implementation of name. This implementation was always problematic because it entailed potentially very costly conversions to toSimpleName. We now have better control over when we convert a name to a simple name.
Diffstat (limited to 'compiler/src/dotty/tools/dotc/core/NameOps.scala')
-rw-r--r--compiler/src/dotty/tools/dotc/core/NameOps.scala101
1 files changed, 36 insertions, 65 deletions
diff --git a/compiler/src/dotty/tools/dotc/core/NameOps.scala b/compiler/src/dotty/tools/dotc/core/NameOps.scala
index 2caaaf1ab..e74bf8ca7 100644
--- a/compiler/src/dotty/tools/dotc/core/NameOps.scala
+++ b/compiler/src/dotty/tools/dotc/core/NameOps.scala
@@ -52,24 +52,32 @@ object NameOps {
implicit class NameDecorator[N <: Name](val name: N) extends AnyVal {
import nme._
+ def testSimple(f: SimpleTermName => Boolean): Boolean = name match {
+ case name: SimpleTermName => f(name)
+ case name: TypeName => name.toTermName.testSimple(f)
+ case _ => false
+ }
+
def likeTyped(n: PreName): N =
(if (name.isTermName) n.toTermName else n.toTypeName).asInstanceOf[N]
def isConstructorName = name == CONSTRUCTOR || name == TRAIT_CONSTRUCTOR
def isStaticConstructorName = name == STATIC_CONSTRUCTOR
def isLocalDummyName = name startsWith LOCALDUMMY_PREFIX
- def isReplWrapperName = name.toSimpleName containsSlice INTERPRETER_IMPORT_WRAPPER
+ def isReplWrapperName = name.toString contains str.INTERPRETER_IMPORT_WRAPPER
def isSetterName = name endsWith SETTER_SUFFIX
- def isScala2LocalSuffix = name.endsWith(" ")
- def isSelectorName = name.startsWith("_") && name.tail.forall(_.isDigit)
+ def isScala2LocalSuffix = testSimple(_.endsWith(" "))
+ def isSelectorName = testSimple(n => n.startsWith("_") && n.drop(1).forall(_.isDigit))
/** Is name a variable name? */
- def isVariableName: Boolean = name.length > 0 && {
- val first = name.head
- (((first.isLower && first.isLetter) || first == '_')
- && (name != false_)
- && (name != true_)
- && (name != null_))
+ def isVariableName: Boolean = testSimple { n =>
+ n.length > 0 && {
+ val first = n.head
+ (((first.isLower && first.isLetter) || first == '_')
+ && (n != false_)
+ && (n != true_)
+ && (n != null_))
+ }
}
def isOpAssignmentName: Boolean = name match {
@@ -91,11 +99,10 @@ object NameOps {
* method needs to work on mangled as well as unmangled names because
* it is also called from the backend.
*/
- def stripModuleClassSuffix: Name = name.toTermName match {
- case n: SimpleTermName if n.endsWith("$") =>
- name.unmangleClassName.exclude(ModuleClassName)
- case _ =>
- name.exclude(ModuleClassName)
+ def stripModuleClassSuffix: N = likeTyped {
+ val name1 =
+ if (name.isSimple && name.endsWith("$")) name.unmangleClassName else name
+ name.exclude(ModuleClassName)
}
/** If flags is a ModuleClass but not a Package, add module class suffix */
@@ -159,56 +166,13 @@ object NameOps {
}
}
- def unmangleClassName: N =
- if (name.isSimple && name.isTypeName)
- if (name.endsWith(MODULE_SUFFIX) && !tpnme.falseModuleClassNames.contains(name.asTypeName))
- likeTyped(name.dropRight(MODULE_SUFFIX.length).moduleClassName)
- else name
- else name
-
- /** Translate a name into a list of simple TypeNames and TermNames.
- * In all segments before the last, type/term is determined by whether
- * the following separator char is '.' or '#'. The last segment
- * is of the same type as the original name.
- *
- * Examples:
- *
- * package foo {
- * object Lorax { object Wog ; class Wog }
- * class Lorax { object Zax ; class Zax }
- * }
- *
- * f("foo.Lorax".toTermName) == List("foo": Term, "Lorax": Term) // object Lorax
- * f("foo.Lorax".toTypeName) == List("foo": Term, "Lorax": Type) // class Lorax
- * f("Lorax.Wog".toTermName) == List("Lorax": Term, "Wog": Term) // object Wog
- * f("Lorax.Wog".toTypeName) == List("Lorax": Term, "Wog": Type) // class Wog
- * f("Lorax#Zax".toTermName) == List("Lorax": Type, "Zax": Term) // object Zax
- * f("Lorax#Zax".toTypeName) == List("Lorax": Type, "Zax": Type) // class Zax
- *
- * Note that in actual scala syntax you cannot refer to object Zax without an
- * instance of Lorax, so Lorax#Zax could only mean the type. One might think
- * that Lorax#Zax.type would work, but this is not accepted by the parser.
- * For the purposes of referencing that object, the syntax is allowed.
- */
- def segments: List[Name] = {
- def mkName(name: Name, follow: Char): Name =
- if (follow == '.') name.toTermName else name.toTypeName
-
- name.indexWhere(ch => ch == '.' || ch == '#') match {
- case -1 =>
- if (name.isEmpty) scala.Nil else name :: scala.Nil
- case idx =>
- mkName(name take idx, name(idx)) :: (name drop (idx + 1)).segments
- }
- }
-
/** Is a synthetic function name
* - N for FunctionN
* - N for ImplicitFunctionN
* - (-1) otherwise
*/
def functionArity: Int =
- functionArityFor(tpnme.Function) max functionArityFor(tpnme.ImplicitFunction)
+ functionArityFor(str.Function) max functionArityFor(str.ImplicitFunction)
/** Is a function name
* - FunctionN for N >= 0
@@ -221,7 +185,7 @@ object NameOps {
* - ImplicitFunctionN for N >= 0
* - false otherwise
*/
- def isImplicitFunction: Boolean = functionArityFor(tpnme.ImplicitFunction) >= 0
+ def isImplicitFunction: Boolean = functionArityFor(str.ImplicitFunction) >= 0
/** Is a synthetic function name
* - FunctionN for N > 22
@@ -229,12 +193,12 @@ object NameOps {
* - false otherwise
*/
def isSyntheticFunction: Boolean = {
- functionArityFor(tpnme.Function) > MaxImplementedFunctionArity ||
- functionArityFor(tpnme.ImplicitFunction) >= 0
+ functionArityFor(str.Function) > MaxImplementedFunctionArity ||
+ functionArityFor(str.ImplicitFunction) >= 0
}
/** Parsed function arity for function with some specific prefix */
- private def functionArityFor(prefix: Name): Int = {
+ private def functionArityFor(prefix: String): Int = {
if (name.startsWith(prefix))
try name.toString.substring(prefix.length).toInt
catch { case _: NumberFormatException => -1 }
@@ -285,6 +249,13 @@ object NameOps {
/** If name length exceeds allowable limit, replace part of it by hash */
def compactified(implicit ctx: Context): TermName = termName(compactify(name.toString))
+ def unmangleClassName: N = name.toTermName match {
+ case name: SimpleTermName
+ if name.endsWith(str.MODULE_SUFFIX) && !nme.falseModuleClassNames.contains(name) =>
+ likeTyped(name.dropRight(str.MODULE_SUFFIX.length).moduleClassName)
+ case _ => name
+ }
+
def unmangle(kind: NameKind): N = likeTyped {
name rewrite {
case unmangled: SimpleTermName =>
@@ -306,11 +277,11 @@ object NameOps {
implicit class TermNameDecorator(val name: TermName) extends AnyVal {
import nme._
- def setterName: TermName = name.exclude(FieldName) ++ SETTER_SUFFIX
+ def setterName: TermName = name.exclude(FieldName) ++ str.SETTER_SUFFIX
def getterName: TermName =
name.exclude(FieldName).mapLast(n =>
- if (n.endsWith(SETTER_SUFFIX)) n.take(n.length - SETTER_SUFFIX.length).asSimpleName
+ if (n.endsWith(SETTER_SUFFIX)) n.take(n.length - str.SETTER_SUFFIX.length).asSimpleName
else n)
def fieldName: TermName =
@@ -324,7 +295,7 @@ object NameOps {
else FieldName(name)
def stripScala2LocalSuffix: TermName =
- if (name.isScala2LocalSuffix) name.init.asTermName else name
+ if (name.isScala2LocalSuffix) name.asSimpleName.dropRight(1) else name
/** The name unary_x for a prefix operator x */
def toUnaryName: TermName = name match {