diff options
author | Felix Mulder <felix.mulder@gmail.com> | 2016-11-02 11:08:28 +0100 |
---|---|---|
committer | Guillaume Martres <smarter@ubuntu.com> | 2016-11-22 01:35:07 +0100 |
commit | 8a61ff432543a29234193cd1f7c14abd3f3d31a0 (patch) | |
tree | a8147561d307af862c295cfc8100d271063bb0dd /compiler/src/dotty/tools/dotc/util/Attachment.scala | |
parent | 6a455fe6da5ff9c741d91279a2dc6fe2fb1b472f (diff) | |
download | dotty-8a61ff432543a29234193cd1f7c14abd3f3d31a0.tar.gz dotty-8a61ff432543a29234193cd1f7c14abd3f3d31a0.tar.bz2 dotty-8a61ff432543a29234193cd1f7c14abd3f3d31a0.zip |
Move compiler and compiler tests to compiler dir
Diffstat (limited to 'compiler/src/dotty/tools/dotc/util/Attachment.scala')
-rw-r--r-- | compiler/src/dotty/tools/dotc/util/Attachment.scala | 96 |
1 files changed, 96 insertions, 0 deletions
diff --git a/compiler/src/dotty/tools/dotc/util/Attachment.scala b/compiler/src/dotty/tools/dotc/util/Attachment.scala new file mode 100644 index 000000000..20facfd97 --- /dev/null +++ b/compiler/src/dotty/tools/dotc/util/Attachment.scala @@ -0,0 +1,96 @@ +package dotty.tools.dotc.util + +/** A class inheriting from Attachment.Container supports + * adding, removing and lookup of attachments. Attachments are typed key/value pairs. + */ +object Attachment { + import Property.Key + + /** An implementation trait for attachments. + * Clients should inherit from Container instead. + */ + trait LinkSource { + private[Attachment] var next: Link[_] + + /** Optionally get attachment corresponding to `key` */ + final def getAttachment[V](key: Key[V]): Option[V] = { + val nx = next + if (nx == null) None + else if (nx.key eq key) Some(nx.value.asInstanceOf[V]) + else nx.getAttachment[V](key) + } + + /** The attachment corresponding to `key`. + * @throws NoSuchElementException if no attachment with key exists + */ + final def attachment[V](key: Key[V]): V = { + val nx = next + if (nx == null) throw new NoSuchElementException + else if (nx.key eq key) nx.value.asInstanceOf[V] + else nx.attachment(key) + } + + /** The attachment corresponding to `key`, or `default` + * if no attachment with `key` exists. + */ + final def attachmentOrElse[V](key: Key[V], default: V): V = { + val nx = next + if (nx == null) default + else if (nx.key eq key) nx.value.asInstanceOf[V] + else nx.attachmentOrElse(key, default) + } + + /** Add attachment with given `key` and `value`. + * @return Optionally, the old attachment with given `key` if one existed before. + * The new attachment is added at the position of the old one, or at the end + * if no attachment with same `key` existed. + */ + final def putAttachment[V](key: Key[V], value: V): Option[V] = { + val nx = next + if (nx == null) { + next = new Link(key, value, null) + None + } + else if (nx.key eq key) { + next = new Link(key, value, nx.next) + Some(nx.value.asInstanceOf[V]) + } + else nx.putAttachment(key, value) + } + + /** Remove attachment with given `key`, if it exists. + * @return Optionally, the removed attachment with given `key` if one existed before. + */ + final def removeAttachment[V](key: Key[V]): Option[V] = { + val nx = next + if (nx == null) + None + else if (nx.key eq key) { + next = nx.next + Some(nx.value.asInstanceOf[V]) + } + else nx.removeAttachment(key) + } + + /** The list of all keys and values attached to this container. */ + final def allAttachments: List[(Key[_], Any)] = { + val nx = next + if (nx == null) Nil else (nx.key, nx.value) :: nx.allAttachments + } + } + + /** A private, concrete implementation class linking attachments. + */ + private[Attachment] class Link[+V](val key: Key[V], val value: V, var next: Link[_]) + extends LinkSource + + /** A trait for objects that can contain attachments */ + trait Container extends LinkSource { + private[Attachment] var next: Link[_] = null + + final def pushAttachment[V](key: Key[V], value: V): Unit = { + assert(!getAttachment(key).isDefined, s"duplicate attachment for key $key") + next = new Link(key, value, next) + } + } +} |