I am fairly new to Scala macros, and am trying to write a very basic DSL.
I have the following Scala class:
abstract class SpecialFunction {
def apply(): Unit
}
and the following Scala macro:
def mImpl(c: Context)(bodyBlock: c.Expr[Unit]): c.Expr[X] =
c.universe.reify {
new X(new SpecialFunction {
override def apply() {
bodyBlock.splice
}
})
}
def m(bodyBlock: Unit): X = macro mImpl
So far so good. For example, it allows me to write:
def example = m {
println("Hello, world")
}
And this compiles down to:
def example = new X(new SpecialFunction {
override def apply() {
println("Hello, world")
}
})
But this formulation does not allow me to have local variables in such an "m block". For example, I cannot write:
def example = m {
val x = 7
println(x.toString)
}
At compile time I get the error:
symbol value x does not exist in example
However, what I want to achieve is this:
def example = new X(new SpecialFunction {
override def apply() {
val x = 7
println(x.toString)
}
})
(I think I understand why this is the case: sub-expressions are evaluated before being passed to the macro, and thus the reference to x is invalid).
So my question is this: How can I get the above to work? (I just want the extra code defined in the macro to be "copy-pasted" around the code in the "m block", like in a C++ macro.)
Any help would be greatly appreciated :-)
Your output expression is keeping a reference to the old x
symbol, but instead it should be a reference to a new one. Therefore, you can reset all the junk references in the tree you aim to reuse by applying resetLocalAttrs
from Context .
How about...?
def mImpl(c: Context)(bodyBlock: c.Expr[Unit]): c.Expr[X] =
c.universe.reify {
new X(new SpecialFunction {
override def apply() {
c.Expr[Unit](c.resetLocalAttrs(bodyBlock.tree)).splice
}
})
}
In this question , you can read a great explanation by the Scala Macros guy.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.