Skip to content

Commit cbca568

Browse files
committed
Add splices to the unpickler
1 parent a3fbf5c commit cbca568

File tree

7 files changed

+51
-34
lines changed

7 files changed

+51
-34
lines changed

compiler/src/dotty/tools/dotc/core/tasty/DottyUnpickler.scala

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,14 +38,18 @@ class DottyUnpickler(bytes: Array[Byte]) extends ClassfileParser.Embedded {
3838

3939
val unpickler = new TastyUnpickler(bytes)
4040
private val posUnpicklerOpt = unpickler.unpickle(new PositionsSectionUnpickler)
41-
private val treeUnpickler = unpickler.unpickle(new TreeSectionUnpickler(posUnpicklerOpt)).get
41+
private val treeUnpickler = unpickler.unpickle(treeSectionUnpickler(posUnpicklerOpt)).get
4242

4343
/** Enter all toplevel classes and objects into their scopes
4444
* @param roots a set of SymDenotations that should be overwritten by unpickling
4545
*/
4646
def enter(roots: Set[SymDenotation])(implicit ctx: Context): Unit =
4747
treeUnpickler.enterTopLevel(roots)
4848

49+
protected def treeSectionUnpickler(posUnpicklerOpt: Option[PositionUnpickler]): TreeSectionUnpickler = {
50+
new TreeSectionUnpickler(posUnpicklerOpt)
51+
}
52+
4953
/** Only used if `-Yretain-trees` is set. */
5054
private[this] var myBody: List[Tree] = _
5155
/** The unpickled trees, and the source file they come from. */

compiler/src/dotty/tools/dotc/interpreter/Expressions.scala

Lines changed: 0 additions & 17 deletions
This file was deleted.

compiler/src/dotty/tools/dotc/quoted/ExprFrontend.scala

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,11 @@ package dotty.tools.dotc.quoted
33
import dotty.tools.dotc.CompilationUnit
44
import dotty.tools.dotc.ast.tpd
55
import dotty.tools.dotc.core.Contexts.Context
6-
import dotty.tools.dotc.core.Decorators._
76
import dotty.tools.dotc.core.Flags._
87
import dotty.tools.dotc.core.Scopes._
98
import dotty.tools.dotc.core.StdNames._
109
import dotty.tools.dotc.core.Symbols._
1110
import dotty.tools.dotc.core.Types._
12-
import dotty.tools.dotc.interpreter.Expressions.exprToTree
1311
import dotty.tools.dotc.typer.FrontEnd
1412
import dotty.tools.dotc.util.Positions._
1513
import dotty.tools.dotc.util.SourceFile
@@ -20,6 +18,7 @@ import scala.quoted.Expr
2018
/** Frontend that receives scala.quoted.Expr as input */
2119
class ExprFrontend(putInClass: Boolean) extends FrontEnd {
2220
import tpd._
21+
import PickledQuotes.quotedToTree
2322

2423
override def isTyper = false
2524

@@ -28,7 +27,7 @@ class ExprFrontend(putInClass: Boolean) extends FrontEnd {
2827
case exprUnit: ExprCompilationUnit =>
2928
val tree =
3029
if (putInClass) inClass(exprUnit.expr)
31-
else exprToTree(exprUnit.expr)
30+
else quotedToTree(exprUnit.expr)
3231
val source = new SourceFile("", Seq())
3332
CompilationUnit.mkCompilationUnit(source, tree, forceTrees = true)
3433
}
@@ -43,7 +42,7 @@ class ExprFrontend(putInClass: Boolean) extends FrontEnd {
4342
cls.enter(ctx.newDefaultConstructor(cls), EmptyScope)
4443
val meth = ctx.newSymbol(cls, nme.apply, Method, ExprType(defn.AnyType), coord = coord).entered
4544

46-
val quoted = exprToTree(expr)(ctx.withOwner(meth))
45+
val quoted = quotedToTree(expr)(ctx.withOwner(meth))
4746

4847
val run = DefDef(meth, quoted)
4948
val classTree = ClassDef(cls, DefDef(cls.primaryConstructor.asTerm), run :: Nil)

compiler/src/dotty/tools/dotc/interpreter/PickledQuotes.scala renamed to compiler/src/dotty/tools/dotc/quoted/PickledQuotes.scala

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,20 @@
1-
package dotty.tools.dotc.interpreter
1+
package dotty.tools.dotc.quoted
22

33
import dotty.tools.dotc.ast.Trees._
44
import dotty.tools.dotc.ast.tpd
55
import dotty.tools.dotc.config.Printers._
6+
import dotty.tools.dotc.core.Constants.Constant
67
import dotty.tools.dotc.core.Contexts._
78
import dotty.tools.dotc.core.Decorators._
89
import dotty.tools.dotc.core.Flags._
9-
import dotty.tools.dotc.core.NameKinds._
10-
import dotty.tools.dotc.core.StdNames._
1110
import dotty.tools.dotc.core.Symbols._
12-
import dotty.tools.dotc.core.Types._
1311
import dotty.tools.dotc.core.tasty._
12+
import dotty.tools.dotc.interpreter.RawQuoted
1413

1514
object PickledQuotes {
1615
import tpd._
1716

18-
/** TODO */
17+
/** Pickle the quote into a TASTY string */
1918
def pickleQuote(tree: Tree)(implicit ctx: Context): String = {
2019
if (ctx.reporter.hasErrors) "<error>"
2120
else {
@@ -25,10 +24,17 @@ object PickledQuotes {
2524
}
2625
}
2726

28-
/** TODO */
29-
def unpickleQuote(expr: quoted.TastyQuoted)(implicit ctx: Context): Tree = {
27+
/** Transform the expression into it's fully spliced Tree */
28+
def quotedToTree(expr: quoted.Quoted)(implicit ctx: Context): Tree = expr match {
29+
case expr: quoted.TastyQuoted => unpickleQuote(expr)
30+
case expr: quoted.ValueExpr[_] => Literal(Constant(expr.value))
31+
case expr: RawQuoted => expr.tree
32+
}
33+
34+
/** Unpickle the tree contained in the TastyQuoted */
35+
private def unpickleQuote(expr: quoted.TastyQuoted)(implicit ctx: Context): Tree = {
3036
val tastyBytes = TastyString.stringToTasty(expr.tasty)
31-
val unpickled = unpickle(tastyBytes)
37+
val unpickled = unpickle(tastyBytes, expr.args.map { case arg: quoted.Quoted => quotedToTree(arg) })
3238
unpickled match {
3339
case PackageDef(_, (vdef: ValDef) :: Nil) => vdef.rhs
3440
}
@@ -72,8 +78,8 @@ object PickledQuotes {
7278
}
7379

7480
/** Unpickle TASTY bytes into it's tree */
75-
private def unpickle(bytes: Array[Byte])(implicit ctx: Context): Tree = {
76-
val unpickler = new DottyUnpickler(bytes)
81+
private def unpickle(bytes: Array[Byte], splices: Seq[Any])(implicit ctx: Context): Tree = {
82+
val unpickler = new QuoteUnpickler(bytes, splices)
7783
unpickler.enter(roots = Set(defn.RootPackage))
7884
val tree = unpickler.body.head
7985
if (pickling ne noPrinter) {
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
package dotty.tools.dotc.quoted
2+
3+
import dotty.tools.dotc.core.tasty._
4+
5+
object QuoteUnpickler {
6+
class QuotedTreeSectionUnpickler(posUnpickler: Option[PositionUnpickler], splices: Seq[Any])
7+
extends DottyUnpickler.TreeSectionUnpickler(posUnpickler) {
8+
override def unpickle(reader: TastyReader, nameAtRef: TastyUnpickler.NameTable) =
9+
new TreeUnpickler(reader, nameAtRef, posUnpickler, splices)
10+
}
11+
}
12+
13+
/** A class for unpickling quoted Tasty trees and symbols.
14+
* @param bytes the bytearray containing the Tasty file from which we unpickle
15+
* @param splices splices that will fill the holes in the quote
16+
*/
17+
class QuoteUnpickler(bytes: Array[Byte], splices: Seq[Any]) extends DottyUnpickler(bytes) {
18+
import DottyUnpickler._
19+
import QuoteUnpickler._
20+
21+
protected override def treeSectionUnpickler(posUnpicklerOpt: Option[PositionUnpickler]): TreeSectionUnpickler =
22+
new QuotedTreeSectionUnpickler(posUnpicklerOpt, splices)
23+
}

compiler/src/dotty/tools/dotc/transform/ReifyQuotes.scala

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,10 @@ import tasty.TreePickler.Hole
1313
import MegaPhase.MiniPhase
1414
import SymUtils._
1515
import NameKinds.OuterSelectName
16+
1617
import scala.collection.mutable
1718
import dotty.tools.dotc.core.StdNames._
18-
import dotty.tools.dotc.interpreter.PickledQuotes
19+
import dotty.tools.dotc.quoted.PickledQuotes
1920

2021

2122
/** Translates quoted terms and types to `unpickle` method calls.

compiler/src/dotty/tools/dotc/transform/Splicer.scala

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import dotty.tools.dotc.core.Symbols._
66
import dotty.tools.dotc.ast.Trees._
77
import dotty.tools.dotc.ast.tpd
88
import dotty.tools.dotc.interpreter._
9+
import dotty.tools.dotc.quoted.PickledQuotes
910

1011
import scala.quoted
1112

@@ -28,7 +29,7 @@ object Splicer {
2829
/** Splice the Tree for a Quoted expression which is constructed via a reflective call to the given method */
2930
private def reflectiveSplice(tree: Tree)(implicit ctx: Context): Tree = {
3031
val interpreter = new Interpreter
31-
interpreter.interpretTree[quoted.Expr[_]](tree).map(Expressions.exprToTree(_)).getOrElse(tree)
32+
interpreter.interpretTree[quoted.Expr[_]](tree).map(PickledQuotes.quotedToTree(_)).getOrElse(tree)
3233
}
3334

3435
}

0 commit comments

Comments
 (0)