Macro access to members of object where macro is defined
Posted
by
Marc Grue
on Stack Overflow
See other posts from Stack Overflow
or by Marc Grue
Published on 2013-06-22T18:30:26Z
Indexed on
2013/06/25
4:21 UTC
Read the original article
Hit count: 511
scala
|scala-macros
Say I have a trait Foo
that I instantiate with an initial value
val foo = new Foo(6) // class Foo(i: Int)
and I later call a second method that in turn calls myMacro
foo.secondMethod(7) // def secondMethod(j: Int) = macro myMacro
then, how can myMacro find out what my initial value of i
(6) is?
I didn't succeed with normal compilation reflection using c.prefix
, c.eval(...)
etc but instead found a 2-project solution:
Project B:
object CompilationB {
def resultB(x: Int, y: Int) = macro resultB_impl
def resultB_impl(c: Context)(x: c.Expr[Int], y: c.Expr[Int]) =
c.universe.reify(x.splice * y.splice)
}
Project A (depends on project B):
trait Foo {
val i: Int
// Pass through `i` to compilation B:
def apply(y: Int) = CompilationB.resultB(i, y)
}
object CompilationA {
def makeFoo(x: Int): Foo = macro makeFoo_impl
def makeFoo_impl(c: Context)(x: c.Expr[Int]): c.Expr[Foo] =
c.universe.reify(new Foo {val i = x.splice})
}
We can create a Foo
and set the i
value either with normal instantiation or with a macro like makeFoo
. The second approach allows us to customize a Foo
at compile time in the first compilation and then in the second compilation further customize its response to input (i
in this case)! In some way we get "meta-meta" capabilities (or "pataphysic"-capabilities ;-)
Normally we would need to have foo in scope to introspect i
(with for instance c.eval(...)). But by saving the i
value inside the Foo
object we can access it anytime and we could instantiate Foo
anywhere:
object Test extends App {
import CompilationA._
// Normal instantiation
val foo1 = new Foo {val i = 7}
val r1 = foo1(6)
// Macro instantiation
val foo2 = makeFoo(7)
val r2 = foo2(6)
// "Curried" invocation
val r3 = makeFoo(6)(7)
println(s"Result 1 2 3: $r1 $r2 $r3")
assert((r1, r2, r3) ==(42, 42, 42))
}
My question
Can I find i
inside my example macros without this double compilation hackery?
© Stack Overflow or respective owner