scala AST - 什么是字符串常量字面值,我如何找到?

时间:2016-10-24 13:25:47

标签: scala pattern-matching abstract-syntax-tree scala-macros

考虑以下代码段

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

我想要打印

Hello World
x = 0
1

通过使用宏:

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{}
  }
}

输出(编译+运行):

[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

所以......显然,“Hello World”是一个文字但是与文字模式不匹配(也尝试了case Literal(_)同样不满意的结果)。

为什么呢?我需要匹配什么呢?

1 个答案:

答案 0 :(得分:2)

您的implDebug方法正在接受c.Expr[Any],这是c.Tree的包装。 Literal(Constant(...))是文字树值的正确匹配器,但由于您希望在树上进行匹配,因此应使用v.tree match {...}代替。