From c653b1ad62e571e8a1e4077d58c4ce93be0c9796 Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Sun, 14 Jan 2018 11:28:01 +0100 Subject: [PATCH 1/3] Enable optimisations in `Runnres.run` --- .../dotty/tools/dotc/quoted/QuoteDriver.scala | 5 ++--- .../src/dotty/tools/dotc/quoted/Runners.scala | 10 ++++++---- .../run-with-compiler/quote-run-optimise.check | 9 +++++++++ .../run-with-compiler/quote-run-optimise.scala | 17 +++++++++++++++++ 4 files changed, 34 insertions(+), 7 deletions(-) create mode 100644 tests/run-with-compiler/quote-run-optimise.check create mode 100644 tests/run-with-compiler/quote-run-optimise.scala diff --git a/compiler/src/dotty/tools/dotc/quoted/QuoteDriver.scala b/compiler/src/dotty/tools/dotc/quoted/QuoteDriver.scala index f79302494793..b2286f466b19 100644 --- a/compiler/src/dotty/tools/dotc/quoted/QuoteDriver.scala +++ b/compiler/src/dotty/tools/dotc/quoted/QuoteDriver.scala @@ -13,10 +13,9 @@ import java.nio.charset.StandardCharsets class QuoteDriver extends Driver { - def run[T](expr: Expr[T]): T = { + def run[T](expr: Expr[T], optimise: Boolean): T = { val ctx: Context = initCtx.fresh - // TODO enable optimisation? - // ctx.settings.optimise.update(true)(ctx) + ctx.settings.optimise.update(optimise)(ctx) val outDir = new VirtualDirectory("(memory)", None) diff --git a/compiler/src/dotty/tools/dotc/quoted/Runners.scala b/compiler/src/dotty/tools/dotc/quoted/Runners.scala index d5f9b18f7dc5..15948ef0a312 100644 --- a/compiler/src/dotty/tools/dotc/quoted/Runners.scala +++ b/compiler/src/dotty/tools/dotc/quoted/Runners.scala @@ -13,10 +13,7 @@ object Runners { implicit def runner[T]: Runner[T] = new Runner[T] { - def run(expr: Expr[T]): T = expr match { - case expr: ConstantExpr[T] => expr.value - case _ => new QuoteDriver().run(expr) - } + def run(expr: Expr[T]): T = Runners.run(expr, optimise = false) def show(expr: Expr[T]): String = expr match { case expr: ConstantExpr[T] => @@ -27,4 +24,9 @@ object Runners { case _ => new QuoteDriver().show(expr) } } + + def run[T](expr: Expr[T], optimise: Boolean): T = expr match { + case expr: ConstantExpr[T] => expr.value + case _ => new QuoteDriver().run(expr, optimise) + } } diff --git a/tests/run-with-compiler/quote-run-optimise.check b/tests/run-with-compiler/quote-run-optimise.check new file mode 100644 index 000000000000..f40d7d1796a8 --- /dev/null +++ b/tests/run-with-compiler/quote-run-optimise.check @@ -0,0 +1,9 @@ +{ + val a: Int = 3 + println("foo") + 2.+(a) +} +foo +5 +foo +5 diff --git a/tests/run-with-compiler/quote-run-optimise.scala b/tests/run-with-compiler/quote-run-optimise.scala new file mode 100644 index 000000000000..227bb8ef26a2 --- /dev/null +++ b/tests/run-with-compiler/quote-run-optimise.scala @@ -0,0 +1,17 @@ + +import dotty.tools.dotc.quoted.Runners._ + +import scala.quoted._ + +object Test { + def main(args: Array[String]): Unit = { + val expr = '{ + val a = 3 + println("foo") + 2 + a + } + println(expr.show) + println(run(expr.run, optimise = true)) + println(expr.run) + } +} From f2a41269bb95f877f58ec20dcad64e4c4f11b8cc Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Mon, 15 Jan 2018 11:34:04 +0100 Subject: [PATCH 2/3] Add settings object to the Runners.run --- compiler/src/dotty/tools/dotc/quoted/QuoteDriver.scala | 4 ++-- compiler/src/dotty/tools/dotc/quoted/Runners.scala | 10 +++++++--- ...un-optimise.check => quote-run-with-settings.check} | 0 ...un-optimise.scala => quote-run-with-settings.scala} | 2 +- 4 files changed, 10 insertions(+), 6 deletions(-) rename tests/run-with-compiler/{quote-run-optimise.check => quote-run-with-settings.check} (100%) rename tests/run-with-compiler/{quote-run-optimise.scala => quote-run-with-settings.scala} (81%) diff --git a/compiler/src/dotty/tools/dotc/quoted/QuoteDriver.scala b/compiler/src/dotty/tools/dotc/quoted/QuoteDriver.scala index b2286f466b19..4077b019c8ea 100644 --- a/compiler/src/dotty/tools/dotc/quoted/QuoteDriver.scala +++ b/compiler/src/dotty/tools/dotc/quoted/QuoteDriver.scala @@ -13,9 +13,9 @@ import java.nio.charset.StandardCharsets class QuoteDriver extends Driver { - def run[T](expr: Expr[T], optimise: Boolean): T = { + def run[T](expr: Expr[T], settings: Runners.RunSettings): T = { val ctx: Context = initCtx.fresh - ctx.settings.optimise.update(optimise)(ctx) + ctx.settings.optimise.update(settings.optimise)(ctx) val outDir = new VirtualDirectory("(memory)", None) diff --git a/compiler/src/dotty/tools/dotc/quoted/Runners.scala b/compiler/src/dotty/tools/dotc/quoted/Runners.scala index 15948ef0a312..4ab34127b462 100644 --- a/compiler/src/dotty/tools/dotc/quoted/Runners.scala +++ b/compiler/src/dotty/tools/dotc/quoted/Runners.scala @@ -13,7 +13,7 @@ object Runners { implicit def runner[T]: Runner[T] = new Runner[T] { - def run(expr: Expr[T]): T = Runners.run(expr, optimise = false) + def run(expr: Expr[T]): T = Runners.run(expr, RunSettings()) def show(expr: Expr[T]): String = expr match { case expr: ConstantExpr[T] => @@ -25,8 +25,12 @@ object Runners { } } - def run[T](expr: Expr[T], optimise: Boolean): T = expr match { + def run[T](expr: Expr[T], settings: RunSettings): T = expr match { case expr: ConstantExpr[T] => expr.value - case _ => new QuoteDriver().run(expr, optimise) + case _ => new QuoteDriver().run(expr, settings) } + + case class RunSettings( + optimise: Boolean = false + ) } diff --git a/tests/run-with-compiler/quote-run-optimise.check b/tests/run-with-compiler/quote-run-with-settings.check similarity index 100% rename from tests/run-with-compiler/quote-run-optimise.check rename to tests/run-with-compiler/quote-run-with-settings.check diff --git a/tests/run-with-compiler/quote-run-optimise.scala b/tests/run-with-compiler/quote-run-with-settings.scala similarity index 81% rename from tests/run-with-compiler/quote-run-optimise.scala rename to tests/run-with-compiler/quote-run-with-settings.scala index 227bb8ef26a2..6b7e793213fa 100644 --- a/tests/run-with-compiler/quote-run-optimise.scala +++ b/tests/run-with-compiler/quote-run-with-settings.scala @@ -11,7 +11,7 @@ object Test { 2 + a } println(expr.show) - println(run(expr.run, optimise = true)) + println(run(expr.run, RunSettings(optimise = true))) println(expr.run) } } From 873058b3cb6c34b7600a027c56f4013f6feeb80a Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Mon, 15 Jan 2018 13:49:08 +0100 Subject: [PATCH 3/3] Allow custom output directory for class generated by run --- .../dotty/tools/dotc/quoted/ExprCompiler.scala | 15 +++++++++------ .../dotty/tools/dotc/quoted/QuoteDriver.scala | 18 +++++++++++++----- .../src/dotty/tools/dotc/quoted/Runners.scala | 5 ++++- .../quote-run-with-settings.check | 1 + .../quote-run-with-settings.scala | 14 +++++++++++++- tests/run-with-compiler/quote-run.check | 2 +- 6 files changed, 41 insertions(+), 14 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/quoted/ExprCompiler.scala b/compiler/src/dotty/tools/dotc/quoted/ExprCompiler.scala index 24de4011e541..5bbc9bfd157d 100644 --- a/compiler/src/dotty/tools/dotc/quoted/ExprCompiler.scala +++ b/compiler/src/dotty/tools/dotc/quoted/ExprCompiler.scala @@ -3,10 +3,11 @@ package quoted import dotty.tools.backend.jvm.GenBCode import dotty.tools.dotc.ast.tpd - import dotty.tools.dotc.core.Contexts.Context -import dotty.tools.dotc.core.Flags.{EmptyFlags, Method} -import dotty.tools.dotc.core.{Mode, Phases} +import dotty.tools.dotc.core.Decorators._ +import dotty.tools.dotc.core.Flags._ +import dotty.tools.dotc.core.Mode +import dotty.tools.dotc.core.Names.TypeName import dotty.tools.dotc.core.Phases.Phase import dotty.tools.dotc.core.Scopes.{EmptyScope, newScope} import dotty.tools.dotc.core.StdNames.nme @@ -17,14 +18,14 @@ import dotty.tools.dotc.transform.ReifyQuotes import dotty.tools.dotc.typer.FrontEnd import dotty.tools.dotc.util.Positions.Position import dotty.tools.dotc.util.SourceFile -import dotty.tools.io.{Path, PlainFile, VirtualDirectory} +import dotty.tools.io.{AbstractFile, Path, PlainFile} import scala.quoted.Expr /** Compiler that takes the contents of a quoted expression `expr` and produces * a class file with `class ' { def apply: Object = expr }`. */ -class ExprCompiler(directory: VirtualDirectory) extends Compiler { +class ExprCompiler(directory: AbstractFile) extends Compiler { import tpd._ /** A GenBCode phase that outputs to a virtual directory */ @@ -47,6 +48,8 @@ class ExprCompiler(directory: VirtualDirectory) extends Compiler { new ExprRun(this, ctx.addMode(Mode.ReadPositions)) } + def outputClassName: TypeName = "Quoted".toTypeName + /** Frontend that receives scala.quoted.Expr as input */ class ExprFrontend(putInClass: Boolean) extends FrontEnd { import tpd._ @@ -72,7 +75,7 @@ class ExprCompiler(directory: VirtualDirectory) extends Compiler { val pos = Position(0) val assocFile = new PlainFile(Path("")) - val cls = ctx.newCompleteClassSymbol(defn.RootClass, nme.QUOTE.toTypeName, EmptyFlags, + val cls = ctx.newCompleteClassSymbol(defn.RootClass, outputClassName, EmptyFlags, defn.ObjectType :: Nil, newScope, coord = pos, assocFile = assocFile).entered.asClass cls.enter(ctx.newDefaultConstructor(cls), EmptyScope) val meth = ctx.newSymbol(cls, nme.apply, Method, ExprType(defn.AnyType), coord = pos).entered diff --git a/compiler/src/dotty/tools/dotc/quoted/QuoteDriver.scala b/compiler/src/dotty/tools/dotc/quoted/QuoteDriver.scala index 4077b019c8ea..ec8016fb3faa 100644 --- a/compiler/src/dotty/tools/dotc/quoted/QuoteDriver.scala +++ b/compiler/src/dotty/tools/dotc/quoted/QuoteDriver.scala @@ -1,9 +1,9 @@ package dotty.tools.dotc.quoted import dotty.tools.dotc.Driver -import dotty.tools.dotc.core.Contexts.{Context, FreshContext} +import dotty.tools.dotc.core.Contexts.Context import dotty.tools.dotc.core.StdNames._ -import dotty.tools.io.VirtualDirectory +import dotty.tools.io.{AbstractFile, Directory, PlainDirectory, VirtualDirectory} import dotty.tools.repl.AbstractFileClassLoader import scala.quoted.Expr @@ -17,13 +17,21 @@ class QuoteDriver extends Driver { val ctx: Context = initCtx.fresh ctx.settings.optimise.update(settings.optimise)(ctx) - val outDir = new VirtualDirectory("(memory)", None) + val outDir: AbstractFile = settings.outDir match { + case Some(out) => + val dir = Directory(out) + dir.createDirectory() + new PlainDirectory(Directory(out)) + case None => + new VirtualDirectory("(memory)", None) + } - new ExprCompiler(outDir).newRun(ctx).compileExpr(expr) + val driver = new ExprCompiler(outDir) + driver.newRun(ctx).compileExpr(expr) val classLoader = new AbstractFileClassLoader(outDir, this.getClass.getClassLoader) - val clazz = classLoader.loadClass(nme.QUOTE.toString) + val clazz = classLoader.loadClass(driver.outputClassName.toString) val method = clazz.getMethod("apply") val instance = clazz.newInstance() diff --git a/compiler/src/dotty/tools/dotc/quoted/Runners.scala b/compiler/src/dotty/tools/dotc/quoted/Runners.scala index 4ab34127b462..33eae39fd17d 100644 --- a/compiler/src/dotty/tools/dotc/quoted/Runners.scala +++ b/compiler/src/dotty/tools/dotc/quoted/Runners.scala @@ -31,6 +31,9 @@ object Runners { } case class RunSettings( - optimise: Boolean = false + /** Enable optimisation when compiling the quoted code */ + optimise: Boolean = false, + /** Output directory for the copiled quote. If set to None the output will be in memory */ + outDir: Option[String] = None ) } diff --git a/tests/run-with-compiler/quote-run-with-settings.check b/tests/run-with-compiler/quote-run-with-settings.check index f40d7d1796a8..c87c7bf36f6e 100644 --- a/tests/run-with-compiler/quote-run-with-settings.check +++ b/tests/run-with-compiler/quote-run-with-settings.check @@ -5,5 +5,6 @@ } foo 5 + foo 5 diff --git a/tests/run-with-compiler/quote-run-with-settings.scala b/tests/run-with-compiler/quote-run-with-settings.scala index 6b7e793213fa..c5c12959e86a 100644 --- a/tests/run-with-compiler/quote-run-with-settings.scala +++ b/tests/run-with-compiler/quote-run-with-settings.scala @@ -1,4 +1,6 @@ +import java.nio.file.{Files, Paths} + import dotty.tools.dotc.quoted.Runners._ import scala.quoted._ @@ -11,7 +13,17 @@ object Test { 2 + a } println(expr.show) - println(run(expr.run, RunSettings(optimise = true))) println(expr.run) + println() + + val outDir = Paths.get("../out/out-quoted-1") + val classFile = outDir.resolve("Quoted.class") + + Files.deleteIfExists(classFile) + + val settings = RunSettings(optimise = true, outDir = Some(outDir.toString)) + + println(run(expr, settings)) + assert(Files.exists(classFile)) } } diff --git a/tests/run-with-compiler/quote-run.check b/tests/run-with-compiler/quote-run.check index fefd8facd664..3c3bfba445f9 100644 --- a/tests/run-with-compiler/quote-run.check +++ b/tests/run-with-compiler/quote-run.check @@ -13,4 +13,4 @@ lambda(5) Foo false Bar -class '$A$1 +class Quoted$A$1