diff options
author | Martin Odersky <odersky@gmail.com> | 2017-03-22 17:59:25 +0100 |
---|---|---|
committer | Martin Odersky <odersky@gmail.com> | 2017-04-11 09:33:10 +0200 |
commit | 19bc1ff09fa73e13be7e3464b8440c04b657aa82 (patch) | |
tree | bc6934a3c47ab403f4dc3dd2c87531081887dc15 /compiler/src/dotty/tools/dotc/core/Names.scala | |
parent | 2cc16c4d990fa404577dbe1c944958a0cf9896a8 (diff) | |
download | dotty-19bc1ff09fa73e13be7e3464b8440c04b657aa82.tar.gz dotty-19bc1ff09fa73e13be7e3464b8440c04b657aa82.tar.bz2 dotty-19bc1ff09fa73e13be7e3464b8440c04b657aa82.zip |
Disentangle Names from Seqs
Structured names are not Seqs anymmore. But the Seq behavior
is required in many places that mangle names. As an intermediate step
we drop the Seq basetype but add Seq behavior through a decorator.
Most Seq operations only work on SimpleTermNames and their
TypeName analogue, will throw an exception wehn called on structured
names.
Diffstat (limited to 'compiler/src/dotty/tools/dotc/core/Names.scala')
-rw-r--r-- | compiler/src/dotty/tools/dotc/core/Names.scala | 128 |
1 files changed, 56 insertions, 72 deletions
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] { |