3

我正在尝试使用以下方法评估Expr宏内部:Context#eval

//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 )
}

但是,编译器抱怨:

[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中找到,则可以使用resetAllAttrs. 然而

  1. 我不明白我应该如何使用它。
  2. 此功能似乎已被弃用

那么有没有办法解决我的问题?


其余代码:

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

}
4

2 回答 2

3

c.eval确实告诉使用的文档c.resetAllAttrs,但是这个函数有许多已知问题,有时会使其处理的树不可挽回地损坏(这就是我们计划在 Scala 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可靠地工作。

于 2014-02-07T19:10:17.613 回答
1

好吧,我明白了他们使用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.

于 2014-02-05T14:57:32.167 回答