@@ -12,6 +12,7 @@ import tasty.TreePickler.Hole
1212import MegaPhase .MiniPhase
1313import SymUtils ._
1414import NameKinds ._
15+ import dotty .tools .dotc .ast .tpd .Tree
1516import typer .Implicits .SearchFailureType
1617
1718import scala .collection .mutable
@@ -72,19 +73,19 @@ class ReifyQuotes extends MacroTransformWithImplicits {
7273 val levelOf = new mutable.HashMap [Symbol , Int ]
7374
7475 /** 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.
7677 * '{
7778 * val x = ???
7879 * { ... '{ ... x ... } ... }.unary_~
7980 * }
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`
8182 * be created by some outer reifier.
8283 *
8384 * This transformation is only applied to definitions at staging level 1.
8485 *
85- * See `needsLifting `
86+ * See `isCaptured `
8687 */
87- val lifters = new mutable.HashMap [Symbol , RefTree => Tree ]
88+ val capturers = new mutable.HashMap [Symbol , RefTree => Tree ]
8889 }
8990
9091 /** The main transformer class
@@ -330,12 +331,25 @@ class ReifyQuotes extends MacroTransformWithImplicits {
330331 }
331332 else {
332333 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 () = {
333342 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)
336345 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()
339353 }
340354 }
341355
@@ -374,7 +388,7 @@ class ReifyQuotes extends MacroTransformWithImplicits {
374388 * { ... '{ ... x$1.unary_~ ... y$1.unary_~ ... } ... }
375389 * }
376390 *
377- * See: `lift `
391+ * See: `capture `
378392 *
379393 * At the same time register `embedded` trees `x` and `y` to place as arguments of the hole
380394 * placed in the original code.
@@ -387,17 +401,17 @@ class ReifyQuotes extends MacroTransformWithImplicits {
387401 private def makeLambda (tree : Tree )(implicit ctx : Context ): Tree = {
388402 def body (arg : Tree )(implicit ctx : Context ): Tree = {
389403 var i = 0
390- transformWithLifter (tree)(
391- (lifted : mutable.ListBuffer [Tree ]) => (tree : RefTree ) => {
404+ transformWithCapturer (tree)(
405+ (captured : mutable.ListBuffer [Tree ]) => (tree : RefTree ) => {
392406 val argTpe =
393407 if (tree.isTerm) defn.QuotedExprType .appliedTo(tree.tpe.widen)
394408 else defn.QuotedTypeType .appliedTo(defn.AnyType )
395409 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)
397411 i += 1
398412 embedded += tree
399- lifted += liftedArg
400- ref(liftedArg .symbol)
413+ captured += capturedArg
414+ ref(capturedArg .symbol)
401415 }
402416 )
403417 }
@@ -408,21 +422,21 @@ class ReifyQuotes extends MacroTransformWithImplicits {
408422 Closure (meth, tss => body(tss.head.head)(ctx.withOwner(meth)).changeOwner(ctx.owner, meth))
409423 }
410424
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 ))
416430 val tree2 = transform(tree)
417- lifters --= outer.enteredSyms
418- seq(lifted .result(), tree2)
431+ capturers --= outer.enteredSyms
432+ seq(captured .result(), tree2)
419433 }
420434
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
424438 level == 1 && ! tree.symbol.is(Inline ) && levelOf.get(tree.symbol).contains(1 ) &&
425- lifters .contains(tree.symbol)
439+ capturers .contains(tree.symbol)
426440 }
427441
428442 /** Transform `tree` and return the resulting tree and all `embedded` quotes
@@ -459,9 +473,9 @@ class ReifyQuotes extends MacroTransformWithImplicits {
459473 splice(ref(splicedType).select(tpnme.UNARY_~ ))
460474 case tree : Select if tree.symbol.isSplice =>
461475 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_~ ))
465479 case Block (stats, _) =>
466480 val last = enteredSyms
467481 stats.foreach(markDef)
@@ -515,3 +529,12 @@ class ReifyQuotes extends MacroTransformWithImplicits {
515529 }
516530 }
517531}
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