I\'m attempting to write a macro that would wrap a function and deducting a parameter from the value its invocation will be assigned to.
object TestMacros {
de
This is very possible. I know, because I've done something like it before. The trick is to search the enclosing tree for a value whose right-hand side has the same position as the macro application:
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.")
)
}
}
And then:
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
Note that you can apply foo
at compile-time, since you know the name of the val
at compile-time. If you wanted it to be applied at runtime that would also be possible, of course.