Skip to content

Pickle quotes directly as expressions in TASTY #4538

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 1 commit into from
May 17, 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
34 changes: 4 additions & 30 deletions compiler/src/dotty/tools/dotc/core/quoted/PickledQuotes.scala
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,7 @@ object PickledQuotes {
if (ctx.reporter.hasErrors) Nil
else {
assert(!tree.isInstanceOf[Hole]) // Should not be pickled as it represents `'(~x)` which should be optimized to `x`
val encapsulated = encapsulateQuote(tree)
val pickled = pickle(encapsulated)
val pickled = pickle(tree)
TastyString.pickle(pickled)
}
}
Expand Down Expand Up @@ -75,37 +74,13 @@ object PickledQuotes {
/** Unpickle the tree contained in the TastyExpr */
private def unpickleExpr(expr: TastyExpr[_])(implicit ctx: Context): Tree = {
val tastyBytes = TastyString.unpickle(expr.tasty)
val unpickled = unpickle(tastyBytes, expr.args)
unpickled match {
case PackageDef(_, (vdef: ValDef) :: Nil) =>
vdef.rhs.changeOwner(vdef.symbol, ctx.owner)
}
unpickle(tastyBytes, expr.args)
}

/** Unpickle the tree contained in the TastyType */
private def unpickleType(ttpe: TastyType[_])(implicit ctx: Context): Tree = {
val tastyBytes = TastyString.unpickle(ttpe.tasty)
val unpickled = unpickle(tastyBytes, ttpe.args)
unpickled match {
case PackageDef(_, (vdef: ValDef) :: Nil) =>
vdef.rhs.asInstanceOf[TypeApply].args.head
.changeOwner(vdef.symbol, ctx.owner)
}
}

/** Encapsulate the tree in a top level `val` or `type`
* `<tree>` ==> `package _root_ { val $quote: Any = <tree> }`
* or
* `<type tree>` ==> `package _root_ { val $typeQuote: Any = null.asInstanceOf[<tree>] }`
*/
private def encapsulateQuote(tree: Tree)(implicit ctx: Context): Tree = {
val name = (if (tree.isTerm) "$quote" else "$typeQuote").toTermName
val sym = ctx.newSymbol(ctx.owner, name, Synthetic, defn.AnyType, coord = tree.pos)
val encoded =
if (tree.isTerm) tree
else Literal(Constant(null)).select(nme.asInstanceOf_).appliedToTypeTrees(tree :: Nil)
val quoted = ValDef(sym, encoded).withPos(tree.pos)
PackageDef(ref(defn.RootPackage).asInstanceOf[Ident], quoted :: Nil).withPos(tree.pos)
unpickle(tastyBytes, ttpe.args)
}

// TASTY picklingtests/pos/quoteTest.scala
Expand Down Expand Up @@ -135,8 +110,7 @@ object PickledQuotes {
/** Unpickle TASTY bytes into it's tree */
private def unpickle(bytes: Array[Byte], splices: Seq[Any])(implicit ctx: Context): Tree = {
val unpickler = new TastyUnpickler(bytes, splices)
unpickler.enter(roots = Set(defn.RootPackage))
val tree = unpickler.tree
val tree = unpickler.unpickleExpr()
if (pickling ne noPrinter) {
println(i"**** unpickled quote for \n${tree.show}")
new TastyPrinter(bytes).printContents()
Expand Down
3 changes: 3 additions & 0 deletions compiler/src/dotty/tools/dotc/core/tasty/DottyUnpickler.scala
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,9 @@ class DottyUnpickler(bytes: Array[Byte]) extends ClassfileParser.Embedded with t
def enter(roots: Set[SymDenotation])(implicit ctx: Context): Unit =
treeUnpickler.enterTopLevel(roots)

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

protected def treeSectionUnpickler(posUnpicklerOpt: Option[PositionUnpickler]): TreeSectionUnpickler = {
new TreeSectionUnpickler(posUnpicklerOpt)
}
Expand Down
9 changes: 8 additions & 1 deletion compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala
Original file line number Diff line number Diff line change
Expand Up @@ -73,11 +73,18 @@ class TreeUnpickler(reader: TastyReader,
*/
def enterTopLevel(roots: Set[SymDenotation])(implicit ctx: Context): Unit = {
this.roots = roots
var rdr = new TreeReader(reader).fork
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 = {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Document what this method does, how it differs from unpickle(), when it is used

this.roots = Set(ctx.owner)
val rdr = new TreeReader(reader).fork
ownerTree = new OwnerTree(NoAddr, 0, rdr.fork, reader.endAddr)
rdr.readTerm()
}

/** The unpickled trees */
def unpickle()(implicit ctx: Context): List[Tree] = {
assert(roots != null, "unpickle without previous enterTopLevel")
Expand Down
14 changes: 14 additions & 0 deletions tests/run-with-compiler/quote-owners-2.check
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
3
{
def ff: Int =
{
val a: List[Int] =
{
type T = List[Int]
val b: T = Nil.::[Int](3)
b: List[Int]
}
a.head: Int
}
ff: Int
}
25 changes: 25 additions & 0 deletions tests/run-with-compiler/quote-owners-2.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@

import quoted._
import dotty.tools.dotc.quoted.Toolbox._

object Test {
def main(args: Array[String]): Unit = {
val q = f(g(Type.IntTag))
println(q.run)
println(q.show)
}

def f(t: Type[List[Int]]): Expr[Int] = '{
def ff: Int = {
val a: ~t = {
type T = ~t
val b: T = 3 :: Nil
b
}
a.head
}
ff
}

def g[T](a: Type[T]): Type[List[T]] = '[List[~a]]
}
9 changes: 9 additions & 0 deletions tests/run-with-compiler/quote-owners.check
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
9
{
def ff: Int =
{
val a: Int = 9
a.+(0)
}
ff: Int
}
22 changes: 22 additions & 0 deletions tests/run-with-compiler/quote-owners.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import quoted._
import dotty.tools.dotc.quoted.Toolbox._

object Test {
def main(args: Array[String]): Unit = {
val q = f
println(q.run)
println(q.show)
}

def f: Expr[Int] = '{
def ff: Int = {
~g
}
ff
}

def g: Expr[Int] = '{
val a = 9
a + 0
}
}
5 changes: 5 additions & 0 deletions tests/run-with-compiler/quote-run-large.scala
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,11 @@ object Test {
def foo42: Int = x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x
def foo43: Int = x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x
def foo44: Int = x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x
def foo45: Int = x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x
def foo46: Int = x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x
def foo47: Int = x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x
def foo48: Int = x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x
def foo49: Int = x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x
}

new Foo(5)
Expand Down