Skip to content

Commit f7063f0

Browse files
committed
Add quote ASTs to TASTy
Add AST nodes for Quote, Splice, QuotePattern, and QuoteSplice to TASTy.
1 parent 62e0641 commit f7063f0

File tree

17 files changed

+75
-28
lines changed

17 files changed

+75
-28
lines changed

compiler/src/dotty/tools/dotc/ast/tpd.scala

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,12 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo {
178178
def Splice(expr: Tree, tpe: Type)(using Context): Splice =
179179
untpd.Splice(expr).withType(tpe)
180180

181+
def Splice(expr: Tree)(using Context): Splice =
182+
ta.assignType(untpd.Splice(expr), expr)
183+
184+
def SplicePattern(pat: Tree, args: List[Tree], tpe: Type)(using Context): SplicePattern =
185+
untpd.SplicePattern(pat, args).withType(tpe)
186+
181187
def Hole(isTerm: Boolean, idx: Int, args: List[Tree], content: Tree, tpe: Type)(using Context): Hole =
182188
untpd.Hole(isTerm, idx, args, content).withType(tpe)
183189

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

Lines changed: 23 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -701,28 +701,33 @@ class TreePickler(pickler: TastyPickler, attributes: Attributes) {
701701
pickleTree(alias)
702702
}
703703
case tree @ Quote(body, Nil) =>
704-
// TODO: Add QUOTE tag to TASTy
705704
assert(body.isTerm,
706705
"""Quote with type should not be pickled.
707706
|Quote with type should only exists after staging phase at staging level 0.""".stripMargin)
708-
pickleTree(
709-
// scala.quoted.runtime.Expr.quoted[<tree.bodyType>](<body>)
710-
ref(defn.QuotedRuntime_exprQuote)
711-
.appliedToType(tree.bodyType)
712-
.appliedTo(body)
713-
.withSpan(tree.span)
714-
)
707+
writeByte(QUOTE)
708+
pickleTree(body)
715709
case Splice(expr) =>
716-
pickleTree( // TODO: Add SPLICE tag to TASTy
717-
// scala.quoted.runtime.Expr.splice[<tree.tpe>](<expr>)
718-
ref(defn.QuotedRuntime_exprSplice)
719-
.appliedToType(tree.tpe)
720-
.appliedTo(expr)
721-
.withSpan(tree.span)
722-
)
723-
case tree: QuotePattern =>
724-
// TODO: Add QUOTEPATTERN tag to TASTy
725-
pickleTree(QuotePatterns.encode(tree))
710+
writeByte(SPLICE)
711+
pickleTree(expr)
712+
case QuotePattern(bindings, body, quotes) =>
713+
writeByte(QUOTEPATTERN)
714+
withLength {
715+
if body.isType then writeByte(EXPLICITtpt)
716+
pickleTree(body)
717+
pickleTree(quotes)
718+
pickleType(tree.tpe)
719+
bindings.foreach(pickleTree)
720+
}
721+
case SplicePattern(pat, args) =>
722+
writeByte(SPLICEPATTERN)
723+
withLength {
724+
pickleTree(pat)
725+
pickleType(tree.tpe)
726+
args.foreach(pickleTree)
727+
// TODO: Handle `targs` for #18271. We should be able to pickle the
728+
// `targs ::: args` if we add an `EXPLICITtpt` to the targs.
729+
// See comment in SPLICEPATTERN unpickling.
730+
}
726731
case Hole(_, idx, args, _) =>
727732
writeByte(HOLE)
728733
withLength {

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

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1314,6 +1314,10 @@ class TreeUnpickler(reader: TastyReader,
13141314
NamedArg(readName(), readTree())
13151315
case EXPLICITtpt =>
13161316
readTpt()
1317+
case QUOTE =>
1318+
Quote(readTree(), Nil)
1319+
case SPLICE =>
1320+
Splice(readTree())
13171321
case _ =>
13181322
readPathTree()
13191323
}
@@ -1379,9 +1383,9 @@ class TreeUnpickler(reader: TastyReader,
13791383
val fn = readTree()
13801384
val args = until(end)(readTree())
13811385
if fn.symbol.isConstructor then constructorApply(fn, args)
1382-
else if fn.symbol == defn.QuotedRuntime_exprQuote then quotedExpr(fn, args)
1383-
else if fn.symbol == defn.QuotedRuntime_exprSplice then splicedExpr(fn, args)
1384-
else if fn.symbol == defn.QuotedRuntime_exprNestedSplice then nestedSpliceExpr(fn, args)
1386+
else if fn.symbol == defn.QuotedRuntime_exprQuote then quotedExpr(fn, args) // decode pre 3.5.0 encoding
1387+
else if fn.symbol == defn.QuotedRuntime_exprSplice then splicedExpr(fn, args) // decode pre 3.5.0 encoding
1388+
else if fn.symbol == defn.QuotedRuntime_exprNestedSplice then nestedSpliceExpr(fn, args) // decode pre 3.5.0 encoding
13851389
else tpd.Apply(fn, args)
13861390
case TYPEAPPLY =>
13871391
tpd.TypeApply(readTree(), until(end)(readTpt()))
@@ -1503,7 +1507,7 @@ class TreeUnpickler(reader: TastyReader,
15031507
val unapply = UnApply(fn, implicitArgs, argPats, patType)
15041508
if fn.symbol == defn.QuoteMatching_ExprMatch_unapply
15051509
|| fn.symbol == defn.QuoteMatching_TypeMatch_unapply
1506-
then QuotePatterns.decode(unapply)
1510+
then QuotePatterns.decode(unapply) // decode pre 3.5.0 encoding
15071511
else unapply
15081512
case REFINEDtpt =>
15091513
val refineCls = symAtAddr.getOrElse(start,
@@ -1551,6 +1555,23 @@ class TreeUnpickler(reader: TastyReader,
15511555
val hi = if currentAddr == end then lo else readTpt()
15521556
val alias = if currentAddr == end then EmptyTree else readTpt()
15531557
createNullableTypeBoundsTree(lo, hi, alias)
1558+
case QUOTEPATTERN =>
1559+
val bodyReader = fork
1560+
skipTree()
1561+
val quotes = readTree()
1562+
val patType = readType()
1563+
val bindings = readStats(ctx.owner, end)
1564+
val body = bodyReader.readTree() // need bindings in scope, so needs to be read before
1565+
QuotePattern(bindings, body, quotes, patType)
1566+
case SPLICEPATTERN =>
1567+
val pat = readTree()
1568+
val patType = readType()
1569+
val args = until(end)(readTree())
1570+
// TODO: for #18271 we need to split the targs from the args.
1571+
// Probably need somthing like this:
1572+
// val (targs, args) = until(end)(readTree()).span(_.isType)
1573+
// See comment in SPLICEPATTERN pickling
1574+
SplicePattern(pat, args, patType)
15541575
case HOLE =>
15551576
readHole(end, isTerm = true)
15561577
case _ =>

compiler/src/dotty/tools/dotc/typer/TypeAssigner.scala

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -531,6 +531,12 @@ trait TypeAssigner {
531531
def assignType(tree: untpd.UnApply, proto: Type)(using Context): UnApply =
532532
tree.withType(proto)
533533

534+
def assignType(tree: untpd.Splice, expr: Tree)(using Context): Splice =
535+
val tpe = expr.tpe // Quotes ?=> Expr[T]
536+
.baseType(defn.FunctionSymbol(1, isContextual = true)).argTypes.last // Expr[T]
537+
.baseType(defn.QuotedExprClass).argTypes.head // T
538+
tree.withType(tpe)
539+
534540
def assignType(tree: untpd.QuotePattern, proto: Type)(using Context): QuotePattern =
535541
tree.withType(proto)
536542

tasty/src/dotty/tools/tasty/TastyFormat.scala

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -110,10 +110,14 @@ Standard-Section: "ASTs" TopLevelStat*
110110
WHILE Length cond_Term body_Term -- while cond do body
111111
REPEATED Length elem_Type elem_Term* -- Varargs argument of type `elem`
112112
SELECTouter Length levels_Nat qual_Term underlying_Type -- Follow `levels` outer links, starting from `qual`, with given `underlying` type
113+
QUOTE body_Term -- Quoted expression `'{ body }`
114+
SPLICE expr_Term -- Spliced expression `${ expr }`
115+
SPLICEPATTEN Length pat_Term tpe_Type args_Term* -- Pattern splice `${pat}` or `$pat(args*)` in a quoted pattern of type `tpe`
113116
-- patterns:
114117
BIND Length boundName_NameRef patType_Type pat_Term -- name @ pat, wherev `patType` is the type of the bound symbol
115118
ALTERNATIVE Length alt_Term* -- alt1 | ... | altn as a pattern
116119
UNAPPLY Length fun_Term ImplicitArg* pat_Type pat_Term* -- Unapply node `fun(_: pat_Type)(implicitArgs)` flowing into patterns `pat`.
120+
QUOTEPATTERN Length body_Term quotes_Term pat_Type bindings_Term* -- Quote pattern node `'{ bindings*; body }(using quotes)`
117121
-- type trees:
118122
IDENTtpt NameRef Type -- Used for all type idents
119123
SELECTtpt NameRef qual_Term -- qual.name
@@ -543,7 +547,8 @@ object TastyFormat {
543547
final val BOUNDED = 102
544548
final val EXPLICITtpt = 103
545549
final val ELIDED = 104
546-
550+
final val QUOTE = 105
551+
final val SPLICE = 106
547552

548553
// Tree Cat. 4: tag Nat AST
549554
final val firstNatASTTreeTag = IDENT
@@ -610,8 +615,8 @@ object TastyFormat {
610615
final val TYPEREFin = 175
611616
final val SELECTin = 176
612617
final val EXPORT = 177
613-
// final val ??? = 178
614-
// final val ??? = 179
618+
final val QUOTEPATTERN = 178
619+
final val SPLICEPATTERN = 179
615620
final val METHODtype = 180
616621
final val APPLYsigpoly = 181
617622

@@ -858,6 +863,10 @@ object TastyFormat {
858863
case PROTECTEDqualified => "PROTECTEDqualified"
859864
case EXPLICITtpt => "EXPLICITtpt"
860865
case ELIDED => "ELIDED"
866+
case QUOTE => "QUOTE"
867+
case SPLICE => "SPLICE"
868+
case QUOTEPATTERN => "QUOTEPATTERN"
869+
case SPLICEPATTERN => "SPLICEPATTERN"
861870
case HOLE => "HOLE"
862871
}
863872

File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
((q: scala.quoted.Quotes) ?=> scala.quoted.runtime.Expr.quote[scala.Int](3).apply(using q))
1+
((q: scala.quoted.Quotes) ?=> scala.quoted.runtime.Expr.quote[3](3).apply(using q))
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
((q: scala.quoted.Quotes) ?=> {
2-
val a: scala.quoted.Expr[scala.Int] = scala.quoted.runtime.Expr.quote[scala.Int](4).apply(using q)
2+
val a: scala.quoted.Expr[scala.Int] = scala.quoted.runtime.Expr.quote[4](4).apply(using q)
33
((contextual$2: scala.quoted.Quotes) ?=> a).apply(using q)
44
})
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
((q: scala.quoted.Quotes) ?=> {
2-
val a: scala.quoted.Expr[scala.Int] = scala.quoted.runtime.Expr.quote[scala.Int](4).apply(using q)
2+
val a: scala.quoted.Expr[scala.Int] = scala.quoted.runtime.Expr.quote[4](4).apply(using q)
33
((q2: scala.quoted.Quotes) ?=> ((contextual$2: scala.quoted.Quotes) ?=> a).apply(using q2))
44
}.apply(using q))

0 commit comments

Comments
 (0)