scala代理宏,问题转换方法args到值

时间:2015-11-17 12:21:16

标签: scala proxy scala-macros

我正在尝试使用scala宏编写代理宏。我希望能够代理特征X并返回X的实例,为X的所有方法调用一个函数。

这是我到目前为止所做的。假设我们要代理特征TheTrait(在下面定义),我们可以运行ProxyMacro.proxy传递一个函数,该函数将被调用代理方法的所有调用。

    trait TheTrait
    {
        def myMethod(x: String)(y: Int): String
    }

    val proxy = ProxyMacro.proxy[TheTrait] {
        case ("myMethod", args) =>
            "ok"
    }
    println(proxy.myMethod("hello")(5))

到目前为止的实施是:

package macrotests

import scala.language.experimental.macros
import scala.reflect.macros.whitebox.Context

object ProxyMacro
{
type Implementor = (String, Any) => Any

def proxy[T](implementor: Implementor): T = macro impl[T]

def impl[T: c.WeakTypeTag](c: Context)(implementor: c.Expr[Implementor]): c.Expr[T] = {
    import c.universe._

    val tpe = weakTypeOf[T]

    val decls = tpe.decls.map { decl =>
        val termName = decl.name.toTermName
        val method = decl.asMethod
        val params = method.paramLists.map(_.map(s => internal.valDef(s)))
        val paramVars = method.paramLists.flatMap(_.map { s =>
            internal.captureVariable(s)
            internal.referenceCapturedVariable(s)
        })

        q""" def $termName (...$params) = {
            $implementor (${termName.toString}, List(..${paramVars}) ).asInstanceOf[${method.returnType}]
           }"""
    }

    c.Expr[T] {
        q"""
      new $tpe {
        ..$decls
      }
  """
    }
}

}

但是有一个问题。由于List(.. $ {paramVars}),这不会编译。这应该只创建一个包含方法参数的所有值的列表。 但是我在那一行得到了编译问题(不值得粘贴)。

如何将方法参数列表转换为其值?

1 个答案:

答案 0 :(得分:2)

showInfo在调试宏

时很有用

def showInfo(s: String) = c.info(c.enclosingPosition, s.split("\n").mkString("\n |---macro info---\n |", "\n |", ""), true)

变化

val paramVars = method.paramLists.flatMap(_.map { s => internal.captureVariable(s) internal.referenceCapturedVariable(s) })(此结果为List(x0$1, x1$1)

val paramVars = method.paramLists.flatMap(_.map { s => s.name })(此结果为List(x, y)