aboutsummaryrefslogtreecommitdiff
path: root/src/dotty/tools/dotc/core/pickling/TreePickler.scala
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2015-02-10 12:39:15 +0100
committerDmitry Petrashko <dmitry.petrashko@gmail.com>2015-03-18 11:09:43 +0100
commit1c5f3b75f7e70e8608d6be442087857bd4a6b2cc (patch)
tree26a197f56bfbd0a0ffa819cf68a730abd88a6260 /src/dotty/tools/dotc/core/pickling/TreePickler.scala
parent41922c14bf1a45a3dcf7afca7719e0be84c2c29a (diff)
downloaddotty-1c5f3b75f7e70e8608d6be442087857bd4a6b2cc.tar.gz
dotty-1c5f3b75f7e70e8608d6be442087857bd4a6b2cc.tar.bz2
dotty-1c5f3b75f7e70e8608d6be442087857bd4a6b2cc.zip
Add TASTY readers and printers for TASTy info.
So far printing is the only reader, ie. deserializer. Numerous bugfixes to make first tests work.
Diffstat (limited to 'src/dotty/tools/dotc/core/pickling/TreePickler.scala')
-rw-r--r--src/dotty/tools/dotc/core/pickling/TreePickler.scala92
1 files changed, 72 insertions, 20 deletions
diff --git a/src/dotty/tools/dotc/core/pickling/TreePickler.scala b/src/dotty/tools/dotc/core/pickling/TreePickler.scala
index 8c92e2ed8..cc5a8b8f2 100644
--- a/src/dotty/tools/dotc/core/pickling/TreePickler.scala
+++ b/src/dotty/tools/dotc/core/pickling/TreePickler.scala
@@ -3,7 +3,6 @@ package dotc
package core
package pickling
-import util.Util.{bestFit, dble}
import ast.Trees._
import PickleFormat._
import core._
@@ -55,6 +54,10 @@ class TreePickler(pickler: TastyPickler, picklePositions: Boolean) {
def pickle(tree: Tree)(implicit ctx: Context) = {
+ 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 = {
def pickleNum(nonNegTag: Int, negTag: Int) = {
val x = c.longValue
@@ -103,12 +106,13 @@ class TreePickler(pickler: TastyPickler, picklePositions: Boolean) {
}
}
- def pickleType(tpe: Type): Unit = {
+ def pickleType(tpe0: Type, richTypes: Boolean = false): Unit = {
+ val tpe = tpe0.stripTypeVar
val prev = pickledTypes.get(tpe)
if (prev == null) {
val addr = currentAddr
- pickleNewType(tpe)
pickledTypes.put(tpe, addr)
+ pickleNewType(tpe, richTypes)
}
else {
writeByte(SHARED)
@@ -116,10 +120,15 @@ class TreePickler(pickler: TastyPickler, picklePositions: Boolean) {
}
}
- def pickleNewType(tpe: Type)= tpe match {
- case ConstantType(value) => pickleConstant(value)
+ def pickleNewType(tpe: Type, richTypes: Boolean): Unit = tpe match {
+ case ConstantType(value) =>
+ pickleConstant(value)
case tpe: WithFixedSym =>
- if (tpe.prefix == NoPrefix) {
+ if (tpe.symbol.isStatic) {
+ writeByte(if (tpe.isType) TYPEREFstatic else TERMREFstatic)
+ pickleName(qualifiedName(tpe.symbol))
+ }
+ else if (tpe.prefix == NoPrefix) {
writeByte(if (tpe.isType) TYPEREFdirect else TERMREFdirect)
pickleSym(tpe.symbol)
}
@@ -135,7 +144,7 @@ class TreePickler(pickler: TastyPickler, picklePositions: Boolean) {
pickleType(tpe.prefix); pickleName(tpe.name)
case tpe: ThisType =>
writeByte(THIS)
- pickleType(tpe.tref)
+ withLength { pickleType(tpe.tref) }
case tpe: SuperType =>
writeByte(SUPERtype)
withLength { pickleType(tpe.thistpe); pickleType(tpe.supertpe)}
@@ -146,11 +155,11 @@ class TreePickler(pickler: TastyPickler, picklePositions: Boolean) {
val args = tpe.argInfos(interpolate = false)
if (args.isEmpty) {
writeByte(REFINEDtype)
- withLength { pickleName(tpe.refinedName); pickleType(tpe.refinedInfo) }
+ withLength { pickleName(tpe.refinedName); pickleType(tpe.refinedInfo, richTypes = true) }
}
else {
writeByte(APPLIEDtype)
- withLength { pickleType(tpe.withoutArgs(args)); args.foreach(pickleType) }
+ withLength { pickleType(tpe.withoutArgs(args)); args.foreach(pickleType(_)) }
}
case tpe: TypeAlias =>
writeByte(TYPEALIAS)
@@ -167,22 +176,56 @@ class TreePickler(pickler: TastyPickler, picklePositions: Boolean) {
case tpe: ExprType =>
writeByte(BYNAMEtype)
withLength { 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 tpe: MethodParam =>
+ assert(pickleParamType(tpe), "method parameter in wrong position")
case NoType =>
writeByte(NOTYPE)
// case NoPrefix => // not sure we need this!
// writeByte(NOPREFIX)
}
+ 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 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) }
+ }
+ pickled
+ }
+
def pickleTpt(tpt: Tree): Unit = pickleType(tpt.tpe) // TODO correlate with original when generating positions
def pickleTreeIfNonEmpty(tree: Tree): Unit =
if (!tree.isEmpty) pickleTree(tree)
- def pickleTree(tree: Tree): Unit = tree match {
+ def pickleTree(tree: Tree): Unit = {
+ tree match {
case Ident(_) | This(_) =>
pickleType(tree.tpe)
case Select(qual, name) =>
writeByte(SELECT)
+ pickleTree(qual)
val sig = tree.tpe.signature
if (sig == Signature.NotAMethod) pickleName(name)
else pickleNameAndSig(name, sig)
@@ -271,26 +314,29 @@ class TreePickler(pickler: TastyPickler, picklePositions: Boolean) {
patterns.foreach(pickleTree)
}
case tree: ValDef =>
- pickleDef(VALDEF, tree.symbol, tree.rhs)
+ pickleDef(VALDEF, tree.symbol, tree.tpt, tree.rhs)
case tree: DefDef =>
def pickleParams = {
- for (tparam <- tree.tparams) pickleDef(TYPEPARAM, tparam.symbol, EmptyTree)
+ for (tparam <- tree.tparams)
+ pickleDef(TYPEPARAM, tparam.symbol, tparam.rhs, EmptyTree)
for (vparams <- tree.vparamss) {
writeByte(PARAMS)
withLength {
- for (vparam <- vparams) pickleDef(PARAM, vparam.symbol, EmptyTree)
+ for (vparam <- vparams)
+ pickleDef(PARAM, vparam.symbol, vparam.tpt, EmptyTree)
}
}
}
- pickleDef(DEFDEF, tree.symbol, tree.rhs, pickleParams)
+ pickleDef(DEFDEF, tree.symbol, tree.tpt, tree.rhs, pickleParams)
case tree: TypeDef =>
- pickleDef(TYPEDEF, tree.symbol, tree.rhs)
+ pickleDef(TYPEDEF, tree.symbol, tree.rhs, EmptyTree)
case tree: Template =>
+ registerDef(tree.symbol)
writeByte(TEMPLATE)
withLength {
tree.parents.foreach(pickleTree)
if (!tree.self.isEmpty)
- pickleDef(PARAM, tree.self.symbol, EmptyTree)
+ pickleDef(PARAM, tree.self.symbol, tree.self.tpt, EmptyTree)
pickleTreeIfNonEmpty(tree.constr)
tree.body.foreach(pickleTree)
}
@@ -313,16 +359,21 @@ class TreePickler(pickler: TastyPickler, picklePositions: Boolean) {
case Annotated(annot, arg) =>
writeByte(ANNOTATED)
withLength { pickleTree(annot); pickleTree(arg) }
- }
+ case EmptyTree =>
+ writeByte(EMPTYTREE)
+ }}
- def pickleDef(tag: Int, sym: Symbol, rhs: Tree, pickleParams: => Unit = ()) = {
+ def pickleDef(tag: Int, sym: Symbol, tpt: Tree, rhs: Tree, pickleParams: => Unit = ()) = {
registerDef(sym)
writeByte(tag)
withLength {
pickleName(sym.name)
pickleParams
- if (tag != TYPEDEF) pickleType(sym.info.finalResultType)
- if (tag != PARAM && tag != TYPEPARAM) pickleTree(rhs)
+ tpt match {
+ case tpt: TypeTree => pickleTpt(tpt)
+ case _ => pickleTree(tpt)
+ }
+ if (tag == VALDEF || tag == DEFDEF) pickleTree(rhs)
pickleModifiers(sym)
}
}
@@ -367,5 +418,6 @@ class TreePickler(pickler: TastyPickler, picklePositions: Boolean) {
}
pickleTree(tree)
+ assert(forwardSymRefs.isEmpty, i"unresolved symbols: ${forwardSymRefs.keySet.toList}%, %")
}
}