From 48076bb9c287d82a1259885dccfa424df16fe912 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Mon, 11 Feb 2013 14:53:24 +0100 Subject: Treating all annotations as wrappers over trees. --- src/dotty/tools/dotc/core/Annotations.scala | 20 +++-- src/dotty/tools/dotc/core/Definitions.scala | 12 ++- src/dotty/tools/dotc/core/SymDenotations.scala | 8 +- src/dotty/tools/dotc/core/pickling/UnPickler.scala | 95 +++++++++++----------- 4 files changed, 71 insertions(+), 64 deletions(-) (limited to 'src/dotty/tools/dotc/core') diff --git a/src/dotty/tools/dotc/core/Annotations.scala b/src/dotty/tools/dotc/core/Annotations.scala index 8aead084d..1bd6fc31f 100644 --- a/src/dotty/tools/dotc/core/Annotations.scala +++ b/src/dotty/tools/dotc/core/Annotations.scala @@ -1,24 +1,28 @@ package dotty.tools.dotc.core -import Symbols._ +import Symbols._, Trees._, Types._, Positions._, Contexts._ object Annotations { abstract class Annotation { - def matches(cls: Symbol) = ??? + def tree: TypedTree + def symbol(implicit ctx: Context): Symbol = tree.tpe.typeSymbol + def matches(cls: Symbol)(implicit ctx: Context): Boolean = symbol.isNonBottomSubClass(cls) def appliesToModule: Boolean = ??? } - abstract class InternalAnnotation extends Annotation { + case class ConcreteAnnotation(val tree: TypedTree) extends Annotation - } + object Annotation { - case class Alias(sym: Symbol) extends InternalAnnotation { + def apply(cls: ClassSymbol, args: List[TypedTree])(implicit ctx: Context): Annotation = + ConcreteAnnotation(makeTypedTree.New(cls.typeConstructor, args)) - } + def makeAlias(sym: TermSymbol)(implicit ctx: Context) = + apply(defn.AliasAnnot, List(makeTypedTree.Ident(TermRef(sym.owner.thisType, sym)))) - case class Child(child: ClassSymbol) extends InternalAnnotation { + def makeChild(sym: ClassSymbol)(implicit ctx: Context) = + apply(defn.ChildAnnot, List(makeTypedTree.Ident(TypeRef(sym.owner.thisType, sym)))) } - } \ No newline at end of file diff --git a/src/dotty/tools/dotc/core/Definitions.scala b/src/dotty/tools/dotc/core/Definitions.scala index b399a77c4..3e5e8b8af 100644 --- a/src/dotty/tools/dotc/core/Definitions.scala +++ b/src/dotty/tools/dotc/core/Definitions.scala @@ -113,11 +113,12 @@ class Definitions(implicit ctx: Context) { lazy val SymbolClass = requiredClass("scala.Symbol") lazy val StringClass = requiredClass("java.lang.String") lazy val ClassClass = requiredClass("java.lang.Class") - //def Class_getMethod = getMemberMethod(ClassClass, nme.getMethod_) + //def Class_getMethod = getMemberMethod(ClassClass, nme.getMethod_) lazy val DynamicClass = requiredClass("scala.Dynamic") - lazy val BoxedNumberClass = requiredClass("java.lang.Number") - lazy val JavaSerializableClass = requiredClass("java.lang.Serializable") - lazy val ComparableClass = requiredClass("java.lang.Comparable") + lazy val BoxedNumberClass = requiredClass("java.lang.Number") + lazy val JavaSerializableClass = requiredClass("java.lang.Serializable") + lazy val ComparableClass = requiredClass("java.lang.Comparable") + lazy val AnnotationClass = requiredClass("scala.annotation.Annotation") lazy val AnyType = AnyClass.typeConstructor lazy val AnyValType = AnyValClass.typeConstructor @@ -129,6 +130,9 @@ class Definitions(implicit ctx: Context) { lazy val SeqType = SeqClass.typeConstructor lazy val ArrayType = ArrayClass.typeConstructor + lazy val AliasAnnot = requiredClass("dotty.annotation.internal.Alias") + lazy val ChildAnnot = requiredClass("dotty.annotation.internal.Alias") + def ClassType(arg: Type)(implicit ctx: Context) = { val ctype = ClassClass.typeConstructor if (ctx.phase.erasedTypes) ctype else ctype.appliedTo(arg) diff --git a/src/dotty/tools/dotc/core/SymDenotations.scala b/src/dotty/tools/dotc/core/SymDenotations.scala index a53ac374f..979e2130f 100644 --- a/src/dotty/tools/dotc/core/SymDenotations.scala +++ b/src/dotty/tools/dotc/core/SymDenotations.scala @@ -95,18 +95,14 @@ object SymDenotations { private[core] def annotations_=(annots: List[Annotation]): Unit = { _annotations = annots } /** Does this denotation have an annotation matching the given class symbol? */ - def hasAnnotation(cls: Symbol) = dropOtherAnnotations(annotations, cls).nonEmpty + def hasAnnotation(cls: Symbol)(implicit ctx: Context) = dropOtherAnnotations(annotations, cls).nonEmpty /** Add given annotation to the annotations of this denotation */ final def addAnnotation(annot: Annotation): Unit = annotations = annot :: annotations - /** Record that the denoting symbol is an alias of given `alias` symbol */ - final def setAlias(alias: Symbol)(implicit ctx: Context): Unit = - addAnnotation(Alias(alias)) - @tailrec - private def dropOtherAnnotations(anns: List[Annotation], cls: Symbol): List[Annotation] = anns match { + private def dropOtherAnnotations(anns: List[Annotation], cls: Symbol)(implicit ctx: Context): List[Annotation] = anns match { case ann :: rest => if (ann matches cls) anns else dropOtherAnnotations(rest, cls) case Nil => Nil } diff --git a/src/dotty/tools/dotc/core/pickling/UnPickler.scala b/src/dotty/tools/dotc/core/pickling/UnPickler.scala index ed97217f3..0183718e4 100644 --- a/src/dotty/tools/dotc/core/pickling/UnPickler.scala +++ b/src/dotty/tools/dotc/core/pickling/UnPickler.scala @@ -9,6 +9,7 @@ import java.lang.Double.longBitsToDouble import Contexts._, Symbols._, Types._, Scopes._, SymDenotations._, Names._ import StdNames._, Denotations._, NameOps._, Flags._, Constants._, Annotations._ +import Trees._ import scala.reflect.internal.pickling.PickleFormat._ import scala.collection.{ mutable, immutable } import scala.collection.mutable.ListBuffer @@ -62,6 +63,8 @@ abstract class UnPickler { /** A map from refinement classes to their associated refinement types */ private val refinementTypes = mutable.HashMap[Symbol, RefinedType]() + private val mk = makeTypedTree + //println("unpickled " + classRoot + ":" + classRoot.rawInfo + ", " + moduleRoot + ":" + moduleRoot.rawInfo);//debug // Laboriously unrolled for performance. @@ -473,19 +476,10 @@ abstract class UnPickler { val boundSyms = until(end, readSymbolRef) elimExistentials(boundSyms, restpe) case ANNOTATEDtpe => - ??? - /* - var typeRef = readNat() - val selfsym = if (isSymbolRef(typeRef)) { - val s = at(typeRef, readSymbol) - typeRef = readNat() - s - } else NoSymbol // selfsym can go. - val tp = at(typeRef, () => readType(forceProperType)) // NMT_TRANSITION + val tp = readTypeRef() + // no annotation self type is supported, so no test whether this is a symbol ref val annots = until(end, readAnnotationRef) - if (selfsym == NoSymbol) AnnotatedType(annots, tp, selfsym) - else tp - */ + AnnotatedType(annots, tp) case _ => noSuchTypeTag(tag, end) } @@ -527,7 +521,7 @@ abstract class UnPickler { val end = readNat() + readIndex val target = readSymbolRef() while (readIndex != end) - target.addAnnotation(Child(readSymbolRef().asClass)) + target.addAnnotation(Annotation.makeChild(readSymbolRef().asClass)) } /* Read a reference to a pickled item */ @@ -552,76 +546,85 @@ abstract class UnPickler { protected def readTypeNameRef(): TypeName = readNameRef().toTypeName protected def readTermNameRef(): TermName = readNameRef().toTermName - protected def readSymbolAnnotation(): Unit = ??? - protected def readAnnotationRef(): Annotation = ??? // at(readNat(), readAnnotation) + protected def readAnnotationRef(): Annotation = at(readNat(), readAnnotation) + // protected def readModifiersRef(): Modifiers = at(readNat(), readModifiers) -// protected def readTreeRef(): Tree = at(readNat(), readTree) -/* + protected def readTreeRef(): TypedTree = at(readNat(), readTree) + + protected def readTree(): TypedTree = ??? + /** Read an annotation argument, which is pickled either * as a Constant or a Tree. */ - protected def readAnnotArg(i: Int): Tree = bytes(index(i)) match { + protected def readAnnotArg(i: Int): TypedTree = bytes(index(i)) match { case TREE => at(i, readTree) - case _ => - val const = at(i, readConstant) - Literal(const) setType const.tpe + case _ => mk.Literal(at(i, readConstant)) } /** Read a ClassfileAnnotArg (argument to a classfile annotation) */ - private def readArrayAnnot() = { + private def readArrayAnnotArg(): TypedTree = { readByte() // skip the `annotargarray` tag val end = readNat() + readIndex - until(end, () => readClassfileAnnotArg(readNat())).toArray(JavaArgumentTag) + // array elements are trees representing instances of scala.annotation.Annotation + mk.ArrayValue( + mk.TypeTree(defn.AnnotationClass.typeConstructor), + until(end, () => readClassfileAnnotArg(readNat()))) } - protected def readClassfileAnnotArg(i: Int): ClassfileAnnotArg = bytes(index(i)) match { - case ANNOTINFO => NestedAnnotArg(at(i, readAnnotation)) - case ANNOTARGARRAY => at(i, () => ArrayAnnotArg(readArrayAnnot())) - case _ => LiteralAnnotArg(at(i, readConstant)) + + private def readAnnotInfoArg(): TypedTree = { + readByte() // skip the `annotinfo` tag + val end = readNat() + readIndex + readAnnotationContents(end) + } + + protected def readClassfileAnnotArg(i: Int): TypedTree = bytes(index(i)) match { + case ANNOTINFO => at(i, readAnnotInfoArg) + case ANNOTARGARRAY => at(i, readArrayAnnotArg) + case _ => readAnnotArg(i) } - /** Read an AnnotationInfo. Not to be called directly, use - * readAnnotation or readSymbolAnnotation + /** Read an annotation's contents. Not to be called directly, use + * readAnnotation, readSymbolAnnotation, or readAnnotInfoArg */ - protected def readAnnotationInfo(end: Int): AnnotationInfo = { + protected def readAnnotationContents(end: Int): TypedTree = { val atp = readTypeRef() - val args = new ListBuffer[Tree] - val assocs = new ListBuffer[(Name, ClassfileAnnotArg)] + val args = new ListBuffer[TypedTree] while (readIndex != end) { val argref = readNat() - if (isNameEntry(argref)) { - val name = at(argref, readName) - val arg = readClassfileAnnotArg(readNat()) - assocs += ((name, arg)) + args += { + if (isNameEntry(argref)) { + val name = at(argref, readName) + val arg = readClassfileAnnotArg(readNat()) + mk.NamedArg(name, arg) + } else readAnnotArg(argref) } - else - args += readAnnotArg(argref) } - AnnotationInfo(atp, args.toList, assocs.toList) + mk.New(atp, args.toList) } /** Read an annotation and as a side effect store it into * the symbol it requests. Called at top-level, for all * (symbol, annotInfo) entries. */ - protected def readSymbolAnnotation() { + protected def readSymbolAnnotation(): Unit = { val tag = readByte() if (tag != SYMANNOT) errorBadSignature("symbol annotation expected ("+ tag +")") val end = readNat() + readIndex val target = readSymbolRef() - target.addAnnotation(readAnnotationInfo(end)) + target.addAnnotation(ConcreteAnnotation(readAnnotationContents(end))) } /** Read an annotation and return it. Used when unpickling * an ANNOTATED(WSELF)tpe or a NestedAnnotArg */ - protected def readAnnotation(): AnnotationInfo = { + protected def readAnnotation(): Annotation = { val tag = readByte() if (tag != ANNOTINFO) errorBadSignature("annotation expected (" + tag + ")") val end = readNat() + readIndex - readAnnotationInfo(end) + ConcreteAnnotation(readAnnotationContents(end)) } - +/* /* Read an abstract syntax tree */ protected def readTree(): Tree = { val outerTag = readByte() @@ -960,8 +963,8 @@ abstract class UnPickler { def disambiguate(alt: Symbol) = denot.info =:= denot.owner.thisType.memberInfo(alt) if (j >= 0) { - val alias = at(j, readDisambiguatedSymbol(disambiguate)) - denot.setAlias(alias) + val alias = at(j, readDisambiguatedSymbol(disambiguate)).asTerm + denot.addAnnotation(Annotation.makeAlias(alias)) } } catch { case e: MissingRequirementError => throw toTypeError(e) -- cgit v1.2.3