From 6bf839cc4262e93a4f347dcb5dfc96a49db5348b Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Mon, 12 Mar 2018 09:28:56 +0100 Subject: [PATCH 1/4] Pickle quoted constants to ValueExpr * Avoid const of unpickling * Smaller bytecode --- .../dotty/tools/dotc/core/Definitions.scala | 6 ++++ .../src/dotty/tools/dotc/quoted/Toolbox.scala | 1 + .../tools/dotc/transform/ReifyQuotes.scala | 31 ++++++++++++++++--- library/src/scala/quoted/Expr.scala | 2 ++ tests/run/quote-compile-constants.check | 12 +++++++ tests/run/quote-compile-constants.scala | 18 +++++++++++ 6 files changed, 66 insertions(+), 4 deletions(-) create mode 100644 tests/run/quote-compile-constants.check create mode 100644 tests/run/quote-compile-constants.scala diff --git a/compiler/src/dotty/tools/dotc/core/Definitions.scala b/compiler/src/dotty/tools/dotc/core/Definitions.scala index 872f7bd6302e..1795f77500c8 100644 --- a/compiler/src/dotty/tools/dotc/core/Definitions.scala +++ b/compiler/src/dotty/tools/dotc/core/Definitions.scala @@ -625,6 +625,12 @@ class Definitions { lazy val QuotedExpr_runR = QuotedExprClass.requiredMethodRef(nme.run) def QuotedExpr_run(implicit ctx: Context) = QuotedExpr_runR.symbol + lazy val QuotedExprsModule = ctx.requiredModule("scala.quoted.Exprs") + def QuotedExprsClass(implicit ctx: Context) = QuotedExprsModule.symbol.asClass + + lazy val QuotedExprs_valueExprR = QuotedExprsModule.requiredMethod("valueExpr") + def QuotedExprs_valueExpr(implicit ctx: Context) = QuotedExprs_valueExprR.symbol + lazy val QuotedTypeType = ctx.requiredClassRef("scala.quoted.Type") def QuotedTypeClass(implicit ctx: Context) = QuotedTypeType.symbol.asClass diff --git a/compiler/src/dotty/tools/dotc/quoted/Toolbox.scala b/compiler/src/dotty/tools/dotc/quoted/Toolbox.scala index f27605179816..2894bdcc0be6 100644 --- a/compiler/src/dotty/tools/dotc/quoted/Toolbox.scala +++ b/compiler/src/dotty/tools/dotc/quoted/Toolbox.scala @@ -4,6 +4,7 @@ import dotty.tools.dotc.ast.Trees._ import dotty.tools.dotc.ast.tpd import dotty.tools.dotc.core.Constants._ import dotty.tools.dotc.printing.RefinedPrinter +import dotty.tools.dotc.transform.ReifyQuotes import scala.quoted.Expr import scala.runtime.BoxedUnit diff --git a/compiler/src/dotty/tools/dotc/transform/ReifyQuotes.scala b/compiler/src/dotty/tools/dotc/transform/ReifyQuotes.scala index b65ebec78600..6360e767a3cb 100644 --- a/compiler/src/dotty/tools/dotc/transform/ReifyQuotes.scala +++ b/compiler/src/dotty/tools/dotc/transform/ReifyQuotes.scala @@ -12,6 +12,7 @@ import tasty.TreePickler.Hole import MegaPhase.MiniPhase import SymUtils._ import NameKinds._ +import dotty.tools.dotc.ast.tpd.Tree import typer.Implicits.SearchFailureType import scala.collection.mutable @@ -290,12 +291,25 @@ class ReifyQuotes extends MacroTransformWithImplicits { } else { val (body1, splices) = nested(isQuote = true).split(body) + pickledQuote(body1, splices, isType).withPos(quote.pos) + } + } + + private def pickledQuote(body: Tree, splices: List[Tree], isType: Boolean)(implicit ctx: Context) = { + def pickleAsValue[T](value: T) = + ref(defn.QuotedExprs_valueExpr).appliedToType(body.tpe.widen).appliedTo(Literal(Constant(value))) + def pickleAsTasty() = { val meth = - if (isType) ref(defn.Unpickler_unpickleType).appliedToType(body1.tpe) - else ref(defn.Unpickler_unpickleExpr).appliedToType(body1.tpe.widen) + if (isType) ref(defn.Unpickler_unpickleType).appliedToType(body.tpe) + else ref(defn.Unpickler_unpickleExpr).appliedToType(body.tpe.widen) meth.appliedTo( - liftList(PickledQuotes.pickleQuote(body1).map(x => Literal(Constant(x))), defn.StringType), - liftList(splices, defn.AnyType)).withPos(quote.pos) + liftList(PickledQuotes.pickleQuote(body).map(x => Literal(Constant(x))), defn.StringType), + liftList(splices, defn.AnyType)) + } + if (splices.nonEmpty) pickleAsTasty() + else ReifyQuotes.toValue(body) match { + case Some(value) => pickleAsValue(value) + case _ => pickleAsTasty() } } @@ -473,3 +487,12 @@ class ReifyQuotes extends MacroTransformWithImplicits { } } } + +object ReifyQuotes { + def toValue(tree: Tree): Option[Any] = tree match { + case Literal(Constant(c)) => Some(c) + case Block(Nil, e) => toValue(e) + case Inlined(_, Nil, e) => toValue(e) + case _ => None + } +} diff --git a/library/src/scala/quoted/Expr.scala b/library/src/scala/quoted/Expr.scala index c1e4cbf9ff7c..dc7843828429 100644 --- a/library/src/scala/quoted/Expr.scala +++ b/library/src/scala/quoted/Expr.scala @@ -35,6 +35,8 @@ object Exprs { override def toString: String = s"Expr($value)" } + def valueExpr[T](value: T): ValueExpr[T] = new ValueExpr[T](value) + /** An Expr backed by a tree. Only the current compiler trees are allowed. */ final class TreeExpr[Tree](val tree: Tree) extends quoted.Expr[Any] { override def toString: String = s"Expr()" diff --git a/tests/run/quote-compile-constants.check b/tests/run/quote-compile-constants.check new file mode 100644 index 000000000000..ca5d0cc45ded --- /dev/null +++ b/tests/run/quote-compile-constants.check @@ -0,0 +1,12 @@ +class scala.quoted.Exprs$ValueExpr +class scala.quoted.Exprs$ValueExpr +class scala.quoted.Exprs$ValueExpr +class scala.quoted.Exprs$ValueExpr +class scala.quoted.Exprs$ValueExpr +class scala.quoted.Exprs$ValueExpr +class scala.quoted.Exprs$ValueExpr +class scala.quoted.Exprs$ValueExpr +class scala.quoted.Exprs$ValueExpr +class scala.quoted.Exprs$ValueExpr +class scala.quoted.Exprs$ValueExpr +class scala.quoted.Exprs$ValueExpr diff --git a/tests/run/quote-compile-constants.scala b/tests/run/quote-compile-constants.scala new file mode 100644 index 000000000000..a81ab5f52bd4 --- /dev/null +++ b/tests/run/quote-compile-constants.scala @@ -0,0 +1,18 @@ +import scala.quoted._ + +object Test { + def main(args: Array[String]): Unit = { + println(('(true)).getClass) + println(('{ 'a' }).getClass) + println(('{ '\n' }).getClass) + println(('{ '"' }).getClass) + println(('{ '\'' }).getClass) + println(('{ '\\' }).getClass) + println(('(1)).getClass) + println(('( { { 2 } } )).getClass) + println(('(3L)).getClass) + println(('(4.0f)).getClass) + println(('(5.0d)).getClass) + println(('("xyz")).getClass) + } +} From a9ec534f34cecf58146374c891cfe9043eabe72e Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Fri, 16 Mar 2018 10:31:10 +0100 Subject: [PATCH 2/4] Add tests cases for Unit --- tests/run/quote-compile-constants.check | 3 +++ tests/run/quote-compile-constants.scala | 3 +++ 2 files changed, 6 insertions(+) diff --git a/tests/run/quote-compile-constants.check b/tests/run/quote-compile-constants.check index ca5d0cc45ded..9ef867162049 100644 --- a/tests/run/quote-compile-constants.check +++ b/tests/run/quote-compile-constants.check @@ -10,3 +10,6 @@ class scala.quoted.Exprs$ValueExpr class scala.quoted.Exprs$ValueExpr class scala.quoted.Exprs$ValueExpr class scala.quoted.Exprs$ValueExpr +class scala.quoted.Exprs$ValueExpr +class scala.quoted.Exprs$ValueExpr +class scala.quoted.Exprs$ValueExpr diff --git a/tests/run/quote-compile-constants.scala b/tests/run/quote-compile-constants.scala index a81ab5f52bd4..bcf98ff0f88b 100644 --- a/tests/run/quote-compile-constants.scala +++ b/tests/run/quote-compile-constants.scala @@ -14,5 +14,8 @@ object Test { println(('(4.0f)).getClass) println(('(5.0d)).getClass) println(('("xyz")).getClass) + println(('()).getClass) + println(('{()}).getClass) + println(('{{()}}).getClass) } } From d8e7c39f149379dab900477b6f6698bdb7baedd1 Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Sat, 17 Mar 2018 17:49:27 +0100 Subject: [PATCH 3/4] Rename ValueExpr to LiftedExpr --- .../dotty/tools/dotc/core/Definitions.scala | 4 +-- .../dotc/core/quoted/PickledQuotes.scala | 2 +- .../src/dotty/tools/dotc/quoted/Toolbox.scala | 9 +++--- .../tools/dotc/transform/ReifyQuotes.scala | 2 +- library/src/scala/quoted/Expr.scala | 6 ++-- library/src/scala/quoted/Liftable.scala | 20 ++++++------- .../src/scala/runtime/quoted/Unpickler.scala | 7 ++++- tests/run/quote-compile-constants.check | 30 +++++++++---------- 8 files changed, 40 insertions(+), 40 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/core/Definitions.scala b/compiler/src/dotty/tools/dotc/core/Definitions.scala index 1795f77500c8..f876f7a70c77 100644 --- a/compiler/src/dotty/tools/dotc/core/Definitions.scala +++ b/compiler/src/dotty/tools/dotc/core/Definitions.scala @@ -628,9 +628,6 @@ class Definitions { lazy val QuotedExprsModule = ctx.requiredModule("scala.quoted.Exprs") def QuotedExprsClass(implicit ctx: Context) = QuotedExprsModule.symbol.asClass - lazy val QuotedExprs_valueExprR = QuotedExprsModule.requiredMethod("valueExpr") - def QuotedExprs_valueExpr(implicit ctx: Context) = QuotedExprs_valueExprR.symbol - lazy val QuotedTypeType = ctx.requiredClassRef("scala.quoted.Type") def QuotedTypeClass(implicit ctx: Context) = QuotedTypeType.symbol.asClass @@ -642,6 +639,7 @@ class Definitions { def QuotedType_apply(implicit ctx: Context) = QuotedType_applyR.symbol def Unpickler_unpickleExpr = ctx.requiredMethod("scala.runtime.quoted.Unpickler.unpickleExpr") + def Unpickler_liftedExpr = ctx.requiredMethod("scala.runtime.quoted.Unpickler.liftedExpr") def Unpickler_unpickleType = ctx.requiredMethod("scala.runtime.quoted.Unpickler.unpickleType") lazy val EqType = ctx.requiredClassRef("scala.Eq") diff --git a/compiler/src/dotty/tools/dotc/core/quoted/PickledQuotes.scala b/compiler/src/dotty/tools/dotc/core/quoted/PickledQuotes.scala index 56961c12c075..8dc68490fa40 100644 --- a/compiler/src/dotty/tools/dotc/core/quoted/PickledQuotes.scala +++ b/compiler/src/dotty/tools/dotc/core/quoted/PickledQuotes.scala @@ -33,7 +33,7 @@ object PickledQuotes { /** Transform the expression into its fully spliced Tree */ def quotedExprToTree(expr: quoted.Expr[_])(implicit ctx: Context): Tree = expr match { case expr: TastyExpr[_] => unpickleExpr(expr) - case expr: ValueExpr[_] => Literal(Constant(expr.value)) + case expr: LiftedExpr[_] => Literal(Constant(expr.value)) case expr: TreeExpr[Tree] @unchecked => expr.tree case expr: FunctionAppliedTo[_, _] => functionAppliedTo(quotedExprToTree(expr.f), quotedExprToTree(expr.x)) diff --git a/compiler/src/dotty/tools/dotc/quoted/Toolbox.scala b/compiler/src/dotty/tools/dotc/quoted/Toolbox.scala index 2894bdcc0be6..0957fac21a83 100644 --- a/compiler/src/dotty/tools/dotc/quoted/Toolbox.scala +++ b/compiler/src/dotty/tools/dotc/quoted/Toolbox.scala @@ -4,11 +4,10 @@ import dotty.tools.dotc.ast.Trees._ import dotty.tools.dotc.ast.tpd import dotty.tools.dotc.core.Constants._ import dotty.tools.dotc.printing.RefinedPrinter -import dotty.tools.dotc.transform.ReifyQuotes import scala.quoted.Expr import scala.runtime.BoxedUnit -import scala.quoted.Exprs.ValueExpr +import scala.quoted.Exprs.LiftedExpr import scala.runtime.quoted._ /** Default runners for quoted expressions */ @@ -24,12 +23,12 @@ object Toolbox { ): Toolbox[T] = new Toolbox[T] { def run(expr: Expr[T]): T = expr match { - case expr: ValueExpr[T] => expr.value + case expr: LiftedExpr[T] => expr.value case _ => new QuoteDriver().run(expr, runSettings) } def show(expr: Expr[T]): String = expr match { - case expr: ValueExpr[T] => + case expr: LiftedExpr[T] => implicit val ctx = new QuoteDriver().initCtx if (showSettings.compilerArgs.contains("-color:never")) ctx.settings.color.update("never") @@ -47,7 +46,7 @@ object Toolbox { case _ => None } expr match { - case expr: ValueExpr[T] => Some(expr.value) + case expr: LiftedExpr[T] => Some(expr.value) case _ => new QuoteDriver().withTree(expr, (tree, _) => toConstantOpt(tree), Settings.run()) } } diff --git a/compiler/src/dotty/tools/dotc/transform/ReifyQuotes.scala b/compiler/src/dotty/tools/dotc/transform/ReifyQuotes.scala index 6360e767a3cb..b381511a4e88 100644 --- a/compiler/src/dotty/tools/dotc/transform/ReifyQuotes.scala +++ b/compiler/src/dotty/tools/dotc/transform/ReifyQuotes.scala @@ -297,7 +297,7 @@ class ReifyQuotes extends MacroTransformWithImplicits { private def pickledQuote(body: Tree, splices: List[Tree], isType: Boolean)(implicit ctx: Context) = { def pickleAsValue[T](value: T) = - ref(defn.QuotedExprs_valueExpr).appliedToType(body.tpe.widen).appliedTo(Literal(Constant(value))) + ref(defn.Unpickler_liftedExpr).appliedToType(body.tpe.widen).appliedTo(Literal(Constant(value))) def pickleAsTasty() = { val meth = if (isType) ref(defn.Unpickler_unpickleType).appliedToType(body.tpe) diff --git a/library/src/scala/quoted/Expr.scala b/library/src/scala/quoted/Expr.scala index dc7843828429..1a0d31b23cb7 100644 --- a/library/src/scala/quoted/Expr.scala +++ b/library/src/scala/quoted/Expr.scala @@ -28,15 +28,13 @@ object Exprs { override def toString(): String = s"Expr()" } - /** An Expr backed by a value. + /** An Expr backed by a lifted value. * Values can only be of type Boolean, Byte, Short, Char, Int, Long, Float, Double, Unit, String or Null. */ - final class ValueExpr[T](val value: T) extends Expr[T] { + final class LiftedExpr[T](val value: T) extends Expr[T] { override def toString: String = s"Expr($value)" } - def valueExpr[T](value: T): ValueExpr[T] = new ValueExpr[T](value) - /** An Expr backed by a tree. Only the current compiler trees are allowed. */ final class TreeExpr[Tree](val tree: Tree) extends quoted.Expr[Any] { override def toString: String = s"Expr()" diff --git a/library/src/scala/quoted/Liftable.scala b/library/src/scala/quoted/Liftable.scala index 6fdd1bacebc8..23e45a47e255 100644 --- a/library/src/scala/quoted/Liftable.scala +++ b/library/src/scala/quoted/Liftable.scala @@ -1,6 +1,6 @@ package scala.quoted -import scala.quoted.Exprs.ValueExpr +import scala.runtime.quoted.Unpickler.liftedExpr /** A typeclass for types that can be turned to `quoted.Expr[T]` * without going through an explicit `'(...)` operation. @@ -15,14 +15,14 @@ abstract class Liftable[T] { * gives an alternative implementation using just the basic staging system. */ object Liftable { - implicit def BooleanIsLiftable: Liftable[Boolean] = (x: Boolean) => new ValueExpr(x) - implicit def ByteLiftable: Liftable[Byte] = (x: Byte) => new ValueExpr(x) - implicit def CharIsLiftable: Liftable[Char] = (x: Char) => new ValueExpr(x) - implicit def ShortIsLiftable: Liftable[Short] = (x: Short) => new ValueExpr(x) - implicit def IntIsLiftable: Liftable[Int] = (x: Int) => new ValueExpr(x) - implicit def LongIsLiftable: Liftable[Long] = (x: Long) => new ValueExpr(x) - implicit def FloatIsLiftable: Liftable[Float] = (x: Float) => new ValueExpr(x) - implicit def DoubleIsLiftable: Liftable[Double] = (x: Double) => new ValueExpr(x) + implicit def BooleanIsLiftable: Liftable[Boolean] = (x: Boolean) => liftedExpr(x) + implicit def ByteLiftable: Liftable[Byte] = (x: Byte) => liftedExpr(x) + implicit def CharIsLiftable: Liftable[Char] = (x: Char) => liftedExpr(x) + implicit def ShortIsLiftable: Liftable[Short] = (x: Short) => liftedExpr(x) + implicit def IntIsLiftable: Liftable[Int] = (x: Int) => liftedExpr(x) + implicit def LongIsLiftable: Liftable[Long] = (x: Long) => liftedExpr(x) + implicit def FloatIsLiftable: Liftable[Float] = (x: Float) => liftedExpr(x) + implicit def DoubleIsLiftable: Liftable[Double] = (x: Double) => liftedExpr(x) - implicit def StringIsLiftable: Liftable[String] = (x: String) => new ValueExpr(x) + implicit def StringIsLiftable: Liftable[String] = (x: String) => liftedExpr(x) } diff --git a/library/src/scala/runtime/quoted/Unpickler.scala b/library/src/scala/runtime/quoted/Unpickler.scala index 4cf1e854f8f0..3d25bb2ab164 100644 --- a/library/src/scala/runtime/quoted/Unpickler.scala +++ b/library/src/scala/runtime/quoted/Unpickler.scala @@ -1,7 +1,7 @@ package scala.runtime.quoted import scala.quoted.Types.TastyType -import scala.quoted.Exprs.TastyExpr +import scala.quoted.Exprs.{LiftedExpr, TastyExpr} import scala.quoted.{Expr, Type} /** Provides methods to unpickle `Expr` and `Type` trees. */ @@ -17,6 +17,11 @@ object Unpickler { */ def unpickleExpr[T](repr: Pickled, args: Seq[Any]): Expr[T] = new TastyExpr[T](repr, args) + /** Lift the `value` to an `Expr` tree. + * Values can only be of type Boolean, Byte, Short, Char, Int, Long, Float, Double, Unit, String or Null. + */ + def liftedExpr[T](value: T): LiftedExpr[T] = new LiftedExpr[T](value) + /** Unpickle `repr` which represents a pickled `Type` tree, * replacing splice nodes with `args` */ diff --git a/tests/run/quote-compile-constants.check b/tests/run/quote-compile-constants.check index 9ef867162049..624206cdecbb 100644 --- a/tests/run/quote-compile-constants.check +++ b/tests/run/quote-compile-constants.check @@ -1,15 +1,15 @@ -class scala.quoted.Exprs$ValueExpr -class scala.quoted.Exprs$ValueExpr -class scala.quoted.Exprs$ValueExpr -class scala.quoted.Exprs$ValueExpr -class scala.quoted.Exprs$ValueExpr -class scala.quoted.Exprs$ValueExpr -class scala.quoted.Exprs$ValueExpr -class scala.quoted.Exprs$ValueExpr -class scala.quoted.Exprs$ValueExpr -class scala.quoted.Exprs$ValueExpr -class scala.quoted.Exprs$ValueExpr -class scala.quoted.Exprs$ValueExpr -class scala.quoted.Exprs$ValueExpr -class scala.quoted.Exprs$ValueExpr -class scala.quoted.Exprs$ValueExpr +class scala.quoted.Exprs$LiftedExpr +class scala.quoted.Exprs$LiftedExpr +class scala.quoted.Exprs$LiftedExpr +class scala.quoted.Exprs$LiftedExpr +class scala.quoted.Exprs$LiftedExpr +class scala.quoted.Exprs$LiftedExpr +class scala.quoted.Exprs$LiftedExpr +class scala.quoted.Exprs$LiftedExpr +class scala.quoted.Exprs$LiftedExpr +class scala.quoted.Exprs$LiftedExpr +class scala.quoted.Exprs$LiftedExpr +class scala.quoted.Exprs$LiftedExpr +class scala.quoted.Exprs$LiftedExpr +class scala.quoted.Exprs$LiftedExpr +class scala.quoted.Exprs$LiftedExpr From 47a68d6f13683f7eb2848a9f70798eb040f50e98 Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Sat, 17 Mar 2018 18:17:29 +0100 Subject: [PATCH 4/4] Rename wrongly named liters to capturers --- .../tools/dotc/transform/ReifyQuotes.scala | 48 +++++++++---------- 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/transform/ReifyQuotes.scala b/compiler/src/dotty/tools/dotc/transform/ReifyQuotes.scala index b381511a4e88..056284d117c6 100644 --- a/compiler/src/dotty/tools/dotc/transform/ReifyQuotes.scala +++ b/compiler/src/dotty/tools/dotc/transform/ReifyQuotes.scala @@ -73,19 +73,19 @@ class ReifyQuotes extends MacroTransformWithImplicits { val levelOf = new mutable.HashMap[Symbol, Int] /** Register a reference defined in a quote but used in another quote nested in a splice. - * Returns a lifted version of the reference that needs to be used in its place. + * Returns a version of the reference that needs to be used in its place. * '{ * val x = ??? * { ... '{ ... x ... } ... }.unary_~ * } - * Lifting the `x` in `{ ... '{ ... x ... } ... }.unary_~` will return a `x$1.unary_~` for which the `x$1` + * Eta expanding the `x` in `{ ... '{ ... x ... } ... }.unary_~` will return a `x$1.unary_~` for which the `x$1` * be created by some outer reifier. * * This transformation is only applied to definitions at staging level 1. * - * See `needsLifting` + * See `isCaptured` */ - val lifters = new mutable.HashMap[Symbol, RefTree => Tree] + val capturers = new mutable.HashMap[Symbol, RefTree => Tree] } /** The main transformer class @@ -348,7 +348,7 @@ class ReifyQuotes extends MacroTransformWithImplicits { * { ... '{ ... x$1.unary_~ ... y$1.unary_~ ... } ... } * } * - * See: `lift` + * See: `capture` * * At the same time register `embedded` trees `x` and `y` to place as arguments of the hole * placed in the original code. @@ -361,17 +361,17 @@ class ReifyQuotes extends MacroTransformWithImplicits { private def makeLambda(tree: Tree)(implicit ctx: Context): Tree = { def body(arg: Tree)(implicit ctx: Context): Tree = { var i = 0 - transformWithLifter(tree)( - (lifted: mutable.ListBuffer[Tree]) => (tree: RefTree) => { + transformWithCapturer(tree)( + (captured: mutable.ListBuffer[Tree]) => (tree: RefTree) => { val argTpe = if (tree.isTerm) defn.QuotedExprType.appliedTo(tree.tpe.widen) else defn.QuotedTypeType.appliedTo(defn.AnyType) val selectArg = arg.select(nme.apply).appliedTo(Literal(Constant(i))).asInstance(argTpe) - val liftedArg = SyntheticValDef(UniqueName.fresh(tree.name.toTermName).toTermName, selectArg) + val capturedArg = SyntheticValDef(UniqueName.fresh(tree.name.toTermName).toTermName, selectArg) i += 1 embedded += tree - lifted += liftedArg - ref(liftedArg.symbol) + captured += capturedArg + ref(capturedArg.symbol) } ) } @@ -382,21 +382,21 @@ class ReifyQuotes extends MacroTransformWithImplicits { Closure(meth, tss => body(tss.head.head)(ctx.withOwner(meth)).changeOwner(ctx.owner, meth)) } - private def transformWithLifter(tree: Tree)( - lifter: mutable.ListBuffer[Tree] => RefTree => Tree)(implicit ctx: Context): Tree = { - val lifted = new mutable.ListBuffer[Tree] - val lifter2 = lifter(lifted) - outer.enteredSyms.foreach(s => lifters.put(s, lifter2)) + private def transformWithCapturer(tree: Tree)( + capturer: mutable.ListBuffer[Tree] => RefTree => Tree)(implicit ctx: Context): Tree = { + val captured = new mutable.ListBuffer[Tree] + val captured2 = capturer(captured) + outer.enteredSyms.foreach(s => capturers.put(s, captured2)) val tree2 = transform(tree) - lifters --= outer.enteredSyms - seq(lifted.result(), tree2) + capturers --= outer.enteredSyms + seq(captured.result(), tree2) } - /** Returns true if this tree will be lifted by `makeLambda` */ - private def needsLifting(tree: RefTree)(implicit ctx: Context): Boolean = { - // Check phase consistency and presence of lifter + /** Returns true if this tree will be captured by `makeLambda` */ + private def isCaptured(tree: RefTree)(implicit ctx: Context): Boolean = { + // Check phase consistency and presence of capturer level == 1 && !tree.symbol.is(Inline) && levelOf.get(tree.symbol).contains(1) && - lifters.contains(tree.symbol) + capturers.contains(tree.symbol) } /** Transform `tree` and return the resulting tree and all `embedded` quotes @@ -430,9 +430,9 @@ class ReifyQuotes extends MacroTransformWithImplicits { quotation(quotedTree, tree) case tree: Select if tree.symbol.isSplice => splice(tree) - case tree: RefTree if needsLifting(tree) => - val lift = lifters(tree.symbol) - splice(lift(tree).select(if (tree.isTerm) nme.UNARY_~ else tpnme.UNARY_~)) + case tree: RefTree if isCaptured(tree) => + val capturer = capturers(tree.symbol) + splice(capturer(tree).select(if (tree.isTerm) nme.UNARY_~ else tpnme.UNARY_~)) case Block(stats, _) => val last = enteredSyms stats.foreach(markDef)