diff options
author | Martin Odersky <odersky@gmail.com> | 2015-03-07 15:39:16 +0100 |
---|---|---|
committer | Dmitry Petrashko <dmitry.petrashko@gmail.com> | 2015-03-18 11:14:16 +0100 |
commit | ac47d1c41a4a1a865ec3b9f1c9dee08f19018c57 (patch) | |
tree | f150978572ea008a7fca9de97559e54446bad047 /src/dotty/tools/dotc/core/pickling/TreeUnpickler.scala | |
parent | 2863af2b89af3ac34ebe9374d68b4018fe82edfd (diff) | |
download | dotty-ac47d1c41a4a1a865ec3b9f1c9dee08f19018c57.tar.gz dotty-ac47d1c41a4a1a865ec3b9f1c9dee08f19018c57.tar.bz2 dotty-ac47d1c41a4a1a865ec3b9f1c9dee08f19018c57.zip |
Re-org of pickling framework to enter before read
Need to enter all top-level symbols before reading any of them, in order
to avoid stale symbols.
Diffstat (limited to 'src/dotty/tools/dotc/core/pickling/TreeUnpickler.scala')
-rw-r--r-- | src/dotty/tools/dotc/core/pickling/TreeUnpickler.scala | 118 |
1 files changed, 74 insertions, 44 deletions
diff --git a/src/dotty/tools/dotc/core/pickling/TreeUnpickler.scala b/src/dotty/tools/dotc/core/pickling/TreeUnpickler.scala index 15b2f6796..9e18a9a6c 100644 --- a/src/dotty/tools/dotc/core/pickling/TreeUnpickler.scala +++ b/src/dotty/tools/dotc/core/pickling/TreeUnpickler.scala @@ -13,34 +13,54 @@ import TastyUnpickler._, TastyBuffer._ import annotation.switch import scala.collection.{ mutable, immutable } import typer.Mode +import config.Printers.pickling import PositionPickler._ /** Unpickler for typed trees * @param reader the reader from which to unpickle * @param tastyName the nametable - * @param roots a set of SymDenotations that should be completed by unpickling - * @param totalRange the range position enclosing all returned trees, - or NoPosition if positions should not be unpickled - * @param positions A map from */ -class TreeUnpickler(reader: TastyReader, tastyName: TastyName.Table, roots: Set[SymDenotation], - totalRange: Position, positions: collection.Map[Addr, Position]) { +class TreeUnpickler(reader: TastyReader, tastyName: TastyName.Table) { import dotty.tools.dotc.core.pickling.PickleFormat._ import TastyName._ import tpd._ - def readPositions = totalRange.exists - + private var readPositions = false + private var totalRange = NoPosition + private var positions: collection.Map[Addr, Position] = _ + + /** Make a subsequent call to `unpickle` return trees with positions + * @param totalRange the range position enclosing all returned trees, + * or NoPosition if positions should not be unpickled + * @param positions a map from tree addresses to their positions relative + * to positions of parent nodes. + */ + def usePositions(totalRange: Position, positions: collection.Map[Addr, Position]): Unit = { + readPositions = true + this.totalRange = totalRange + this.positions = positions + } + 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. - private var stubs: Set[Symbol] = Set() + + private var roots: Set[SymDenotation] = null + + /** Enter all toplevel classes and objects into their scopes + * @param roots a set of SymDenotations that should be overwritten by unpickling + */ + def enterTopLevel(roots: Set[SymDenotation])(implicit ctx: Context): Unit = { + this.roots = roots + new TreeReader(reader).fork.indexStats(reader.endAddr) + } + /** The unpickled trees */ def unpickle()(implicit ctx: Context): List[Tree] = { + assert(roots != null, "unpickle without previous enterTopLevel") val stats = new TreeReader(reader) - .readTopLevelStats()(ctx.addMode(Mode.AllowDependentFunctions)) + .readIndexedStats(NoSymbol, reader.endAddr)(ctx.addMode(Mode.AllowDependentFunctions)) normalizePos(stats, totalRange) stats } @@ -61,7 +81,6 @@ class TreeUnpickler(reader: TastyReader, tastyName: TastyName.Table, roots: Set[ class Completer(reader: TastyReader) extends LazyType { import reader._ def complete(denot: SymDenotation)(implicit ctx: Context): Unit = { - // println(i"complete ${denot.name}") treeAtAddr(currentAddr) = new TreeReader(reader).readIndexedDef() } } @@ -128,7 +147,7 @@ class TreeUnpickler(reader: TastyReader, tastyName: TastyName.Table, roots: Set[ def readType()(implicit ctx: Context): Type = { val start = currentAddr val tag = readByte() - println(s"reading type ${astTagToString(tag)} at $start") + pickling.println(s"reading type ${astTagToString(tag)} at $start") def registeringType[T](tp: Type, op: => T): T = { typeAtAddr(start) = tp @@ -321,7 +340,7 @@ class TreeUnpickler(reader: TastyReader, tastyName: TastyName.Table, roots: Set[ val rhsIsEmpty = noRhs(end) if (!rhsIsEmpty) skipTree() val (givenFlags, annots, privateWithin) = readModifiers(end) - println(i"creating symbol $name at $start with flags $givenFlags") + pickling.println(i"creating symbol $name at $start with flags $givenFlags") val lacksDefinition = rhsIsEmpty && !name.isConstructorName && !givenFlags.is(ParamOrAccessor) || isAbstractType @@ -343,7 +362,7 @@ class TreeUnpickler(reader: TastyReader, tastyName: TastyName.Table, roots: Set[ if (flags is Module) completer = ctx.adjustModuleCompleter(completer, name) val sym = if (roots contains prevDenot) { - println(i"overwriting ${prevDenot.symbol} # ${prevDenot.hashCode}") + pickling.println(i"overwriting ${prevDenot.symbol} # ${prevDenot.hashCode}") prevDenot.info = completer prevDenot.flags = flags &~ Touched // allow one more completion prevDenot.privateWithin = privateWithin @@ -441,13 +460,32 @@ class TreeUnpickler(reader: TastyReader, tastyName: TastyName.Table, roots: Set[ val noInitss = until(end) { nextByte match { - case VALDEF | DEFDEF | TYPEDEF | TYPEPARAM | PARAM => createSymbol() - case EMPTYTREE | IMPORT => skipTree(); true - case _ => skipTree(); false + case VALDEF | DEFDEF | TYPEDEF | TYPEPARAM | PARAM => + createSymbol() + case EMPTYTREE | IMPORT => + skipTree() + true + case PACKAGE => + processPackage { (pid, end) => implicit ctx => indexStats(end) } + case _ => + skipTree() + false } } noInitss.forall(_ == true) } + + /** Process package with given operation `op`. The operation takes as arguments + * - a `RefTree` representing the `pid` of the package, + * - an end address, + * - a context which has the processd package as owner + */ + def processPackage[T](op: (RefTree, Addr) => Context => T)(implicit ctx: Context): T = { + readByte() + val end = readEnd() + val pid = ref(readTermRef()).asInstanceOf[RefTree] + op(pid, end)(localContext(pid.symbol.moduleClass)) + } /** Create symbols the longest consecutive sequence of parameters with given * `tag starting at current address. @@ -475,7 +513,6 @@ class TreeUnpickler(reader: TastyReader, tastyName: TastyName.Table, roots: Set[ private def readNewDef()(implicit ctx: Context): Tree = { val start = currentAddr - // println(s"reading def at $start") val sym = symAtAddr(start) val tag = readByte() val end = readEnd() @@ -508,7 +545,7 @@ class TreeUnpickler(reader: TastyReader, tastyName: TastyName.Table, roots: Set[ def ta = ctx.typeAssigner val name = readName() - println(s"reading def of $name at $start") + pickling.println(s"reading def of $name at $start") val tree: MemberDef = tag match { case DEFDEF => val tparams = readParams[TypeDef](TYPEPARAM)(localCtx) @@ -543,7 +580,7 @@ class TreeUnpickler(reader: TastyReader, tastyName: TastyName.Table, roots: Set[ sym.info = readType() if (noRhs(end)) ValDef(sym.asTerm) else { - println(i"param alias $name -> $currentAddr") + pickling.println(i"reading param alias $name -> $currentAddr") DefDef(Nil, Nil, TypeTree(sym.info)) } } @@ -600,18 +637,27 @@ class TreeUnpickler(reader: TastyReader, tastyName: TastyName.Table, roots: Set[ } def readIndexedStat(exprOwner: Symbol)(implicit ctx: Context): Tree = nextByte match { - case TYPEDEF | VALDEF | DEFDEF | IMPORT => readIndexedDef() - case _ => readTerm()(ctx.withOwner(exprOwner)) + case TYPEDEF | VALDEF | DEFDEF | IMPORT => + readIndexedDef() + case IMPORT => + ??? + case PACKAGE => + val start = currentAddr + processPackage { (pid, end) => implicit ctx => + setPos(start, PackageDef(pid, readIndexedStats(exprOwner, end)(ctx))) + } + case _ => + readTerm()(ctx.withOwner(exprOwner)) } + def readIndexedStats(exprOwner: Symbol, end: Addr)(implicit ctx: Context): List[Tree] = + until(end)(readIndexedStat(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] } @@ -620,7 +666,7 @@ class TreeUnpickler(reader: TastyReader, tastyName: TastyName.Table, roots: Set[ def readTerm()(implicit ctx: Context): Tree = { val start = currentAddr val tag = readByte() - println(s"reading term ${astTagToString(tag)} at $start") + pickling.println(s"reading term ${astTagToString(tag)} at $start") def readPathTerm(): Tree = { goto(start) @@ -754,22 +800,6 @@ class TreeUnpickler(reader: TastyReader, tastyName: TastyName.Table, roots: Set[ setPos(start, CaseDef(pat, guard, rhs)) } - def readTopLevelStat()(implicit ctx: Context): Tree = - if (nextByte == PACKAGE) { - val start = currentAddr - readByte() - val end = readEnd() - val pid = ref(readTermRef()).asInstanceOf[RefTree] - setPos(start, - PackageDef(pid, readTopLevelStats()(localContext(pid.symbol.moduleClass)))) - } - else readIndexedStat(ctx.owner) - - def readTopLevelStats()(implicit ctx: Context): List[Tree] = { - fork.indexStats(endAddr) - until(endAddr)(readTopLevelStat) - } - def readLater[T <: AnyRef](end: Addr, op: TreeReader => Context => T): Trees.Lazy[T] = { val localReader = fork goto(end) @@ -800,7 +830,7 @@ class TreeUnpickler(reader: TastyReader, tastyName: TastyName.Table, roots: Set[ class LazyReader[T <: AnyRef](reader: TreeReader, op: TreeReader => Context => T) extends Trees.Lazy[T] with DeferredPosition { def complete(implicit ctx: Context): T = { - // println(i"starting to read at ${reader.reader.currentAddr}") + pickling.println(i"starting to read at ${reader.reader.currentAddr}") val res = op(reader)(ctx.addMode(Mode.AllowDependentFunctions)) normalizePos(res, parentPos) res |