4

我正在评估创建宏注释来实现这一点的可能性和努力:

@txn class Foo(var bar: Int)

进入这个:

import concurrent.stm.{Ref, InTxn}

class Foo(bar0: Int) {
  private val _bar = Ref(bar0)

  def bar(implicit tx: InTxn): Int = _bar()
  def bar_=(value: Int)(implicit tx: InTxn): Unit = _bar() = value
}

(或者也许Foo用方法创建一个伴随对象apply,还不确定)

现在我从ClassDef身体上看到的是这样的

List(<paramaccessor> var bar: Int = _, 
  def <init>(bar: Int) = {
    super.<init>();
    ()
  })

Sobar显示为没有 init ( _) 的参数访问器,也显示为<init>方法的参数。

我将如何重写那个身体?

import scala.reflect.macros.Context
import scala.language.experimental.macros
import scala.annotation.StaticAnnotation

class txn extends StaticAnnotation {
  def macroTransform(annottees: Any*) = macro txnMacro.impl
}
object txnMacro {
  def impl(c: Context)(annottees: c.Expr[Any]*): c.Expr[Any] = {
    import c.universe._
    val inputs = annottees.map(_.tree).toList

    def reportInvalidAnnotationTarget(): Unit =
      c.error(c.enclosingPosition,
        "This annotation can only be used on a class definition")

    val expandees: List[Tree] = inputs match {
      case cd @ ClassDef(mods, nme, tp, tmp @ Template(parents, self, body)) :: Nil =>
        println(s"Body: $body")
        ???

      case _ =>
        reportInvalidAnnotationTarget()
        inputs
    }

    val outputs = expandees
    c.Expr[Any](Block(outputs, Literal(Constant(()))))
  }
}
4

1 回答 1

2

正如 Eugene 所建议的,使用 quasiquotes 可以使这更容易。我还没有提出一个完整的解决方案,但我尝试了一些部分,所以我认为这些方面的一些东西会起作用:

case q"class $name extends $parent with ..$traits { ..$body }"=>
  val newBody = body.flatMap {
    case q"var $varName = $varBody" =>
       List(
         //put the three defs you need here.  some variant of this ...
         q"""private val ${stringToTermName("_" + varName.toString)} = Ref(${stringToTermName(varName.name + "0")})""",
         //etc ...
       )
    case other => other
  }
  q"class $name extends $parent with ..$ttraits { ..${(newBody).toList} }"

您可能会发现我的博客文章相关:http: //imranrashid.com/posts/learning-scala-macros/

最相关的代码片段在这里: https ://github.com/squito/learn_macros/blob/master/macros/src/main/scala/com/imranrashid/oleander/macros/FillTraitDefs.scala#L78

您可能还会发现这对于定义 getter 和 setter 很有用: https ://groups.google.com/forum/#!searchin/scala-user/macro|sort:date/scala-user/Ug75FW73mJI/F1ijU0uxZAUJ

于 2013-11-13T02:40:04.183 回答