'How to access parent class params literals?
Using Scala 2.x macros, how to access literals passed to parent classes when defining subclasses, typically with ADTs such as the following:
sealed abstract class Base(val s: String, val i: Int)
object Base {
case object A extends Base("a", 1)
case object B extends Base("b", 2)
case class C(override val s: String) extends Base(s, 3)
}
For object A, I would like to know parameter values are literals "a" and 1.
For object B, I would like to know parameter values are literals "b" and 2.
For case class C, I would like to know the second parameter is literal 3.
How can I accomplish this with Scala 2.x macros?
Solution 1:[1]
After much investigation and getting inspiration from bwmcadams /
supreme-macro-adventure, it looks like one solution is based on the combination of Macro Paradise and the creation of an @ADT annotation.
Macro paradise provides a mechanism to expand annotations on ADTs to rewrite them, thanks to the macroTransform function.
import scala.annotation.{compileTimeOnly, StaticAnnotation}
import scala.language.experimental.macros
import scala.reflect.macros.whitebox.Context
@compileTimeOnly("enable macro paradise to expand macro annotations")
class ADT extends StaticAnnotation {
def macroTransform(annottees: Any*): Any = macro ADT.impl
}
object ADT {
def impl(c: Context)(annottees: c.Expr[Any]*): c.Expr[Any] = {
import c.universe._
val trees = annottees.map(_.tree)
val rewritten = trees match {
case (cd: ClassDef) :: q"object $name { ..$body }" :: Nil =>
$body match {
case q"case object $name extends $_($literal, $_)" :: tail =>
[...]
}
case _ =>
trees
}
c.Expr[Any](q"{..$rewritten}")
}
}
With the help of quasiquotes, one can navigate $body and pattern match the different cases to access the arguments passed to the parent class (here $literal). Finally, one returns the rewritten ADT.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | pgrandjean |
