Example project at
I want to be able to add a debugging statement after every val
definition in a block:
object Main {
def main(args: Array[String]): Unit = {
val str = concatStrings("hello", "world")
println(s"concatStrings = $str")
}
def concatStrings(s1: String, s2: String): String = {
dumpVars {
val result = s1 + s2
result
}(s => println(s.toString))
}
}
And I ALMOST have it working with this:
case class DumpTerm(name: String, value: Any)
class MacroBundle(val c: blackbox.Context) {
import c.universe._
def dumpVars(expr: c.Tree)(output: c.Expr[DumpTerm => Unit]): c.Tree = {
val q"..$stats" = expr
val loggedStats = stats.flatMap { stat =>
stat match {
case ValDef(_, termName, _, rhs) =>
//val ident = Ident(TermName("s1")) // works fine on parameter
//val ident = rhs // can cheat by using the rvalue
val ident = Ident(termName) // doesn't work on ident of a val def defined inside :-/
List(stat, q"$output(DumpTerm(${termName.encodedName.toString}, ${ident}))")
case _ =>
List(stat)
}
}
println(showRaw(q"..$loggedStats"))
q"..$loggedStats"
}
}
Somehow the debug statement doesn’t have access to the val that was just defined in the previous line:
[error] /home/wsargent/work/debug-after-valdef-macro/example/src/main/scala/example/Main.scala:16:6: not found: value result
[error] }(s => println(s.toString))
I’ve printed out the AST and generated code in the README. It looks like it should work. I am kind of flummoxed.