В целом - нет. f
может быть абстрактным или определяться как внешний вызов, пользовательский ввод, случайный или один из многих других случаев.
Но в некоторых частных случаях вы могли бы получить его. Вы знаете почти все, что знает компилятор!
Взгляните на c.enclosingClass
:
object Macros {
def get(a: Int) = macro getImpl
def getImpl(c: Context)(a: c.Expr[Int]) = {
import c.universe._
println(showRaw(c.enclosingClass))
c.Expr[Unit](Literal(Constant(())))
}
}
object Test { val f = 1; Macros.get(f) }
// ModuleDef(Modifiers(), $line55.$read.$iw.$iw.$iw.$iw.Test, Template(List(Select(Ident(scala), newTypeName("AnyRef"))), emptyValDef, List(DefDef(Modifiers(), nme.CONSTRUCTOR, List(), List(List()), TypeTree(), Block(List(Apply(Select(Super(This(newTypeName("Test")), tpnme.EMPTY), nme.CONSTRUCTOR), List())), Literal(Constant(())))), ValDef(Modifiers(), newTermName("f "), TypeTree(), Literal(Constant(1))), Apply(Select(Ident(newTermName("Macros")), newTermName("get")), List(Ident(newTermName("f")))))))
Интересная часть здесь ValDef(Modifiers(), newTermName("f "), TypeTree(), Literal(Constant(1)))
.
Мы должны извлечь его:
object Macros {
def get(a: Int) = macro getImpl
def getImpl(c: Context)(a: c.Expr[Int]) = {
import c.universe._
val (enclosing, name) = a.tree match {
case Select(This(enclosing), name) => enclosing -> name
case _ => c.abort(c.enclosingPosition, "Not a `this` memver")
}
val impl = c.enclosingClass match {
case impl: ImplDef if impl.name.toString == enclosing.toString => impl
case impl: ImplDef => c.abort(c.enclosingPosition, "Should search in another parent")
case _ => c.abort(c.enclosingPosition, "Not an `ImplDef`")
}
val body = impl.children.collect{
case Template(_, _, body) => body
} match {
case Seq(body) => body
case _ => c.abort(c.enclosingPosition, "Should be a single template.")
}
val rhss = body.collect{
case ValDef(_, valName, _, rhs) if valName.toString == name.toString => rhs
}
val rhs = rhss match {
case Seq(rhs) => rhs
case Seq() => c.abort(c.enclosingPosition, "Not found. Maybe it's a DefDef or somethong else")
case _ => c.abort(c.enclosingPosition, "Some other error.")
}
val res = rhs match {
case Literal(Constant(i: Int)) => i
case Literal(Constant(_)) => c.abort(c.enclosingPosition, "Literal, but not an Int.")
case _ => c.abort(c.enclosingPosition, "Implemented not as literal.")
}
println(s"Int value in this particular case: $res")
c.Expr[Any](Literal(Constant(res)))
}
}
Результат:
object Test { val f = 1; Macros.get(f) }
// Int value in this particular case: 1
Итак, у нас есть значение f
во время компиляции.
Я почти уверен, что это не то, что вы ожидали.
person
senia
schedule
27.12.2013