Làm cách nào để nhận macro macro để thay thế cuộc gọi phương thức?Làm thế nào để tôi có được macro scala để thay thế một phương thức gọi
Mục tiêu của tôi là tạo một đặc điểm được gọi là ToStringAdder
. Giả sử tôi có một đối tượng x
với đặc tính này, sau đó khi tôi gọi x.add(any)
Tôi muốn macro thực sự gọi x.add(any, string)
trong đó chuỗi là biểu diễn chuỗi của AST. (Điều này là để tôi có thể có tốt đẹp tostring
khi 'bất kỳ' là một chức năng).
- Tôi đã viết các macro được đưa ra trong các tài liệu http://docs.scala-lang.org/overviews/macros/overview.html,
- đọc http://docs.scala-lang.org/sips/pending/self-cleaning-macros.html
- đọc các file PDF http://scalamacros.org/paperstalks/2013-04-22-LetOurPowersCombine.pdf.
- Tôi đã xem xét các mã trong https://github.com/retronym/macrocosm/blob/master/src/main/scala/com/github/retronym/macrocosm/Macrocosm.scala
- Và mã trong https://github.com/pniederw/expecty/tree/master/src/main/scala/org/expecty, nhưng tôi buồn mà nói tôi không grok nó tất cả
- Tôi đã có một cái nhìn tại các scaladoc, nhưng. ..woo .. đó là phức tạp ... Tôi nghi ngờ rằng tôi sẽ cần một số thời gian đáng kể để có được lên đến tốc độ với cách trình biên dịch hoạt động.
Ngoại trừ Expecty tất cả các ví dụ này tôi đã thấy đang sử dụng hiệu quả các cuộc gọi phương thức tĩnh: đối tượng mà macro được gọi không được sử dụng. Expecty có các phương pháp sau đây, trong đó cung cấp cho tôi một đầu mối về cách phát hiện 'ngầm này', nhưng tôi không thể tìm thấy một cách để tham khảo nó trong một cuộc gọi reify.
private[this] def recordAllValues(expr: Tree): Tree = expr match {
case New(_) => expr // only record after ctor call
case Literal(_) => expr // don't record
// don't record value of implicit "this" added by compiler; couldn't find a better way to detect implicit "this" than via point
case Select([email protected](_), y) if getPosition(expr).point == getPosition(x).point => expr
case _ => recordValue(recordSubValues(expr), expr)
}
Vậy làm cách nào để thay thế cuộc gọi đến đối tượng mà macro đã được gọi. Mã tôi có vào lúc này là dưới đây, và nó là mã trong cuộc gọi cụ thể hóa mà cần phải được sắp xếp
trait ToStringAdder {
def add(param: Any): Any = macro ToStringAdder.toStringAndValueImpl
def add(param: Any, toStringBasedOnAST: String): Any ; //This is the actual method I want the above method call to be replaced by
}
object ToStringAdder {
def toStringAndValueImpl(c: Context)(param: c.Expr[Any]): c.Expr[Unit] = {
import c.universe._
val paramRep = show(param.tree)
val paramRepTree = Literal(Constant(paramRep))
val paramRepExpr = c.Expr[String](paramRepTree)
//need to put something here
reify { c.someMethodCall("something to represent the method any", param.splice, paramRepExpr.splice) }
}
}
Đây là một câu hỏi thật sự tốt đẹp nếu tôi hiểu nó một cách chính xác. Tôi tin rằng điểm là với một toString trên một 'chức năng' trả về một AST duy nhất bạn có thể thực hiện một toán tử bình đẳng trên' chức năng '. Người ta có thể làm những điều tuyệt vời như không lo lắng về việc sao chép các hàm trong một 'Danh sách' - chỉ cần gọi' toSet'. – samthebest