Skip to content

Commit b4c10e5

Browse files
committed
Use single interface for pickled quotes
1 parent 807bbba commit b4c10e5

File tree

9 files changed

+74
-92
lines changed

9 files changed

+74
-92
lines changed

compiler/src/dotty/tools/dotc/core/Definitions.scala

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -837,9 +837,9 @@ class Definitions {
837837

838838
@tu lazy val TastyReflectionClass: ClassSymbol = requiredClass("scala.tasty.Reflection")
839839

840-
@tu lazy val PickledExpr_make: Symbol = requiredMethod("scala.internal.quoted.PickledExpr.make")
841-
@tu lazy val PickledType_make: Symbol = requiredMethod("scala.internal.quoted.PickledType.make")
842-
@tu lazy val PickledSplices_make: Symbol = requiredMethod("scala.internal.quoted.PickledSplices.make")
840+
@tu lazy val PickledQuote_make: Symbol = requiredMethod("scala.internal.quoted.PickledQuote.make")
841+
@tu lazy val PickledQuote_unpickleExpr: Symbol = requiredMethod("scala.internal.quoted.PickledQuote.unpickleExpr")
842+
@tu lazy val PickledQuote_unpickleType: Symbol = requiredMethod("scala.internal.quoted.PickledQuote.unpickleType")
843843

844844
@tu lazy val EqlClass: ClassSymbol = requiredClass("scala.Eql")
845845
def Eql_eqlAny(using Context): TermSymbol = EqlClass.companionModule.requiredMethod(nme.eqlAny)

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

Lines changed: 15 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,7 @@ import dotty.tools.dotc.report
1919

2020
import scala.reflect.ClassTag
2121

22-
import scala.internal.quoted.PickledExpr
23-
import scala.internal.quoted.PickledSplices
24-
import scala.internal.quoted.PickledType
22+
import scala.internal.quoted.PickledQuote
2523
import scala.quoted.QuoteContext
2624
import scala.collection.mutable
2725

@@ -52,25 +50,25 @@ object PickledQuotes {
5250
}
5351

5452
/** Unpickle the tree contained in the TastyExpr */
55-
def unpickleTerm(tastyBytes: Array[Byte], splices: PickledSplices)(using Context): Tree = {
53+
def unpickleTerm(pickledQuote: PickledQuote)(using Context): Tree = {
5654
val unpickled = withMode(Mode.ReadPositions)(
57-
unpickle(tastyBytes, splices, isType = false))
55+
unpickle(pickledQuote, isType = false))
5856
val Inlined(call, Nil, expnasion) = unpickled
5957
val inlineCtx = inlineContext(call)
60-
val expansion1 = spliceTypes(expnasion, splices)(using inlineCtx)
61-
val expansion2 = spliceTerms(expansion1, splices)(using inlineCtx)
58+
val expansion1 = spliceTypes(expnasion, pickledQuote)(using inlineCtx)
59+
val expansion2 = spliceTerms(expansion1, pickledQuote)(using inlineCtx)
6260
cpy.Inlined(unpickled)(call, Nil, expansion2)
6361
}
6462

6563
/** Unpickle the tree contained in the TastyType */
66-
def unpickleTypeTree(tastyBytes: Array[Byte], splices: PickledSplices)(using Context): Tree = {
64+
def unpickleTypeTree(pickledQuote: PickledQuote)(using Context): Tree = {
6765
val unpickled = withMode(Mode.ReadPositions)(
68-
unpickle(tastyBytes, splices, isType = true))
69-
spliceTypes(unpickled, splices)
66+
unpickle(pickledQuote, isType = true))
67+
spliceTypes(unpickled, pickledQuote)
7068
}
7169

7270
/** Replace all term holes with the spliced terms */
73-
private def spliceTerms(tree: Tree, splices: PickledSplices)(using Context): Tree = {
71+
private def spliceTerms(tree: Tree, pickledQuote: PickledQuote)(using Context): Tree = {
7472
val evaluateHoles = new TreeMap {
7573
override def transform(tree: tpd.Tree)(using Context): tpd.Tree = tree match {
7674
case Hole(isTerm, idx, args) =>
@@ -79,7 +77,7 @@ object PickledQuotes {
7977
else new scala.internal.quoted.Type(arg, QuoteContextImpl.scopeId)
8078
}
8179
if isTerm then
82-
val quotedExpr = splices.exprSplice(idx)(reifiedArgs)(dotty.tools.dotc.quoted.QuoteContextImpl())
80+
val quotedExpr = pickledQuote.exprSplice(idx)(reifiedArgs)(dotty.tools.dotc.quoted.QuoteContextImpl())
8381
val filled = PickledQuotes.quotedExprToTree(quotedExpr)
8482

8583
// We need to make sure a hole is created with the source file of the surrounding context, even if
@@ -89,7 +87,7 @@ object PickledQuotes {
8987
else
9088
// Replaces type holes generated by ReifyQuotes (non-spliced types).
9189
// These are types defined in a quote and used at the same level in a nested quote.
92-
val quotedType = splices.typeSplice(idx)(reifiedArgs)
90+
val quotedType = pickledQuote.typeSplice(idx)(reifiedArgs)
9391
PickledQuotes.quotedTypeToTree(quotedType)
9492
case tree: Select =>
9593
// Retain selected members
@@ -124,15 +122,15 @@ object PickledQuotes {
124122
}
125123

126124
/** Replace all type holes generated with the spliced types */
127-
private def spliceTypes(tree: Tree, splices: PickledSplices)(using Context): Tree = {
125+
private def spliceTypes(tree: Tree, pickledQuote: PickledQuote)(using Context): Tree = {
128126
tree match
129127
case Block(stat :: rest, expr1) if stat.symbol.hasAnnotation(defn.InternalQuoted_QuoteTypeTagAnnot) =>
130128
val typeSpliceMap = (stat :: rest).iterator.map {
131129
case tdef: TypeDef =>
132130
assert(tdef.symbol.hasAnnotation(defn.InternalQuoted_QuoteTypeTagAnnot))
133131
val tree = tdef.rhs match
134132
case TypeBoundsTree(_, Hole(_, idx, args), _) =>
135-
val quotedType = splices.typeSplice(idx)(args)
133+
val quotedType = pickledQuote.typeSplice(idx)(args)
136134
PickledQuotes.quotedTypeToTree(quotedType)
137135
case TypeBoundsTree(_, tpt, _) =>
138136
tpt
@@ -178,7 +176,8 @@ object PickledQuotes {
178176
}
179177

180178
/** Unpickle TASTY bytes into it's tree */
181-
private def unpickle(bytes: Array[Byte], splices: PickledSplices, isType: Boolean)(using Context): Tree = {
179+
private def unpickle(pickledQuote: PickledQuote, isType: Boolean)(using Context): Tree = {
180+
val bytes = pickledQuote.bytes()
182181
quotePickling.println(s"**** unpickling quote from TASTY\n${new TastyPrinter(bytes).printContents()}")
183182

184183
val mode = if (isType) UnpickleMode.TypeTree else UnpickleMode.Term

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

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,7 @@ import dotty.tools.dotc.core.Decorators._
1515
import scala.quoted.QuoteContext
1616
import scala.quoted.show.SyntaxHighlight
1717

18-
import scala.internal.quoted.PickledExpr
19-
import scala.internal.quoted.PickledSplices
20-
import scala.internal.quoted.PickledType
18+
import scala.internal.quoted.PickledQuote
2119
import scala.tasty.reflect._
2220

2321
object QuoteContextImpl {
@@ -2609,11 +2607,11 @@ class QuoteContextImpl private (ctx: Context) extends QuoteContext:
26092607
private def withDefaultPos[T <: Tree](fn: Context ?=> T): T =
26102608
fn(using ctx.withSource(rootPosition.source)).withSpan(rootPosition.span)
26112609

2612-
def unpickleTerm(bytes: Array[Byte], splices: PickledSplices): Term =
2613-
PickledQuotes.unpickleTerm(bytes, splices)
2610+
def unpickleTerm(pickledQuote: PickledQuote): Term =
2611+
PickledQuotes.unpickleTerm(pickledQuote)
26142612

2615-
def unpickleTypeTree(bytes: Array[Byte], splices: PickledSplices): TypeTree =
2616-
PickledQuotes.unpickleTypeTree(bytes, splices)
2613+
def unpickleTypeTree(pickledQuote: PickledQuote): TypeTree =
2614+
PickledQuotes.unpickleTypeTree(pickledQuote)
26172615

26182616
def termMatch(scrutinee: Term, pattern: Term): Option[Tuple] =
26192617
treeMatch(scrutinee, pattern)

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -163,12 +163,12 @@ class ReifyQuotes extends MacroTransform {
163163
}
164164

165165
def pickleAsTasty() = {
166-
val meth = if isType then defn.PickledType_make else defn.PickledExpr_make
166+
val unpickleMeth = if isType then defn.PickledQuote_unpickleType else defn.PickledQuote_unpickleExpr
167167
val pickledQuoteStrings = liftList(PickledQuotes.pickleQuote(body).map(x => Literal(Constant(x))), defn.StringType)
168168
// TODO: generate an instance of PickledSplices directly instead of passing through a List
169169
val splicesList = liftList(splices, defn.FunctionType(1).appliedTo(defn.SeqType.appliedTo(defn.AnyType), defn.AnyType))
170-
val pickledSplices = ref(defn.PickledSplices_make).appliedTo(splicesList)
171-
ref(meth).appliedToType(originalTp).appliedTo(pickledQuoteStrings, pickledSplices).select("unpickle".toTermName).appliedToArgs(Nil)
170+
val pickledQuote = ref(defn.PickledQuote_make).appliedTo(pickledQuoteStrings, splicesList)
171+
ref(unpickleMeth).appliedToType(originalTp).appliedTo(pickledQuote)
172172
}
173173

174174
def taggedType(sym: Symbol) = ref(defn.InternalQuotedTypeModule).select(sym.name.toTermName)

library/src/scala/internal/quoted/PickledExpr.scala

Lines changed: 0 additions & 18 deletions
This file was deleted.
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
package scala.internal.quoted
2+
3+
import scala.quoted._
4+
import scala.internal.tasty.CompilerInterface.quoteContextWithCompilerInterface
5+
6+
/** Pickled representation of a quoted expression or type */
7+
trait PickledQuote:
8+
9+
/** Bytes of the TASTy containing the quoted expression or type */
10+
def bytes(): Array[Byte]
11+
12+
/** Expression that will fill the hole `Hole(<idx> | <args>*)` */
13+
def exprSplice(idx: Int)(args: Seq[Any /* Expr[Any] | Type[?] */])(qctx: QuoteContext): Expr[Any]
14+
15+
/** Type that will fill the hole `Hole(<idx> | <args>*)` */
16+
def typeSplice(idx: Int)(args: Seq[Any /* Expr[Any] | Type[?] */]): Type[?]
17+
18+
object PickledQuote:
19+
20+
def unpickleExpr[T](pickledQuote: PickledQuote): QuoteContext ?=> Expr[T] =
21+
val qctx = quoteContextWithCompilerInterface(summon[QuoteContext])
22+
val tree = qctx.reflect.unpickleTerm(pickledQuote)
23+
new scala.internal.quoted.Expr(tree, qctx.hashCode).asInstanceOf[Expr[T]]
24+
25+
def unpickleType[T](pickledQuote: PickledQuote): QuoteContext ?=> Type[T] =
26+
val qctx = quoteContextWithCompilerInterface(summon[QuoteContext])
27+
val tree = qctx.reflect.unpickleTypeTree(pickledQuote)
28+
new scala.internal.quoted.Type(tree, qctx.hashCode).asInstanceOf[Type[T]]
29+
30+
/** Create an instance of PickledExpr from encoded tasty and sequence of labmdas to fill holes
31+
*
32+
* @param pickled: Bytes of tasty encoded using TastyString.pickle
33+
* @param seq: Sequence containing all the functions needed to fill the holes of the quote
34+
*/
35+
def make(pickled: List[String], seq: Seq[Seq[Any /* Expr[Any] | Type[?] */] => Any]): PickledQuote =
36+
// TODO: generate a more efficient representation
37+
// - avoid creation of lambdas
38+
// - use swich on id
39+
new PickledQuote:
40+
def bytes(): Array[Byte] =
41+
TastyString.unpickle(pickled)
42+
def exprSplice(idx: Int)(args: Seq[Any])(qctx: QuoteContext): Expr[Any] =
43+
seq(idx)(args).asInstanceOf[QuoteContext => Expr[Any]](qctx)
44+
def typeSplice(idx: Int)(args: Seq[Any]): Type[?] =
45+
seq(idx)(args).asInstanceOf[Type[?]]

library/src/scala/internal/quoted/PickledSplices.scala

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

library/src/scala/internal/quoted/PickledType.scala

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

library/src/scala/internal/tasty/CompilerInterface.scala

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,7 @@ package scala.internal.tasty
22

33
import scala.quoted.QuoteContext
44
import scala.tasty.reflect._
5-
import scala.internal.quoted.PickledExpr
6-
import scala.internal.quoted.PickledSplices
7-
import scala.internal.quoted.PickledType
5+
import scala.internal.quoted.PickledQuote
86

97
/** Part of the reflection interface that needs to be implemented by the compiler */
108
trait CompilerInterface { self: scala.tasty.Reflection =>
@@ -16,12 +14,12 @@ trait CompilerInterface { self: scala.tasty.Reflection =>
1614
/** Unpickle `repr` which represents a pickled `Expr` tree,
1715
* replacing splice nodes with `holes`
1816
*/
19-
def unpickleTerm(bytes: Array[Byte], splices: PickledSplices): Term
17+
def unpickleTerm(pickledQuote: PickledQuote): Term
2018

2119
/** Unpickle `repr` which represents a pickled `Type` tree,
2220
* replacing splice nodes with `holes`
2321
*/
24-
def unpickleTypeTree(bytes: Array[Byte], splices: PickledSplices): TypeTree
22+
def unpickleTypeTree(pickledQuote: PickledQuote): TypeTree
2523

2624
/** Pattern matches the scrutinee against the pattern and returns a tuple
2725
* with the matched holes if successful.

0 commit comments

Comments
 (0)