User1291 User1291 - 1 month ago 10
Scala Question

scala AST - what IS a string constant literal and how do I find out?

Consider the following snippet

object Main {
def main(args:Array[String]): Unit ={
import Debugger.debug
debug("Hello World")
val x = 0
debug(x)
debug(1)
}
}


I want this to print

Hello World
x = 0
1


by making use of a macro:

import scala.language.experimental.macros
import scala.reflect.macros._


object Debugger {
val doDebug = true

def debug(v : Any) :Unit = macro implDebug

def implDebug(c:blackbox.Context)(v:c.Expr[Any]): c.Expr[Unit] ={
import c.universe._

if(doDebug) {
v match {
case Literal(Constant(_)) => reify{println(v.splice)}
case _ =>
println(v.tree)
println(v.tree.getClass.getName)
val rep = show(v.tree)
val repTree = Literal(Constant(rep))
val repExpr = c.Expr[String](repTree)
reify{
println(repExpr.splice + " = " + v.splice)
}
}
}
else reify{}
}
}


This outputs (compile + run):

[sbt compile bla bla]
"Hello World"
scala.reflect.internal.Trees$Literal
x
scala.reflect.internal.Trees$Ident
1
scala.reflect.internal.Trees$Literal
[info] Running Main
"Hello World" = Hello World
x = 0
1 = 1


so ... apparently, "Hello World" is a literal but doesn't match the literal pattern (also tried
case Literal(_)
with equally unsatisfying results).

Why? And what do I need to match instead?

Answer

Your implDebug method is accepting a c.Expr[Any], which is a wrapper for a c.Tree. Literal(Constant(...)) is the correct matcher for a literal tree value, but since you want to be matching on the tree, you should use v.tree match {...} instead.

Comments