Skip to content

Join logic for unpickling top level and term tasty #4546

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Jul 18, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions compiler/src/dotty/tools/dotc/core/quoted/PickledQuotes.scala
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,13 @@ import dotty.tools.dotc.config.Printers._
import dotty.tools.dotc.core.Constants.Constant
import dotty.tools.dotc.core.Contexts._
import dotty.tools.dotc.core.Decorators._
import dotty.tools.dotc.core.Flags._
import dotty.tools.dotc.core.StdNames._
import dotty.tools.dotc.core.NameKinds
import dotty.tools.dotc.core.Symbols._
import dotty.tools.dotc.core.Types.Type
import dotty.tools.dotc.core.tasty.TreePickler.Hole
import dotty.tools.dotc.core.tasty.{TastyPickler, TastyPrinter, TastyString}
import dotty.tools.dotc.core.tasty.TreeUnpickler.UnpickleMode

import scala.quoted.Types._
import scala.quoted.Exprs._
Expand Down Expand Up @@ -99,15 +99,15 @@ object PickledQuotes {

/** Unpickle TASTY bytes into it's tree */
private def unpickle(bytes: Array[Byte], splices: Seq[Any], isType: Boolean)(implicit ctx: Context): Tree = {
val unpickler = new TastyUnpickler(bytes, splices)
if (pickling ne noPrinter) {
println(i"**** unpickling quote from TASTY")
new TastyPrinter(bytes).printContents()
}

val tree =
if (isType) unpickler.unpickleTypeTree()
else unpickler.unpickleExpr()
val mode = if (isType) UnpickleMode.TypeTree else UnpickleMode.Term
val unpickler = new QuoteUnpickler(bytes, splices, mode)
unpickler.enter(Set.empty)
val tree = unpickler.tree

if (pickling ne noPrinter)
println(i"**** unpickle quote ${tree.show}")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@ package dotty.tools.dotc.core.quoted

import dotty.tools.dotc.core.tasty._
import dotty.tools.dotc.core.tasty.TastyUnpickler.NameTable
import dotty.tools.dotc.core.tasty.TreeUnpickler.UnpickleMode

object TastyUnpickler {
object QuoteUnpickler {
class QuotedTreeSectionUnpickler(posUnpickler: Option[PositionUnpickler], splices: Seq[Any])
extends DottyUnpickler.TreeSectionUnpickler(posUnpickler, None) {
override def unpickle(reader: TastyReader, nameAtRef: NameTable) =
Expand All @@ -15,9 +16,9 @@ object TastyUnpickler {
* @param bytes the bytearray containing the Tasty file from which we unpickle
* @param splices splices that will fill the holes in the quote
*/
class TastyUnpickler(bytes: Array[Byte], splices: Seq[Any]) extends DottyUnpickler(bytes) {
class QuoteUnpickler(bytes: Array[Byte], splices: Seq[Any], mode: UnpickleMode) extends DottyUnpickler(bytes, mode) {
import DottyUnpickler._
import TastyUnpickler._
import QuoteUnpickler._

protected override def treeSectionUnpickler(posUnpicklerOpt: Option[PositionUnpickler], commentUnpicklerOpt: Option[CommentUnpickler]): TreeSectionUnpickler =
new QuotedTreeSectionUnpickler(posUnpicklerOpt, splices)
Expand Down
11 changes: 5 additions & 6 deletions compiler/src/dotty/tools/dotc/core/tasty/DottyUnpickler.scala
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import util.{SourceFile, NoSource}
import Annotations.Annotation
import classfile.ClassfileParser
import Names.SimpleName
import TreeUnpickler.UnpickleMode

object DottyUnpickler {

Expand All @@ -36,8 +37,9 @@ object DottyUnpickler {

/** A class for unpickling Tasty trees and symbols.
* @param bytes the bytearray containing the Tasty file from which we unpickle
* @param mode the tasty file contains package (TopLevel), an expression (Term) or a type (TypeTree)
*/
class DottyUnpickler(bytes: Array[Byte]) extends ClassfileParser.Embedded with tpd.TreeProvider {
class DottyUnpickler(bytes: Array[Byte], mode: UnpickleMode = UnpickleMode.TopLevel) extends ClassfileParser.Embedded with tpd.TreeProvider {
import tpd._
import DottyUnpickler._

Expand All @@ -50,10 +52,7 @@ class DottyUnpickler(bytes: Array[Byte]) extends ClassfileParser.Embedded with t
* @param roots a set of SymDenotations that should be overwritten by unpickling
*/
def enter(roots: Set[SymDenotation])(implicit ctx: Context): Unit =
treeUnpickler.enterTopLevel(roots)

def unpickleExpr()(implicit ctx: Context): Tree =
treeUnpickler.unpickleExpr()
treeUnpickler.enter(roots)

def unpickleTypeTree()(implicit ctx: Context): Tree =
treeUnpickler.unpickleTypeTree()
Expand All @@ -62,7 +61,7 @@ class DottyUnpickler(bytes: Array[Byte]) extends ClassfileParser.Embedded with t
new TreeSectionUnpickler(posUnpicklerOpt, commentUnpicklerOpt)
}

protected def computeTrees(implicit ctx: Context) = treeUnpickler.unpickle()
protected def computeTrees(implicit ctx: Context) = treeUnpickler.unpickle(mode)

private[this] var ids: Array[String] = null

Expand Down
57 changes: 36 additions & 21 deletions compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala
Original file line number Diff line number Diff line change
Expand Up @@ -74,18 +74,12 @@ class TreeUnpickler(reader: TastyReader,
/** 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 = {
def enter(roots: Set[SymDenotation])(implicit ctx: Context): Unit = {
this.roots = roots
val rdr = new TreeReader(reader).fork
ownerTree = new OwnerTree(NoAddr, 0, rdr.fork, reader.endAddr)
rdr.indexStats(reader.endAddr)
}

def unpickleExpr()(implicit ctx: Context): Tree = {
this.roots = Set(ctx.owner)
val rdr = new TreeReader(reader).fork
ownerTree = new OwnerTree(NoAddr, 0, rdr.fork, reader.endAddr)
rdr.readTerm()
if (rdr.isTopLevel)
rdr.indexStats(reader.endAddr)
}

def unpickleTypeTree()(implicit ctx: Context): Tree = {
Expand All @@ -96,9 +90,14 @@ class TreeUnpickler(reader: TastyReader,
}

/** The unpickled trees */
def unpickle()(implicit ctx: Context): List[Tree] = {
def unpickle(mode: UnpickleMode)(implicit ctx: Context): List[Tree] = {
assert(roots != null, "unpickle without previous enterTopLevel")
new TreeReader(reader).readTopLevel()
val rdr = new TreeReader(reader)
mode match {
case UnpickleMode.TopLevel => rdr.readTopLevel()
case UnpickleMode.Term => rdr.readTerm() :: Nil
case UnpickleMode.TypeTree => rdr.readTpt() :: Nil
}
}

class Completer(owner: Symbol, reader: TastyReader) extends LazyType {
Expand Down Expand Up @@ -885,21 +884,22 @@ class TreeUnpickler(reader: TastyReader,
}

def skipToplevel()(implicit ctx: Context): Unit= {
if (!isAtEnd)
nextByte match {
case IMPORT | PACKAGE =>
skipTree()
skipToplevel()
case _ =>
}
if (!isAtEnd && isTopLevel) {
skipTree()
skipToplevel()
}
}

def isTopLevel(implicit ctx: Context): Boolean =
nextByte == IMPORT || nextByte == PACKAGE

def readTopLevel()(implicit ctx: Context): List[Tree] = {
@tailrec def read(acc: ListBuffer[Tree]): List[Tree] = nextByte match {
case IMPORT | PACKAGE =>
@tailrec def read(acc: ListBuffer[Tree]): List[Tree] = {
if (isTopLevel) {
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
}
else // top-level trees which are not imports or packages are not part of tree
acc.toList
}
read(new ListBuffer[tpd.Tree])
Expand Down Expand Up @@ -1298,6 +1298,21 @@ class TreeUnpickler(reader: TastyReader,

object TreeUnpickler {

/** Define the expected format of the tasty bytes
* - TopLevel: Tasty that contains a full class nested in its package
* - Term: Tasty that contains only a term tree
* - TypeTree: Tasty that contains only a type tree or a reference to a type
*/
sealed trait UnpickleMode
object UnpickleMode {
/** Unpickle a full class in some package */
object TopLevel extends UnpickleMode
/** Unpickle as a TermTree */
object Term extends UnpickleMode
/** Unpickle as a TypeTree */
object TypeTree extends UnpickleMode
}

/** A marker value used to detect cyclic reference while unpickling definitions. */
@sharable val PoisonTree: tpd.Tree = Thicket(Nil)

Expand Down
2 changes: 1 addition & 1 deletion compiler/src/dotty/tools/dotc/transform/Pickler.scala
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ class Pickler extends Phase {
val unpicklers =
for ((cls, pickler) <- picklers) yield {
val unpickler = new DottyUnpickler(pickler.assembleParts())
unpickler.enter(roots = Set())
unpickler.enter(roots = Set.empty)
cls -> unpickler
}
pickling.println("************* entered toplevel ***********")
Expand Down