Reputation: 1270
This is probably a very easy question to answer. And maybe also easy to find the answer. However, I couldn't find it after several hours. The documentation for the Scala API scala.quoted.Quotes.reflectModule
is not very helpful.
I need to know how on earth to get the value of a field declared in the primary constructor of a regular class (not a case class) using metaprogramming with Scala 3.5.1.
Specifically, I need to implement the select
function below. Preferably with splices and quotes.
I've included the toStrImpl
method below as a usage example just to provide context and purpose for the matter. It generates the toString
implementation of regular clases.
/** Given the expression `productExpr` that gets an instance of
* a regular class `A`, and the symbol of a parameter of `A`'s
* primary-constructor, obtain the expression that gets the value
* of said parameter. */
def select[A: Type](using quotes: Quotes)(productExpr: Expr[A], elemSymbol: quotes.reflect.Symbol): Expr[Any] =
??? // TODO implement
def toStrImpl[A: Type](product: Expr[A])(using quotes: Quotes): Expr[String] = {
import quotes.reflect.*
val productSymbol = TypeRepr.of[T].typeSymbol
val primaryConstructor = productSymbol.primaryConstructor
val productTerm = productExpr.asTerm
var stringBuilderExpr = '{ new StringBuilder(${ Expr[String](productSymbol.name) }) }
for {
paramsList <- primaryConstructor.paramSymss
if paramsList.forall(_.isTerm) // skips type parameters
} do {
stringBuilderExpr = '{ $stringBuilderExpr.append('(') }
var isFirst = true
for param <- paramsList do {
if isFirst then isFirst = false else stringBuilderExpr = '{ $stringBuilderExpr.append(", ") }
val argValueExpr: Expr[Any] = select(product, param)
stringBuilderExpr = '{ $stringBuilderExpr.append(${ Expr(paramName) }).append('=').append($argValueExpr.toString) }
}
stringBuilderExpr = '{ $stringBuilderExpr.append(')') }
}
'{ $stringBuilderExpr.toString }
}
Upvotes: 0
Views: 41
Reputation: 1270
This is a response but does not use slices and quotes:
def select[A: Type](using quotes: Quotes)(productExpr: Expr[A], elemSymbol: quotes.reflect.Symbol): Expr[Any] =
Select.unique(productExpr.asTerm, elemSymbol.name).asExpr
Upvotes: 0