From c868038423b5c28234e66788158e379754ed47b3 Mon Sep 17 00:00:00 2001 From: Eugene Burmako Date: Wed, 3 Oct 2012 23:17:31 +0200 Subject: moves Attachments from api to macros Because they are only available in macros.Universe, not in api.Universe, therefore I'd argue that the confusion factor is stronger than the weirdness of scala.reflect.api.Position extending scala.reflect.macros.Attachments. --- src/reflect/scala/reflect/api/Attachments.scala | 50 ------------------- src/reflect/scala/reflect/api/Position.scala | 2 + .../scala/reflect/internal/StdAttachments.scala | 2 +- .../scala/reflect/internal/util/Position.scala | 2 +- src/reflect/scala/reflect/macros/Attachments.scala | 57 ++++++++++++++++++++++ src/reflect/scala/reflect/macros/Universe.scala | 2 +- 6 files changed, 62 insertions(+), 53 deletions(-) delete mode 100644 src/reflect/scala/reflect/api/Attachments.scala create mode 100644 src/reflect/scala/reflect/macros/Attachments.scala (limited to 'src/reflect') diff --git a/src/reflect/scala/reflect/api/Attachments.scala b/src/reflect/scala/reflect/api/Attachments.scala deleted file mode 100644 index edbb0131ca..0000000000 --- a/src/reflect/scala/reflect/api/Attachments.scala +++ /dev/null @@ -1,50 +0,0 @@ -package scala.reflect -package api - -/** Attachments is a generalization of Position. Typically it stores a Position of a tree, but this can be extended to - * encompass arbitrary payloads. Payloads are stored in type-indexed slots, which can be read with `get[T]` and written - * with `update[T]` and `remove[T]`. - * - * Attachments always carry positions because we don't want to introduce an additional field for attachments in `Tree` - * imposing an unnecessary memory tax because of something that will not be used in most cases. - */ -abstract class Attachments { self => - - /** The position type of this attachment */ - type Pos >: Null - - /** The underlying position */ - def pos: Pos - - /** Creates a copy of this attachment with the position replaced by `newPos` */ - def withPos(newPos: Pos): Attachments { type Pos = self.Pos } - - /** The underlying payload with the guarantee that no two elements have the same type. */ - def all: Set[Any] = Set.empty - - private def matchesTag[T: ClassTag](datum: Any) = - classTag[T].runtimeClass == datum.getClass - - /** An underlying payload of the given class type `T`. */ - def get[T: ClassTag]: Option[T] = - (all filter matchesTag[T]).headOption.asInstanceOf[Option[T]] - - /** Creates a copy of this attachment with the payload slot of T added/updated with the provided value. - * - * Replaces an existing payload of the same type, if exists. - */ - def update[T: ClassTag](attachment: T): Attachments { type Pos = self.Pos } = - new NonemptyAttachments(this.pos, remove[T].all + attachment) - - /** Creates a copy of this attachment with the payload of the given class type `T` removed. */ - def remove[T: ClassTag]: Attachments { type Pos = self.Pos } = { - val newAll = all filterNot matchesTag[T] - if (newAll.isEmpty) pos.asInstanceOf[Attachments { type Pos = self.Pos }] - else new NonemptyAttachments(this.pos, newAll) - } - - private class NonemptyAttachments(override val pos: Pos, override val all: Set[Any]) extends Attachments { - type Pos = self.Pos - def withPos(newPos: Pos) = new NonemptyAttachments(newPos, all) - } -} diff --git a/src/reflect/scala/reflect/api/Position.scala b/src/reflect/scala/reflect/api/Position.scala index 9c63e4becf..d3dc9c884f 100644 --- a/src/reflect/scala/reflect/api/Position.scala +++ b/src/reflect/scala/reflect/api/Position.scala @@ -1,6 +1,8 @@ package scala.reflect package api +import scala.reflect.macros.Attachments + /** The Position class and its subclasses represent positions of ASTs and symbols. * Except for NoPosition and FakePos, every position refers to a SourceFile * and to an offset in the sourcefile (its `point`). For batch compilation, diff --git a/src/reflect/scala/reflect/internal/StdAttachments.scala b/src/reflect/scala/reflect/internal/StdAttachments.scala index 5c4d1f7e28..9fe443bf50 100644 --- a/src/reflect/scala/reflect/internal/StdAttachments.scala +++ b/src/reflect/scala/reflect/internal/StdAttachments.scala @@ -8,7 +8,7 @@ trait StdAttachments { * Common code between reflect-internal Symbol and Tree related to Attachments. */ trait Attachable { - protected var rawatt: scala.reflect.api.Attachments { type Pos = Position } = NoPosition + protected var rawatt: scala.reflect.macros.Attachments { type Pos = Position } = NoPosition def attachments = rawatt def updateAttachment[T: ClassTag](attachment: T): this.type = { rawatt = rawatt.update(attachment); this } def removeAttachment[T: ClassTag]: this.type = { rawatt = rawatt.remove[T]; this } diff --git a/src/reflect/scala/reflect/internal/util/Position.scala b/src/reflect/scala/reflect/internal/util/Position.scala index 151a64daff..d4225bcff5 100644 --- a/src/reflect/scala/reflect/internal/util/Position.scala +++ b/src/reflect/scala/reflect/internal/util/Position.scala @@ -7,7 +7,7 @@ package scala.reflect.internal.util import scala.reflect.ClassTag -import scala.reflect.api.Attachments +import scala.reflect.macros.Attachments object Position { val tabInc = 8 diff --git a/src/reflect/scala/reflect/macros/Attachments.scala b/src/reflect/scala/reflect/macros/Attachments.scala new file mode 100644 index 0000000000..ba5ccf88f1 --- /dev/null +++ b/src/reflect/scala/reflect/macros/Attachments.scala @@ -0,0 +1,57 @@ +package scala.reflect +package macros + +/** Attachments provide a way to associate custom metadata with symbols and trees. + * + * Along with `symbol` and `tpe`, which represent core metadata of trees, each tree + * carries the `attachments` field that can store other metadata: compiler-defined (e.g. positions) or user-defined. + * Same story is true for symbols, which also have extensible metadata by the virtue + * of the same `attachments` field. + * + * Typically attachments just store a [[scala.reflect.api.Position]], but they can be extended to + * encompass arbitrary payloads. Payloads are stored in type-indexed slots, which can be read with `get[T]` and written + * with `update[T]` and `remove[T]`. + * + * This API doesn't have much use in the runtime reflection API (the [[scala.reflect.api]] package), but it might be of help + * for macro writers, providing a way to coordinate multiple macros operating on the same code. Therefore the `attachments` + * field is only declared in trees and symbols belonging to [[scala.reflect.macros.Universe]]. + */ +abstract class Attachments { self => + + /** The position type of this attachment */ + type Pos >: Null + + /** The underlying position */ + def pos: Pos + + /** Creates a copy of this attachment with the position replaced by `newPos` */ + def withPos(newPos: Pos): Attachments { type Pos = self.Pos } + + /** The underlying payload with the guarantee that no two elements have the same type. */ + def all: Set[Any] = Set.empty + + private def matchesTag[T: ClassTag](datum: Any) = + classTag[T].runtimeClass == datum.getClass + + /** An underlying payload of the given class type `T`. */ + def get[T: ClassTag]: Option[T] = + (all filter matchesTag[T]).headOption.asInstanceOf[Option[T]] + + /** Creates a copy of this attachment with the payload slot of T added/updated with the provided value. + * Replaces an existing payload of the same type, if exists. + */ + def update[T: ClassTag](attachment: T): Attachments { type Pos = self.Pos } = + new NonemptyAttachments(this.pos, remove[T].all + attachment) + + /** Creates a copy of this attachment with the payload of the given class type `T` removed. */ + def remove[T: ClassTag]: Attachments { type Pos = self.Pos } = { + val newAll = all filterNot matchesTag[T] + if (newAll.isEmpty) pos.asInstanceOf[Attachments { type Pos = self.Pos }] + else new NonemptyAttachments(this.pos, newAll) + } + + private class NonemptyAttachments(override val pos: Pos, override val all: Set[Any]) extends Attachments { + type Pos = self.Pos + def withPos(newPos: Pos) = new NonemptyAttachments(newPos, all) + } +} diff --git a/src/reflect/scala/reflect/macros/Universe.scala b/src/reflect/scala/reflect/macros/Universe.scala index 97d0a8d98a..3e38691d85 100644 --- a/src/reflect/scala/reflect/macros/Universe.scala +++ b/src/reflect/scala/reflect/macros/Universe.scala @@ -7,7 +7,7 @@ abstract class Universe extends scala.reflect.api.Universe { trait AttachableApi { /** ... */ - def attachments: scala.reflect.api.Attachments { type Pos = Position } + def attachments: Attachments { type Pos = Position } /** ... */ def updateAttachment[T: ClassTag](attachment: T): AttachableApi.this.type -- cgit v1.2.3