diff --git a/compiler/src/dotty/tools/dotc/quoted/QuoteDriver.scala b/compiler/src/dotty/tools/dotc/quoted/QuoteDriver.scala index 69b1d2d2c976..e10ee7c9f705 100644 --- a/compiler/src/dotty/tools/dotc/quoted/QuoteDriver.scala +++ b/compiler/src/dotty/tools/dotc/quoted/QuoteDriver.scala @@ -11,12 +11,13 @@ import scala.quoted.Expr import java.net.URLClassLoader +import Runners.{Settings, Run, Show} + class QuoteDriver extends Driver { import tpd._ - def run[T](expr: Expr[T], settings: Runners.RunSettings): T = { - val ctx: Context = initCtx.fresh - ctx.settings.optimise.update(settings.optimise)(ctx) + def run[T](expr: Expr[T], settings: Settings[Run]): T = { + val (_, ctx: Context) = setup(settings.compilerArgs.toArray :+ "dummy.scala", initCtx.fresh) val outDir: AbstractFile = settings.outDir match { case Some(out) => @@ -39,25 +40,25 @@ class QuoteDriver extends Driver { method.invoke(instance).asInstanceOf[T] } - def show(expr: Expr[_]): String = { + def show(expr: Expr[_], settings: Settings[Show]): String = { def show(tree: Tree, ctx: Context): String = { val printer = new DecompilerPrinter(ctx) val pageWidth = ctx.settings.pageWidth.value(ctx) printer.toText(tree).mkString(pageWidth, false) } - withTree(expr, show) + withTree(expr, show, settings) } - def withTree[T](expr: Expr[_], f: (Tree, Context) => T): T = { - val ctx: Context = initCtx.fresh - ctx.settings.color.update("never")(ctx) // TODO support colored show + def withTree[T](expr: Expr[_], f: (Tree, Context) => T, settings: Settings[_]): T = { + val (_, ctx: Context) = setup(settings.compilerArgs.toArray :+ "dummy.scala", initCtx.fresh) + var output: Option[T] = None def registerTree(tree: tpd.Tree)(ctx: Context): Unit = { assert(output.isEmpty) output = Some(f(tree, ctx)) } new ExprDecompiler(registerTree).newRun(ctx).compileExpr(expr) - output.getOrElse(throw new Exception("Could not extact " + expr)) + output.getOrElse(throw new Exception("Could not extract " + expr)) } override def initCtx: Context = { diff --git a/compiler/src/dotty/tools/dotc/quoted/Runners.scala b/compiler/src/dotty/tools/dotc/quoted/Runners.scala index c9560c5d2de3..1bd66050f515 100644 --- a/compiler/src/dotty/tools/dotc/quoted/Runners.scala +++ b/compiler/src/dotty/tools/dotc/quoted/Runners.scala @@ -14,19 +14,14 @@ import scala.runtime.quoted._ object Runners { import tpd._ + type Run + type Show + implicit def runner[T]: Runner[T] = new Runner[T] { - def run(expr: Expr[T]): T = Runners.run(expr, RunSettings()) + def run(expr: Expr[T]): T = Runners.run(expr, Settings.run()) - def show(expr: Expr[T]): String = expr match { - case expr: ConstantExpr[T] => - implicit val ctx = new QuoteDriver().initCtx - ctx.settings.color.update("never") - val printer = new RefinedPrinter(ctx) - if (expr.value == BoxedUnit.UNIT) "()" - else printer.toText(Literal(Constant(expr.value))).mkString(Int.MaxValue, false) - case _ => new QuoteDriver().show(expr) - } + def show(expr: Expr[T]): String = Runners.show(expr, Settings.show()) def toConstantOpt(expr: Expr[T]): Option[T] = { def toConstantOpt(tree: Tree): Option[T] = tree match { @@ -37,21 +32,59 @@ object Runners { } expr match { case expr: ConstantExpr[T] => Some(expr.value) - case _ => new QuoteDriver().withTree(expr, (tree, _) => toConstantOpt(tree)) + case _ => new QuoteDriver().withTree(expr, (tree, _) => toConstantOpt(tree), Settings.run()) } } } - def run[T](expr: Expr[T], settings: RunSettings): T = expr match { + def run[T](expr: Expr[T], settings: Settings[Run]): 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 - ) + def show[T](expr: Expr[T], settings: Settings[Show]): String = expr match { + case expr: ConstantExpr[T] => + implicit val ctx = new QuoteDriver().initCtx + if (settings.compilerArgs.contains("-color:never")) + ctx.settings.color.update("never") + val printer = new RefinedPrinter(ctx) + if (expr.value == BoxedUnit.UNIT) "()" + else printer.toText(Literal(Constant(expr.value))).mkString(Int.MaxValue, false) + case _ => new QuoteDriver().show(expr, settings) + } + + class Settings[T] private (val outDir: Option[String], val compilerArgs: List[String]) + + object Settings { + + /** Quote run settings + * @param optimise Enable optimisation when compiling the quoted code + * @param outDir Output directory for the compiled quote. If set to None the output will be in memory + * @param compilerArgs Compiler arguments. Use only if you know what you are doing. + */ + def run( + optimise: Boolean = false, + outDir: Option[String] = None, + compilerArgs: List[String] = Nil + ): Settings[Run] = { + var compilerArgs1 = compilerArgs + if (optimise) compilerArgs1 = "-optimise" :: compilerArgs1 + new Settings(outDir, compilerArgs1) + } + + /** Quote show settings + * @param compilerArgs Compiler arguments. Use only if you know what you are doing. + */ + def show( + color: Boolean = false, + compilerArgs: List[String] = Nil + ): Settings[Show] = { + var compilerArgs1 = compilerArgs + compilerArgs1 = s"-color:${if (color) "always" else "never"}" :: compilerArgs1 + new Settings(None, compilerArgs1) + } + + } + } diff --git a/tests/run-with-compiler/quote-run-with-settings.scala b/tests/run-with-compiler/quote-run-with-settings.scala index c5c12959e86a..5eea7fbc2033 100644 --- a/tests/run-with-compiler/quote-run-with-settings.scala +++ b/tests/run-with-compiler/quote-run-with-settings.scala @@ -21,7 +21,7 @@ object Test { Files.deleteIfExists(classFile) - val settings = RunSettings(optimise = true, outDir = Some(outDir.toString)) + val settings = Settings.run(optimise = true, outDir = Some(outDir.toString)) println(run(expr, settings)) assert(Files.exists(classFile))