I have a scala macro which outputs nested case classes. I can assemble fragments of expressions created using reify to build up the nested case classes programmatically:
case class Foo(name: String)
case class Bar(foo: Foo)
def foo(name: String) = {
c.universe reify {
Foo(c.literal(name).splice)
}
}
def bar(foo: Expr[Foo]) = {
c.universe reify {
Bar(foo.splice)
}
}
// output Bar(Foo("MyFoo"))
c.Expr( bar(foo("MyFoo").asInstanceOf[Expr[Foo]]).tree )
Things work well apart from the annoying cast (how can i fix that?). Where I am stuck is when I want the macro to output some case class which require a collection of inner objects whos size varies based on what the marco sees within the AST it is processing.
So if I have a class which takes a sequence of foo:
case class Baz(foos: Seq[Foo])
I would like to do something along the lines of:
def baz(foos: Seq[Expr[Foo]]): Expr[Baz] = {
val flipped: Expr[Seq[Foo]] = ??? // convert foos from Seq[Expr[Foo]] to Expr[Seq[Foo]]
c.universe reify {
Baz(flipped.splice)
}
}
// now pack any number of Foos into an output Baz as required
c.Expr(baz(Seq(foo("MyFoo1"),foo("MyFoo2"))).tree)
I am unable to convert a Seq[Expr[Foo]] into an Expr[Seq[Foo]] to do the splice such that I can pack a variable number nested objects into the macro output. How can I reify a dynamically built list to use as the constructor arg?