summaryrefslogtreecommitdiff
path: root/src/compiler
diff options
context:
space:
mode:
authorPaul Phillips <paulp@improving.org>2011-11-23 23:09:30 +0000
committerPaul Phillips <paulp@improving.org>2011-11-23 23:09:30 +0000
commit4cfca8a7f6763fbbaab37a3473d74118b3ec52bc (patch)
tree0fcd94312cbb08a4c58add11a8cc51bd0c0c9b6a /src/compiler
parent8e965f00e472398b466bc08da1a2d25f4566a670 (diff)
downloadscala-4cfca8a7f6763fbbaab37a3473d74118b3ec52bc.tar.gz
scala-4cfca8a7f6763fbbaab37a3473d74118b3ec52bc.tar.bz2
scala-4cfca8a7f6763fbbaab37a3473d74118b3ec52bc.zip
AnnotationInfo inertia takes me into continuati...
AnnotationInfo inertia takes me into continuations. And kept carrying me until I was carried away. The changes are mostly of the janitorial variety, just doing my part to make the interesting logic visible without being buried in low level compiler plumbing. Added at least one seriously convenient convenience method: tree modifyType fn // equivalent to if (tree.tpe == null) tree else tree setType fn(tree.tpe) This is the analogue to the recently added: symbol modifyInfo fn // same idea It's like having our carpets steam cleaned when we can keep pushing until machinery stays in the machine and the relevant logic stands gloriously on top. You'll eventually exclaim, "I didn't even know these carpets were that color!"
Diffstat (limited to 'src/compiler')
-rw-r--r--src/compiler/scala/reflect/internal/AnnotationInfos.scala15
-rw-r--r--src/compiler/scala/reflect/internal/Symbols.scala3
-rw-r--r--src/compiler/scala/reflect/internal/Trees.scala7
-rw-r--r--src/compiler/scala/reflect/internal/Types.scala17
4 files changed, 35 insertions, 7 deletions
diff --git a/src/compiler/scala/reflect/internal/AnnotationInfos.scala b/src/compiler/scala/reflect/internal/AnnotationInfos.scala
index 68d487f520..f17243bc28 100644
--- a/src/compiler/scala/reflect/internal/AnnotationInfos.scala
+++ b/src/compiler/scala/reflect/internal/AnnotationInfos.scala
@@ -24,6 +24,7 @@ trait AnnotationInfos extends api.AnnotationInfos { self: SymbolTable =>
def annotations: List[AnnotationInfo] // Annotations on this type.
def setAnnotations(annots: List[AnnotationInfo]): Self // Replace annotations with argument list.
def withAnnotations(annots: List[AnnotationInfo]): Self // Add annotations to this type.
+ def filterAnnotations(p: AnnotationInfo => Boolean): Self // Retain only annotations meeting the condition.
def withoutAnnotations: Self // Remove all annotations from this type.
/** Symbols of any @throws annotations on this symbol.
@@ -35,9 +36,8 @@ trait AnnotationInfos extends api.AnnotationInfos { self: SymbolTable =>
/** Test for, get, or remove an annotation */
def hasAnnotation(cls: Symbol) = annotations exists (_ matches cls)
def getAnnotation(cls: Symbol) = annotations find (_ matches cls)
- def removeAnnotation(cls: Symbol): Self =
- if (hasAnnotation(cls)) setAnnotations(annotations filterNot (_ matches cls))
- else this
+ def removeAnnotation(cls: Symbol): Self = filterAnnotations(ann => !(ann matches cls))
+ final def withAnnotation(annot: AnnotationInfo): Self = withAnnotations(List(annot))
}
/** Arguments to classfile annotations (which are written to
@@ -95,6 +95,9 @@ trait AnnotationInfos extends api.AnnotationInfos { self: SymbolTable =>
object NestedAnnotArg extends NestedAnnotArgExtractor
object AnnotationInfo extends AnnotationInfoExtractor {
+ def marker(atp: Type): AnnotationInfo =
+ apply(atp, Nil, Nil)
+
def lazily(lazyInfo: => AnnotationInfo) =
new LazyAnnotationInfo(lazyInfo)
@@ -233,6 +236,12 @@ trait AnnotationInfos extends api.AnnotationInfos { self: SymbolTable =>
def argAtIndex(index: Int): Option[Tree] =
if (index < args.size) Some(args(index)) else None
+
+ override def hashCode = atp.## + args.## + assocs.##
+ override def equals(other: Any) = other match {
+ case x: AnnotationInfo => (atp == x.atp) && (args == x.args) && (assocs == x.assocs)
+ case _ => false
+ }
}
lazy val classfileAnnotArgManifest: ClassManifest[ClassfileAnnotArg] =
diff --git a/src/compiler/scala/reflect/internal/Symbols.scala b/src/compiler/scala/reflect/internal/Symbols.scala
index 2fc3eb3652..1b1d26d038 100644
--- a/src/compiler/scala/reflect/internal/Symbols.scala
+++ b/src/compiler/scala/reflect/internal/Symbols.scala
@@ -1200,6 +1200,9 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
def withoutAnnotations: this.type =
setAnnotations(Nil)
+ def filterAnnotations(p: AnnotationInfo => Boolean): this.type =
+ setAnnotations(annotations filter p)
+
def addAnnotation(annot: AnnotationInfo): this.type =
setAnnotations(annot :: annotations)
diff --git a/src/compiler/scala/reflect/internal/Trees.scala b/src/compiler/scala/reflect/internal/Trees.scala
index 9a9b34a391..566ee0e9cf 100644
--- a/src/compiler/scala/reflect/internal/Trees.scala
+++ b/src/compiler/scala/reflect/internal/Trees.scala
@@ -102,6 +102,13 @@ trait Trees extends api.Trees { self: SymbolTable =>
def isErroneous = (tree.tpe ne null) && tree.tpe.isErroneous
def isTyped = (tree.tpe ne null) && !tree.tpe.isErroneous
+ /** Sets the tree's type to the result of the given function.
+ * If the type is null, it remains null - the function is not called.
+ */
+ def modifyType(f: Type => Type): Tree =
+ if (tree.tpe eq null) tree
+ else tree setType f(tree.tpe)
+
/** If `pf` is defined for a given subtree, call super.traverse(pf(tree)),
* otherwise super.traverse(tree).
*/
diff --git a/src/compiler/scala/reflect/internal/Types.scala b/src/compiler/scala/reflect/internal/Types.scala
index 88019f51f7..0f8d28ff03 100644
--- a/src/compiler/scala/reflect/internal/Types.scala
+++ b/src/compiler/scala/reflect/internal/Types.scala
@@ -1022,11 +1022,10 @@ trait Types extends api.Types { self: SymbolTable =>
// overrides these.
def annotations: List[AnnotationInfo] = Nil
def withoutAnnotations: Type = this
+ def filterAnnotations(p: AnnotationInfo => Boolean): Type = this
def setAnnotations(annots: List[AnnotationInfo]): Type = annotatedType(annots, this)
def withAnnotations(annots: List[AnnotationInfo]): Type = annotatedType(annots, this)
- final def withAnnotation(annot: AnnotationInfo): Type = withAnnotations(List(annot))
-
/** Remove any annotations from this type and from any
* types embedded in this type. */
def stripAnnotations = StripAnnotationsMap(this)
@@ -2715,8 +2714,14 @@ A type's typeSymbol should never be inspected directly.
override def safeToString = annotations.mkString(underlying + " @", " @", "")
+ override def filterAnnotations(p: AnnotationInfo => Boolean): Type = {
+ val (yes, no) = annotations partition p
+ if (yes.isEmpty) underlying
+ else if (no.isEmpty) this
+ else copy(annotations = yes)
+ }
override def setAnnotations(annots: List[AnnotationInfo]): Type =
- if (annots.isEmpty) withoutAnnotations
+ if (annots.isEmpty) underlying
else copy(annotations = annots)
/** Add a number of annotations to this type */
@@ -2724,7 +2729,11 @@ A type's typeSymbol should never be inspected directly.
if (annots.isEmpty) this
else copy(annots ::: this.annotations)
- /** Remove any annotations from this type */
+ /** Remove any annotations from this type.
+ * TODO - is it allowed to nest AnnotatedTypes? If not then let's enforce
+ * that at creation. At the moment if they do ever turn up nested this
+ * recursively calls withoutAnnotations.
+ */
override def withoutAnnotations = underlying.withoutAnnotations
/** Set the self symbol */