aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/dotty/tools/dotc/ast/Trees.scala4
-rw-r--r--src/dotty/tools/dotc/core/Signature.scala2
-rw-r--r--src/dotty/tools/dotc/core/pickling/DottyUnpickler.scala654
-rw-r--r--src/dotty/tools/dotc/core/pickling/PickleFormat.scala84
-rw-r--r--src/dotty/tools/dotc/core/pickling/TastyPrinter.scala2
-rw-r--r--src/dotty/tools/dotc/core/pickling/TreePickler.scala34
6 files changed, 725 insertions, 55 deletions
diff --git a/src/dotty/tools/dotc/ast/Trees.scala b/src/dotty/tools/dotc/ast/Trees.scala
index 57cbb7f8f..1973a4947 100644
--- a/src/dotty/tools/dotc/ast/Trees.scala
+++ b/src/dotty/tools/dotc/ast/Trees.scala
@@ -19,8 +19,8 @@ object Trees {
// Note: it would be more logical to make Untyped = Nothing.
// However, this interacts in a bad way with Scala's current type inference.
- // In fact, we cannot write soemthing like Select(pre, name), where pre is
- // of type Tree[Nothing]; type inference will treat the Nothing as an uninstantited
+ // In fact, we cannot write something like Select(pre, name), where pre is
+ // of type Tree[Nothing]; type inference will treat the Nothing as an uninstantiated
// value and will not infer Nothing as the type parameter for Select.
// We should come back to this issue once type inference is changed.
type Untyped = Null
diff --git a/src/dotty/tools/dotc/core/Signature.scala b/src/dotty/tools/dotc/core/Signature.scala
index 0f7f33b6b..4e041e629 100644
--- a/src/dotty/tools/dotc/core/Signature.scala
+++ b/src/dotty/tools/dotc/core/Signature.scala
@@ -23,7 +23,7 @@ import TypeErasure.sigName
*
* The signatures of non-method types are always `NotAMethod`.
*/
-case class Signature private (paramsSig: List[TypeName], resSig: TypeName) {
+case class Signature(paramsSig: List[TypeName], resSig: TypeName) {
/** Does this signature conincide with that signature on their parameter parts? */
final def sameParams(that: Signature): Boolean = this.paramsSig == that.paramsSig
diff --git a/src/dotty/tools/dotc/core/pickling/DottyUnpickler.scala b/src/dotty/tools/dotc/core/pickling/DottyUnpickler.scala
new file mode 100644
index 000000000..021480469
--- /dev/null
+++ b/src/dotty/tools/dotc/core/pickling/DottyUnpickler.scala
@@ -0,0 +1,654 @@
+package dotty.tools
+package dotc
+package core
+package pickling
+
+import java.io.IOException
+
+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 dotty.tools.dotc.ast.{tpd, Trees, untpd}
+import Trees._
+import printing.Texts._
+import printing.Printer
+import io.AbstractFile
+import util.common._
+import typer.Checking.checkNonCyclic
+import Decorators._
+import TastyUnpickler._, TastyBuffer._
+import annotation.switch
+import scala.collection.{ mutable, immutable }
+import typer.Mode
+
+object DottyUnpickler {
+
+ /** Exception thrown if classfile is corrupted */
+ class BadSignature(msg: String) extends RuntimeException(msg)
+}
+
+/** Unpickle symbol table information descending from a class and/or module root
+ * from an array of bytes.
+ * @param bytes bytearray from which we unpickle
+ * @param classroot the top-level class which is unpickled, or NoSymbol if inapplicable
+ * @param moduleroot the top-level module class which is unpickled, or NoSymbol if inapplicable
+ * @param filename filename associated with bytearray, only used for error messages
+ */
+class DottyUnpickler(bytes: Array[Byte], classRoot: ClassDenotation, moduleClassRoot: ClassDenotation)(ictx: Context) {
+ import tpd._
+
+ val moduleRoot = moduleClassRoot.sourceModule(ictx).denot(ictx)
+ assert(moduleRoot.isTerm)
+
+ val unpickler = new TastyUnpickler(bytes)
+
+ def result: List[Tree] =
+ unpickler.unpickle(new TreeSectionUnpickler()(ictx)).getOrElse(Nil)
+
+ private val symAtAddr = new mutable.HashMap[Addr, Symbol]
+ private val defAtAttr = new mutable.HashMap[Addr, MemberDef]
+ private val typeAtAddr = new mutable.HashMap[Addr, Type]
+
+ class TreeSectionUnpickler(implicit ctx: Context) extends SectionUnpickler[List[Tree]]("ASTs") {
+ def unpickle(reader: TastyReader, tastyName: TastyName.Table): List[Tree] =
+ new TreesUnpickler(reader, tastyName, classRoot.owner, Set(classRoot, moduleClassRoot, moduleRoot))
+ .unpickle()
+ }
+}
+
+class TreesUnpickler(reader: TastyReader, tastyName: TastyName.Table, rootOwner: Symbol, roots: Set[SymDenotation]) {
+ import dotty.tools.dotc.core.pickling.PickleFormat._
+ import TastyName._
+ import tpd._
+
+ private val symAtAddr = new mutable.HashMap[Addr, Symbol]
+ private val treeAtAddr = new mutable.HashMap[Addr, Tree]
+
+ private val typeAtAddr = new mutable.HashMap[Addr, Type] // currently populated only for types that are known to be SHAREd.
+
+ def unpickle()(implicit ctx: Context): List[Tree] =
+ new TreeReader(reader).readTopLevelStats()
+
+ def toTermName(tname: TastyName): TermName = tname match {
+ case Simple(name) => name
+ case Qualified(qual, name) => toTermName(qual) ++ "." ++ toTermName(name)
+ case Signed(original, params, result) => toTermName(original)
+ case Expanded(original) => ???
+ case ModuleClass(original) => toTermName(original).moduleClassName.toTermName
+ case SuperAccessor(accessed) => ???
+ case DefaultGetter(meth, num) => ???
+ }
+
+ def toTermName(ref: NameRef): TermName = toTermName(tastyName(ref))
+ def toTypeName(ref: NameRef): TypeName = toTermName(ref).toTypeName
+
+ class Completer(reader: TastyReader) extends LazyType {
+ import reader._
+ def complete(denot: SymDenotation)(implicit ctx: Context): Unit = {
+ treeAtAddr(currentAddr) = new TreeReader(reader).readIndexedDef()
+ }
+ }
+
+ class TreeReader(val reader: TastyReader) {
+ import reader._
+
+ def forkAt(start: Addr) = new TreeReader(subReader(start, endAddr))
+ def fork = forkAt(currentAddr)
+
+ def skipTree(tag: Int): Unit =
+ if (tag >= firstLengthTreeTag) skipTo(readEnd())
+ else if (tag >= firstNatASTTreeTag) { readNat(); skipTree() }
+ else if (tag >= firstNatTreeTag) readNat()
+
+ def skipTree(): Unit = skipTree(readByte())
+
+ def skipParams(): Unit =
+ while (nextByte == PARAM || nextByte== TYPEPARAM) skipTree()
+
+ def readName(): TermName = toTermName(readNameRef())
+
+ def readNameSplitSig()(implicit ctx: Context): Any /* TermName | (TermName, Signature) */ =
+ tastyName(readNameRef()) match {
+ case Signed(original, params, result) =>
+ var sig = Signature(params map toTypeName, toTypeName(result))
+ if (sig == Signature.NotAMethod) sig = Signature.NotAMethod
+ (toTermName(original), sig)
+ case name =>
+ toTermName(name)
+ }
+
+// ------ Reading types -----------------------------------------------------
+
+ /** Read names in an interleaved sequence of (parameter) names and types/bounds */
+ def readParamNames[N <: Name](end: Addr): List[N] =
+ until(end) { try readName().asInstanceOf[N] finally skipTree() }
+
+ /** Read types or bounds in an interleaved sequence of (parameter) names and types/bounds */
+ def readParamTypes[T <: Type](end: Addr)(implicit ctx: Context): List[T] =
+ until(end) { readNat(); readType().asInstanceOf[T] }
+
+ /** Read referece to definition and return symbol created at that definition */
+ def readSymRef()(implicit ctx: Context): Symbol = symAtAddr(readAddr())
+
+ /** Read a type */
+ def readType()(implicit ctx: Context): Type = {
+ val start = currentAddr
+ val tag = readByte()
+
+ def registeringType[T](tp: Type, op: => T): T = {
+ typeAtAddr(start) = tp
+ op
+ }
+
+ def readLengthType(): Type = {
+ val end = readEnd()
+
+ def readNamesSkipParams[N <: Name]: (List[N], TreeReader) = {
+ val nameReader = fork
+ nameReader.skipTree() // skip result
+ val paramReader = nameReader.fork
+ (nameReader.readParamNames[N](end), paramReader)
+ }
+
+ try {
+ (tag: @switch) match {
+ case THIS =>
+ ThisType.raw(readType().asInstanceOf[TypeRef])
+ case SUPERtype =>
+ SuperType(readType(), readType())
+ case REFINEDtype =>
+ val parent = readType()
+ var name: Name = readName()
+ if (nextByte == TYPEBOUNDS || nextByte == TYPEALIAS) name = name.toTypeName
+ RefinedType(parent, name, registeringType(_, readType()))
+ case APPLIEDtype =>
+ readType().appliedTo(until(end)(readType()))
+ case TYPEBOUNDS =>
+ TypeBounds(readType(), readType())
+ case TYPEALIAS =>
+ TypeAlias(readType())
+ case ANNOTATED =>
+ AnnotatedType(Annotation(readTerm()), readType())
+ case ANDtype =>
+ AndType(readType(), readType())
+ case ORtype =>
+ OrType(readType(), readType())
+ case BIND =>
+ symAtAddr(start) =
+ ctx.newSymbol(ctx.owner, readName().toTypeName, BindDefinedType, readType())
+ readType()
+ case BYNAMEtype =>
+ ExprType(readType())
+ case POLYtype =>
+ val (names, paramReader) = readNamesSkipParams[TypeName]
+ try PolyType(names)(
+ registeringType(_, paramReader.readParamTypes[TypeBounds](end)),
+ _ => readType())
+ finally skipTo(end)
+ case METHODtype =>
+ val (names, paramReader) = readNamesSkipParams[TermName]
+ try MethodType(names, paramReader.readParamTypes[Type](end))(
+ registeringType(_, readType()))
+ finally skipTo(end)
+ case PARAMtype =>
+ readTypeRef() match {
+ case binder: PolyType => PolyParam(binder, readNat())
+ case binder: MethodType => MethodParam(binder, readNat())
+ }
+ case CLASSconst =>
+ readEnd()
+ ConstantType(Constant(readType()))
+ case ENUMconst =>
+ readEnd()
+ ConstantType(Constant(readTermRef().termSymbol))
+ }
+ }
+ finally assert(currentAddr == end)
+ }
+
+ def readSimpleType(): Type = (tag: @switch) match {
+ case TYPEREFdirect | TERMREFdirect =>
+ NamedType.withFixedSym(NoPrefix, readSymRef())
+ case TYPEREFsymbol | TERMREFsymbol =>
+ val sym = readSymRef()
+ NamedType.withFixedSym(readType(), sym)
+ case TYPEREFstatic =>
+ ctx.requiredClass(readName().toTypeName).typeRef
+ case TERMREFstatic =>
+ ctx.requiredModule(readName()).termRef
+ case TYPEREF =>
+ val name = readName().toTypeName
+ TypeRef(readType(), name)
+ case TERMREF =>
+ readNameSplitSig() match {
+ case name: TermName => TermRef.all(readType(), name)
+ case (name: TermName, sig: Signature) => TermRef.withSig(readType(), name, sig)
+ }
+ case SKOLEMtype =>
+ SkolemType(readTypeRef())
+ case NOTYPE =>
+ NoType
+ case SHARED =>
+ val ref = readAddr()
+ typeAtAddr.getOrElseUpdate(ref, forkAt(ref).readType())
+ case UNITconst =>
+ ConstantType(Constant(()))
+ case TRUEconst =>
+ ConstantType(Constant(true))
+ case FALSEconst =>
+ ConstantType(Constant(false))
+ case BYTEconst =>
+ ConstantType(Constant(readInt().toByte))
+ case SHORTconst =>
+ ConstantType(Constant(readInt().toShort))
+ case CHARconst =>
+ ConstantType(Constant(readNat().toChar))
+ case INTconst =>
+ ConstantType(Constant(readInt()))
+ case LONGconst =>
+ ConstantType(Constant(readLongInt()))
+ case FLOATconst =>
+ ConstantType(Constant(java.lang.Float.intBitsToFloat(readInt())))
+ case DOUBLEconst =>
+ ConstantType(Constant(java.lang.Double.longBitsToDouble(readLongInt())))
+ case STRINGconst =>
+ ConstantType(Constant(readName().toString))
+ case NULLconst =>
+ ConstantType(Constant(null))
+ }
+
+ if (tag < firstLengthTreeTag) readSimpleType() else readLengthType()
+ }
+
+ def readTypeRef(): Type =
+ typeAtAddr(readAddr())
+
+ def readPath()(implicit ctx: Context): Type = {
+ val tp = readType()
+ assert(tp.isInstanceOf[SingletonType])
+ tp
+ }
+
+ def readTermRef()(implicit ctx: Context): TermRef =
+ readType().asInstanceOf[TermRef]
+
+// ------ Reading definitions -----------------------------------------------------
+
+ /** Create symbol of definition node and enter in symAtAddr map */
+ def createSymbol()(implicit ctx: Context): Unit = {
+ val start = currentAddr
+ val tag = readByte()
+ val end = readEnd()
+ val name = if (tag == TYPEDEF || tag == TYPEPARAM) readName().toTypeName else readName()
+ skipParams()
+ val isAbstractType = nextByte == TYPEBOUNDS
+ val isClass = nextByte == TEMPLATE
+ val templateStart = currentAddr
+ skipTree()
+ val rhsIsEmpty =
+ (tag == VALDEF || tag == DEFDEF) && {
+ val nxTag = readByte()
+ try nxTag == EMPTYTREE
+ finally skipTree(nxTag) // skip rhs
+ }
+ val (givenFlags, annots, privateWithin) = readModifiers(end)
+ val lacksDefinition =
+ rhsIsEmpty && !name.isConstructorName && !givenFlags.is(ParamOrAccessor) ||
+ isAbstractType
+ var flags = givenFlags
+ if (lacksDefinition) flags |= Deferred
+ if (ctx.mode.is(Mode.InSuperCall) && !flags.is(ParamOrAccessor)) flags |= InSuperCall
+ if (ctx.owner.isClass) {
+ if (tag == TYPEPARAM) flags |= Param
+ else if (tag == PARAM) flags |= ParamAccessor // TODO: try to unify param and paramaccessor
+ }
+ else if (isParamTag(tag)) flags |= Param
+ val nameMatches = (_: Denotation).symbol.name == name
+ val isRoot = ctx.owner == rootOwner && roots.exists(nameMatches)
+ val completer =
+ if (isRoot) new Completer(subReader(start, end)) with SymbolLoaders.SecondCompleter
+ else new Completer(subReader(start, end))
+ def adjustIfModule(completer: Completer) =
+ if (flags is Module) ctx.adjustModuleCompleter(completer, name) else completer
+ val sym =
+ if (isRoot) {
+ val d = roots.find(nameMatches).get
+ d.info = completer
+ d.setFlag(flags)
+ d.privateWithin = privateWithin
+ d.symbol
+ } else if (isClass)
+ ctx.newClassSymbol(ctx.owner, name.asTypeName, flags, completer, privateWithin, coord = start.index)
+ else {
+ ctx.newSymbol(ctx.owner, name, flags, completer, privateWithin, coord = start.index)
+ } // TODO set position
+ sym.annotations = annots
+ ctx.enter(sym)
+ symAtAddr(start) = sym
+ if (isClass) {
+ completer.withDecls(newScope)
+ forkAt(templateStart).indexTemplateParams()(ctx.fresh.setOwner(sym))
+ }
+ }
+
+ /** Read modifier list into triplet of flags, annotations and a privateWithin
+ * boindary symbol.
+ */
+ def readModifiers(end: Addr)(implicit ctx: Context): (FlagSet, List[Annotation], Symbol) = {
+ var flags: FlagSet = EmptyFlags
+ var annots = new mutable.ListBuffer[Annotation]
+ var privateWithin: Symbol = NoSymbol
+ while (currentAddr.index != end.index) {
+ def addFlag(flag: FlagSet) = {
+ flags |= flag
+ readByte()
+ }
+ nextByte match {
+ case PRIVATE => addFlag(Private)
+ case INTERNAL => ??? // addFlag(Internal)
+ case PROTECTED => addFlag(Protected)
+ case ABSTRACT => addFlag(Abstract)
+ case FINAL => addFlag(Final)
+ case SEALED => addFlag(Sealed)
+ case CASE => addFlag(Case)
+ case IMPLICIT => addFlag(Implicit)
+ case LAZY => addFlag(Lazy)
+ case OVERRIDE => addFlag(Override)
+ case INLINE => addFlag(Inline)
+ case ABSOVERRIDE => addFlag(AbsOverride)
+ case STATIC => addFlag(JavaStatic)
+ case MODULE => addFlag(Module)
+ case LOCAL => addFlag(Local)
+ case SYNTHETIC => addFlag(Synthetic)
+ case ARTIFACT => addFlag(Artifact)
+ case MUTABLE => addFlag(Mutable)
+ case LABEL => addFlag(Label)
+ case FIELDaccessor => addFlag(Accessor)
+ case PARAMaccessor => addFlag(ParamAccessor)
+ case CASEaccessor => addFlag(CaseAccessor)
+ case COVARIANT => addFlag(Covariant)
+ case CONTRAVARIANT => addFlag(Contravariant)
+ case SCALA2X => addFlag(Scala2x)
+ case DEFAULTparameterized => addFlag(DefaultParameterized)
+ case DEFAULTinit => addFlag(DefaultInit)
+ case INSUPERCALL => addFlag(InSuperCall)
+ case PRIVATEqualified =>
+ readByte()
+ readEnd()
+ privateWithin = readType().typeSymbol
+ case PROTECTEDqualified =>
+ addFlag(Protected)
+ readEnd()
+ privateWithin = readType().typeSymbol
+ case ANNOTATION =>
+ readByte()
+ val end = readEnd()
+ val sym = readType().typeSymbol
+ val lazyAnnotTree = readLater(end, _.readTerm())
+ annots += Annotation.deferred(sym, _ => lazyAnnotTree.complete)
+ }
+ }
+ (flags, annots.toList, privateWithin)
+ }
+
+ /** Create symbols for a definitions in statement sequence between
+ * current address and `end`.
+ */
+ def indexStats(end: Addr)(implicit ctx: Context) =
+ until(end) { if (isDefTag(nextByte)) createSymbol() else skipTree() }
+
+ /** Create symbols the longest consecutive sequence of parameters with given
+ * `tag starting at current address.
+ */
+ def indexParams(tag: Int)(implicit ctx: Context) =
+ while (nextByte == tag) createSymbol()
+
+ /** Create symbols for all type and value parameters of template starting
+ * at current address.
+ */
+ def indexTemplateParams()(implicit ctx: Context) = {
+ assert(readByte() == TEMPLATE)
+ readEnd()
+ indexParams(TYPEPARAM)
+ indexParams(PARAM)
+ }
+
+ /** If definition was already read by a completer, return the previously read tree
+ * or else read definition.
+ */
+ def readIndexedDef()(implicit ctx: Context): Tree = treeAtAddr.remove(currentAddr) match {
+ case Some(tree) => skipTree(); tree
+ case none => readNewDef()
+ }
+
+ private def readNewDef()(implicit ctx: Context): Tree = {
+ val sym = symAtAddr(currentAddr)
+ val tag = readByte()
+ val end = readEnd()
+
+ def readParams[T <: MemberDef](tag: Int)(implicit ctx: Context): List[T] = {
+ fork.indexParams(tag)
+ readIndexedParams(tag)
+ }
+
+ def readParamss(implicit ctx: Context): List[List[ValDef]] = {
+ collectWhile(nextByte == PARAMS) {
+ readByte()
+ readEnd()
+ readParams[ValDef](PARAM)
+ }
+ }
+
+ def readRhs(implicit ctx: Context) = readLater(end, _.readTerm())
+
+ def localCtx = ctx.fresh.setOwner(sym)
+
+ def ta = ctx.typeAssigner
+
+ readName()
+ tag match {
+ case DEFDEF =>
+ val tparams = readParams[TypeDef](TYPEPARAM)(localCtx)
+ val vparamss = readParamss(localCtx)
+ val tree = ta.assignType(
+ untpd.DefDef(
+ sym.name.asTermName, tparams, vparamss, readTpt(), readRhs(localCtx)),
+ sym)
+ val typeParams = tparams.map(_.symbol)
+ val valueParamss = vparamss.nestedMap(_.symbol)
+ val resType = ctx.effectiveResultType(sym, typeParams, tree.tpt.tpe)
+ sym.info = ctx.methodType(typeParams, valueParamss, resType)
+ tree
+ case VALDEF =>
+ sym.info = readType()
+ ValDef(sym.asTerm, readRhs(localCtx))
+ case TYPEDEF | TYPEPARAM =>
+ if (sym.isClass)
+ ta.assignType(
+ untpd.TypeDef(sym.name.asTypeName, readTemplate(localCtx)),
+ sym)
+ else {
+ sym.info = readType()
+ TypeDef(sym.asType)
+ }
+ case PARAM =>
+ sym.info = readType()
+ ValDef(sym.asTerm)
+ }
+ }
+
+ def readTemplate(implicit ctx: Context): Template = {
+ val cls = ctx.owner.asClass
+ val localDummy = ctx.newLocalDummy(cls)
+ assert(readByte() == TEMPLATE)
+ val end = readEnd()
+ readIndexedParams(TYPEPARAM)
+ readIndexedParams(PARAM)
+ val parents = collectWhile(nextByte != SELFDEF && nextByte != DEFDEF) {
+ nextByte match {
+ case APPLY | TYPEAPPLY => readTerm()
+ case _ => readTpt()
+ }
+ }
+ fork.indexStats(end)
+ val self = if (nextByte == SELFDEF) readIndexedDef().asInstanceOf[ValDef] else EmptyValDef
+ val constr = readIndexedDef().asInstanceOf[DefDef]
+ val lazyStats = readLater(end, _.readIndexedStats(localDummy, end))
+ untpd.Template(constr, parents, self, lazyStats)
+ .withType(localDummy.nonMemberTermRef)
+ }
+
+ def readIndexedStat(exprOwner: Symbol)(implicit ctx: Context): Tree = nextByte match {
+ case TYPEDEF | VALDEF | DEFDEF | IMPORT => readIndexedDef()
+ case _ => readTerm()(ctx.withOwner(exprOwner))
+ }
+
+ def readStats(exprOwner: Symbol, end: Addr)(implicit ctx: Context): List[Tree] = {
+ fork.indexStats(end)
+ readIndexedStats(exprOwner, end)
+ }
+
+ def readIndexedStats(exprOwner: Symbol, end: Addr)(implicit ctx: Context): List[Tree] =
+ until(end)(readIndexedStat(exprOwner))
+
+ def readIndexedParams[T <: MemberDef](tag: Int)(implicit ctx: Context): List[T] =
+ collectWhile(nextByte == tag) { readIndexedDef().asInstanceOf[T] }
+
+// ------ Reading terms -----------------------------------------------------
+
+ def readTerm()(implicit ctx: Context): Tree = {
+ val start = currentAddr
+ val tag = readByte()
+
+ def readSimpleTerm(): Tree = tag match {
+ case IDENT =>
+ untpd.Ident(readName()).withType(readType())
+ case SELECT =>
+ def readQual(name: Name) = {
+ val localCtx =
+ if (name == nme.CONSTRUCTOR) ctx.fresh.addMode(Mode.InSuperCall) else ctx
+ readTerm()(localCtx)
+ }
+ readNameSplitSig match {
+ case name: Name => readQual(name).select(name)
+ case (name: Name, sig: Signature) => readQual(name).selectWithSig(name, sig)
+ }
+ case EMPTYTREE =>
+ EmptyTree
+ case _ =>
+ ref(readTermRef())
+ }
+
+ def readLengthTerm(): Tree = {
+ val end = readEnd()
+
+ try {
+ (tag: @switch) match {
+ case SUPER =>
+ val qual = readTerm()
+ val mixClass = ifBefore(end)(readType().typeSymbol, NoSymbol)
+ val mixName = if (mixClass.exists) mixClass.name.asTypeName else tpnme.EMPTY
+ tpd.Super(qual, mixName, ctx.mode.is(Mode.InSuperCall), mixClass)
+ case APPLY =>
+ val fn = readTerm()
+ val isJava = fn.tpe.isInstanceOf[JavaMethodType]
+ def readArg() = readTerm() match {
+ case SeqLiteral(elems) if isJava => JavaSeqLiteral(elems)
+ case arg => arg
+ }
+ tpd.Apply(readTerm(), until(end)(readArg()))
+ case TYPEAPPLY =>
+ tpd.TypeApply(readTerm(), until(end)(readTpt()))
+ case NEW =>
+ New(readTpt())
+ case PAIR =>
+ Pair(readTerm(), readTerm())
+ case TYPED =>
+ Typed(readTerm(), readTpt())
+ case NAMEDARG =>
+ NamedArg(readName(), readTerm())
+ case ASSIGN =>
+ Assign(readTerm(), readTerm())
+ case BLOCK =>
+ val exprReader = fork
+ skipTree()
+ Block(readStats(ctx.owner, end), exprReader.readTerm())(ctx.fresh.setNewScope)
+ case IF =>
+ If(readTerm(), readTerm(), readTerm())
+ case CLOSURE =>
+ val meth = readTerm()
+ val tpt = readTpt()
+ Closure(until(end)(readTerm()), meth, tpt)
+ case MATCH =>
+ Match(readTerm(), readCases())
+ case RETURN =>
+ val from = readSymRef()
+ val expr = ifBefore(end)(readTerm(), EmptyTree)
+ Return(expr, Ident(from.termRef))
+ case TRY =>
+ Try(readTerm(), readCases(), ifBefore(end)(readTerm(), EmptyTree))
+ case THROW =>
+ Throw(readTerm())
+ case REPEATED =>
+ SeqLiteral(until(end)(readTerm()))
+ case BIND =>
+ val name = readName()
+ val info = readType()
+ val sym = ctx.newSymbol(ctx.owner, name, EmptyFlags, info)
+ symAtAddr(start) = sym
+ Bind(sym, readTerm())
+ case ALTERNATIVE =>
+ Alternative(until(end)(readTerm()))
+ case UNAPPLY =>
+ val fn = readTerm()
+ val implicitArgs =
+ collectWhile(nextByte == IMPLICITARG) {
+ readByte()
+ readEnd()
+ readTerm()
+ }
+ val patType = readType()
+ val argPats = until(end)(readTerm())
+ UnApply(fn, implicitArgs, argPats, patType)
+ }
+ }
+ finally assert(currentAddr == end)
+ }
+
+ if (tag < firstLengthTreeTag) readSimpleTerm()
+ else readLengthTerm()
+ }
+
+ def readTpt()(implicit ctx: Context) = TypeTree(readType())
+
+ def readCases()(implicit ctx: Context): List[CaseDef] =
+ collectWhile(nextByte == CASEDEF) {
+ readByte()
+ val end = readEnd()
+ val pat = readTerm()
+ val rhs = readTerm()
+ val guard = ifBefore(end)(readTerm(), EmptyTree)
+ CaseDef(pat, guard, rhs)
+ }
+
+ def readTopLevelStats()(implicit ctx: Context): List[Tree] = {
+ fork.indexStats(endAddr)
+ until(endAddr) {
+ if (nextByte == PACKAGE) {
+ readByte()
+ val end = readEnd()
+ val pid = ref(readTermRef()).asInstanceOf[RefTree]
+ PackageDef(pid, readStats(NoSymbol, end)(ctx.fresh.setOwner(pid.symbol)))
+ }
+ else readIndexedStat(ctx.owner)
+ }
+ }
+
+ def readLater[T](end: Addr, op: TreeReader => T): Trees.Lazy[T] = {
+ val localReader = fork
+ skipTo(end)
+ new Trees.Lazy[T] { def complete: T = op(localReader) }
+ }
+ }
+}
diff --git a/src/dotty/tools/dotc/core/pickling/PickleFormat.scala b/src/dotty/tools/dotc/core/pickling/PickleFormat.scala
index 42a1cc1b5..9de471204 100644
--- a/src/dotty/tools/dotc/core/pickling/PickleFormat.scala
+++ b/src/dotty/tools/dotc/core/pickling/PickleFormat.scala
@@ -43,9 +43,9 @@ Macro-format:
Note: Unqualified names in the name table are strings. The context decides whether a name is
a type-name or a term-name. The same string can represent both.
-Standard-Section: "ASTs" Tree*
+Standard-Section: "ASTs" TopLevelStat*
- Tree = PACKAGE Length Path Tree*
+ TopLevelStat = PACKAGE Length Path TopLevelStat*
Stat
Stat = Term
@@ -58,15 +58,18 @@ Standard-Section: "ASTs" Tree*
TypeParam = TYPEPARAM Length NameRef Type Modifier*
Params = PARAMS Length Param*
Param = PARAM Length NameRef Type Modifier*
+ Template = TEMPLATE Length TypeParam* Param* Parent* Self? Stat* // Stat* always starts with the primary constructor.
+ Parent = Application
+ Type
+ Self = SELFDEF Length NameRef Type
Selector = IMPORTED Length name_NameRef
RENAMED Length from_NameRef to_NameRef
Term = Path
+ Application
IDENT NameRef Type
SELECT possiblySigned_NameRef qual_Term
SUPER Length this_Term mixinTrait_Type?
- APPLY Length fn_Term arg_Term*
- TYPEAPPLY Length fn_Term arg_Type*
NEW Length cls_Type
PAIR Length left_Term right_Term
TYPED Length expr_Term ascription_Type
@@ -79,18 +82,16 @@ Standard-Section: "ASTs" Tree*
RETURN Length meth_ASTRef expr_Term?
TRY Length expr_Term CaseDef* finalizer_Term?
THROW Length expr_Term
- SEQLITERAL Length elem_Term*
- JSEQLITERAL Length elem_Term*
+ REPEATED Length elem_Term*
BIND Length boundName_NameRef patType_Type pat_Term
ALTERNATIVE Length alt_Term*
- UNAPPLY Length fun_Term ImplicitArg* pat_Term*
+ UNAPPLY Length fun_Term ImplicitArg* pat_Type pat_Term*
EMPTYTREE
-
- CaseDef = CASEDEF Length pat_Tree guard_Tree rhs_Tree
+ Application = APPLY Length fn_Term arg_Term*
+ TYPEAPPLY Length fn_Term arg_Type*
+ CaseDef = CASEDEF Length pat_Tree rhs_Tree guard_Tree?
ImplicitArg = IMPLICITARG Length arg_Tree
- Template = TEMPLATE Length parent_Tree* SelfDef? Stat* // Stat* always starts with the primary constructor.
- SelfDef = Param
- Annotation = ANNOTATION Length tycon_Symbol fullAnnotation_Tree
+ Annotation = ANNOTATION Length tycon_Symbol fullAnnotation_Term
ASTRef = Nat // byte position in AST payload
Path = Constant
@@ -128,7 +129,7 @@ Standard-Section: "ASTs" Tree*
APPLIEDtype Length tycon_Type arg_Type*
TYPEBOUNDS Length low_Type high_Type
TYPEALIAS Length alias_Type
- ANNOTATED Length Annotation underlying_Type
+ ANNOTATED Length fullAnnotation_Term underlying_Type
ANDtype Length left_Type right_Type
ORtype Length left_Type right_Type
BIND Length boundName_NameRef underlying_Type selfRef_Type
@@ -288,40 +289,47 @@ object PickleFormat {
final val RETURN = 149
final val TRY = 150
final val THROW = 151
- final val SEQLITERAL = 152
- final val JSEQLITERAL = 153
- final val BIND = 154
- final val ALTERNATIVE = 155
- final val UNAPPLY = 156
- final val ANNOTATED = 157
- final val CASEDEF = 158
- final val IMPLICITarg = 159
- final val TEMPLATE = 160
+ final val REPEATED = 152
+ final val BIND = 153
+ final val ALTERNATIVE = 154
+ final val UNAPPLY = 155
+ final val ANNOTATED = 156
+ final val CASEDEF = 157
+ final val IMPLICITarg = 158
+ final val TEMPLATE = 159
+ final val SELFDEF = 160
final val THIS = 161
final val SUPER = 162
final val CLASSconst = 163
final val ENUMconst = 164
final val SUPERtype = 165
- final val REFINEDtype = 167
- final val APPLIEDtype = 168
- final val TYPEBOUNDS = 169
- final val TYPEALIAS = 170
- final val ANDtype = 171
- final val ORtype = 172
- final val BYNAMEtype = 173
- final val METHODtype = 174
- final val POLYtype = 175
- final val PARAMtype = 176
- final val IMPLICITARG = 177
- final val ANNOTATION = 178
- final val PRIVATEqualified = 179
- final val PROTECTEDqualified = 180
+ final val REFINEDtype = 166
+ final val APPLIEDtype = 167
+ final val TYPEBOUNDS = 168
+ final val TYPEALIAS = 169
+ final val ANDtype = 170
+ final val ORtype = 171
+ final val BYNAMEtype = 172
+ final val METHODtype = 173
+ final val POLYtype = 174
+ final val PARAMtype = 175
+ final val IMPLICITARG = 176
+ final val ANNOTATION = 177
+ final val PRIVATEqualified = 178
+ final val PROTECTEDqualified = 179
final val firstSimpleTreeTag = EMPTYTREE
final val firstNatTreeTag = SHARED
final val firstNatASTTreeTag = IDENT
final val firstLengthTreeTag = PACKAGE
+ def isDefTag(tag: Int) = tag match {
+ case VALDEF | DEFDEF | TYPEDEF | TYPEPARAM | PARAM | SELFDEF => true
+ case _ => false
+ }
+
+ def isParamTag(tag: Int) = tag == PARAM || tag == TYPEPARAM
+
def nameTagToString(tag: Int): String = tag match {
case UTF8 => "UTF8"
case QUALIFIED => "QUALIFIED"
@@ -414,8 +422,7 @@ object PickleFormat {
case RETURN => "RETURN"
case TRY => "TRY"
case THROW => "THROW"
- case SEQLITERAL => "SEQLITERAL"
- case JSEQLITERAL => "JSEQLITERAL"
+ case REPEATED => "REPEATED"
case BIND => "BIND"
case ALTERNATIVE => "ALTERNATIVE"
case UNAPPLY => "UNAPPLY"
@@ -423,6 +430,7 @@ object PickleFormat {
case CASEDEF => "CASEDEF"
case IMPLICITarg => "IMPLICITarg"
case TEMPLATE => "TEMPLATE"
+ case SELFDEF => "SELFDEF"
case THIS => "THIS"
case SUPER => "SUPER"
case CLASSconst => "CLASSconst"
diff --git a/src/dotty/tools/dotc/core/pickling/TastyPrinter.scala b/src/dotty/tools/dotc/core/pickling/TastyPrinter.scala
index d4b4330e8..8056e600d 100644
--- a/src/dotty/tools/dotc/core/pickling/TastyPrinter.scala
+++ b/src/dotty/tools/dotc/core/pickling/TastyPrinter.scala
@@ -62,7 +62,7 @@ class TastyPrinter(bytes: Array[Byte])(implicit ctx: Context) {
printName()
case RENAMED =>
printName(); printName()
- case VALDEF | DEFDEF | TYPEDEF | TYPEPARAM | PARAM | NAMEDARG | BIND | REFINEDtype =>
+ case VALDEF | DEFDEF | TYPEDEF | TYPEPARAM | PARAM | NAMEDARG | SELFDEF | BIND | REFINEDtype =>
printName(); printTrees()
case RETURN =>
printNat(); printTrees()
diff --git a/src/dotty/tools/dotc/core/pickling/TreePickler.scala b/src/dotty/tools/dotc/core/pickling/TreePickler.scala
index cc81ae7ae..32eb5f47f 100644
--- a/src/dotty/tools/dotc/core/pickling/TreePickler.scala
+++ b/src/dotty/tools/dotc/core/pickling/TreePickler.scala
@@ -190,7 +190,7 @@ class TreePickler(pickler: TastyPickler, picklePositions: Boolean) {
withLength { pickleType(tpe.lo, richTypes); pickleType(tpe.hi, richTypes) }
case tpe: AnnotatedType =>
writeByte(ANNOTATED)
- withLength { pickleAnnotation(tpe.annot); pickleType(tpe.tpe, richTypes) }
+ withLength { pickleTree(tpe.annot.tree); pickleType(tpe.tpe, richTypes) }
case tpe: AndOrType =>
writeByte(if (tpe.isAnd) ANDtype else ORtype)
withLength { pickleType(tpe.tp1, richTypes); pickleType(tpe.tp2, richTypes) }
@@ -313,7 +313,7 @@ class TreePickler(pickler: TastyPickler, picklePositions: Boolean) {
withLength { pickleTree(selector); cases.foreach(pickleTree) }
case CaseDef(pat, guard, rhs) =>
writeByte(CASEDEF)
- withLength { pickleTree(pat); pickleTree(guard); pickleTree(rhs) }
+ withLength { pickleTree(pat); pickleTree(rhs); pickleTreeIfNonEmpty(guard) }
case Return(expr, from) =>
writeByte(RETURN)
withLength { pickleSym(from.symbol); pickleTreeIfNonEmpty(expr) }
@@ -324,7 +324,7 @@ class TreePickler(pickler: TastyPickler, picklePositions: Boolean) {
writeByte(THROW)
withLength { pickleTree(expr) }
case SeqLiteral(elems) =>
- writeByte(if (tree.isInstanceOf[JavaSeqLiteral]) JSEQLITERAL else SEQLITERAL)
+ writeByte(REPEATED)
withLength { elems.foreach(pickleTree) }
case TypeTree(original) =>
pickleTpt(tree)
@@ -343,34 +343,37 @@ class TreePickler(pickler: TastyPickler, picklePositions: Boolean) {
writeByte(IMPLICITARG)
withLength { pickleTree(implicitArg) }
}
+ pickleType(tree.tpe)
patterns.foreach(pickleTree)
}
case tree: ValDef =>
pickleDef(VALDEF, tree.symbol, tree.tpt, tree.rhs)
case tree: DefDef =>
def pickleParams = {
- for (tparam <- tree.tparams)
- pickleDef(TYPEPARAM, tparam.symbol, tparam.rhs, EmptyTree)
+ tree.tparams.foreach(pickleParam)
for (vparams <- tree.vparamss) {
writeByte(PARAMS)
- withLength {
- for (vparam <- vparams)
- pickleDef(PARAM, vparam.symbol, vparam.tpt, EmptyTree)
- }
+ withLength { vparams.foreach(pickleParam) }
}
}
pickleDef(DEFDEF, tree.symbol, tree.tpt, tree.rhs, pickleParams)
case tree: TypeDef =>
- pickleDef(TYPEDEF, tree.symbol, tree.rhs, EmptyTree)
+ pickleDef(TYPEDEF, tree.symbol, tree.rhs)
case tree: Template =>
registerDef(tree.symbol)
writeByte(TEMPLATE)
+ val (params, rest) = tree.body span {
+ case stat: TypeDef => stat.mods is Flags.Param
+ case stat: ValDef => stat.mods is Flags.ParamAccessor
+ case _ => false
+ }
withLength {
+ params.foreach(pickleParam)
tree.parents.foreach(pickleTree)
if (!tree.self.isEmpty)
- pickleDef(PARAM, tree.self.symbol, tree.self.tpt, EmptyTree)
+ pickleDef(SELFDEF, tree.self.symbol, tree.self.tpt)
pickleTree(tree.constr)
- tree.body.foreach(pickleTree)
+ rest.foreach(pickleTree)
}
case Import(expr, selectors) =>
writeByte(IMPORT)
@@ -398,7 +401,7 @@ class TreePickler(pickler: TastyPickler, picklePositions: Boolean) {
}
- def pickleDef(tag: Int, sym: Symbol, tpt: Tree, rhs: Tree, pickleParams: => Unit = ()) = {
+ def pickleDef(tag: Int, sym: Symbol, tpt: Tree, rhs: Tree = EmptyTree, pickleParams: => Unit = ()) = {
registerDef(sym)
writeByte(tag)
withLength {
@@ -412,6 +415,11 @@ class TreePickler(pickler: TastyPickler, picklePositions: Boolean) {
pickleModifiers(sym)
}
}
+
+ def pickleParam(tree: Tree): Unit = tree match {
+ case tree: ValDef => pickleDef(PARAM, tree.symbol, tree.tpt)
+ case tree: TypeDef => pickleDef(TYPEPARAM, tree.symbol, tree.rhs)
+ }
def pickleModifiers(sym: Symbol): Unit = {
import Flags._