合成语法树和变量树以避免跨阶段求值

Synthesizing syntax tree and variable tree to avoid cross stage evaluation

在创建语法树时,我想将语法树中的变量综合为一棵树。 但是,跨阶段评估错误。

是否可以通过组合不同阶段的树来创建一棵树?

这是查看错误的示例。

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
          )
        }
      }
    }
  }
}

在这种情况下,t是跨阶段的。 这是一个示例,其中会发生跨阶段评估错误,但即使已解决也不会起作用。

用准引号试试

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)
        )
      }
    }""")

reify/splice试试

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)
        )
      }
    }
  }