Skip to content

QuoteContext show can show code that does not compile #8585

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

Closed
valencik opened this issue Mar 21, 2020 · 4 comments · Fixed by #8665
Closed

QuoteContext show can show code that does not compile #8585

valencik opened this issue Mar 21, 2020 · 4 comments · Fixed by #8665

Comments

@valencik
Copy link
Contributor

The following code is based of the dotty-staging.g8 project.

import scala.quoted._
import scala.quoted.staging.{run, withQuoteContext, Toolbox}

object Main {
  given Toolbox = Toolbox.make(getClass.getClassLoader)

  def main(args: Array[String]): Unit = {
    val toTheEighth = stagedPower(8)
    println("3^8 = " + toTheEighth(3))
  }

  def stagedPower(n: Int): Double => Double = {
    def code(using QuoteContext) = '{ (x: Double) => ${ powerCode(n, 'x) } }
    println("The following would not compile:")
    println(withQuoteContext(code.show))
    run(code)
  }

  def powerCode(n: Int, x: Expr[Double])(using ctx: QuoteContext): Expr[Double] =
    if (n == 1) x
    else if (n == 2) '{ $x * $x }
    else if (n % 2 == 1)  '{ $x * ${ powerCode(n - 1, x) } }
    else '{ val y = $x * $x; ${ powerCode(n / 2, 'y) } }
}

It has been slightly trimmed and modified such that powerCode recursively calls itself twice.
This results in generating two lines starting val y: scala.Double =.

Output

Running this yields the following output:

The following would not compile:
((x: scala.Double) => {
  val y: scala.Double = x.*(x)
  val y: scala.Double = y.*(y)
  y.*(y)
})
3^8 = 6561.0

Attempting to compile that source code yields an error:

[error] 4 |  val y: scala.Double = y.*(y)
[error]   |  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
[error]   |  y is already defined as value y

Expectation

code.show should produce a source code representation that compiles.
We can, however, see that the staging works and we get our answer 3^8 = 6561

@odersky
Copy link
Contributor

odersky commented Mar 22, 2020

That looks like a rather tall order. Macro-generated code might not compile when printed as source in a myriad different ways. I agree it would be useful to have this, but it looks like a sizeable project on its own to get there.

@valencik
Copy link
Contributor Author

@odersky thanks for the insight. Is there a way to see more directly what code was generated/run by the staging process?
i.e. What is the difference between the code that was able to evaluate 3^8 and the code that was printed as source?

@odersky
Copy link
Contributor

odersky commented Mar 22, 2020

The staged code uses internal symbols instead of printable names. That's what makes it hard to print correctly in the first place.

@nicolasstucki
Copy link
Contributor

#7388 would give a way to print this code without repeating names.

nicolasstucki added a commit to dotty-staging/dotty that referenced this issue Apr 3, 2020
nicolasstucki added a commit to dotty-staging/dotty that referenced this issue Apr 4, 2020
@nicolasstucki nicolasstucki linked a pull request Apr 4, 2020 that will close this issue
nicolasstucki added a commit that referenced this issue Apr 5, 2020
Fix #8585: Refresh names to avoid name clashes
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants