This is a simplified version of the problem I am facing but the underlying issue remains. After calling a macro, I want to generate case classes dynamically. I am able to retrieve parameters from macro call etc. The issue I am having is trying to use a string variable within quasiquotes. I essentially want to have the following:
def expand_impl(c: Context)(annottees: c.Expr[Any]*): c.Expr[Any] = {
import c.universe._
val toGen = "case class Foo()"
val toReturn = c.Expr[Any](
q"$toGen"
)
toReturn
}
However, the case class is not generated. Now I know that if I change toGen to q"case class Foo()" it will work, however toGen is a string I will generate after some other processing which returns a string, so I can't do that. Compiling it like this and manually looking at the the value of toReturn I get the following:
Expr[Any]("case class Foo()")
The string toGen is simply pasted in, along the quotes, meaning the case class is not generated.
I have looked for similar issues but can't find this example anywhere. How can I unquote the double quotes of a string variable within quasiquotes?
There is a parse
method defined on Context
. It returns a Tree
, and because trees can be interpolated in quasiquotes, you can very easily mix and match parsing with quasiquoting.
By example:
scala> :paste
// Entering paste mode (ctrl-D to finish)
import scala.reflect.macros.whitebox.Context
import scala.language.experimental.macros
def test_impl(c: Context)(): c.Tree = {
import c.universe._
val tree = c.parse("""println(2)""")
q"println(1); $tree; println(3)"
}
def test(): Unit = macro test_impl
// Exiting paste mode, now interpreting.
import scala.reflect.macros.whitebox.Context
import scala.language.experimental.macros
test_impl: (c: scala.reflect.macros.whitebox.Context)()c.Tree
defined term macro test: ()Unit
scala> test()
1
2
3
In this example I defined a def macro, but it should work just as well with macro annotations (as in your case).