Macros: how can we use quasiquotes to match on a function type?



I have a macro function that can successfully match on an expression
(functions only) using quasiquotes and get an identifier if possible (not
the case of anonymous functions). Now I would like to:

a) Find information regarding the function types
b) And in particular find were the function was declared (type and
position were it is defined)

As an initial step I defined this function:

  private def getFuncDef[T:c.WeakTypeTag](c: blackbox.Context)(expr: c.Expr[T]): String = {
    import c.universe._

    expr.tree.tpe match {
      case tq"(..$param) => $body" =>
      case _ =>

Now my problem is that when I pass a function, it never matches.
Say I have a class were in I define a method f.

class FuncBlob() {
  def f(b:Int):Int = -b
  val h: Int => Double = (b:Int) => (2*b).toDouble

When I pass on f, I have the following information:

func.tree = {
((b: Int) => blob.f(b))
func.tree.type = Int => Int
func.tree.class = class scala.reflect.internal.Trees$Block
func.actualType = Int => Int
func.staticType = Nothing
func.tree.isDef = false
func.tree.isTerm = true
func.tree.isType = false
Raw: Block(List(), Function(List(ValDef(Modifiers(PARAM | SYNTHETIC), TermName(“b”), TypeTree(), EmptyTree)), Apply(Select(Ident(TermName(“blob”)), TermName(“f”)), List(Ident(TermName(“b”))))))

In this case this match works:

    expr.tree match {
      case q"{ ($paramIn) => $call($param)}" =>
        println(s"$call($paramIn) => ???")

Notice how we have a Block that has a Function. The getFuncDef
prints out:

TypeRef(ThisType(scala), scala.Function1, List(TypeRef(ThisType(scala), scala.Int, List()), TypeRef(ThisType(scala), scala.Int, List())))

Again, we have a Functon1, but matching fails (2.12.6). So what is wrong
with the quasiquote?

In regards to point (b), is it possible for me to determine that blob.f is is the def f
in the FuncBlob class.

Appreciate any pointers.


You receive a tree that is already typed, so the tree for the selection has a symbol.


@som-snytt Apologies for being so obtuse but I cannot understand what your trying to explain.
Are you saying that to get the type information I simple match the function on the tree and then
extract the type information with the tq on the matched tree.symbol?


To see what function is being applied,

  def mImpl(c: Context)(f: c.Expr[() => Any]): c.Expr[String] = {
    import c.universe._

    val q"() => $x($p)" = f.tree


Thank you.