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 f79302494793..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 @@ -13,18 +13,25 @@ import java.nio.charset.StandardCharsets class QuoteDriver extends Driver { - def run[T](expr: Expr[T]): T = { + def run[T](expr: Expr[T], settings: Runners.RunSettings): T = { val ctx: Context = initCtx.fresh - // TODO enable optimisation? - // ctx.settings.optimise.update(true)(ctx) - - val outDir = new VirtualDirectory("(memory)", None) + ctx.settings.optimise.update(settings.optimise)(ctx) + + 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 d5f9b18f7dc5..33eae39fd17d 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, RunSettings()) def show(expr: Expr[T]): String = expr match { case expr: ConstantExpr[T] => @@ -27,4 +24,16 @@ object Runners { case _ => new QuoteDriver().show(expr) } } + + def run[T](expr: Expr[T], settings: RunSettings): T = expr match { + case expr: ConstantExpr[T] => expr.value + case _ => new QuoteDriver().run(expr, settings) + } + + case class RunSettings( + /** 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 new file mode 100644 index 000000000000..c87c7bf36f6e --- /dev/null +++ b/tests/run-with-compiler/quote-run-with-settings.check @@ -0,0 +1,10 @@ +{ + val a: Int = 3 + println("foo") + 2.+(a) +} +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 new file mode 100644 index 000000000000..c5c12959e86a --- /dev/null +++ b/tests/run-with-compiler/quote-run-with-settings.scala @@ -0,0 +1,29 @@ + +import java.nio.file.{Files, Paths} + +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(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