diff options
author | Paul Phillips <paulp@improving.org> | 2011-11-23 23:09:30 +0000 |
---|---|---|
committer | Paul Phillips <paulp@improving.org> | 2011-11-23 23:09:30 +0000 |
commit | 4cfca8a7f6763fbbaab37a3473d74118b3ec52bc (patch) | |
tree | 0fcd94312cbb08a4c58add11a8cc51bd0c0c9b6a /src/compiler | |
parent | 8e965f00e472398b466bc08da1a2d25f4566a670 (diff) | |
download | scala-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')
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 */ |