2015-07-03 183 views
1

我想使用宏和静态注释生成case类。斯卡拉宏:c.universe.Tree到c.universe.Name

有什么办法可以将c.universe.Tree转换成另一种c.universe类型,特别是c.universe.Name

+0

什么样的树?你想用这个名字做什么? –

+0

@TravisBrown我想使用它作为从宏内生成的新案例类的名称。理想情况下,案例类用参数列表进行注释,这些参数将被剥离以生成新的案例类定义。 –

+0

树是字符串文字吗? –

回答

1

答案取决于你有什么样的树,但在任何情况下,你想从你的树去一个字符串,然后你可以创建无论是TypeNameTermNameTypeNameTermName构造。

例如,我们这里的树是一个字符串:

import scala.language.experimental.macros 
import scala.reflect.macros.blackbox.Context 

def callFooImpl(c: Context)(name: c.Expr[String]): c.Expr[Unit] = { 
    import c.universe._ 

    val termName: TermName = name.tree match { 
    case Literal(Constant(s: String)) => TermName(s) 
    case _ => c.abort(c.enclosingPosition, "Not a string literal") 
    } 

    c.Expr[Unit](q"$termName.foo()") 
} 

def callFoo(name: String): Unit = macro callFooImpl 

case class Foo(i: Int) { 
    def foo(): Unit = println(s"Called foo() on $this") 
} 

然后:

scala> :paste 
// Entering paste mode (ctrl-D to finish) 

val myFoo = Foo(10) 
callFoo("myFoo") 

// Exiting paste mode, now interpreting. 

Called foo() on Foo(10) 
myFoo: Foo = Foo(10) 

这里我们解构字符串文字树LiteralConstant得到一个编译期然后我们用它来创建一个TermName,我们可以在我们生成的代码中使用它。

+0

这起作用。谢谢! –