Skip to content

Commit

Permalink
Add quote ASTs to TASTy
Browse files Browse the repository at this point in the history
  • Loading branch information
nicolasstucki committed Apr 11, 2024
1 parent dfff8f6 commit 4b7da46
Show file tree
Hide file tree
Showing 3 changed files with 54 additions and 22 deletions.
40 changes: 22 additions & 18 deletions compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala
Original file line number Diff line number Diff line change
Expand Up @@ -701,28 +701,32 @@ class TreePickler(pickler: TastyPickler, attributes: Attributes) {
pickleTree(alias)
}
case tree @ Quote(body, Nil) =>
// TODO: Add QUOTE tag to TASTy
assert(body.isTerm,
"""Quote with type should not be pickled.
|Quote with type should only exists after staging phase at staging level 0.""".stripMargin)
pickleTree(
// scala.quoted.runtime.Expr.quoted[<tree.bodyType>](<body>)
ref(defn.QuotedRuntime_exprQuote)
.appliedToType(tree.bodyType)
.appliedTo(body)
.withSpan(tree.span)
)
writeByte(QUOTE)
pickleTree(body)
case Splice(expr) =>
pickleTree( // TODO: Add SPLICE tag to TASTy
// scala.quoted.runtime.Expr.splice[<tree.tpe>](<expr>)
ref(defn.QuotedRuntime_exprSplice)
.appliedToType(tree.tpe)
.appliedTo(expr)
.withSpan(tree.span)
)
case tree: QuotePattern =>
// TODO: Add QUOTEPATTERN tag to TASTy
pickleTree(QuotePatterns.encode(tree))
writeByte(SPLICE)
withLength {
pickleTree(expr)
pickleType(tree.tpe) // TODO is is possible to recompute this type from `expr`?
}
case QuotePattern(bindings, body, quotes) =>
writeByte(QUOTEPATTERN)
withLength {
if body.isType then writeByte(EXPLICITtpt)
pickleTree(body)
pickleTree(quotes)
pickleType(tree.tpe)
bindings.foreach(pickleTree)
}
case SplicePattern(pat, args) =>
writeByte(SPLICEPATTERN)
withLength {
pickleTree(pat)
args.foreach(pickleTree)
}
case Hole(_, idx, args, _) =>
writeByte(HOLE)
withLength {
Expand Down
21 changes: 20 additions & 1 deletion compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala
Original file line number Diff line number Diff line change
Expand Up @@ -1314,6 +1314,9 @@ class TreeUnpickler(reader: TastyReader,
NamedArg(readName(), readTree())
case EXPLICITtpt =>
readTpt()
case QUOTE =>
val body = readTree()
Quote(body, Nil)
case _ =>
readPathTree()
}
Expand Down Expand Up @@ -1503,7 +1506,7 @@ class TreeUnpickler(reader: TastyReader,
val unapply = UnApply(fn, implicitArgs, argPats, patType)
if fn.symbol == defn.QuoteMatching_ExprMatch_unapply
|| fn.symbol == defn.QuoteMatching_TypeMatch_unapply
then QuotePatterns.decode(unapply)
then QuotePatterns.decode(unapply) // decode pre 3.5.0 encoding
else unapply
case REFINEDtpt =>
val refineCls = symAtAddr.getOrElse(start,
Expand Down Expand Up @@ -1551,6 +1554,22 @@ class TreeUnpickler(reader: TastyReader,
val hi = if currentAddr == end then lo else readTpt()
val alias = if currentAddr == end then EmptyTree else readTpt()
createNullableTypeBoundsTree(lo, hi, alias)
case SPLICE =>
val expr = readTree()
val tpe = readType() // TODO is is possible to recompute this type from `expr`?
Splice(expr, tpe)
case QUOTEPATTERN =>
val bodyReader = fork
skipTree()
val quotes = readTree()
val patType = readType()
val bindings = readStats(ctx.owner, end)
val body = bodyReader.readTree() // need bindings in scope, so needs to be read before
QuotePattern(bindings, body, quotes, patType)
case SPLICEPATTERN =>
val pat = readTree()
val args = until(end)(readTree())
untpd.SplicePattern(pat, args) // TODO set type?
case HOLE =>
readHole(end, isTerm = true)
case _ =>
Expand Down
15 changes: 12 additions & 3 deletions tasty/src/dotty/tools/tasty/TastyFormat.scala
Original file line number Diff line number Diff line change
Expand Up @@ -110,10 +110,14 @@ Standard-Section: "ASTs" TopLevelStat*
WHILE Length cond_Term body_Term -- while cond do body
REPEATED Length elem_Type elem_Term* -- Varargs argument of type `elem`
SELECTouter Length levels_Nat qual_Term underlying_Type -- Follow `levels` outer links, starting from `qual`, with given `underlying` type
QUOTE body_Term -- Quoted expression `'{ body }`
SPLICE Length expr_Term tpe_Type -- Spliced expression `${ expr }` with type `tpe`
SPLICEPATTEN Length pat_Term args_Term* -- Pattern splice `${pat}` or `$pat(args*)` in a quoted pattern
-- patterns:
BIND Length boundName_NameRef patType_Type pat_Term -- name @ pat, wherev `patType` is the type of the bound symbol
ALTERNATIVE Length alt_Term* -- alt1 | ... | altn as a pattern
UNAPPLY Length fun_Term ImplicitArg* pat_Type pat_Term* -- Unapply node `fun(_: pat_Type)(implicitArgs)` flowing into patterns `pat`.
QUOTEPATTERN Length body_Term quotes_Term pat_Type bindings_Term* -- Quote pattern node `'{ bindings*; body }(using quotes)'`
-- type trees:
IDENTtpt NameRef Type -- Used for all type idents
SELECTtpt NameRef qual_Term -- qual.name
Expand Down Expand Up @@ -543,6 +547,7 @@ object TastyFormat {
final val BOUNDED = 102
final val EXPLICITtpt = 103
final val ELIDED = 104
final val QUOTE = 105


// Tree Cat. 4: tag Nat AST
Expand Down Expand Up @@ -600,7 +605,7 @@ object TastyFormat {
final val ANDtype = 165
// final val ??? = 166
final val ORtype = 167
// final val ??? = 168
final val SPLICE = 168
final val POLYtype = 169
final val TYPELAMBDAtype = 170
final val LAMBDAtpt = 171
Expand All @@ -610,8 +615,8 @@ object TastyFormat {
final val TYPEREFin = 175
final val SELECTin = 176
final val EXPORT = 177
// final val ??? = 178
// final val ??? = 179
final val QUOTEPATTERN = 178
final val SPLICEPATTERN = 179
final val METHODtype = 180
final val APPLYsigpoly = 181

Expand Down Expand Up @@ -858,6 +863,10 @@ object TastyFormat {
case PROTECTEDqualified => "PROTECTEDqualified"
case EXPLICITtpt => "EXPLICITtpt"
case ELIDED => "ELIDED"
case QUOTE => "QUOTE"
case SPLICE => "SPLICE"
case QUOTEPATTERN => "QUOTEPATTERN"
case SPLICEPATTERN => "SPLICEPATTERN"
case HOLE => "HOLE"
}

Expand Down

0 comments on commit 4b7da46

Please sign in to comment.