合成语法树和变量树以避免跨阶段评估

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

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

这是查看错误的示例。

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为跨阶段。 这是一个样本,其中会出现跨阶段评估错误,但即使解决也将不起作用。

zchng 回答:合成语法树和变量树以避免跨阶段评估

使用准引用尝试

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)
        )
      }
    }
  }
本文链接:https://www.f2er.com/3116487.html

大家都在问