@@ -12,6 +12,7 @@ import tasty.TreePickler.Hole
12
12
import MegaPhase .MiniPhase
13
13
import SymUtils ._
14
14
import NameKinds ._
15
+ import dotty .tools .dotc .ast .tpd .Tree
15
16
import typer .Implicits .SearchFailureType
16
17
17
18
import scala .collection .mutable
@@ -72,19 +73,19 @@ class ReifyQuotes extends MacroTransformWithImplicits {
72
73
val levelOf = new mutable.HashMap [Symbol , Int ]
73
74
74
75
/** Register a reference defined in a quote but used in another quote nested in a splice.
75
- * Returns a lifted version of the reference that needs to be used in its place.
76
+ * Returns a version of the reference that needs to be used in its place.
76
77
* '{
77
78
* val x = ???
78
79
* { ... '{ ... x ... } ... }.unary_~
79
80
* }
80
- * Lifting the `x` in `{ ... '{ ... x ... } ... }.unary_~` will return a `x$1.unary_~` for which the `x$1`
81
+ * Eta expanding the `x` in `{ ... '{ ... x ... } ... }.unary_~` will return a `x$1.unary_~` for which the `x$1`
81
82
* be created by some outer reifier.
82
83
*
83
84
* This transformation is only applied to definitions at staging level 1.
84
85
*
85
- * See `needsLifting `
86
+ * See `isCaptured `
86
87
*/
87
- val lifters = new mutable.HashMap [Symbol , RefTree => Tree ]
88
+ val capturers = new mutable.HashMap [Symbol , RefTree => Tree ]
88
89
}
89
90
90
91
/** The main transformer class
@@ -330,12 +331,25 @@ class ReifyQuotes extends MacroTransformWithImplicits {
330
331
}
331
332
else {
332
333
val (body1, splices) = nested(isQuote = true ).split(body)
334
+ pickledQuote(body1, splices, isType).withPos(quote.pos)
335
+ }
336
+ }
337
+
338
+ private def pickledQuote (body : Tree , splices : List [Tree ], isType : Boolean )(implicit ctx : Context ) = {
339
+ def pickleAsValue [T ](value : T ) =
340
+ ref(defn.Unpickler_liftedExpr ).appliedToType(body.tpe.widen).appliedTo(Literal (Constant (value)))
341
+ def pickleAsTasty () = {
333
342
val meth =
334
- if (isType) ref(defn.Unpickler_unpickleType ).appliedToType(body1 .tpe)
335
- else ref(defn.Unpickler_unpickleExpr ).appliedToType(body1 .tpe.widen)
343
+ if (isType) ref(defn.Unpickler_unpickleType ).appliedToType(body .tpe)
344
+ else ref(defn.Unpickler_unpickleExpr ).appliedToType(body .tpe.widen)
336
345
meth.appliedTo(
337
- liftList(PickledQuotes .pickleQuote(body1).map(x => Literal (Constant (x))), defn.StringType ),
338
- liftList(splices, defn.AnyType )).withPos(quote.pos)
346
+ liftList(PickledQuotes .pickleQuote(body).map(x => Literal (Constant (x))), defn.StringType ),
347
+ liftList(splices, defn.AnyType ))
348
+ }
349
+ if (splices.nonEmpty) pickleAsTasty()
350
+ else ReifyQuotes .toValue(body) match {
351
+ case Some (value) => pickleAsValue(value)
352
+ case _ => pickleAsTasty()
339
353
}
340
354
}
341
355
@@ -374,7 +388,7 @@ class ReifyQuotes extends MacroTransformWithImplicits {
374
388
* { ... '{ ... x$1.unary_~ ... y$1.unary_~ ... } ... }
375
389
* }
376
390
*
377
- * See: `lift `
391
+ * See: `capture `
378
392
*
379
393
* At the same time register `embedded` trees `x` and `y` to place as arguments of the hole
380
394
* placed in the original code.
@@ -387,17 +401,17 @@ class ReifyQuotes extends MacroTransformWithImplicits {
387
401
private def makeLambda (tree : Tree )(implicit ctx : Context ): Tree = {
388
402
def body (arg : Tree )(implicit ctx : Context ): Tree = {
389
403
var i = 0
390
- transformWithLifter (tree)(
391
- (lifted : mutable.ListBuffer [Tree ]) => (tree : RefTree ) => {
404
+ transformWithCapturer (tree)(
405
+ (captured : mutable.ListBuffer [Tree ]) => (tree : RefTree ) => {
392
406
val argTpe =
393
407
if (tree.isTerm) defn.QuotedExprType .appliedTo(tree.tpe.widen)
394
408
else defn.QuotedTypeType .appliedTo(defn.AnyType )
395
409
val selectArg = arg.select(nme.apply).appliedTo(Literal (Constant (i))).asInstance(argTpe)
396
- val liftedArg = SyntheticValDef (UniqueName .fresh(tree.name.toTermName).toTermName, selectArg)
410
+ val capturedArg = SyntheticValDef (UniqueName .fresh(tree.name.toTermName).toTermName, selectArg)
397
411
i += 1
398
412
embedded += tree
399
- lifted += liftedArg
400
- ref(liftedArg .symbol)
413
+ captured += capturedArg
414
+ ref(capturedArg .symbol)
401
415
}
402
416
)
403
417
}
@@ -408,21 +422,21 @@ class ReifyQuotes extends MacroTransformWithImplicits {
408
422
Closure (meth, tss => body(tss.head.head)(ctx.withOwner(meth)).changeOwner(ctx.owner, meth))
409
423
}
410
424
411
- private def transformWithLifter (tree : Tree )(
412
- lifter : mutable.ListBuffer [Tree ] => RefTree => Tree )(implicit ctx : Context ): Tree = {
413
- val lifted = new mutable.ListBuffer [Tree ]
414
- val lifter2 = lifter(lifted )
415
- outer.enteredSyms.foreach(s => lifters .put(s, lifter2 ))
425
+ private def transformWithCapturer (tree : Tree )(
426
+ capturer : mutable.ListBuffer [Tree ] => RefTree => Tree )(implicit ctx : Context ): Tree = {
427
+ val captured = new mutable.ListBuffer [Tree ]
428
+ val captured2 = capturer(captured )
429
+ outer.enteredSyms.foreach(s => capturers .put(s, captured2 ))
416
430
val tree2 = transform(tree)
417
- lifters --= outer.enteredSyms
418
- seq(lifted .result(), tree2)
431
+ capturers --= outer.enteredSyms
432
+ seq(captured .result(), tree2)
419
433
}
420
434
421
- /** Returns true if this tree will be lifted by `makeLambda` */
422
- private def needsLifting (tree : RefTree )(implicit ctx : Context ): Boolean = {
423
- // Check phase consistency and presence of lifter
435
+ /** Returns true if this tree will be captured by `makeLambda` */
436
+ private def isCaptured (tree : RefTree )(implicit ctx : Context ): Boolean = {
437
+ // Check phase consistency and presence of capturer
424
438
level == 1 && ! tree.symbol.is(Inline ) && levelOf.get(tree.symbol).contains(1 ) &&
425
- lifters .contains(tree.symbol)
439
+ capturers .contains(tree.symbol)
426
440
}
427
441
428
442
/** Transform `tree` and return the resulting tree and all `embedded` quotes
@@ -459,9 +473,9 @@ class ReifyQuotes extends MacroTransformWithImplicits {
459
473
splice(ref(splicedType).select(tpnme.UNARY_~ ))
460
474
case tree : Select if tree.symbol.isSplice =>
461
475
splice(tree)
462
- case tree : RefTree if needsLifting (tree) =>
463
- val lift = lifters (tree.symbol)
464
- splice(lift (tree).select(if (tree.isTerm) nme.UNARY_~ else tpnme.UNARY_~ ))
476
+ case tree : RefTree if isCaptured (tree) =>
477
+ val capturer = capturers (tree.symbol)
478
+ splice(capturer (tree).select(if (tree.isTerm) nme.UNARY_~ else tpnme.UNARY_~ ))
465
479
case Block (stats, _) =>
466
480
val last = enteredSyms
467
481
stats.foreach(markDef)
@@ -515,3 +529,12 @@ class ReifyQuotes extends MacroTransformWithImplicits {
515
529
}
516
530
}
517
531
}
532
+
533
+ object ReifyQuotes {
534
+ def toValue (tree : Tree ): Option [Any ] = tree match {
535
+ case Literal (Constant (c)) => Some (c)
536
+ case Block (Nil , e) => toValue(e)
537
+ case Inlined (_, Nil , e) => toValue(e)
538
+ case _ => None
539
+ }
540
+ }
0 commit comments