aboutsummaryrefslogtreecommitdiff
path: root/src/dotty/tools/dotc
diff options
context:
space:
mode:
authorDmitry Petrashko <dark@d-d.me>2016-01-04 11:41:39 +0100
committerDmitry Petrashko <dark@d-d.me>2016-01-04 11:41:39 +0100
commit013c82356d2bf000edaed164ae8f369e43d0072c (patch)
tree7172aa58ec832838bcecce915e73b86fd9287222 /src/dotty/tools/dotc
parent4bca33233bb11e9a8ef8461b66707c37e8a09184 (diff)
parentef73669cef8f34257176c4720c0b5c0e63d98c3e (diff)
downloaddotty-013c82356d2bf000edaed164ae8f369e43d0072c.tar.gz
dotty-013c82356d2bf000edaed164ae8f369e43d0072c.tar.bz2
dotty-013c82356d2bf000edaed164ae8f369e43d0072c.zip
Merge pull request #1003 from dotty-staging/linker/tasty
Fixes&Changes to TASTY inspired by Linker
Diffstat (limited to 'src/dotty/tools/dotc')
-rw-r--r--src/dotty/tools/dotc/CompilationUnit.scala4
-rw-r--r--src/dotty/tools/dotc/FromTasty.scala1
-rw-r--r--src/dotty/tools/dotc/core/SymDenotations.scala2
-rw-r--r--src/dotty/tools/dotc/core/Types.scala8
-rw-r--r--src/dotty/tools/dotc/core/tasty/DottyUnpickler.scala33
-rw-r--r--src/dotty/tools/dotc/core/tasty/TastyPickler.scala5
-rw-r--r--src/dotty/tools/dotc/core/tasty/TastyReader.scala2
-rw-r--r--src/dotty/tools/dotc/core/tasty/TreePickler.scala550
-rw-r--r--src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala28
-rw-r--r--src/dotty/tools/dotc/transform/Pickler.scala2
10 files changed, 339 insertions, 296 deletions
diff --git a/src/dotty/tools/dotc/CompilationUnit.scala b/src/dotty/tools/dotc/CompilationUnit.scala
index 6f05b831f..16a59250b 100644
--- a/src/dotty/tools/dotc/CompilationUnit.scala
+++ b/src/dotty/tools/dotc/CompilationUnit.scala
@@ -2,7 +2,7 @@ package dotty.tools
package dotc
import dotty.tools.dotc.core.Types.Type
-import dotty.tools.dotc.core.tasty.{TastyBuffer, TastyPickler}
+import dotty.tools.dotc.core.tasty.{TastyUnpickler, TastyBuffer, TastyPickler}
import util.SourceFile
import ast.{tpd, untpd}
import dotty.tools.dotc.core.Symbols._
@@ -23,4 +23,6 @@ class CompilationUnit(val source: SourceFile) {
* Subsequent phases can add new sections.
*/
var picklers: Map[ClassSymbol, TastyPickler] = Map()
+
+ var unpicklers: Map[ClassSymbol, TastyUnpickler] = Map()
}
diff --git a/src/dotty/tools/dotc/FromTasty.scala b/src/dotty/tools/dotc/FromTasty.scala
index 705deedd3..d8d8b8b1e 100644
--- a/src/dotty/tools/dotc/FromTasty.scala
+++ b/src/dotty/tools/dotc/FromTasty.scala
@@ -86,6 +86,7 @@ object FromTasty extends Driver {
val (List(unpickled), source) = unpickler.body(readPositions = true)
val unit1 = new CompilationUnit(source)
unit1.tpdTree = unpickled
+ unit1.unpicklers += (clsd.classSymbol -> unpickler.unpickler)
force.traverse(unit1.tpdTree)
unit1
case _ =>
diff --git a/src/dotty/tools/dotc/core/SymDenotations.scala b/src/dotty/tools/dotc/core/SymDenotations.scala
index e351557a3..8016c57f3 100644
--- a/src/dotty/tools/dotc/core/SymDenotations.scala
+++ b/src/dotty/tools/dotc/core/SymDenotations.scala
@@ -69,7 +69,7 @@ object SymDenotations {
ownerIfExists: Symbol,
final val name: Name,
initFlags: FlagSet,
- initInfo: Type,
+ final val initInfo: Type,
initPrivateWithin: Symbol = NoSymbol) extends SingleDenotation(symbol) {
//assert(symbol.id != 4940, name)
diff --git a/src/dotty/tools/dotc/core/Types.scala b/src/dotty/tools/dotc/core/Types.scala
index b72185492..1086fcdd6 100644
--- a/src/dotty/tools/dotc/core/Types.scala
+++ b/src/dotty/tools/dotc/core/Types.scala
@@ -1011,6 +1011,14 @@ object Types {
case _ => Nil
}
+ /** The parameter names of a PolyType or MethodType, Empty list for others */
+ final def paramNamess(implicit ctx: Context): List[List[TermName]] = this match {
+ case mt: MethodType => mt.paramNames :: mt.resultType.paramNamess
+ case pt: PolyType => pt.resultType.paramNamess
+ case _ => Nil
+ }
+
+
/** The parameter types in the first parameter section of a PolyType or MethodType, Empty list for others */
final def firstParamTypes(implicit ctx: Context): List[Type] = this match {
case mt: MethodType => mt.paramTypes
diff --git a/src/dotty/tools/dotc/core/tasty/DottyUnpickler.scala b/src/dotty/tools/dotc/core/tasty/DottyUnpickler.scala
index ccd3f78e8..d62762571 100644
--- a/src/dotty/tools/dotc/core/tasty/DottyUnpickler.scala
+++ b/src/dotty/tools/dotc/core/tasty/DottyUnpickler.scala
@@ -6,6 +6,7 @@ package tasty
import Contexts._, SymDenotations._
import dotty.tools.dotc.ast.tpd
import TastyUnpickler._, TastyBuffer._
+import dotty.tools.dotc.core.tasty.DottyUnpickler.{SourceFileUnpickler, TreeSectionUnpickler, PositionsSectionUnpickler}
import util.Positions._
import util.{SourceFile, NoSource}
import PositionUnpickler._
@@ -15,6 +16,21 @@ object DottyUnpickler {
/** Exception thrown if classfile is corrupted */
class BadSignature(msg: String) extends RuntimeException(msg)
+
+ class SourceFileUnpickler extends SectionUnpickler[SourceFile]("Sourcefile") {
+ def unpickle(reader: TastyReader, tastyName: TastyName.Table) =
+ new SourceFile(tastyName(reader.readNameRef()).toString, Seq())
+ }
+
+ class TreeSectionUnpickler extends SectionUnpickler[TreeUnpickler]("ASTs") {
+ def unpickle(reader: TastyReader, tastyName: TastyName.Table) =
+ new TreeUnpickler(reader, tastyName)
+ }
+
+ class PositionsSectionUnpickler extends SectionUnpickler[(Position, AddrToPosition)]("Positions") {
+ def unpickle(reader: TastyReader, tastyName: TastyName.Table) =
+ new PositionUnpickler(reader).unpickle()
+ }
}
/** A class for unpickling Tasty trees and symbols.
@@ -23,7 +39,7 @@ object DottyUnpickler {
class DottyUnpickler(bytes: Array[Byte]) extends ClassfileParser.Embedded {
import tpd._
- private val unpickler = new TastyUnpickler(bytes)
+ val unpickler = new TastyUnpickler(bytes)
private val treeUnpickler = unpickler.unpickle(new TreeSectionUnpickler).get
/** Enter all toplevel classes and objects into their scopes
@@ -42,19 +58,4 @@ class DottyUnpickler(bytes: Array[Byte]) extends ClassfileParser.Embedded {
treeUnpickler.usePositions(totalRange, positions)
(treeUnpickler.unpickle(), source)
}
-
- private class SourceFileUnpickler extends SectionUnpickler[SourceFile]("Sourcefile") {
- def unpickle(reader: TastyReader, tastyName: TastyName.Table) =
- new SourceFile(tastyName(reader.readNameRef()).toString, Seq())
- }
-
- private class TreeSectionUnpickler extends SectionUnpickler[TreeUnpickler]("ASTs") {
- def unpickle(reader: TastyReader, tastyName: TastyName.Table) =
- new TreeUnpickler(reader, tastyName)
- }
-
- private class PositionsSectionUnpickler extends SectionUnpickler[(Position, AddrToPosition)]("Positions") {
- def unpickle(reader: TastyReader, tastyName: TastyName.Table) =
- new PositionUnpickler(reader).unpickle()
- }
}
diff --git a/src/dotty/tools/dotc/core/tasty/TastyPickler.scala b/src/dotty/tools/dotc/core/tasty/TastyPickler.scala
index f53a97c0c..83e6020d5 100644
--- a/src/dotty/tools/dotc/core/tasty/TastyPickler.scala
+++ b/src/dotty/tools/dotc/core/tasty/TastyPickler.scala
@@ -13,13 +13,13 @@ import ast.tpd
class TastyPickler {
private val sections = new mutable.ArrayBuffer[(TastyName.NameRef, TastyBuffer)]
+ val uuid = UUID.randomUUID()
private val headerBuffer = {
val buf = new TastyBuffer(24)
for (ch <- header) buf.writeByte(ch.toByte)
buf.writeNat(MajorVersion)
buf.writeNat(MinorVersion)
- val uuid = UUID.randomUUID()
buf.writeUncompressedLong(uuid.getMostSignificantBits)
buf.writeUncompressedLong(uuid.getLeastSignificantBits)
buf
@@ -31,6 +31,7 @@ class TastyPickler {
sections += ((nameBuffer.nameIndex(name), buf))
def assembleParts(): Array[Byte] = {
+ treePkl.compactify()
def lengthWithLength(buf: TastyBuffer) = {
buf.assemble()
buf.length + natSize(buf.length)
@@ -67,4 +68,6 @@ class TastyPickler {
* so one can reliably use this function only dirrectly after `pickler`
*/
var addrOfSym: Symbol => Option[Addr] = (_ => None)
+
+ val treePkl = new TreePickler(this)
}
diff --git a/src/dotty/tools/dotc/core/tasty/TastyReader.scala b/src/dotty/tools/dotc/core/tasty/TastyReader.scala
index c6a222d2b..e583c4793 100644
--- a/src/dotty/tools/dotc/core/tasty/TastyReader.scala
+++ b/src/dotty/tools/dotc/core/tasty/TastyReader.scala
@@ -99,7 +99,7 @@ class TastyReader(val bytes: Array[Byte], start: Int, end: Int, val base: Int =
/** Read an uncompressed Long stored in 8 bytes in big endian format */
def readUncompressedLong(): Long = {
- var x = 0
+ var x: Long = 0
for (i <- 0 to 7)
x = (x << 8) | (readByte() & 0xff)
x
diff --git a/src/dotty/tools/dotc/core/tasty/TreePickler.scala b/src/dotty/tools/dotc/core/tasty/TreePickler.scala
index d11d6f4b7..bb6c3cd2e 100644
--- a/src/dotty/tools/dotc/core/tasty/TreePickler.scala
+++ b/src/dotty/tools/dotc/core/tasty/TreePickler.scala
@@ -80,225 +80,251 @@ class TreePickler(pickler: TastyPickler) {
case None => false
}
- def pickle(trees: List[Tree])(implicit ctx: Context) = {
+ def pickleConstant(c: Constant)(implicit ctx: Context): Unit = c.tag match {
+ case UnitTag =>
+ writeByte(UNITconst)
+ case BooleanTag =>
+ writeByte(if (c.booleanValue) TRUEconst else FALSEconst)
+ case ByteTag =>
+ writeByte(BYTEconst)
+ writeInt(c.byteValue)
+ case ShortTag =>
+ writeByte(SHORTconst)
+ writeInt(c.shortValue)
+ case CharTag =>
+ writeByte(CHARconst)
+ writeNat(c.charValue)
+ case IntTag =>
+ writeByte(INTconst)
+ writeInt(c.intValue)
+ case LongTag =>
+ writeByte(LONGconst)
+ writeLongInt(c.longValue)
+ case FloatTag =>
+ writeByte(FLOATconst)
+ writeInt(java.lang.Float.floatToRawIntBits(c.floatValue))
+ case DoubleTag =>
+ writeByte(DOUBLEconst)
+ writeLongInt(java.lang.Double.doubleToRawLongBits(c.doubleValue))
+ case StringTag =>
+ writeByte(STRINGconst)
+ writeNat(nameIndex(c.stringValue).index)
+ case NullTag =>
+ writeByte(NULLconst)
+ case ClazzTag =>
+ writeByte(CLASSconst)
+ pickleType(c.typeValue)
+ case EnumTag =>
+ writeByte(ENUMconst)
+ pickleType(c.symbolValue.termRef)
+ }
- def qualifiedName(sym: Symbol): TastyName =
- if (sym.isRoot || sym.owner.isRoot) TastyName.Simple(sym.name.toTermName)
- else TastyName.Qualified(nameIndex(qualifiedName(sym.owner)), nameIndex(sym.name))
-
- def pickleConstant(c: Constant): Unit = c.tag match {
- case UnitTag =>
- writeByte(UNITconst)
- case BooleanTag =>
- writeByte(if (c.booleanValue) TRUEconst else FALSEconst)
- case ByteTag =>
- writeByte(BYTEconst)
- writeInt(c.byteValue)
- case ShortTag =>
- writeByte(SHORTconst)
- writeInt(c.shortValue)
- case CharTag =>
- writeByte(CHARconst)
- writeNat(c.charValue)
- case IntTag =>
- writeByte(INTconst)
- writeInt(c.intValue)
- case LongTag =>
- writeByte(LONGconst)
- writeLongInt(c.longValue)
- case FloatTag =>
- writeByte(FLOATconst)
- writeInt(java.lang.Float.floatToRawIntBits(c.floatValue))
- case DoubleTag =>
- writeByte(DOUBLEconst)
- writeLongInt(java.lang.Double.doubleToRawLongBits(c.doubleValue))
- case StringTag =>
- writeByte(STRINGconst)
- writeNat(nameIndex(c.stringValue).index)
- case NullTag =>
- writeByte(NULLconst)
- case ClazzTag =>
- writeByte(CLASSconst)
- pickleType(c.typeValue)
- case EnumTag =>
- writeByte(ENUMconst)
- pickleType(c.symbolValue.termRef)
+ def pickleType(tpe0: Type, richTypes: Boolean = false)(implicit ctx: Context): Unit = try {
+ val tpe = tpe0.stripTypeVar
+ val prev = pickledTypes.get(tpe)
+ if (prev == null) {
+ pickledTypes.put(tpe, currentAddr)
+ pickleNewType(tpe, richTypes)
}
-
- def pickleType(tpe0: Type, richTypes: Boolean = false): Unit = try {
- val tpe = tpe0.stripTypeVar
- val prev = pickledTypes.get(tpe)
- if (prev == null) {
- pickledTypes.put(tpe, currentAddr)
- pickleNewType(tpe, richTypes)
- }
- else {
- writeByte(SHARED)
- writeRef(prev.asInstanceOf[Addr])
- }
- } catch {
- case ex: AssertionError =>
- println(i"error when pickling type $tpe0")
- throw ex
+ else {
+ writeByte(SHARED)
+ writeRef(prev.asInstanceOf[Addr])
}
+ } catch {
+ case ex: AssertionError =>
+ println(i"error when pickling type $tpe0")
+ throw ex
+ }
- def pickleNewType(tpe: Type, richTypes: Boolean): Unit = try { tpe match {
- case AppliedType(tycon, args) =>
- writeByte(APPLIEDtype)
- withLength { pickleType(tycon); args.foreach(pickleType(_)) }
- case ConstantType(value) =>
- pickleConstant(value)
- case tpe: TypeRef if tpe.info.isAlias && tpe.symbol.is(Flags.AliasPreferred) =>
- pickleType(tpe.info.bounds.hi)
- case tpe: WithFixedSym =>
- val sym = tpe.symbol
- def pickleRef() =
- if (tpe.prefix == NoPrefix) {
- writeByte(if (tpe.isType) TYPEREFdirect else TERMREFdirect)
- pickleSymRef(sym)
- }
- else {
- assert(tpe.symbol.isClass)
- assert(tpe.symbol.is(Flags.Scala2x), tpe.symbol.showLocated)
- writeByte(TYPEREF) // should be changed to a new entry that keeps track of prefix, symbol & owner
- pickleName(tpe.name)
- pickleType(tpe.prefix)
- }
- if (sym.is(Flags.Package)) {
- writeByte(if (tpe.isType) TYPEREFpkg else TERMREFpkg)
- pickleName(qualifiedName(sym))
+ private def pickleNewType(tpe: Type, richTypes: Boolean)(implicit ctx: Context): Unit = try { tpe match {
+ case AppliedType(tycon, args) =>
+ writeByte(APPLIEDtype)
+ withLength { pickleType(tycon); args.foreach(pickleType(_)) }
+ case ConstantType(value) =>
+ pickleConstant(value)
+ case tpe: TypeRef if tpe.info.isAlias && tpe.symbol.is(Flags.AliasPreferred) =>
+ pickleType(tpe.info.bounds.hi)
+ case tpe: WithFixedSym =>
+ val sym = tpe.symbol
+ def pickleRef() =
+ if (tpe.prefix == NoPrefix) {
+ writeByte(if (tpe.isType) TYPEREFdirect else TERMREFdirect)
+ pickleSymRef(sym)
}
- else if (sym is Flags.BindDefinedType) {
- registerDef(sym)
- writeByte(BIND)
- withLength {
- pickleName(sym.name)
- pickleType(sym.info)
- pickleRef()
- }
- }
- else pickleRef()
- case tpe: TermRefWithSignature =>
- if (tpe.symbol.is(Flags.Package)) picklePackageRef(tpe.symbol)
- else {
- writeByte(TERMREF)
- pickleNameAndSig(tpe.name, tpe.signature); pickleType(tpe.prefix)
- }
- case tpe: NamedType =>
- if (isLocallyDefined(tpe.symbol)) {
- writeByte(if (tpe.isType) TYPEREFsymbol else TERMREFsymbol)
- pickleSymRef(tpe.symbol); pickleType(tpe.prefix)
- } else {
- writeByte(if (tpe.isType) TYPEREF else TERMREF)
- pickleName(tpe.name); pickleType(tpe.prefix)
- }
- case tpe: ThisType =>
- if (tpe.cls.is(Flags.Package) && !tpe.cls.isEffectiveRoot)
- picklePackageRef(tpe.cls)
else {
- writeByte(THIS)
- pickleType(tpe.tref)
+ assert(tpe.symbol.isClass)
+ assert(tpe.symbol.is(Flags.Scala2x), tpe.symbol.showLocated)
+ writeByte(TYPEREF) // should be changed to a new entry that keeps track of prefix, symbol & owner
+ pickleName(tpe.name)
+ pickleType(tpe.prefix)
}
- case tpe: SuperType =>
- writeByte(SUPERtype)
- withLength { pickleType(tpe.thistpe); pickleType(tpe.supertpe)}
- case tpe: RefinedThis =>
- writeByte(REFINEDthis)
- val binderAddr = pickledTypes.get(tpe.binder)
- assert(binderAddr != null, tpe.binder)
- writeRef(binderAddr.asInstanceOf[Addr])
- case tpe: SkolemType =>
- pickleType(tpe.info)
- case tpe: RefinedType =>
- writeByte(REFINEDtype)
+ if (sym.is(Flags.Package)) {
+ writeByte(if (tpe.isType) TYPEREFpkg else TERMREFpkg)
+ pickleName(qualifiedName(sym))
+ }
+ else if (sym is Flags.BindDefinedType) {
+ registerDef(sym)
+ writeByte(BIND)
withLength {
- pickleType(tpe.parent)
- pickleName(tpe.refinedName)
- pickleType(tpe.refinedInfo, richTypes = true)
+ pickleName(sym.name)
+ pickleType(sym.info)
+ pickleRef()
}
- case tpe: TypeAlias =>
- writeByte(TYPEALIAS)
- withLength {
- pickleType(tpe.alias, richTypes)
- tpe.variance match {
- case 1 => writeByte(COVARIANT)
- case -1 => writeByte(CONTRAVARIANT)
- case 0 =>
- }
+ }
+ else pickleRef()
+ case tpe: TermRefWithSignature =>
+ if (tpe.symbol.is(Flags.Package)) picklePackageRef(tpe.symbol)
+ else {
+ writeByte(TERMREF)
+ pickleNameAndSig(tpe.name, tpe.signature); pickleType(tpe.prefix)
+ }
+ case tpe: NamedType =>
+ if (isLocallyDefined(tpe.symbol)) {
+ writeByte(if (tpe.isType) TYPEREFsymbol else TERMREFsymbol)
+ pickleSymRef(tpe.symbol); pickleType(tpe.prefix)
+ } else {
+ writeByte(if (tpe.isType) TYPEREF else TERMREF)
+ pickleName(tpe.name); pickleType(tpe.prefix)
+ }
+ case tpe: ThisType =>
+ if (tpe.cls.is(Flags.Package) && !tpe.cls.isEffectiveRoot)
+ picklePackageRef(tpe.cls)
+ else {
+ writeByte(THIS)
+ pickleType(tpe.tref)
+ }
+ case tpe: SuperType =>
+ writeByte(SUPERtype)
+ withLength { pickleType(tpe.thistpe); pickleType(tpe.supertpe)}
+ case tpe: RefinedThis =>
+ writeByte(REFINEDthis)
+ val binderAddr = pickledTypes.get(tpe.binder)
+ assert(binderAddr != null, tpe.binder)
+ writeRef(binderAddr.asInstanceOf[Addr])
+ case tpe: SkolemType =>
+ pickleType(tpe.info)
+ case tpe: RefinedType =>
+ writeByte(REFINEDtype)
+ withLength {
+ pickleType(tpe.parent)
+ pickleName(tpe.refinedName)
+ pickleType(tpe.refinedInfo, richTypes = true)
+ }
+ case tpe: TypeAlias =>
+ writeByte(TYPEALIAS)
+ withLength {
+ pickleType(tpe.alias, richTypes)
+ tpe.variance match {
+ case 1 => writeByte(COVARIANT)
+ case -1 => writeByte(CONTRAVARIANT)
+ case 0 =>
}
- case tpe: TypeBounds =>
- writeByte(TYPEBOUNDS)
- withLength { pickleType(tpe.lo, richTypes); pickleType(tpe.hi, richTypes) }
- case tpe: AnnotatedType =>
- writeByte(ANNOTATED)
- withLength { pickleType(tpe.tpe, richTypes); pickleTree(tpe.annot.tree) }
- case tpe: AndOrType =>
- writeByte(if (tpe.isAnd) ANDtype else ORtype)
- withLength { pickleType(tpe.tp1, richTypes); pickleType(tpe.tp2, richTypes) }
- case tpe: ExprType =>
- writeByte(BYNAMEtype)
- pickleType(tpe.underlying)
- case tpe: MethodType if richTypes =>
- writeByte(METHODtype)
- pickleMethodic(tpe.resultType, tpe.paramNames, tpe.paramTypes)
- case tpe: PolyType if richTypes =>
- writeByte(POLYtype)
- pickleMethodic(tpe.resultType, tpe.paramNames, tpe.paramBounds)
- case tpe: PolyParam =>
- if (!pickleParamType(tpe))
- // TODO figure out why this case arises in e.g. pickling AbstractFileReader.
- ctx.typerState.constraint.entry(tpe) match {
- case TypeBounds(lo, hi) if lo eq hi => pickleNewType(lo, richTypes)
- case _ => assert(false, s"orphan poly parameter: $tpe")
- }
- case tpe: MethodParam =>
- assert(pickleParamType(tpe), s"orphan method parameter: $tpe")
- case tpe: LazyRef =>
- pickleType(tpe.ref)
- }} catch {
- case ex: AssertionError =>
- println(i"error while pickling type $tpe")
- throw ex
+ }
+ case tpe: TypeBounds =>
+ writeByte(TYPEBOUNDS)
+ withLength { pickleType(tpe.lo, richTypes); pickleType(tpe.hi, richTypes) }
+ case tpe: AnnotatedType =>
+ writeByte(ANNOTATED)
+ withLength { pickleType(tpe.tpe, richTypes); pickleTree(tpe.annot.tree) }
+ case tpe: AndOrType =>
+ writeByte(if (tpe.isAnd) ANDtype else ORtype)
+ withLength { pickleType(tpe.tp1, richTypes); pickleType(tpe.tp2, richTypes) }
+ case tpe: ExprType =>
+ writeByte(BYNAMEtype)
+ pickleType(tpe.underlying)
+ case tpe: MethodType if richTypes =>
+ writeByte(METHODtype)
+ pickleMethodic(tpe.resultType, tpe.paramNames, tpe.paramTypes)
+ case tpe: PolyType if richTypes =>
+ writeByte(POLYtype)
+ pickleMethodic(tpe.resultType, tpe.paramNames, tpe.paramBounds)
+ case tpe: PolyParam =>
+ if (!pickleParamType(tpe))
+ // TODO figure out why this case arises in e.g. pickling AbstractFileReader.
+ ctx.typerState.constraint.entry(tpe) match {
+ case TypeBounds(lo, hi) if lo eq hi => pickleNewType(lo, richTypes)
+ case _ => assert(false, s"orphan poly parameter: $tpe")
+ }
+ case tpe: MethodParam =>
+ assert(pickleParamType(tpe), s"orphan method parameter: $tpe")
+ case tpe: LazyRef =>
+ pickleType(tpe.ref)
+ }} catch {
+ case ex: AssertionError =>
+ println(i"error while pickling type $tpe")
+ throw ex
+ }
+
+ def picklePackageRef(pkg: Symbol)(implicit ctx: Context): Unit = {
+ writeByte(TERMREFpkg)
+ pickleName(qualifiedName(pkg))
+ }
+
+ def pickleMethodic(result: Type, names: List[Name], types: List[Type])(implicit ctx: Context) =
+ withLength {
+ pickleType(result, richTypes = true)
+ (names, types).zipped.foreach { (name, tpe) =>
+ pickleName(name); pickleType(tpe)
+ }
}
- def picklePackageRef(pkg: Symbol): Unit = {
- writeByte(TERMREFpkg)
- pickleName(qualifiedName(pkg))
+ def pickleParamType(tpe: ParamType)(implicit ctx: Context): Boolean = {
+ val binder = pickledTypes.get(tpe.binder)
+ val pickled = binder != null
+ if (pickled) {
+ writeByte(PARAMtype)
+ withLength { writeRef(binder.asInstanceOf[Addr]); writeNat(tpe.paramNum) }
}
+ pickled
+ }
- def pickleMethodic(result: Type, names: List[Name], types: List[Type]) =
- withLength {
- pickleType(result, richTypes = true)
- (names, types).zipped.foreach { (name, tpe) =>
- pickleName(name); pickleType(tpe)
- }
- }
+ def pickleTpt(tpt: Tree)(implicit ctx: Context): Unit = pickleType(tpt.tpe) // TODO correlate with original when generating positions
+
+ def pickleTreeUnlessEmpty(tree: Tree)(implicit ctx: Context): Unit =
+ if (!tree.isEmpty) pickleTree(tree)
- def pickleParamType(tpe: ParamType): Boolean = {
- val binder = pickledTypes.get(tpe.binder)
- val pickled = binder != null
- if (pickled) {
- writeByte(PARAMtype)
- withLength { writeRef(binder.asInstanceOf[Addr]); writeNat(tpe.paramNum) }
+ def pickleDef(tag: Int, sym: Symbol, tpt: Tree, rhs: Tree = EmptyTree, pickleParams: => Unit = ())(implicit ctx: Context) = {
+ assert(symRefs(sym) == NoAddr)
+ registerDef(sym)
+ writeByte(tag)
+ withLength {
+ pickleName(sym)
+ pickleParams
+ tpt match {
+ case tpt: TypeTree => pickleTpt(tpt)
+ case _ => pickleTree(tpt)
}
- pickled
+ pickleTreeUnlessEmpty(rhs)
+ pickleModifiers(sym)
}
+ }
- def pickleTpt(tpt: Tree): Unit = pickleType(tpt.tpe) // TODO correlate with original when generating positions
+ def pickleParam(tree: Tree)(implicit ctx: Context): Unit = tree match {
+ case tree: ValDef => pickleDef(PARAM, tree.symbol, tree.tpt)
+ case tree: DefDef => pickleDef(PARAM, tree.symbol, tree.tpt, tree.rhs)
+ case tree: TypeDef => pickleDef(TYPEPARAM, tree.symbol, tree.rhs)
+ }
- def pickleTreeUnlessEmpty(tree: Tree): Unit =
- if (!tree.isEmpty) pickleTree(tree)
+ def pickleParams(trees: List[Tree])(implicit ctx: Context): Unit = {
+ trees.foreach(preRegister)
+ trees.foreach(pickleParam)
+ }
+
+ def pickleStats(stats: List[Tree])(implicit ctx: Context) = {
+ stats.foreach(preRegister)
+ stats.foreach(stat => if (!stat.isEmpty) pickleTree(stat))
+ }
- def pickleTree(tree: Tree): Unit = try {
- pickledTrees.put(tree, currentAddr)
- tree match {
+ def pickleTree(tree: Tree)(implicit ctx: Context): Unit = try {
+ pickledTrees.put(tree, currentAddr)
+ tree match {
case Ident(name) =>
tree.tpe match {
case tp: TermRef => pickleType(tp)
case _ =>
- writeByte(IDENT)
- pickleName(name)
- pickleType(tree.tpe)
+ writeByte(IDENT)
+ pickleName(name)
+ pickleType(tree.tpe)
}
case This(_) =>
pickleType(tree.tpe)
@@ -459,95 +485,73 @@ class TreePickler(pickler: TastyPickler) {
writeByte(PACKAGE)
withLength { pickleType(pid.tpe); pickleStats(stats) }
}}
- catch {
- case ex: AssertionError =>
- println(i"error when pickling tree $tree")
- throw ex
- }
+ catch {
+ case ex: AssertionError =>
+ println(i"error when pickling tree $tree")
+ throw ex
+ }
- def pickleDef(tag: Int, sym: Symbol, tpt: Tree, rhs: Tree = EmptyTree, pickleParams: => Unit = ()) = {
- assert(symRefs(sym) == NoAddr)
- registerDef(sym)
- writeByte(tag)
- withLength {
- pickleName(sym)
- pickleParams
- tpt match {
- case tpt: TypeTree => pickleTpt(tpt)
- case _ => pickleTree(tpt)
- }
- pickleTreeUnlessEmpty(rhs)
- pickleModifiers(sym)
- }
- }
+ def qualifiedName(sym: Symbol)(implicit ctx: Context): TastyName =
+ if (sym.isRoot || sym.owner.isRoot) TastyName.Simple(sym.name.toTermName)
+ else TastyName.Qualified(nameIndex(qualifiedName(sym.owner)), nameIndex(sym.name))
- def pickleParam(tree: Tree): Unit = tree match {
- case tree: ValDef => pickleDef(PARAM, tree.symbol, tree.tpt)
- case tree: DefDef => pickleDef(PARAM, tree.symbol, tree.tpt, tree.rhs)
- case tree: TypeDef => pickleDef(TYPEPARAM, tree.symbol, tree.rhs)
+ def pickleModifiers(sym: Symbol)(implicit ctx: Context): Unit = {
+ import Flags._
+ val flags = sym.flags
+ val privateWithin = sym.privateWithin
+ if (privateWithin.exists) {
+ writeByte(if (flags is Protected) PROTECTEDqualified else PRIVATEqualified)
+ pickleType(privateWithin.typeRef)
}
-
- def pickleParams(trees: List[Tree]): Unit = {
- trees.foreach(preRegister)
- trees.foreach(pickleParam)
+ if (flags is Private) writeByte(PRIVATE)
+ if (flags is Protected) if (!privateWithin.exists) writeByte(PROTECTED)
+ if ((flags is Final) && !(sym is Module)) writeByte(FINAL)
+ if (flags is Case) writeByte(CASE)
+ if (flags is Override) writeByte(OVERRIDE)
+ if (flags is Inline) writeByte(INLINE)
+ if (flags is JavaStatic) writeByte(STATIC)
+ if (flags is Module) writeByte(OBJECT)
+ if (flags is Local) writeByte(LOCAL)
+ if (flags is Synthetic) writeByte(SYNTHETIC)
+ if (flags is Artifact) writeByte(ARTIFACT)
+ if (flags is Scala2x) writeByte(SCALA2X)
+ if (flags is InSuperCall) writeByte(INSUPERCALL)
+ if (sym.isTerm) {
+ if (flags is Implicit) writeByte(IMPLICIT)
+ if ((flags is Lazy) && !(sym is Module)) writeByte(LAZY)
+ if (flags is AbsOverride) { writeByte(ABSTRACT); writeByte(OVERRIDE) }
+ if (flags is Mutable) writeByte(MUTABLE)
+ if (flags is Accessor) writeByte(FIELDaccessor)
+ if (flags is CaseAccessor) writeByte(CASEaccessor)
+ if (flags is DefaultParameterized) writeByte(DEFAULTparameterized)
+ if (flags is Stable) writeByte(STABLE)
+ } else {
+ if (flags is Sealed) writeByte(SEALED)
+ if (flags is Abstract) writeByte(ABSTRACT)
+ if (flags is Trait) writeByte(TRAIT)
+ if (flags is Covariant) writeByte(COVARIANT)
+ if (flags is Contravariant) writeByte(CONTRAVARIANT)
}
+ sym.annotations.foreach(pickleAnnotation)
+ }
- def pickleStats(stats: List[Tree]) = {
- stats.foreach(preRegister)
- stats.foreach(stat => if (!stat.isEmpty) pickleTree(stat))
- }
+ def pickleAnnotation(ann: Annotation)(implicit ctx: Context) = {
+ writeByte(ANNOTATION)
+ withLength { pickleType(ann.symbol.typeRef); pickleTree(ann.tree) }
+ }
- def pickleModifiers(sym: Symbol): Unit = {
- import Flags._
- val flags = sym.flags
- val privateWithin = sym.privateWithin
- if (privateWithin.exists) {
- writeByte(if (flags is Protected) PROTECTEDqualified else PRIVATEqualified)
- pickleType(privateWithin.typeRef)
- }
- if (flags is Private) writeByte(PRIVATE)
- if (flags is Protected) if (!privateWithin.exists) writeByte(PROTECTED)
- if ((flags is Final) && !(sym is Module)) writeByte(FINAL)
- if (flags is Case) writeByte(CASE)
- if (flags is Override) writeByte(OVERRIDE)
- if (flags is Inline) writeByte(INLINE)
- if (flags is JavaStatic) writeByte(STATIC)
- if (flags is Module) writeByte(OBJECT)
- if (flags is Local) writeByte(LOCAL)
- if (flags is Synthetic) writeByte(SYNTHETIC)
- if (flags is Artifact) writeByte(ARTIFACT)
- if (flags is Scala2x) writeByte(SCALA2X)
- if (flags is InSuperCall) writeByte(INSUPERCALL)
- if (sym.isTerm) {
- if (flags is Implicit) writeByte(IMPLICIT)
- if ((flags is Lazy) && !(sym is Module)) writeByte(LAZY)
- if (flags is AbsOverride) { writeByte(ABSTRACT); writeByte(OVERRIDE) }
- if (flags is Mutable) writeByte(MUTABLE)
- if (flags is Accessor) writeByte(FIELDaccessor)
- if (flags is CaseAccessor) writeByte(CASEaccessor)
- if (flags is DefaultParameterized) writeByte(DEFAULTparameterized)
- if (flags is Stable) writeByte(STABLE)
- } else {
- if (flags is Sealed) writeByte(SEALED)
- if (flags is Abstract) writeByte(ABSTRACT)
- if (flags is Trait) writeByte(TRAIT)
- if (flags is Covariant) writeByte(COVARIANT)
- if (flags is Contravariant) writeByte(CONTRAVARIANT)
- }
- sym.annotations.foreach(pickleAnnotation)
- }
+ def pickle(trees: List[Tree])(implicit ctx: Context) = {
+ trees.foreach(tree => if (!tree.isEmpty) pickleTree(tree))
+ assert(forwardSymRefs.isEmpty, i"unresolved symbols: ${forwardSymRefs.keySet.toList}%, %")
+ }
- def pickleAnnotation(ann: Annotation) = {
- writeByte(ANNOTATION)
- withLength { pickleType(ann.symbol.typeRef); pickleTree(ann.tree) }
- }
+ def compactify() = {
+ buf.compactify()
+ assert(forwardSymRefs.isEmpty, s"unresolved symbols: ${forwardSymRefs.keySet.toList}%, %")
def updateMapWithDeltas[T](mp: collection.mutable.Map[T, Addr]) =
for (key <- mp.keysIterator.toBuffer[T]) mp(key) = adjusted(mp(key))
- trees.foreach(tree => if (!tree.isEmpty) pickleTree(tree))
- assert(forwardSymRefs.isEmpty, i"unresolved symbols: ${forwardSymRefs.keySet.toList}%, %")
- compactify()
updateMapWithDeltas(symRefs)
}
}
diff --git a/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala b/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala
index eadccb2a3..81d19f7e4 100644
--- a/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala
+++ b/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala
@@ -10,7 +10,8 @@ import ast.{tpd, Trees, untpd}
import Trees._
import Decorators._
import TastyUnpickler._, TastyBuffer._, PositionPickler._
-import annotation.switch
+import scala.annotation.{tailrec, switch}
+import scala.collection.mutable.ListBuffer
import scala.collection.{ mutable, immutable }
import typer.Mode
import config.Printers.pickling
@@ -65,7 +66,7 @@ class TreeUnpickler(reader: TastyReader, tastyName: TastyName.Table) {
def unpickle()(implicit ctx: Context): List[Tree] = {
assert(roots != null, "unpickle without previous enterTopLevel")
val stats = new TreeReader(reader)
- .readIndexedStats(NoSymbol, reader.endAddr)(ctx.addMode(Mode.AllowDependentFunctions))
+ .readTopLevel()(ctx.addMode(Mode.AllowDependentFunctions))
normalizePos(stats, totalRange)
stats
}
@@ -676,6 +677,29 @@ class TreeUnpickler(reader: TastyReader, tastyName: TastyName.Table) {
.withType(localDummy.nonMemberTermRef))
}
+ def skipToplevel()(implicit ctx: Context): Unit= {
+ if (!isAtEnd)
+ nextByte match {
+ case IMPORT | PACKAGE =>
+ skipTree()
+ skipToplevel()
+ case _ =>
+ }
+ }
+
+ def readTopLevel()(implicit ctx: Context): List[Tree] = {
+ @tailrec def read(acc: ListBuffer[Tree]): List[Tree] = nextByte match {
+ case IMPORT | PACKAGE =>
+ acc += readIndexedStat(NoSymbol)
+ if (!isAtEnd)
+ read(acc)
+ else acc.toList
+ case _ => // top-level trees which are not imports or packages are not part of tree
+ acc.toList
+ }
+ read(new ListBuffer[tpd.Tree])
+ }
+
def readIndexedStat(exprOwner: Symbol)(implicit ctx: Context): Tree = nextByte match {
case TYPEDEF | VALDEF | DEFDEF =>
readIndexedDef()
diff --git a/src/dotty/tools/dotc/transform/Pickler.scala b/src/dotty/tools/dotc/transform/Pickler.scala
index 0d9bdcc3c..8040c86d4 100644
--- a/src/dotty/tools/dotc/transform/Pickler.scala
+++ b/src/dotty/tools/dotc/transform/Pickler.scala
@@ -44,7 +44,7 @@ class Pickler extends Phase {
if (ctx.settings.YtestPickler.value) beforePickling(cls) = tree.show
val pickler = new TastyPickler()
unit.picklers += (cls -> pickler)
- val treePkl = new TreePickler(pickler)
+ val treePkl = pickler.treePkl
treePkl.pickle(tree :: Nil)
pickler.addrOfTree = treePkl.buf.addrOfTree
pickler.addrOfSym = treePkl.addrOfSym