From 990bf88c26595ba87838ebd317acf664f0b33bc1 Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Tue, 20 Mar 2018 21:01:24 +0100 Subject: [PATCH] Create single argument for each capture --- .../tools/dotc/transform/ReifyQuotes.scala | 31 +++++++++++-------- .../quote-two-captured-ref.check | 5 +++ .../quote-two-captured-ref.scala | 18 +++++++++++ 3 files changed, 41 insertions(+), 13 deletions(-) create mode 100644 tests/run-with-compiler/quote-two-captured-ref.check create mode 100644 tests/run-with-compiler/quote-two-captured-ref.scala diff --git a/compiler/src/dotty/tools/dotc/transform/ReifyQuotes.scala b/compiler/src/dotty/tools/dotc/transform/ReifyQuotes.scala index c1efa6ce2966..d235b33fa7d8 100644 --- a/compiler/src/dotty/tools/dotc/transform/ReifyQuotes.scala +++ b/compiler/src/dotty/tools/dotc/transform/ReifyQuotes.scala @@ -402,16 +402,21 @@ class ReifyQuotes extends MacroTransformWithImplicits { def body(arg: Tree)(implicit ctx: Context): Tree = { var i = 0 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 capturedArg = SyntheticValDef(UniqueName.fresh(tree.name.toTermName).toTermName, selectArg) - i += 1 - embedded += tree - captured += capturedArg - ref(capturedArg.symbol) + (captured: mutable.Map[Symbol, Tree]) => { + (tree: RefTree) => { + def newCapture = { + 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 capturedArg = SyntheticValDef(UniqueName.fresh(tree.name.toTermName).toTermName, selectArg) + i += 1 + embedded += tree + captured.put(tree.symbol, capturedArg) + capturedArg + } + ref(captured.getOrElseUpdate(tree.symbol, newCapture).symbol) + } } ) } @@ -423,13 +428,13 @@ class ReifyQuotes extends MacroTransformWithImplicits { } private def transformWithCapturer(tree: Tree)( - capturer: mutable.ListBuffer[Tree] => RefTree => Tree)(implicit ctx: Context): Tree = { - val captured = new mutable.ListBuffer[Tree] + capturer: mutable.Map[Symbol, Tree] => RefTree => Tree)(implicit ctx: Context): Tree = { + val captured = mutable.LinkedHashMap.empty[Symbol, Tree] val captured2 = capturer(captured) outer.enteredSyms.foreach(s => capturers.put(s, captured2)) val tree2 = transform(tree) capturers --= outer.enteredSyms - seq(captured.result(), tree2) + seq(captured.result().valuesIterator.toList, tree2) } /** Returns true if this tree will be captured by `makeLambda` */ diff --git a/tests/run-with-compiler/quote-two-captured-ref.check b/tests/run-with-compiler/quote-two-captured-ref.check new file mode 100644 index 000000000000..62c016a6094c --- /dev/null +++ b/tests/run-with-compiler/quote-two-captured-ref.check @@ -0,0 +1,5 @@ +1 +{ + val x: Int = 1 + println(x.+(x)) +} diff --git a/tests/run-with-compiler/quote-two-captured-ref.scala b/tests/run-with-compiler/quote-two-captured-ref.scala new file mode 100644 index 000000000000..a04da52aad15 --- /dev/null +++ b/tests/run-with-compiler/quote-two-captured-ref.scala @@ -0,0 +1,18 @@ +import quoted._ +import dotty.tools.dotc.quoted.Toolbox._ + +object Test { + def main(args: Array[String]): Unit = { + val q = '{ + val x = 1 + println(~{ + println(1) + val a = '(x) + val b = '(x) + '{ ~a + ~b } + }) + } + + println(q.show) + } +}