简体   繁体   中英

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

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?

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.

You just need to switch on

scalacOptions += "-Yretain-trees"

Then

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

will print Some(Literal(Constant(1))) too.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM