Description
We currently define macros with inline and quotes link this
object Macros {
inline def foo(inline n: Int): Int = ~fooImpl(n)
def fooImpl(n: Int): Expr[Int] = n + 1 // Lifted by quoted.Liftables
}
When a foo
is inlined by the compiler, the code/tree for fooImpl(n)
is interpreted. This assumes that fooImpl
was already compiled and is static.
Now the question is what should we do with
object Macros {
inline def foo(inline n: Int): Int = ~{
(n + 1): Expr[Int]
}
}
In the current scheme, we would need to interpret n + 1
(or 1 + 1
after inlining). This implies that we need to be able to interpret at least all primitive operations. Potentially ending implementing a full interpreter for Scala (which sounds fun but extremely hard).
One alternative would be to extract the contents of ~{...}
into a helper method which would receive all the parameters that foo
receives. All inliened parameters are passed as they are and all non-inlined are passed as Expr[T]
(i.e. as trees). Basically desugaring into the original implementation.
inline def foo(inline n: Int, m: Int): Int = ~fooImpl(n)
def foo$macro(n: Int) = (n + 1): Expr[Int] // Should be a static location
This comes with the following advantages
- The interpreter logic can be kept simple
- Performace of the evaluation of the
Expr[T]
and the only reflective call is tofoo$macro
.