Reputation: 189
While creating a syntax tree, I want to synthesize variables in the syntax tree as a tree. However, error in cross-stage evaluation.
Is it possible to create a single tree by compositing trees with different stages?
This is a sample to see errors.
object Sample {
case class Input(a: String, b: Int)
trait Scriber[T] {
def scribe(i: Input): T
}
trait Hoge[T] {
def exec(t: Input): Either[Throwable, T]
}
}
object Macro {
def exec[T](scribers: Seq[Scriber[_]]): Hoge[T] = macro SampleMacro.test[T]
}
class SampleMacro(val c: blackbox.Context) {
import c.universe._
def test[T: c.WeakTypeTag](scribers: c.Expr[Seq[Scriber[_]]]): c.Expr[Hoge[T]] = {
reify {
new Hoge[T] {
override def exec(t: Input): Either[Throwable, T] = {
val x = reify {
scribers.splice.map(_.scribe(t)) // <- cross stage evaluation.
}
Right(
c.Expr[T](
q"${weakTypeOf[T].typeSymbol.companion}.apply(..$x)"
).splice
)
}
}
}
}
}
In this case, t is cross stage. This is a sample where cross stage evaluation errors will occur, but will not work even if resolved.
Upvotes: 0
Views: 105
Reputation: 51658
With quasiquotes try
def test[T: c.WeakTypeTag](scribers: c.Expr[Seq[Scriber[_]]]): c.Expr[Hoge[T]] = {
c.Expr[Hoge[T]](q"""
new Hoge[T] {
override def exec(t: Input): Either[Throwable, T] = {
val x = $scribers.map(_.scribe(t))
Right(
${weakTypeOf[T].typeSymbol.companion}.apply(x)
)
}
}""")
With reify
/splice
try
def test[T: c.WeakTypeTag](scribers: c.Expr[Seq[Scriber[_]]]): c.Expr[Hoge[T]] =
reify {
new Hoge[T] {
override def exec(t: Input): Either[Throwable, T] = {
val x = scribers.splice.map(_.scribe(t))
Right(
c.Expr[Seq[_] => T](
q"${weakTypeOf[T].typeSymbol.companion}"
).splice.apply(x)
)
}
}
}
Upvotes: 1