diff options
Diffstat (limited to 'src/dotty/tools/dotc/core')
-rw-r--r-- | src/dotty/tools/dotc/core/Annotations.scala | 15 | ||||
-rw-r--r-- | src/dotty/tools/dotc/core/Flags.scala | 11 | ||||
-rw-r--r-- | src/dotty/tools/dotc/core/TypeApplications.scala | 5 | ||||
-rw-r--r-- | src/dotty/tools/dotc/core/Types.scala | 17 | ||||
-rw-r--r-- | src/dotty/tools/dotc/core/pickling/ClassfileParser.scala | 44 | ||||
-rw-r--r-- | src/dotty/tools/dotc/core/pickling/PickleBuffer.scala | 3 | ||||
-rw-r--r-- | src/dotty/tools/dotc/core/pickling/UnPickler.scala | 32 |
7 files changed, 107 insertions, 20 deletions
diff --git a/src/dotty/tools/dotc/core/Annotations.scala b/src/dotty/tools/dotc/core/Annotations.scala index 92b28a193..79aa058ef 100644 --- a/src/dotty/tools/dotc/core/Annotations.scala +++ b/src/dotty/tools/dotc/core/Annotations.scala @@ -3,6 +3,9 @@ package core import Symbols._, Types._, util.Positions._, Contexts._, Constants._, ast.tpd._ import config.ScalaVersion +import StdNames._ +import dotty.tools.dotc.ast.{tpd, untpd} +import dotty.tools.dotc.typer.ProtoTypes.FunProtoTyped object Annotations { @@ -61,12 +64,24 @@ object Annotations { def apply(atp: Type, args: List[Tree])(implicit ctx: Context): Annotation = apply(New(atp, args)) + private def resolveConstructor(atp: Type, args:List[Tree])(implicit ctx: Context): Tree = { + val targs = atp.argTypes + tpd.applyOverloaded(New(atp withoutArgs targs), nme.CONSTRUCTOR, args, targs, atp, isAnnotConstructor = true) + } + + def applyResolve(atp: Type, args: List[Tree])(implicit ctx: Context): Annotation = { + apply(resolveConstructor(atp, args)) + } + def deferred(sym: Symbol, treeFn: Context => Tree)(implicit ctx: Context): Annotation = new LazyAnnotation(sym)(treeFn) def deferred(atp: Type, args: List[Tree])(implicit ctx: Context): Annotation = deferred(atp.classSymbol, implicit ctx => New(atp, args)) + def deferredResolve(atp: Type, args: List[Tree])(implicit ctx: Context): Annotation = + deferred(atp.classSymbol, implicit ctx => resolveConstructor(atp, args)) + def makeAlias(sym: TermSymbol)(implicit ctx: Context) = apply(defn.AliasAnnot, List( ref(TermRef.withSigAndDenot(sym.owner.thisType, sym.name, sym.signature, sym)))) diff --git a/src/dotty/tools/dotc/core/Flags.scala b/src/dotty/tools/dotc/core/Flags.scala index db969767b..0e86a2936 100644 --- a/src/dotty/tools/dotc/core/Flags.scala +++ b/src/dotty/tools/dotc/core/Flags.scala @@ -318,7 +318,7 @@ object Flags { /** An unpickled Scala 2.x class */ final val Scala2x = typeFlag(26, "<scala-2.x>") - /** A method that has default params */ // TODO: drop + /** A method that has default params */ final val DefaultParameterized = termFlag(27, "<defaultparam>") /** Symbol is initialized to the default value, e.g. var x: T = _ */ @@ -356,6 +356,12 @@ object Flags { /** Symbol is a Java-style varargs method */ final val JavaVarargs = termFlag(37, "<varargs>") + /** Symbol is a Java default method */ + final val DefaultMethod = termFlag(38, "<defaultmethod>") + + /** Symbol is a Java enum */ + final val Enum = commonFlag(40, "<enum>") + // Flags following this one are not pickled /** Symbol always defines a fresh named type */ @@ -547,6 +553,9 @@ object Flags { /** A Java interface, potentially with default methods */ final val JavaTrait = allOf(JavaDefined, Trait, NoInits) + + /** A Java interface */ + final val JavaInterface = allOf(JavaDefined, Trait) /** A Java companion object */ final val JavaModule = allOf(JavaDefined, Module) diff --git a/src/dotty/tools/dotc/core/TypeApplications.scala b/src/dotty/tools/dotc/core/TypeApplications.scala index bf756facf..3beb680d9 100644 --- a/src/dotty/tools/dotc/core/TypeApplications.scala +++ b/src/dotty/tools/dotc/core/TypeApplications.scala @@ -284,7 +284,10 @@ class TypeApplications(val self: Type) extends AnyVal { * or, if isJava is true, Array type, else the type itself. */ def underlyingIfRepeated(isJava: Boolean)(implicit ctx: Context): Type = - if (self.isRepeatedParam) translateParameterized(defn.RepeatedParamClass, defn.SeqClass) + if (self.isRepeatedParam) { + val seqClass = if(isJava) defn.ArrayClass else defn.SeqClass + translateParameterized(defn.RepeatedParamClass, seqClass) + } else self /** If this is an encoding of a (partially) applied type, return its arguments, diff --git a/src/dotty/tools/dotc/core/Types.scala b/src/dotty/tools/dotc/core/Types.scala index aa8036fc5..2997e9e77 100644 --- a/src/dotty/tools/dotc/core/Types.scala +++ b/src/dotty/tools/dotc/core/Types.scala @@ -35,6 +35,8 @@ object Types { private var recCount = 0 // used temporarily for debugging. TODO: remove + private var nextId = 0 + /** The class of types. * The principal subclasses and sub-objects are as follows: * @@ -70,6 +72,13 @@ object Types { // ----- Tests ----------------------------------------------------- + val uniqId = { + nextId = nextId + 1 +// if(nextId == 19555) +// println("foo") + nextId + } + /** Is this type different from NoType? */ def exists: Boolean = true @@ -1965,7 +1974,9 @@ object Types { def fromSymbols(params: List[Symbol], resultType: Type)(implicit ctx: Context) = { def paramInfo(param: Symbol): Type = param.info match { case AnnotatedType(annot, tp) if annot matches defn.RepeatedAnnot => - tp.translateParameterized(defn.SeqClass, defn.RepeatedParamClass) + val typeSym = param.info.typeSymbol.asClass + assert(typeSym == defn.SeqClass || typeSym == defn.ArrayClass) + tp.translateParameterized(typeSym, defn.RepeatedParamClass) case tp => tp } @@ -2024,9 +2035,9 @@ object Types { def derivedPolyType(paramNames: List[TypeName], paramBounds: List[TypeBounds], restpe: Type)(implicit ctx: Context) = if ((paramNames eq this.paramNames) && (paramBounds eq this.paramBounds) && (restpe eq this.resultType)) this - else copy(paramNames, paramBounds, restpe) + else duplicate(paramNames, paramBounds, restpe) - def copy(paramNames: List[TypeName], paramBounds: List[TypeBounds], restpe: Type)(implicit ctx: Context) = + def duplicate(paramNames: List[TypeName] = this.paramNames, paramBounds: List[TypeBounds] = this.paramBounds, restpe: Type)(implicit ctx: Context) = PolyType(paramNames)( x => paramBounds mapConserve (_.subst(this, x).bounds), x => restpe.subst(this, x)) diff --git a/src/dotty/tools/dotc/core/pickling/ClassfileParser.scala b/src/dotty/tools/dotc/core/pickling/ClassfileParser.scala index 8dd9314ee..f92573d22 100644 --- a/src/dotty/tools/dotc/core/pickling/ClassfileParser.scala +++ b/src/dotty/tools/dotc/core/pickling/ClassfileParser.scala @@ -128,6 +128,7 @@ class ClassfileParser( for (i <- 0 until in.nextChar) parseMember(method = false) for (i <- 0 until in.nextChar) parseMember(method = true) classInfo = parseAttributes(classRoot.symbol, classInfo) + if (isAnnotation) addAnnotationConstructor(classInfo) setClassInfo(classRoot, classInfo) setClassInfo(moduleRoot, staticInfo) } @@ -421,7 +422,7 @@ class ClassfileParser( case None => hasError = true } if (hasError) None - else if (skip) None else Some(SeqLiteral(arr.toList)) + else if (skip) None else Some(JavaSeqLiteral(arr.toList)) case ANNOTATION_TAG => parseAnnotation(index, skip) map (_.tree) } @@ -443,7 +444,7 @@ class ClassfileParser( } } if (hasError || skip) None - else Some(Annotation.deferred(attrType, argbuf.toList)) + else Some(Annotation.deferredResolve(attrType, argbuf.toList)) } catch { case f: FatalError => throw f // don't eat fatal errors, they mean a class was not found case ex: Throwable => @@ -551,6 +552,45 @@ class ClassfileParser( newType } + /** Add a synthetic constructor and potentially also default getters which + * reflects the fields of the annotation with given `classInfo`. + * Annotations in Scala are assumed to get all their arguments as constructor + * parameters. For Java annotations we need to fake it by making up the constructor. + * Note that default getters have type Nothing. That's OK because we need + * them only to signal that the corresponding parameter is optional. + */ + def addAnnotationConstructor(classInfo: Type, tparams: List[Symbol] = Nil)(implicit ctx: Context): Unit = { + def addDefaultGetter(attr: Symbol, n: Int) = + ctx.newSymbol( + owner = moduleRoot.symbol, + name = nme.CONSTRUCTOR.defaultGetterName(n), + flags = attr.flags & Flags.AccessFlags, + info = defn.NothingType).entered + + classInfo match { + case classInfo @ TempPolyType(tparams, restpe) if tparams.isEmpty => + addAnnotationConstructor(restpe, tparams) + case classInfo: TempClassInfoType => + val attrs = classInfo.decls.toList.filter(_.isTerm) + val targs = tparams.map(_.typeRef) + val methType = MethodType( + attrs.map(_.name.asTermName), + attrs.map(_.info.resultType), + classRoot.typeRef.appliedTo(targs)) + val constr = ctx.newSymbol( + owner = classRoot.symbol, + name = nme.CONSTRUCTOR, + flags = Flags.Synthetic, + info = if (tparams.isEmpty) methType else TempPolyType(tparams, methType) + ).entered + for ((attr, i) <- attrs.zipWithIndex) + if (attr.hasAnnotation(defn.AnnotationDefaultAnnot)) { + constr.setFlag(Flags.HasDefaultParams) + addDefaultGetter(attr, i) + } + } + } + /** Enter own inner classes in the right scope. It needs the scopes to be set up, * and implicitly current class' superclasses. */ diff --git a/src/dotty/tools/dotc/core/pickling/PickleBuffer.scala b/src/dotty/tools/dotc/core/pickling/PickleBuffer.scala index 9f8d4fc2d..c16b794b7 100644 --- a/src/dotty/tools/dotc/core/pickling/PickleBuffer.scala +++ b/src/dotty/tools/dotc/core/pickling/PickleBuffer.scala @@ -251,7 +251,8 @@ object PickleBuffer { SPECIALIZED -> Specialized, DEFAULTINIT -> DefaultInit, VBRIDGE -> VBridge, - VARARGS -> JavaVarargs) + VARARGS -> JavaVarargs, + ENUM -> Enum) // generate initial maps from Scala flags to Dotty flags val termMap, typeMap = new Array[Long](64) diff --git a/src/dotty/tools/dotc/core/pickling/UnPickler.scala b/src/dotty/tools/dotc/core/pickling/UnPickler.scala index 60000441c..728048700 100644 --- a/src/dotty/tools/dotc/core/pickling/UnPickler.scala +++ b/src/dotty/tools/dotc/core/pickling/UnPickler.scala @@ -9,8 +9,9 @@ import java.lang.Double.longBitsToDouble import Contexts._, Symbols._, Types._, Scopes._, SymDenotations._, Names._, NameOps._ import StdNames._, Denotations._, NameOps._, Flags._, Constants._, Annotations._ +import dotty.tools.dotc.typer.ProtoTypes.{FunProtoTyped, FunProto} import util.Positions._ -import ast.Trees, ast.tpd._, ast.untpd +import dotty.tools.dotc.ast.{tpd, Trees, untpd}, ast.tpd._ import printing.Texts._ import printing.Printer import io.AbstractFile @@ -815,19 +816,26 @@ class UnPickler(bytes: Array[Byte], classRoot: ClassDenotation, moduleClassRoot: */ protected def readAnnotationContents(end: Int)(implicit ctx: Context): Tree = { val atp = readTypeRef() - val args = new ListBuffer[Tree] - while (readIndex != end) { - val argref = readNat() - args += { - if (isNameEntry(argref)) { - val name = at(argref, readName) - val arg = readClassfileAnnotArg(readNat()) - NamedArg(name.asTermName, arg) - } else readAnnotArg(argref) + val args = { + val t = new ListBuffer[Tree] + + while (readIndex != end) { + val argref = readNat() + t += { + if (isNameEntry(argref)) { + val name = at(argref, readName) + val arg = readClassfileAnnotArg(readNat()) + NamedArg(name.asTermName, arg) + } else readAnnotArg(argref) + } } + t.toList } - New(atp, args.toList) - } + // println(atp) + val targs = atp.argTypes + + tpd.applyOverloaded(tpd.New(atp withoutArgs targs), nme.CONSTRUCTOR, args, targs, atp) +} /** Read an annotation and as a side effect store it into * the symbol it requests. Called at top-level, for all |