Обтекание строки интерполяционного макроса в другой - PullRequest
1 голос
/ 08 мая 2019

У меня есть интерполятор xxx реализуется макросом (я владею кодом) и возвращает XXX. Я хочу реализовать интерполятор yyy, когда у меня есть функция f: XXX => YYY

код

class XXXMacro(val c: blackbox.Context) {
  import c.universe._

  final def xxx(args: c.Expr[Any]*): c.Expr[XXX] = {
      val Apply(_, Apply(_, parts) :: Nil) = c.prefix.tree
      ???
  }
}

implicit class XXXInterpolator(sc: StringContext) {
  def xxx(args: Any*): XXX = macro XXXMacro.xxx
}

class YYYMacro(val c: blackbox.Context) {
  import c.universe._

  final def yyy(args: c.Expr[Any]*): c.Expr[YYY] = q"yyy($xxx\"args\")"
}

implicit class YYYInterpolator(sc: StringContext) {
  def yyy(args: Any*): YYY = macro XXXMacro.yyy
}

Проблема в том, что я не могу легко параметризовать код. Компилятор не позволит мне сделать macro XXXMacro(f).yyy или macro XXXMacro.yyy(f).

Также, когда я обертываю это как def yyy(args: Any*): YYY = f(new XXXInterpolator(sc).xxx(args)), контекст в макросе совершенно другой и усложняет его, и я не могу использовать его повторно. Есть ли способ сделать это проще?

Ответы [ 2 ]

2 голосов
/ 08 мая 2019

Я не хочу, чтобы XXXMacro зависел от YYY. Таким образом, решение для пользователя trait и Tree

trait XXXMacroTree {
  val c: blackbox.Context
  import c.universe._

  final def xxxTree(args: c.Expr[Any]*): Tree = ???

  final def xxx(args: c.Expr[Any]*): c.Expr[XXX] = c.Expr[XXX](xxxTree(args: _*))
}
class XXXMacro(val c: blackbox.Context) extends XXXMacroTree

implicit class XXXInterpolator(sc: StringContext) {
  def xxx(args: Any*): XXX = macro XXXMacro.xxx
}

class YYYMacro(val c: blackbox.Context) extends XXXMacroTree {
  import c.universe._

  final def yyy(args: c.Expr[Any]*): c.Expr[YYY] = c.Expr[YYY](q"f(${xxxTree(args: _*)}))
}

implicit class YYYInterpolator(sc: StringContext) {
  def yyy(args: Any*): YYY = macro YYYMacro.yyy
}
2 голосов
/ 08 мая 2019

Попробуйте

class XXXMacro(val c: blackbox.Context) {
  import c.universe._

  final def xxx(args: c.Expr[Any]*): c.Expr[XXX] = {
    val Apply(_, Apply(_, parts) :: Nil) = c.prefix.tree
    ???
  }

  final def yyy(args: c.Expr[Any]*): c.Expr[YYY] =
    reify {
      f(xxx(args: _*).splice)
    }
}

implicit class XXXInterpolator(sc: StringContext) {
  def xxx(args: Any*): XXX = macro XXXMacro.xxx
}

implicit class YYYInterpolator(sc: StringContext) {
  def yyy(args: Any*): YYY = macro XXXMacro.yyy
}
...