diff options
10 files changed, 71 insertions, 83 deletions
diff --git a/compiler/src/dotty/tools/backend/jvm/DottyBackendInterface.scala b/compiler/src/dotty/tools/backend/jvm/DottyBackendInterface.scala index 77e979e4d..309d97261 100644 --- a/compiler/src/dotty/tools/backend/jvm/DottyBackendInterface.scala +++ b/compiler/src/dotty/tools/backend/jvm/DottyBackendInterface.scala @@ -544,8 +544,8 @@ class DottyBackendInterface(outputDirectory: AbstractFile, val superCallsMap: Ma def toTermName: Name = n.toTermName def dropModule: Name = n.stripModuleClassSuffix - def len: Int = n.length - def offset: Int = n.start + def len: Int = n.toSimpleName.length + def offset: Int = n.toSimpleName.start def isTermName: Boolean = n.isTermName def startsWith(s: String): Boolean = n.startsWith(s) } diff --git a/compiler/src/dotty/tools/dotc/core/NameInfos.scala b/compiler/src/dotty/tools/dotc/core/NameInfos.scala index 51c04b9e4..650a0c0a4 100644 --- a/compiler/src/dotty/tools/dotc/core/NameInfos.scala +++ b/compiler/src/dotty/tools/dotc/core/NameInfos.scala @@ -6,9 +6,11 @@ import Names._ /** Additional info associated with a name. At a minimum its kind and * a way to turn it into a string. */ -abstract class NameInfo { +abstract class NameInfo extends util.DotClass { def kind: NameInfo.Kind def mkString(underlying: TermName): String + def contains(ch: Char): Boolean = false + def ++(other: String): NameInfo = unsupported("++") } object NameInfo { @@ -30,6 +32,8 @@ object NameInfo { case class Qualified(name: TermName, separator: String) extends NameInfo { def kind = QualifiedKind def mkString(underlying: TermName) = s"$underlying$separator$name" + override def contains(ch: Char): Boolean = name.contains(ch) + override def ++(other: String): NameInfo = Qualified(name ++ other, separator) override def toString = s"Qualified($name, $separator)" } diff --git a/compiler/src/dotty/tools/dotc/core/NameOps.scala b/compiler/src/dotty/tools/dotc/core/NameOps.scala index 38eb21446..27065a50a 100644 --- a/compiler/src/dotty/tools/dotc/core/NameOps.scala +++ b/compiler/src/dotty/tools/dotc/core/NameOps.scala @@ -390,7 +390,7 @@ object NameOps { // has form <$-separated-trait-name>$_setter_$ `name`_$eq val start = name.indexOfSlice(TRAIT_SETTER_SEPARATOR) + TRAIT_SETTER_SEPARATOR.length val end = name.indexOfSlice(SETTER_SUFFIX) - name.slice(start, end) ++ LOCAL_SUFFIX + (name.slice(start, end) ++ LOCAL_SUFFIX).asTermName } else getterName.fieldName } else name ++ LOCAL_SUFFIX diff --git a/compiler/src/dotty/tools/dotc/core/Names.scala b/compiler/src/dotty/tools/dotc/core/Names.scala index 9488aef61..9ec9e73f2 100644 --- a/compiler/src/dotty/tools/dotc/core/Names.scala +++ b/compiler/src/dotty/tools/dotc/core/Names.scala @@ -39,20 +39,11 @@ object Names { * 3. Names are intended to be encoded strings. @see dotc.util.NameTransformer. * The encoding will be applied when converting a string to a name. */ - abstract class Name extends DotClass - with PreName - with collection.immutable.Seq[Char] - with IndexedSeqOptimized[Char, Name] { + abstract class Name extends DotClass with PreName { /** A type for names of the same kind as this name */ type ThisName <: Name - /** The start index in the character array */ - def start: Int - - /** The length of the names */ - override def length: Int - /** Is this name a type name? */ def isTypeName: Boolean @@ -71,6 +62,8 @@ object Names { /** This name downcasted to a term name */ def asTermName: TermName + def toSimpleName: SimpleTermName = this.asInstanceOf[SimpleTermName] + /** A name of the same kind as this name and with same characters as given `name` */ def fromName(name: Name): ThisName @@ -81,17 +74,6 @@ object Names { def toText(printer: Printer): Text = printer.toText(this) - /** Write to UTF8 representation of this name to given character array. - * Start copying to index `to`. Return index of next free byte in array. - * Array must have enough remaining space for all bytes - * (i.e. maximally 3*length bytes). - */ - final def copyUTF8(bs: Array[Byte], offset: Int): Int = { - val bytes = Codec.toUTF8(chrs, start, length) - scala.compat.Platform.arraycopy(bytes, 0, bs, offset, bytes.length) - offset + bytes.length - } - /** Replace \$op_name's by corresponding operator symbols. */ def decode: Name = if (contains('$')) fromName(termName(NameTransformer.decode(toString))) @@ -103,41 +85,13 @@ object Names { /** A more efficient version of concatenation */ def ++ (other: Name): ThisName = ++ (other.toString) + def ++ (other: String): ThisName - def ++ (other: String): ThisName = fromName(termName(toString + other)) - - def replace(from: Char, to: Char): ThisName = { - val cs = new Array[Char](length) - Array.copy(chrs, start, cs, 0, length) - for (i <- 0 until length) { - if (cs(i) == from) cs(i) = to - } - fromName(termName(cs, 0, length)) - } - - def contains(ch: Char): Boolean = { - var i = 0 - while (i < length && chrs(start + i) != ch) i += 1 - i < length - } + def replace(from: Char, to: Char): ThisName = fromName(toSimpleName.replace(from, to)) - def firstChar = chrs(start) - - // ----- Collections integration ------------------------------------- - - override protected[this] def thisCollection: WrappedString = new WrappedString(repr.toString) - override protected[this] def toCollection(repr: Name): WrappedString = new WrappedString(repr.toString) - - override protected[this] def newBuilder: Builder[Char, Name] = unsupported("newBuilder") - - override def apply(index: Int): Char = chrs(start + index) - - override def slice(from: Int, until: Int): ThisName = - fromName(termName(chrs, start + from, until - from)) + def contains(ch: Char): Boolean override def equals(that: Any) = this eq that.asInstanceOf[AnyRef] - - override def seq = toCollection(this) } abstract class TermName extends Name { @@ -226,12 +180,30 @@ object Names { ownKind == kind || !NameInfo.definesNewName(ownKind) && ownKind > kind && underlying.is(kind) } - - override protected[this] def newBuilder: Builder[Char, Name] = termNameBuilder } class SimpleTermName(val start: Int, val length: Int, @sharable private[Names] var next: SimpleTermName) extends TermName { // `next` is @sharable because it is only modified in the synchronized block of termName. + + def apply(n: Int) = chrs(start + n) + + def ++ (other: String): ThisName = termName(toString + other) + + def contains(ch: Char): Boolean = { + var i = 0 + while (i < length && chrs(start + i) != ch) i += 1 + i < length + } + + override def replace(from: Char, to: Char): ThisName = { + val cs = new Array[Char](length) + Array.copy(chrs, start, cs, 0, length) + for (i <- 0 until length) { + if (cs(i) == from) cs(i) = to + } + fromName(termName(cs, 0, length)) + } + override def hashCode: Int = start override def toString = @@ -241,8 +213,12 @@ object Names { } class TypeName(val toTermName: TermName) extends Name { - def start = toTermName.start - override def length = toTermName.length + + override def toSimpleName: SimpleTermName = toTermName.toSimpleName + + def ++ (other: String): ThisName = toTermName.++(other).toTypeName + + def contains(ch: Char): Boolean = toTermName.contains(ch) type ThisName = TypeName def isTypeName = true @@ -257,9 +233,6 @@ object Names { def without(kind: NameInfo.Kind): TypeName = toTermName.without(kind).toTypeName def is(kind: NameInfo.Kind) = toTermName.is(kind) - override protected[this] def newBuilder: Builder[Char, Name] = - termNameBuilder.mapResult(_.toTypeName) - override def toString = toTermName.toString override def debugString = toTermName.debugString + "/T" } @@ -269,8 +242,8 @@ object Names { */ class DerivedTermName(override val underlying: TermName, override val info: NameInfo) extends TermName { - def start = underlying.start - override def length = underlying.length + def ++ (other: String): ThisName = derived(info ++ other) + def contains(ch: Char): Boolean = underlying.contains(ch) || info.contains(ch) override def toString = info.mkString(underlying) override def debugString = s"${underlying.debugString}[$info]" } @@ -319,7 +292,7 @@ object Names { /** Create a term name from the characters in cs[offset..offset+len-1]. * Assume they are already encoded. */ - def termName(cs: Array[Char], offset: Int, len: Int): TermName = synchronized { + def termName(cs: Array[Char], offset: Int, len: Int): SimpleTermName = synchronized { util.Stats.record("termName") val h = hashValue(cs, offset, len) & (table.size - 1) @@ -385,7 +358,7 @@ object Names { /** Create a term name from the UTF8 encoded bytes in bs[offset..offset+len-1]. * Assume they are already encoded. */ - def termName(bs: Array[Byte], offset: Int, len: Int): TermName = { + def termName(bs: Array[Byte], offset: Int, len: Int): SimpleTermName = { val chars = Codec.fromUTF8(bs, offset, len) termName(chars, 0, chars.length) } @@ -397,7 +370,7 @@ object Names { termName(bs, offset, len).toTypeName /** Create a term name from a string, without encoding operators */ - def termName(s: String): TermName = termName(s.toCharArray, 0, s.length) + def termName(s: String): SimpleTermName = termName(s.toCharArray, 0, s.length) /** Create a type name from a string, without encoding operators */ def typeName(s: String): TypeName = typeName(s.toCharArray, 0, s.length) @@ -411,20 +384,31 @@ object Names { val EmptyTypeName = EmptyTermName.toTypeName // can't move CONSTRUCTOR/EMPTY_PACKAGE to `nme` because of bootstrap failures in `encode`. - val CONSTRUCTOR = termName("<init>") - val STATIC_CONSTRUCTOR = termName("<clinit>") - val EMPTY_PACKAGE = termName("<empty>") + val CONSTRUCTOR: TermName = termName("<init>") + val STATIC_CONSTRUCTOR: TermName = termName("<clinit>") + val EMPTY_PACKAGE: TermName = termName("<empty>") val dontEncode = Set[TermName](CONSTRUCTOR, EMPTY_PACKAGE) def termNameBuilder: Builder[Char, TermName] = StringBuilder.newBuilder.mapResult(termName) - implicit val nameCanBuildFrom: CanBuildFrom[Name, Char, Name] = new CanBuildFrom[Name, Char, Name] { - def apply(from: Name): Builder[Char, Name] = - StringBuilder.newBuilder.mapResult(s => - from.fromName(termName(s.toCharArray, 0, s.length))) - def apply(): Builder[Char, Name] = termNameBuilder + def typeNameBuilder: Builder[Char, TypeName] = + StringBuilder.newBuilder.mapResult(termName(_).toTypeName) + + implicit class nameToSeq(val name: Name) extends IndexedSeqOptimized[Char, Name] { + def length = name.toSimpleName.length + def apply(n: Int) = name.toSimpleName.apply(n) + override protected[this] def newBuilder: Builder[Char, Name] = + if (name.isTypeName) typeNameBuilder else termNameBuilder + + def seq: WrappedString = new WrappedString(name.toString) + override protected[this] def thisCollection: WrappedString = seq + def startsWith(name: Name): Boolean = startsWith(name.toString) + def endsWith(name: Name): Boolean = endsWith(name.toString) + def indexOfSlice(name: Name): Int = indexOfSlice(name.toString) + def lastIndexOfSlice(name: Name): Int = lastIndexOfSlice(name.toString) + def containsSlice(name: Name): Boolean = containsSlice(name.toString) } implicit val NameOrdering: Ordering[Name] = new Ordering[Name] { diff --git a/compiler/src/dotty/tools/dotc/core/classfile/ClassfileParser.scala b/compiler/src/dotty/tools/dotc/core/classfile/ClassfileParser.scala index a0e4cc62b..131c9cf9b 100644 --- a/compiler/src/dotty/tools/dotc/core/classfile/ClassfileParser.scala +++ b/compiler/src/dotty/tools/dotc/core/classfile/ClassfileParser.scala @@ -256,7 +256,7 @@ class ClassfileParser( def subName(isDelimiter: Char => Boolean): TermName = { val start = index while (!isDelimiter(sig(index))) { index += 1 } - sig.slice(start, index) + sig.slice(start, index).asTermName } // Warning: sigToType contains nested completers which might be forced in a later run! // So local methods need their own ctx parameters. diff --git a/compiler/src/dotty/tools/dotc/core/tasty/NameBuffer.scala b/compiler/src/dotty/tools/dotc/core/tasty/NameBuffer.scala index 3ff7298ce..b05e6ef21 100644 --- a/compiler/src/dotty/tools/dotc/core/tasty/NameBuffer.scala +++ b/compiler/src/dotty/tools/dotc/core/tasty/NameBuffer.scala @@ -27,7 +27,7 @@ class NameBuffer extends TastyBuffer(10000) { def nameIndex(name: Name): NameRef = { val tname = if (name.isShadowedName) Shadowed(nameIndex(name.revertShadowed)) - else Simple(name.toTermName) + else Simple(name.toTermName.toSimpleName) nameIndex(tname) } diff --git a/compiler/src/dotty/tools/dotc/core/tasty/TastyName.scala b/compiler/src/dotty/tools/dotc/core/tasty/TastyName.scala index 26807115c..da205542e 100644 --- a/compiler/src/dotty/tools/dotc/core/tasty/TastyName.scala +++ b/compiler/src/dotty/tools/dotc/core/tasty/TastyName.scala @@ -3,7 +3,7 @@ package dotc package core package tasty -import core.Names.TermName +import core.Names.SimpleTermName import collection.mutable abstract class TastyName @@ -12,7 +12,7 @@ object TastyName { case class NameRef(index: Int) extends AnyVal - case class Simple(name: TermName) extends TastyName + case class Simple(name: SimpleTermName) extends TastyName case class Qualified(qualified: NameRef, selector: NameRef) extends TastyName case class Signed(original: NameRef, params: List[NameRef], result: NameRef) extends TastyName case class Expanded(prefix: NameRef, original: NameRef) extends TastyName diff --git a/compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala b/compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala index 902d01c21..7a6b6b7ea 100644 --- a/compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala +++ b/compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala @@ -576,7 +576,7 @@ class TreePickler(pickler: TastyPickler) { } def qualifiedName(sym: Symbol)(implicit ctx: Context): TastyName = - if (sym.isRoot || sym.owner.isRoot) TastyName.Simple(sym.name.toTermName) + if (sym.isRoot || sym.owner.isRoot) TastyName.Simple(sym.name.toTermName.toSimpleName) else TastyName.Qualified(nameIndex(qualifiedName(sym.owner)), nameIndex(sym.name)) def pickleModifiers(sym: Symbol)(implicit ctx: Context): Unit = { diff --git a/compiler/src/dotty/tools/dotc/parsing/Scanners.scala b/compiler/src/dotty/tools/dotc/parsing/Scanners.scala index ff5019dc9..bcf6eb4a5 100644 --- a/compiler/src/dotty/tools/dotc/parsing/Scanners.scala +++ b/compiler/src/dotty/tools/dotc/parsing/Scanners.scala @@ -101,7 +101,7 @@ object Scanners { target.name = flushBuf(litBuf).toTermName target.token = idtoken if (idtoken == IDENTIFIER) { - val idx = target.name.start + val idx = target.name.toSimpleName.start target.token = toToken(idx) } } diff --git a/compiler/src/dotty/tools/dotc/parsing/Tokens.scala b/compiler/src/dotty/tools/dotc/parsing/Tokens.scala index d2ea9240c..96ae25c9e 100644 --- a/compiler/src/dotty/tools/dotc/parsing/Tokens.scala +++ b/compiler/src/dotty/tools/dotc/parsing/Tokens.scala @@ -129,7 +129,7 @@ abstract class TokensCommon { final val lastParen = RBRACE def buildKeywordArray(keywords: TokenSet) = { - def start(tok: Token) = tokenString(tok).toTermName.start + def start(tok: Token) = tokenString(tok).toTermName.toSimpleName.start def sourceKeywords = keywords.toList.filter { (kw: Token) => val ts = tokenString(kw) (ts != null) && !ts.contains(' ') |