aboutsummaryrefslogtreecommitdiff
path: root/compiler/src
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2017-03-21 14:47:59 +0100
committerMartin Odersky <odersky@gmail.com>2017-04-11 09:33:10 +0200
commitf827882850754ba7862a1ff1615d78b350cf56cb (patch)
tree6ede26bbf347e52d92458396d22548cc01b7ca98 /compiler/src
parentefb5fa4fb946db7a2543ac60b613117828a92990 (diff)
downloaddotty-f827882850754ba7862a1ff1615d78b350cf56cb.tar.gz
dotty-f827882850754ba7862a1ff1615d78b350cf56cb.tar.bz2
dotty-f827882850754ba7862a1ff1615d78b350cf56cb.zip
Add derived name machinery
Add machinery to define and hash cons derived names.
Diffstat (limited to 'compiler/src')
-rw-r--r--compiler/src/dotty/tools/dotc/core/NameInfos.scala39
-rw-r--r--compiler/src/dotty/tools/dotc/core/NameOps.scala1
-rw-r--r--compiler/src/dotty/tools/dotc/core/Names.scala85
3 files changed, 114 insertions, 11 deletions
diff --git a/compiler/src/dotty/tools/dotc/core/NameInfos.scala b/compiler/src/dotty/tools/dotc/core/NameInfos.scala
new file mode 100644
index 000000000..4bbc5bbcf
--- /dev/null
+++ b/compiler/src/dotty/tools/dotc/core/NameInfos.scala
@@ -0,0 +1,39 @@
+package dotty.tools.dotc
+package core
+
+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 {
+ def kind: NameInfo.Kind
+ def oneOfAKind = true
+ def mkString(underlying: TermName): String
+}
+
+object NameInfo {
+
+ type Kind = Int
+
+ val TermNameKind = 0
+ val QualifiedKind = 1
+
+ /** TermNames have the lowest possible kind */
+ val TermName = new NameInfo {
+ def kind = 0
+ def mkString(underlying: TermName) = underlying.toString // will cause an unsupptored exception
+ }
+
+ case class Qualified(name: TermName) extends NameInfo {
+ def kind = 1
+ override def oneOfAKind = false
+ def mkString(underlying: TermName) = s"$underlying.$name"
+ }
+
+ val ModuleClass = new NameInfo {
+ def kind = 10
+ def mkString(underlying: TermName) = underlying + "$"
+ }
+
+} \ No newline at end of file
diff --git a/compiler/src/dotty/tools/dotc/core/NameOps.scala b/compiler/src/dotty/tools/dotc/core/NameOps.scala
index 240ad359b..a6e5fefc7 100644
--- a/compiler/src/dotty/tools/dotc/core/NameOps.scala
+++ b/compiler/src/dotty/tools/dotc/core/NameOps.scala
@@ -65,7 +65,6 @@ object NameOps {
def isConstructorName = name == CONSTRUCTOR || name == TRAIT_CONSTRUCTOR
def isStaticConstructorName = name == STATIC_CONSTRUCTOR
- def isExceptionResultName = name startsWith EXCEPTION_RESULT_PREFIX
def isImplClassName = name endsWith IMPL_CLASS_SUFFIX
def isLocalDummyName = name startsWith LOCALDUMMY_PREFIX
def isLoopHeaderLabel = (name startsWith WHILE_PREFIX) || (name startsWith DO_WHILE_PREFIX)
diff --git a/compiler/src/dotty/tools/dotc/core/Names.scala b/compiler/src/dotty/tools/dotc/core/Names.scala
index 6f970aae1..74e1fd2d2 100644
--- a/compiler/src/dotty/tools/dotc/core/Names.scala
+++ b/compiler/src/dotty/tools/dotc/core/Names.scala
@@ -10,10 +10,12 @@ import Decorators._
import Contexts.Context
import collection.IndexedSeqOptimized
import collection.generic.CanBuildFrom
-import collection.mutable.{ Builder, StringBuilder }
+import collection.mutable.{ Builder, StringBuilder, AnyRefMap }
import collection.immutable.WrappedString
import collection.generic.CanBuildFrom
-import util.DotClass
+import util.{DotClass, SimpleMap}
+import java.util.HashMap
+
//import annotation.volatile
object Names {
@@ -158,6 +160,64 @@ object Names {
def fromName(name: Name): TermName = name.toTermName
+ def info = NameInfo.TermName
+ def underlying: TermName = unsupported("underlying")
+
+ private var derivedNames: AnyRef /* SimpleMap | j.u.HashMap */ =
+ SimpleMap.Empty[NameInfo]
+
+ private def getDerived(info: NameInfo): DerivedTermName /* | Null */= derivedNames match {
+ case derivedNames: SimpleMap[NameInfo, DerivedTermName] @unchecked =>
+ derivedNames(info)
+ case derivedNames: HashMap[NameInfo, DerivedTermName] @unchecked =>
+ derivedNames.get(info)
+ }
+
+ private def putDerived(info: NameInfo, name: DerivedTermName): name.type = {
+ derivedNames match {
+ case derivedNames: SimpleMap[NameInfo, DerivedTermName] @unchecked =>
+ if (derivedNames.size < 4)
+ this.derivedNames = derivedNames.updated(info, name)
+ else {
+ val newMap = new HashMap[NameInfo, DerivedTermName]
+ derivedNames.foreachBinding(newMap.put(_, _))
+ newMap.put(info, name)
+ this.derivedNames = newMap
+ }
+ case derivedNames: HashMap[NameInfo, DerivedTermName] @unchecked =>
+ derivedNames.put(info, name)
+ }
+ name
+ }
+
+ /** Return derived name with given `info` and the current
+ * name as underlying name.
+ */
+ def derived(info: NameInfo): TermName = {
+ def addIt() = synchronized {
+ getDerived(info) match {
+ case null => putDerived(info, new DerivedTermName(this, info))
+ case derivedName => derivedName
+ }
+ }
+
+ val ownKind = this.info.kind
+ if (ownKind > info.kind)
+ underlying.derived(info).derived(this.info)
+ else if (ownKind == info.kind)
+ if (info.oneOfAKind) {
+ assert(info == this.info)
+ this
+ }
+ else addIt()
+ else addIt()
+ }
+
+ def is(kind: NameInfo.Kind): Boolean = {
+ val ownKind = info.kind
+ ownKind == kind || ownKind > kind && underlying.is(kind)
+ }
+
override def hashCode: Int = start
override protected[this] def newBuilder: Builder[Char, Name] = termNameBuilder
@@ -167,14 +227,9 @@ object Names {
// `next` is @sharable because it is only modified in the synchronized block of termName.
}
- abstract class DerivedName extends Name {
- def underlying: Name
- def start = underlying.start
- override def length = underlying.length
- }
-
- class TypeName(val toTermName: TermName) extends DerivedName {
- def underlying = toTermName
+ class TypeName(val toTermName: TermName) extends Name {
+ def start = toTermName.start
+ override def length = toTermName.length
type ThisName = TypeName
def isTypeName = true
@@ -191,6 +246,16 @@ object Names {
termNameBuilder.mapResult(_.toTypeName)
}
+ /** A term name that's derived from an `underlying` name and that
+ * adds `info` to it.
+ */
+ class DerivedTermName(override val underlying: TermName, override val info: NameInfo)
+ extends TermName {
+ def start = underlying.start
+ override def length = underlying.length
+ override def toString = info.mkString(underlying)
+ }
+
// Nametable
private final val InitialHashSize = 0x8000