Ale*_*ron 2 macros scala scala-2.10 scala-macros
我正在尝试编写一个宏,它将包装一个函数并从其调用将赋值的值中扣除一个参数.
object TestMacros {
def foo(name: String): String = name.toUpper
def bar = macro barImpl
def barImpl(c: Context): c.Expr[String] = {
import c.universe._
//TODO extract value name (should be baz)
c.Expr[String](Apply(
Select(newTermName("TestMacros"), newTermName("foo")), // Probably wrong, just typed it quickly for demonstration purposes
List(Literal(Constant("test"))))) // Should replace test by value name
}
}
object TestUsage {
val baz = bar // should be BAZ
}
Run Code Online (Sandbox Code Playgroud)
我不知道这是否足够清楚.我已经调查了c.prefix和c.macroApplication而没有成功.我在没有宏天堂编译器插件的情况下使用Scala 2.10.2.
这很有可能.我知道,因为我之前做过类似的事情.诀窍是在封闭树中搜索右侧与宏应用程序具有相同位置的值:
import scala.language.experimental.macros
import scala.reflect.macros.Context
object TestMacros {
def foo(name: String): String = name.toUpperCase
def bar = macro barImpl
def barImpl(c: Context): c.Expr[String] = {
import c.universe._
c.enclosingClass.collect {
case ValDef(_, name, _, rhs)
if rhs.pos == c.macroApplication.pos => c.literal(foo(name.decoded))
}.headOption.getOrElse(
c.abort(c.enclosingPosition, "Not a valid application.")
)
}
}
Run Code Online (Sandbox Code Playgroud)
然后:
scala> object TestUsage { val baz = TestMacros.bar }
defined module TestUsage
scala> TestUsage.baz
res0: String = BAZ
scala> class TestClassUsage { val zab = TestMacros.bar }
defined class TestClassUsage
scala> (new TestClassUsage).zab
res1: String = ZAB
Run Code Online (Sandbox Code Playgroud)
请注意,您可以foo在编译时应用,因为您知道编译时的名称val.如果你想在运行时应用它,当然也是可能的.