0

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?

User1291
  • 7,664
  • 8
  • 51
  • 108

1 Answers1

2

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.

fmt
  • 993
  • 9
  • 18