Skip to content

Commit e12cb19

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

File tree

14 files changed

+72
-25
lines changed

14 files changed

+72
-25
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.

0 commit comments

Comments
 (0)