Skip to content

Rename scala.quoted.staging.{Toolbox => Compiler} #11129

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Jan 18, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 10 additions & 10 deletions docs/docs/reference/metaprogramming/staging.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,15 +60,15 @@ The framework as discussed so far allows code to be staged, i.e. be prepared
to be executed at a later stage. To run that code, there is another method
in class `Expr` called `run`. Note that `$` and `run` both map from `Expr[T]`
to `T` but only `$` is subject to the PCP, whereas `run` is just a normal method.
`run` provides a `Quotes` that can be used to show the expression in its scope.
On the other hand `withQuotes` provides a `Quotes` without evaluating the expression.
`scala.quoted.staging.run` provides a `Quotes` that can be used to show the expression in its scope.
On the other hand `scala.quoted.staging.withQuotes` provides a `Quotes` without evaluating the expression.

```scala
package scala.quoted.staging

def run[T](expr: Quotes ?=> Expr[T])(using toolbox: Toolbox): T = ...
def run[T](expr: Quotes ?=> Expr[T])(using Compiler): T = ...

def withQuotes[T](thunk: Quotes ?=> T)(using toolbox: Toolbox): T = ...
def withQuotes[T](thunk: Quotes ?=> T)(using Compiler): T = ...
```

## Create a new Scala 3 project with staging enabled
Expand Down Expand Up @@ -99,17 +99,17 @@ scala -with-compiler -classpath out Test
Now take exactly the same example as in [Macros](./macros.md). Assume that we
do not want to pass an array statically but generate code at run-time and pass
the value, also at run-time. Note, how we make a future-stage function of type
`Expr[Array[Int] => Int]` in line 6 below. Using `run { ... }` we can evaluate an
expression at runtime. Within the scope of `run` we can also invoke `show` on an expression
`Expr[Array[Int] => Int]` in line 6 below. Using `staging.run { ... }` we can evaluate an
expression at runtime. Within the scope of `staging.run` we can also invoke `show` on an expression
to get a source-like representation of the expression.

```scala
import scala.quoted.staging._
import scala.quoted._

// make available the necessary toolbox for runtime code generation
given Toolbox = Toolbox.make(getClass.getClassLoader)
// make available the necessary compiler for runtime code generation
given staging.Compiler = staging.Compiler.make(getClass.getClassLoader)

val f: Array[Int] => Int = run {
val f: Array[Int] => Int = staging.run {
val stagedSum: Expr[Array[Int] => Int] =
'{ (arr: Array[Int]) => ${sum('arr)}}
println(stagedSum.show) // Prints "(arr: Array[Int]) => { var sum = 0; ... }"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import scala.quoted._, staging._

given Toolbox = Toolbox.make(getClass.getClassLoader)
given Compiler = Compiler.make(getClass.getClassLoader)

val f: Array[Int] => Int = run {
val stagedSum: Expr[Array[Int] => Int] = '{ (arr: Array[Int]) => 6 }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@ package hello

// Import `Expr` and some extension methods
import scala.quoted._
import scala.quoted.staging.{run, Toolbox}
import scala.quoted.staging.{run, Compiler}

object Main {

given Toolbox = Toolbox.make(getClass.getClassLoader)
given Compiler = Compiler.make(getClass.getClassLoader)

def main(args: Array[String]): Unit = {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,11 @@ import org.junit.Test

// Import Expr and some extension methods
import scala.quoted._
import scala.quoted.staging._

class Tests {

implicit val toolbox: scala.quoted.staging.Toolbox = scala.quoted.staging.Toolbox.make(getClass.getClassLoader)
given Compiler = Compiler.make(getClass.getClassLoader)

@Test def test(): Unit = {
import hello.Main._
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,26 +5,26 @@ import scala.annotation.implicitNotFound

import scala.quoted.runtime.impl.ScopeException

@implicitNotFound("Could not find implicit scala.quoted.staging.Toolbox.\n\nDefault toolbox can be instantiated with:\n `given scala.quoted.staging.Toolbox = scala.quoted.staging.Toolbox.make(getClass.getClassLoader)`\n\n")
trait Toolbox:
@implicitNotFound("Could not find implicit scala.quoted.staging.Compiler.\n\nDefault compiler can be instantiated with:\n `import scala.quoted.staging.Compiler; given Compiler = Compiler.make(getClass.getClassLoader)`\n\n")
trait Compiler:
def run[T](expr: Quotes => Expr[T]): T

object Toolbox:
object Compiler:

/** Create a new instance of the toolbox using the the classloader of the application.
/** Create a new instance of the compiler using the the classloader of the application.
*
* Usuage:
* ```
* import scala.quoted.staging._
* given Toolbox = Toolbox.make(getClass.getClassLoader)
* given Compiler = Compiler.make(getClass.getClassLoader)
* ```
*
* @param appClassloader classloader of the application that generated the quotes
* @param settings toolbox settings
* @return A new instance of the toolbox
* @param settings compiler settings
* @return A new instance of the compiler
*/
def make(appClassloader: ClassLoader)(implicit settings: Settings): Toolbox =
new Toolbox:
def make(appClassloader: ClassLoader)(implicit settings: Settings): Compiler =
new Compiler:

private[this] val driver: QuoteDriver = new QuoteDriver(appClassloader)

Expand All @@ -43,14 +43,14 @@ object Toolbox:

end new

/** Setting of the Toolbox instance. */
/** Setting of the Compiler instance. */
case class Settings private (outDir: Option[String], compilerArgs: List[String])

object Settings:

implicit def default: Settings = make()

/** Make toolbox settings
/** Make compiler settings
* @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.
*/
Expand All @@ -62,4 +62,4 @@ object Toolbox:

end Settings

end Toolbox
end Compiler
8 changes: 4 additions & 4 deletions staging/src/scala/quoted/staging/QuoteDriver.scala
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import dotty.tools.repl.AbstractFileClassLoader
import dotty.tools.dotc.reporting._
import dotty.tools.dotc.util.ClasspathFromClassloader
import scala.quoted._
import scala.quoted.staging.Toolbox
import scala.quoted.staging.Compiler
import java.io.File
import scala.annotation.tailrec

Expand All @@ -22,7 +22,7 @@ private class QuoteDriver(appClassloader: ClassLoader) extends Driver:

private[this] val contextBase: ContextBase = new ContextBase

def run[T](exprBuilder: Quotes => Expr[T], settings: Toolbox.Settings): T =
def run[T](exprBuilder: Quotes => Expr[T], settings: Compiler.Settings): T =
val outDir: AbstractFile =
settings.outDir match
case Some(out) =>
Expand All @@ -34,7 +34,7 @@ private class QuoteDriver(appClassloader: ClassLoader) extends Driver:
end outDir

val (_, ctx0: Context) = setup(settings.compilerArgs.toArray :+ "dummy.scala", initCtx.fresh)
val ctx = setToolboxSettings(ctx0.fresh.setSetting(ctx0.settings.outputDir, outDir), settings)
val ctx = setCompilerSettings(ctx0.fresh.setSetting(ctx0.settings.outputDir, outDir), settings)

new QuoteCompiler().newRun(ctx).compileExpr(exprBuilder) match
case Right(value) =>
Expand All @@ -59,7 +59,7 @@ private class QuoteDriver(appClassloader: ClassLoader) extends Driver:
ictx.settings.classpath.update(ClasspathFromClassloader(appClassloader))(using ictx)
ictx

private def setToolboxSettings(ctx: FreshContext, settings: Toolbox.Settings): ctx.type =
private def setCompilerSettings(ctx: FreshContext, settings: Compiler.Settings): ctx.type =
// An error in the generated code is a bug in the compiler
// Setting the throwing reporter however will report any exception
ctx.setReporter(new ThrowingReporter(ctx.reporter))
Expand Down
8 changes: 4 additions & 4 deletions staging/src/scala/quoted/staging/staging.scala
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ package object staging:
* This method should not be called in a context where there is already has a `Quotes`
* such as within a `run` or a `withQuotes`.
*/
def run[T](expr: Quotes ?=> Expr[T])(using toolbox: Toolbox): T = toolbox.run(expr(using _))
def run[T](expr: Quotes ?=> Expr[T])(using compiler: Compiler): T = compiler.run(expr(using _))

/** Provide a new quote context within the scope of the argument that is only valid within the scope the argument.
* Return the result of the argument.
Expand All @@ -32,15 +32,15 @@ package object staging:
* This method should not be called in a context where there is already has a `Quotes`
* such as within a `run` or a `withQuotes`.
*/
def withQuotes[T](thunk: Quotes ?=> T)(using toolbox: Toolbox): T =
def withQuotes[T](thunk: Quotes ?=> T)(using compiler: Compiler): T =
val noResult = new Object
var result: T = noResult.asInstanceOf[T]
def dummyRun(using Quotes): Expr[Unit] = {
result = thunk
'{}
}
toolbox.run(dummyRun(using _))
assert(result != noResult) // toolbox.run should have thrown an exception
compiler.run(dummyRun(using _))
assert(result != noResult) // compiler.run should have thrown an exception
result
end withQuotes

Expand Down
6 changes: 3 additions & 3 deletions staging/test-resources/repl-staging/i6007
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
scala> import scala.quoted._
scala> import scala.quoted.staging._
scala> implicit def toolbox: Toolbox = Toolbox.make(getClass.getClassLoader)
def toolbox: quoted.staging.Toolbox
scala> import quoted.staging.{Compiler => StagingCompiler, _}
scala> implicit def compiler: StagingCompiler = StagingCompiler.make(getClass.getClassLoader)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I had to rename it here due to some strange interaction with java.lang.Compiler import

scala> import quoted._
scala> import quoted.staging._
scala> implicit def compiler: Compiler = Compiler.make(getClass.getClassLoader)
1 | implicit def compiler: Compiler = Compiler.make(getClass.getClassLoader)
  |                        ^^^^^^^^
  |                       Reference to Compiler is ambiguous,
  |                       it is both imported by import quoted.staging._
  |                       and imported subsequently by import java.lang.{...}

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

StagingCompiler sounds like an even better name than Compiler.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a more general issue. I opened #11146.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If staging compiler sound better, maybe we could rewrite the docs to use

import scala.quoted._

given staging.Compiler = staging.Compiler.make(...)

staging.run {
  ...
}

That does not affect the API changes and could be done later.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it will help in avoiding misuse of the staging API --- the users are forced to think what's staging and its difference from macros.

def compiler: quoted.staging.Compiler
scala> def v(using Quotes) = '{ (if true then Some(1) else None).map(v => v+1) }
def v(using x$1: quoted.Quotes): quoted.Expr[Option[Int]]
scala> scala.quoted.staging.withQuotes(v.show)
Expand Down
6 changes: 3 additions & 3 deletions staging/test-resources/repl-staging/i6263
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
scala> import quoted._
scala> import quoted.staging._
scala> implicit def toolbox: Toolbox = Toolbox.make(getClass.getClassLoader)
def toolbox: quoted.staging.Toolbox
scala> import quoted.staging.{Compiler => StagingCompiler, _}
scala> implicit def compiler: StagingCompiler = StagingCompiler.make(getClass.getClassLoader)
def compiler: quoted.staging.Compiler
scala> def fn[T : Type](v : T) = println("ok")
def fn[T](v: T)(implicit evidence$1: quoted.Type[T]): Unit
scala> withQuotes { fn("foo") }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ object Macros {

inline def foo(i: => Int): Int = ${ fooImpl('i) }
def fooImpl(i: Expr[Int])(using Quotes): Expr[Int] = {
given Toolbox = Toolbox.make(getClass.getClassLoader)
given Compiler = Compiler.make(getClass.getClassLoader)
val y: Int = run(i)
y
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import scala.quoted.staging._
import Macros._

object Test {
given Toolbox = Toolbox.make(getClass.getClassLoader)
given Compiler = Compiler.make(getClass.getClassLoader)
def main(args: Array[String]): Unit = withQuotes {
val x = '{
val y = 1
Expand Down
2 changes: 1 addition & 1 deletion tests/neg-staging/i5941/macro_1.scala
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ object Lens {
}

def impl[S: Type, T: Type](getter: Expr[S => T])(using Quotes): Expr[Lens[S, T]] = {
implicit val toolbox: scala.quoted.staging.Toolbox = scala.quoted.staging.Toolbox.make(this.getClass.getClassLoader)
implicit val toolbox: scala.quoted.staging.Compiler = scala.quoted.staging.Compiler.make(this.getClass.getClassLoader)
import quotes.reflect._
import util._
// obj.copy(field = value)
Expand Down
4 changes: 2 additions & 2 deletions tests/neg-staging/i9692.scala
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ import scala.quoted.staging._

object Test extends App {

// make available the necessary toolbox for runtime code generation
given Toolbox = Toolbox.make(getClass.getClassLoader)
// make available the necessary compiler for runtime code generation
given Compiler = Compiler.make(getClass.getClassLoader)

run {
val expr: Expr[Int] = '{ var x = 1; x = 2; 42 }
Expand Down
2 changes: 1 addition & 1 deletion tests/neg-staging/i9693.scala
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import scala.quoted.staging._
object Test extends App {

// make available the necessary toolbox for runtime code generation
given Toolbox = Toolbox.make(getClass.getClassLoader)
given Compiler = Compiler.make(getClass.getClassLoader)

run {
val expr: Expr[Int] = '{ var x = 1; x = 2; 42 }
Expand Down
2 changes: 1 addition & 1 deletion tests/neg-staging/quote-run-in-macro-1/quoted_1.scala
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import scala.quoted.staging._

object Macros {

given Toolbox = Toolbox.make(getClass.getClassLoader)
given Compiler = Compiler.make(getClass.getClassLoader)
inline def foo(i: => Int): Int = ${ fooImpl('i) }
def fooImpl(i: Expr[Int])(using Quotes): Expr[Int] = {
val y: Int = run(i)
Expand Down
2 changes: 1 addition & 1 deletion tests/pos-staging/quote-0.scala
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ object Macros {

class Test {

given Toolbox = Toolbox.make(getClass.getClassLoader)
given Compiler = Compiler.make(getClass.getClassLoader)

run {
val program = '{
Expand Down
2 changes: 1 addition & 1 deletion tests/pos-staging/quote-assert/quoted_2.scala
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,6 @@ object Test {
${ assertImpl('{x != 0}) }
}

given Toolbox = Toolbox.make(getClass.getClassLoader)
given Compiler = Compiler.make(getClass.getClassLoader)
run(program)
}
2 changes: 1 addition & 1 deletion tests/run-staging/abstract-int-quote.scala
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import scala.quoted.staging._

object Test:

given Toolbox = Toolbox.make(getClass.getClassLoader)
given Compiler = Compiler.make(getClass.getClassLoader)

def main(args: Array[String]): Unit =
def reduce[T: Type](using Quotes)(succ: Expr[T] => Expr[T], zero: Expr[T]): Expr[T] = '{
Expand Down
2 changes: 1 addition & 1 deletion tests/run-staging/expr-matches.scala
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import scala.quoted.staging._


object Test {
given Toolbox = Toolbox.make(getClass.getClassLoader)
given Compiler = Compiler.make(getClass.getClassLoader)
def main(args: Array[String]): Unit = withQuotes {
assert('{1} matches '{1})
assert('{println("foo")} matches '{println("foo")})
Expand Down
2 changes: 1 addition & 1 deletion tests/run-staging/i3823-b.scala
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import scala.quoted._
import scala.quoted.staging._
object Test {
given Toolbox = Toolbox.make(getClass.getClassLoader)
given Compiler = Compiler.make(getClass.getClassLoader)
def main(args: Array[String]): Unit = withQuotes {
def f[T](x: Expr[T])(implicit t: Type[T]) = '{
val z: t.Underlying = $x
Expand Down
2 changes: 1 addition & 1 deletion tests/run-staging/i3823-c.scala
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import scala.quoted._
import scala.quoted.staging._
object Test {
given Toolbox = Toolbox.make(getClass.getClassLoader)
given Compiler = Compiler.make(getClass.getClassLoader)
def main(args: Array[String]): Unit = withQuotes {
def f[T](x: Expr[T])(implicit t: Type[T]) = '{
val z = $x
Expand Down
2 changes: 1 addition & 1 deletion tests/run-staging/i3823.scala
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import scala.quoted._
import scala.quoted.staging._
object Test {
given Toolbox = Toolbox.make(getClass.getClassLoader)
given Compiler = Compiler.make(getClass.getClassLoader)
def main(args: Array[String]): Unit = withQuotes {
def f[T](x: Expr[T])(using t: Type[T]) = '{
val z: t.Underlying = $x
Expand Down
2 changes: 1 addition & 1 deletion tests/run-staging/i3847-b.scala
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ object Arrays {
}

object Test {
given Toolbox = Toolbox.make(getClass.getClassLoader)
given Compiler = Compiler.make(getClass.getClassLoader)
def main(args: Array[String]): Unit = withQuotes {
import Arrays._
implicit val ct: Expr[ClassTag[Int]] = '{ClassTag.Int}
Expand Down
2 changes: 1 addition & 1 deletion tests/run-staging/i3847.scala
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ object Arrays {
}

object Test {
implicit val toolbox: scala.quoted.staging.Toolbox = scala.quoted.staging.Toolbox.make(this.getClass.getClassLoader)
implicit val toolbox: scala.quoted.staging.Compiler = scala.quoted.staging.Compiler.make(this.getClass.getClassLoader)
def main(args: Array[String]): Unit = withQuotes {
import Arrays._
implicit val ct: Expr[ClassTag[Int]] = '{ClassTag.Int}
Expand Down
2 changes: 1 addition & 1 deletion tests/run-staging/i3876-b.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import scala.quoted._
import scala.quoted.staging._
object Test {
def main(args: Array[String]): Unit = {
given Toolbox = Toolbox.make(getClass.getClassLoader)
given Compiler = Compiler.make(getClass.getClassLoader)

def x(using Quotes): Expr[Int] = '{3}

Expand Down
2 changes: 1 addition & 1 deletion tests/run-staging/i3876-c.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import scala.quoted._
import scala.quoted.staging._
object Test {
def main(args: Array[String]): Unit = {
implicit def toolbox: scala.quoted.staging.Toolbox = scala.quoted.staging.Toolbox.make(getClass.getClassLoader)
implicit def toolbox: scala.quoted.staging.Compiler = scala.quoted.staging.Compiler.make(getClass.getClassLoader)

def x(using Quotes): Expr[Int] = '{3}

Expand Down
2 changes: 1 addition & 1 deletion tests/run-staging/i3876-d.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import scala.quoted._
import scala.quoted.staging._
object Test {
def main(args: Array[String]): Unit = {
given Toolbox = Toolbox.make(getClass.getClassLoader)
given Compiler = Compiler.make(getClass.getClassLoader)

def x(using Quotes): Expr[Int] = '{3}

Expand Down
2 changes: 1 addition & 1 deletion tests/run-staging/i3876-e.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import scala.quoted._
import scala.quoted.staging._
object Test {
def main(args: Array[String]): Unit = {
given Toolbox = Toolbox.make(getClass.getClassLoader)
given Compiler = Compiler.make(getClass.getClassLoader)

def x(using Quotes): Expr[Int] = '{ println(); 3 }

Expand Down
Loading