Home > Software design >  How to get the body of variable initialisation from outer scope in Scala 3 macros?
How to get the body of variable initialisation from outer scope in Scala 3 macros?

Time:11-27

Suppose I have this code for extracting the code initialising a variable:

def extractBodyImpl[T: Type](expr: Expr[T])(using Quotes) =
    import quotes.reflect._
    expr.asTerm.underlyingArgument match
        case ident @ Ident(_) =>
            ident.symbol.tree match
                case ValDef(_,_,rhs) => println(rhs)
                case DefDef(_,_,_,rhs) => println(rhs)
    '{ () }

inline def extractBody[T](inline expr: T) = ${ extractBodyImpl('expr) }

When called on a variable declared in the same scope it works as desired:

@main def hello() =
  val x = 1
  extractBody(x)

prints Some(Literal(Constant(1))).

However, on a variable from outer scope, it prints None:

val x = 1
@main def hello() =
  extractBody(x)

How can I make it work in the second case?

CodePudding user response:

You cannot do it in macro. A function which received argument might have been called from everywhere. How would static analysis would access the information only available in runtime? The only reliable solution would be to force user to expand this extractBody macro right after defining the value and passing the result in some wrapper combining both value and its origin.

  • Related