2014-02-05 53 views
2

我試圖用Context#eval方法來評估宏觀內的Expr如何評估Scala宏中的表達式?

[error] /home/falcone/prg/sbt-example-paradise/core/src/main/scala/Test.scala:20: exception during macro expansion: 
[error] scala.tools.reflect.ToolBoxError: reflective toolbox has failed 

如果scala-user ML發現,該問題可能是:

//Dummy implementation 
def evalArrayTree(c: Context)(a: c.Expr[ArrayTree]): c.Expr[Array[Double]] = { 
    import c.universe._ 
    println(c.eval(a)) 

    val tree = reify(Array(0.0,0.0,0.0)).tree 
    c.Expr[Array[Double]](tree) 
} 

然而,編譯器抱怨使用resetAllAttrs解決。然而,

  1. 我不明白我應該如何使用它。
  2. 此功能seems to be deprecated

那麼有沒有辦法解決我的問題?


的其餘代碼:

object ArrayEval { 

    import scala.language.experimental.macros 

    def eval(a: ArrayOps.ArrayTree): Array[Double] = macro Macros.evalArrayTree 

} 

object ArrayOps { 

    sealed trait ArrayTree { 
    def +(that: ArrayTree) = Plus(this, that) 
    } 

    implicit class Ary(val ary: Array[Double]) extends ArrayTree 
    case class Plus(left: ArrayTree, right: ArrayTree) extends ArrayTree 

} 
+0

如果您可以在github項目中發佈整個代碼,將會有所幫助。然後,我會確保在修復resetAttrs時我們不會錯過您的用例。 –

回答

0

好吧,我想通了,他們所說的使用resetAllAttrs。我的例子是簡化了的Int輸入,但我可以複製和修復錯誤,你這樣做說明如下:

import scala.language.experimental.macros 
import scala.reflect.runtime.universe._ 
import scala.reflect.macros.BlackboxContext 

def _evalMacro(c: BlackboxContext)(a: c.Expr[Int]) = { 
    import c.universe._ 

    val treeReset = c.resetAllAttrs(a.tree) // Reset the symbols in the tree for 'a' 
    val newExpr = c.Expr(treeReset)   // Construct a new expression for the updated tree 

    println(c.eval(newExpr)) // Perform evaluation on the newly constructed expression 
    ...      // Do what you do 
} 

def evalMacro(a: Int) = macro _evalMacro 

我打算做一個猜測,你沒事使用resetAllAttrs,至少在未來的一些Scala版本出來之前。 2.11甚至不提供使用的棄用警告。

注意:我使用的是Scala 2.11。我相信這應該在2.10中完全相同,除非您將使用Context而不是BlackboxContext

+0

我有更大的錯誤:'對象Ary不是包ArrayOps'的成員,這是真的,因爲'Ary'不是一個對象,而是一個隱含的類,如上所示。 – paradigmatic

+0

@paradigmatic你從哪裏得到它?你確定這是一個宏/上下文錯誤?我知道宏並不總是和implicits相配,儘管我不確定它在多大程度上。 – KChaloux

+0

我在這裏添加了主要方法和錯誤:https://gist.github.com/paradigmatic/8827878謝謝 – paradigmatic

3

c.eval該文檔確實告訴使用c.resetAllAttrs,不過這個功能有一些已知問題,有時使其無可挽回的損壞,它處理的樹(這就是爲什麼我們打算在斯卡拉2.11刪除它 - 我只是提交了一個請求:https://github.com/scala/scala/pull/3485)。

您可以嘗試的是c.resetLocalAttrs,它具有較小的樹木腐敗可能性。不幸的是它仍然有點壞。我們計劃修復它(https://groups.google.com/forum/#!topic/scala-internals/TtCTPlj_qcQ),但是在Scala 2.10.x和2.11.0中,將無法使c.eval可靠地工作。