aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/dotty/tools/dotc/core/pickling/TastyBuffer.scala2
-rw-r--r--src/dotty/tools/dotc/core/pickling/TreePickler.scala64
-rw-r--r--src/dotty/tools/dotc/reporting/Reporter.scala4
-rw-r--r--src/dotty/tools/dotc/transform/Pickler.scala6
4 files changed, 51 insertions, 25 deletions
diff --git a/src/dotty/tools/dotc/core/pickling/TastyBuffer.scala b/src/dotty/tools/dotc/core/pickling/TastyBuffer.scala
index 61dce9efb..9197a2acc 100644
--- a/src/dotty/tools/dotc/core/pickling/TastyBuffer.scala
+++ b/src/dotty/tools/dotc/core/pickling/TastyBuffer.scala
@@ -18,6 +18,8 @@ object TastyBuffer {
def relativeTo(base: Addr): Addr = this - base.index - AddrWidth
}
+
+ val NoAddr = Addr(-1)
/** The maximal number of address bytes.
* Since addresses are written as base-128 natural numbers,
diff --git a/src/dotty/tools/dotc/core/pickling/TreePickler.scala b/src/dotty/tools/dotc/core/pickling/TreePickler.scala
index 5f18a7552..dc98a58f3 100644
--- a/src/dotty/tools/dotc/core/pickling/TreePickler.scala
+++ b/src/dotty/tools/dotc/core/pickling/TreePickler.scala
@@ -26,8 +26,14 @@ class TreePickler(pickler: TastyPickler) {
op
fillRef(lengthAddr, currentAddr, relative = true)
}
+
+ def preRegister(tree: Tree)(implicit ctx: Context): Unit = tree match {
+ case tree: MemberDef =>
+ if (!symRefs.contains(tree.symbol)) symRefs(tree.symbol) = NoAddr
+ case _ =>
+ }
- def registerDef(sym: Symbol) = {
+ def registerDef(sym: Symbol): Unit = {
symRefs(sym) = currentAddr
forwardSymRefs.get(sym) match {
case Some(refs) =>
@@ -44,14 +50,18 @@ class TreePickler(pickler: TastyPickler) {
pickleName(TastyName.Signed(nameIndex(name), params.map(nameIndex), nameIndex(result)))
}
- private def pickleSym(sym: Symbol)(implicit ctx: Context) = symRefs.get(sym) match {
+ private def pickleSymRef(sym: Symbol)(implicit ctx: Context) = symRefs.get(sym) match {
case Some(label) =>
- writeRef(label)
+ if (label != NoAddr) writeRef(label) else pickleForwardSymRef(sym)
case None =>
- val ref = reserveRef(relative = false)
- assert(!sym.is(Flags.Package), sym)
- //assert(!sym.is(Flags.Param) || sym.owner.isClass, sym.showLocated) // TODO enable
- forwardSymRefs(sym) = ref :: forwardSymRefs.getOrElse(sym, Nil)
+ ctx.log(i"pickling reference to as yet undefined $sym in ${sym.owner}", sym.pos)
+ pickleForwardSymRef(sym)
+ }
+
+ private def pickleForwardSymRef(sym: Symbol)(implicit ctx: Context) = {
+ val ref = reserveRef(relative = false)
+ assert(!sym.is(Flags.Package), sym)
+ forwardSymRefs(sym) = ref :: forwardSymRefs.getOrElse(sym, Nil)
}
def pickle(trees: List[Tree])(implicit ctx: Context) = {
@@ -116,7 +126,7 @@ class TreePickler(pickler: TastyPickler) {
throw ex
}
- def pickleNewType(tpe: Type, richTypes: Boolean): Unit = tpe match {
+ def pickleNewType(tpe: Type, richTypes: Boolean): Unit = try { tpe match {
case ConstantType(value) =>
pickleConstant(value)
case tpe: TypeRef if tpe.info.isAlias && tpe.symbol.is(Flags.AliasPreferred) =>
@@ -130,7 +140,7 @@ class TreePickler(pickler: TastyPickler) {
else if (tpe.prefix == NoPrefix) {
def pickleRef() = {
writeByte(if (tpe.isType) TYPEREFdirect else TERMREFdirect)
- pickleSym(sym)
+ pickleSymRef(sym)
}
if (sym is Flags.BindDefinedType) {
registerDef(sym)
@@ -145,7 +155,7 @@ class TreePickler(pickler: TastyPickler) {
}
else {
writeByte(if (tpe.isType) TYPEREFsymbol else TERMREFsymbol)
- pickleSym(sym); pickleType(tpe.prefix)
+ pickleSymRef(sym); pickleType(tpe.prefix)
}
case tpe: TermRefWithSignature =>
writeByte(TERMREF)
@@ -212,6 +222,10 @@ class TreePickler(pickler: TastyPickler) {
writeByte(NOTYPE)
// case NoPrefix => // not sure we need this!
// writeByte(NOPREFIX)
+ }} catch {
+ case ex: AssertionError =>
+ println(i"error while pickling type $tpe")
+ throw ex
}
def pickleMethodic(result: Type, names: List[Name], types: List[Type]) =
@@ -296,6 +310,7 @@ class TreePickler(pickler: TastyPickler) {
withLength { pickleTree(lhs); pickleTree(rhs) }
case Block(stats, expr) =>
writeByte(BLOCK)
+ stats.foreach(preRegister)
withLength { pickleTree(expr); stats.foreach(pickleTree) }
case If(cond, thenp, elsep) =>
writeByte(IF)
@@ -311,7 +326,7 @@ class TreePickler(pickler: TastyPickler) {
withLength { pickleTree(pat); pickleTree(rhs); pickleTreeIfNonEmpty(guard) }
case Return(expr, from) =>
writeByte(RETURN)
- withLength { pickleSym(from.symbol); pickleTreeIfNonEmpty(expr) }
+ withLength { pickleSymRef(from.symbol); pickleTreeIfNonEmpty(expr) }
case Try(block, cases, finalizer) =>
writeByte(TRY)
withLength { pickleTree(block); cases.foreach(pickleTree); pickleTreeIfNonEmpty(finalizer) }
@@ -344,14 +359,14 @@ class TreePickler(pickler: TastyPickler) {
case tree: ValDef =>
pickleDef(VALDEF, tree.symbol, tree.tpt, tree.rhs)
case tree: DefDef =>
- def pickleParams = {
- tree.tparams.foreach(pickleParam)
+ def pickleAllParams = {
+ pickleParams(tree.tparams)
for (vparams <- tree.vparamss) {
writeByte(PARAMS)
- withLength { vparams.foreach(pickleParam) }
+ withLength { pickleParams(vparams) }
}
}
- pickleDef(DEFDEF, tree.symbol, tree.tpt, tree.rhs, pickleParams)
+ pickleDef(DEFDEF, tree.symbol, tree.tpt, tree.rhs, pickleAllParams)
case tree: TypeDef =>
pickleDef(TYPEDEF, tree.symbol, tree.rhs)
case tree: Template =>
@@ -363,7 +378,7 @@ class TreePickler(pickler: TastyPickler) {
case _ => false
}
withLength {
- params.foreach(pickleParam)
+ pickleParams(params)
tree.parents.foreach(pickleTree)
val cinfo @ ClassInfo(_, _, _, _, selfInfo) = tree.symbol.owner.info
if ((selfInfo ne NoType) || !tree.self.isEmpty) {
@@ -373,8 +388,7 @@ class TreePickler(pickler: TastyPickler) {
pickleType(cinfo.selfType)
}
}
- pickleTree(tree.constr)
- rest.foreach(pickleTree)
+ pickleStats(tree.constr :: rest)
}
case Import(expr, selectors) =>
writeByte(IMPORT)
@@ -391,7 +405,7 @@ class TreePickler(pickler: TastyPickler) {
}
case PackageDef(pid, stats) =>
writeByte(PACKAGE)
- withLength { pickleType(pid.tpe); stats.foreach(pickleTree) }
+ withLength { pickleType(pid.tpe); pickleStats(stats) }
case EmptyTree =>
writeByte(EMPTYTREE)
}}
@@ -401,8 +415,8 @@ class TreePickler(pickler: TastyPickler) {
throw ex
}
-
def pickleDef(tag: Int, sym: Symbol, tpt: Tree, rhs: Tree = EmptyTree, pickleParams: => Unit = ()) = {
+ assert(symRefs(sym) == NoAddr)
registerDef(sym)
writeByte(tag)
withLength {
@@ -421,6 +435,16 @@ class TreePickler(pickler: TastyPickler) {
case tree: ValDef => pickleDef(PARAM, tree.symbol, tree.tpt)
case tree: TypeDef => pickleDef(TYPEPARAM, tree.symbol, tree.rhs)
}
+
+ def pickleParams(trees: List[Tree]): Unit = {
+ trees.foreach(preRegister)
+ trees.foreach(pickleParam)
+ }
+
+ def pickleStats(stats: List[Tree]) = {
+ stats.foreach(preRegister)
+ stats.foreach(pickleTree)
+ }
def pickleModifiers(sym: Symbol): Unit = {
import Flags._
diff --git a/src/dotty/tools/dotc/reporting/Reporter.scala b/src/dotty/tools/dotc/reporting/Reporter.scala
index 5bb660cdb..223fc33d5 100644
--- a/src/dotty/tools/dotc/reporting/Reporter.scala
+++ b/src/dotty/tools/dotc/reporting/Reporter.scala
@@ -109,9 +109,9 @@ trait Reporting { this: Context =>
* See [[config.CompilerCommand#explainAdvanced]] for the exact meaning of
* "contains" here.
*/
- def log(msg: => String): Unit =
+ def log(msg: => String, pos: SourcePosition = NoSourcePosition): Unit =
if (this.settings.log.value.containsPhase(phase))
- echo(s"[log ${ctx.phasesStack.reverse.mkString(" -> ")}] $msg")
+ echo(s"[log ${ctx.phasesStack.reverse.mkString(" -> ")}] $msg", pos)
def debuglog(msg: => String): Unit =
if (ctx.debug) log(msg)
diff --git a/src/dotty/tools/dotc/transform/Pickler.scala b/src/dotty/tools/dotc/transform/Pickler.scala
index fd50df6ba..7bc41321c 100644
--- a/src/dotty/tools/dotc/transform/Pickler.scala
+++ b/src/dotty/tools/dotc/transform/Pickler.scala
@@ -6,7 +6,7 @@ import TreeTransforms._
import Contexts.Context
import Decorators._
import pickling._
-import config.Printers
+import config.Printers.{noPrinter, pickling}
import java.io.PrintStream
import Periods._
@@ -25,7 +25,7 @@ class Pickler extends MiniPhaseTransform { thisTransform =>
override def transformUnit(tree: Tree)(implicit ctx: Context, info: TransformerInfo): Tree = {
if (!ctx.compilationUnit.isJava) {
val pickler = new TastyPickler
- println(i"unpickling in run ${ctx.runId}")
+ pickling.println(i"unpickling in run ${ctx.runId}")
val previous = if (ctx.settings.YtestPickler.value) tree.show else ""
val treePkl = new TreePickler(pickler)
@@ -40,7 +40,7 @@ class Pickler extends MiniPhaseTransform { thisTransform =>
case (row, i) => s"${i}0: ${row.mkString(" ")}"
}
// println(i"rawBytes = \n$rawBytes%\n%") // DEBUG
- if (Printers.pickling ne Printers.noPrinter) new TastyPrinter(bytes).printContents()
+ if (pickling ne noPrinter) new TastyPrinter(bytes).printContents()
if (ctx.settings.YtestPickler.value)
unpickle(bytes, previous)(ctx.fresh.setPeriod(Period(ctx.runId + 1, FirstPhaseId)))