Skip to content

Decoupling Macros in ReifyQuotes #4795

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

Conversation

nicolasstucki
Copy link
Contributor

@nicolasstucki nicolasstucki commented Jul 16, 2018

Transforms macro implementations from

object PowerMacro {
  inline def power(inline n: Long, x: Double) = ~{
    if (n == 0) '(1)
    else powerCode(n, '(x))
  }

  def powerCode(n: Long, x: Expr[Double]): Expr[Double] = ...
}

to

object PowerMacro {
  inline def power(inline n: Long, x: Double) = ~power$splice$1(n, '(x))

  def power$splice$1(n: Long, x: Expr[Double]) = ~{
    if (n == 0) '(1)
    else powerCode(n, '(~x))
  }

  def powerCode(n: Long, x: Expr[Double]): Expr[Double] = ...
}

This way the inlined code is always a static method with a single list of arguments. Which is easy to interpret when inlined. This transformation is performed before pickling to ensure the new body will be inlined.

This implementation is also a first step to fix #4801 and #4803.

@nicolasstucki nicolasstucki reopened this Jul 17, 2018
@nicolasstucki nicolasstucki self-assigned this Jul 17, 2018
@nicolasstucki nicolasstucki changed the title Remove Macro flag from ReifyQuotes Decoupling Macros in ReifyQuotes Jul 17, 2018
@nicolasstucki nicolasstucki force-pushed the remove-macro-key-from-reify-quotes branch 9 times, most recently from 9bd6589 to 7c7b3bd Compare July 18, 2018 12:07
@nicolasstucki nicolasstucki force-pushed the remove-macro-key-from-reify-quotes branch from 7c7b3bd to 9fef39b Compare July 18, 2018 12:10
@nicolasstucki nicolasstucki requested a review from odersky July 18, 2018 15:44
@nicolasstucki nicolasstucki force-pushed the remove-macro-key-from-reify-quotes branch from 63cfe8c to 45641b7 Compare July 18, 2018 18:19
Copy link
Contributor

@odersky odersky left a comment

Choose a reason for hiding this comment

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

I must admit I understand none of this. Before proceeding, I propose to write a document explaining the transformations in detail. Not just this one, but everything relevant to how code with toplevel splices is transformed to code that can be run.

@@ -47,6 +47,7 @@ class Compiler {
List(new sbt.ExtractDependencies) :: // Sends information on classes' dependencies to sbt via callbacks
List(new PostTyper) :: // Additional checks and cleanups after type checking
List(new sbt.ExtractAPI) :: // Sends a representation of the API of classes to sbt via callbacks
List(new MacrosSplitter) :: // Applies ReifyQuotes transformation to the body of the macros
Copy link
Contributor

Choose a reason for hiding this comment

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

"to macro bodies"

* Checks that the phase consistency principle (PCP) holds on the body of a macro.
*
*
* Transforms an inline macro definitions we assume that we have a single ~ directly as the RHS.
Copy link
Contributor

Choose a reason for hiding this comment

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

(?) Should be two sentences, maybe?

* ```
* inline def foo[T1, ...](inline x1: X, ..., y1: Y, ....): Z = ~foo$splice$1[T1, ...]('[T1], ..., x1, ..., '(y1), ...)
*
* def foo$splice$1[T1, ...](T1$1: Type[T1], ..., x1$1: X, ..., y1: Expr[Y], ....): Z =
Copy link
Contributor

Choose a reason for hiding this comment

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

What if the original splice is already of the form

~bar(...)

In that case, we can simply forward to bar, no? Would it not be simpler to require that all toplevel splices are of this form?

If we do have a requirement like this, what is the added benefit of the phase?

* into
*
* ```
* def foo$splice$1[T1, ...](T1$1: Type[T1], ..., x1$1: X, ..., y1: Expr[Y], ....): Z =
Copy link
Contributor

Choose a reason for hiding this comment

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

Where does foo come from. It does not appear in the input.

@nicolasstucki
Copy link
Contributor Author

Here is a description of how this phase should work (gist). The current implementation does not mach the description, but it should be addapted to it.

@odersky
Copy link
Contributor

odersky commented Jul 20, 2018

We have two concerns here:

  1. Where can the inline method be placed? I'd say, best are no restrictions at all.
  2. What is a legal right hand side? Ideally, anything, but here I am willing to compromise to
    say it must be a call of the form ~f[...](....) where f is a static method.

If we do implement that restriction, the phase becomes redundant.

What is the price for allowing more flexibility in the right hand side? We must find a suitable location for the static method, with suitable parameters and so on. This looks pretty hard! It will require at least a call to FulllParameterization to account for all possible combinations of enclosing parameters and so on. But the problem is even harder if we also want to support local inline methods that can refer to type parameters of enclosing classes.

So, since we do not want to compromise (1) over (2), and (2) does not look really important anyway, I'd be in favor to impose the restriction and close the PR.

@nicolasstucki
Copy link
Contributor Author

Instead, I will implement the proposed simplification. I extracted useful cleanups from this PR in #4818

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Allow multiple splices in macros
2 participants