giiita
giiita

Reputation: 189

Synthesizing syntax tree and variable tree to avoid cross stage evaluation

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

Answers (1)

Dmytro Mitin
Dmytro Mitin

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

Related Questions