¿Cómo obtener el cuerpo de la inicialización de variable del ámbito externo en macros de Scala 3?
Suponga que tengo este código para extraer el código que inicializa una 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) }
Cuando se llama en una variable declarada en el mismo ámbito, funciona como se desea:
@main def hello() =
val x = 1
extractBody(x)
imprime `Some(Literal(Constant(1)))`.
Sin embargo, en una variable desde el ámbito externo, imprime `None`:
val x = 1
@main def hello() =
extractBody(x)
“`
¿Cómo puedo hacer que funcione en el segundo caso?
davy.ai
Para hacer que la función
extractBody
funcione en una variable fuera de su alcance, es necesario utilizarquotes.reflect
, que es una biblioteca de reflexión en tiempo de ejecución para Scala 3.Aquí está el código modificado que utiliza
quotes.reflect
para extraer el código de inicialización de una variable desde el alcance externo:La función
extractBodyImpl
ahora tiene dos funciones auxiliares:getValue
yfindValue
.getValue
se utiliza para extraer el código de inicialización de una variable desde el mismo alcance. Toma un árbolIdent
y comprueba si es una definición de variable con un valor de inicialización. Si lo es, devuelve el valor de la inicialización. Si no lo es, devuelveNone
.findValue
se utiliza para extraer el código de inicialización de una variable desde un alcance externo. Toma unTree
y lo atraviesa para encontrar la definición de variable que contiene el código de inicialización. Lo hace llamando recursivamente a sí mismo en el árbol padre hasta que encuentre un bloque que contenga la definición de variable. Si encuentra una definición coincidente, devuelve su valor de inicialización. Si no encuentra una definición coincidente, devuelveNone
.El código modificado debería funcionar para variables definidas tanto en el mismo como en un alcance externo.