2014-08-29 4 views
1

Я пытался использовать панель инструментов и quasiquote вместе, чтобы выполнять задачи генерации кода, и столкнулись с StackOverflowError при использовании AST объекта вернулся из reify(x).tree, мой код выглядит следующим образом:AST unquoting используя quasiquotes и дерево вернулся из материализовать

abstract class A[T] {def i: T} 
class B(val i: Int) extends A[Int] 
object A { 

    import scala.reflect.runtime.universe._ 
    import scala.reflect.runtime.{universe => ru} 
    import scala.tools.reflect.ToolBox 

    val javaSeparator = "$" 
    val curId = new java.util.concurrent.atomic.AtomicInteger() 

    protected def freshName(prefix: String): TermName = { 
     newTermName(s"$prefix$javaSeparator${curId.getAndIncrement}") 
} 

def main(args: Array[String]) { 
    val b = new B(2) 
    calculate(b) 
} 

def calculate(a: A[_]): Unit = { 

    val toolBox = runtimeMirror(getClass.getClassLoader).mkToolBox() 
    val i = freshName("i") 
    val aTree = reify(a).tree 

    val tree = q""" 
     val $i = $aTree.i 
     println($i) 
    """ 

    toolBox.eval(tree) 
    } 
} 

, когда я удаляю параметр типа класса A или использую def calculate(a: B), toolBox.eval успех и работа, как ожидалось, т.е. печать 2 в консоли.

Я не совсем понимаю, почему это происходит, может кто-нибудь объяснить, почему определение класса с параметрами типа не дает оценку?

+0

Похож на ошибку. Хотя сначала я хотел бы спросить, чего вы хотели достичь, выполнив 'reify (a) .tree'. Какой результат вы ожидаете? –

+0

@EugeneBurmako, приведенный выше код был просто для того, чтобы показать неудачу, с которой я столкнулся. В моем реальном проекте, поскольку A имеет много подклассов с разным типом массива, я хочу манипулировать ими во всех вычислениях, в то же время избегая боковых и ненужных издержек из-за полинома. reify (a) .tree было просто использовать параметр в AST, который я могу рассмотреть. Есть ли более эффективные способы использования аргумента непосредственно в AST? Спасибо. –

+0

Итак, когда вы пишете 'reify (a) .tree', вы хотите получить' Ident (TermName («a»)), который сохраняет ссылку на значение времени выполнения аргумента 'a', переданного текущему вызову метода, правильно? –

ответ

1

Это https://issues.scala-lang.org/browse/SI-8833. Пока ошибка не будет исправлена, вы можете использовать обходной путь, описанный в комментариях в JIRA. Я только предоставил обходное решение для 2.11.x, и если вам нужно один для 2.10.x, оставьте комментарий.

+0

Пожалуйста, покажите обходной путь для 2.10.x, thx :) –

+0

Я сделаю через 1-2 часа. Теперь нужно идти. –

+0

Готово. Обновлен комментарий в JIRA. –