Tôi đang cố gắng viết một trình biên dịch Scala plugin cho phép tạo mã cực kỳ chung chung: một cái gì đó giống như tính tổng quát của bộ tiền xử lý C, nhưng an toàn hơn một chút (tôi không chắc chắn nếu đây là một ý tưởng khủng khiếp, nhưng đó là một bài tập thú vị). trường hợp sử dụng lý tưởng của tôi trông giống như sau:Vượt qua đóng cửa cho trình biên dịch Scala plugin
// User code. This represents some function that might take some args
// and outputs an abstract syntax tree.
def createFooTree(...): scala.reflect.runtime.universe.Tree = ...
// Later user code (maybe separate compilation?). Here the user generates
// code programmatically using the function call to |createFooTree| and inserts
// the code using insertTree.
insertTree(createFooTree(...))
Mã plugin quan trọng có thể trông như thế này (dựa trên this):
class InsertTreeComponent(val global: Global)
extends PluginComponent
with TypingTransformers {
import global._
import definitions._
override val phaseName = "insertTree"
override val runsRightAfter = Some("parser")
override val runsAfter = runsRightAfter.toList
override val runsBefore = List[String]("typer")
def newPhase(prev: Phase): StdPhase = new StdPhase(prev) {
def apply(unit: CompilationUnit) {
val onTransformer = new TypingTransformer(unit) {
override def transform(tree: Tree): Tree = tree match {
case orig @ Apply(
function,
// |treeClosure| is the closure we passed, which should
// evaluate to a Tree (albeit a runtime Tree).
// The function.toString bit matches anything that looks like a
// function call with a function called |insertTree|.
treeClosure) if (function.toString == "insertTree") => {
// This function evaluates and returns the Tree, inserting it
// into the call site as automatically-generated code.
// Unfortunately, the following line isn't valid.
eval(treeClosure): Tree
}
...
Bất kỳ ý tưởng làm thế nào để làm điều này? Vui lòng không nói "chỉ sử dụng macro"; ít nhất là 2,10, chúng không đủ chung.
BTW, tôi thấy hai vấn đề với cách tiếp cận mà tôi đã phác thảo: 1) Trình biên dịch plugin mất một AST, không phải là đóng. Nó sẽ cần một số cách để tạo ra các đóng cửa, có lẽ thêm một sự phụ thuộc xây dựng trên mã người dùng. 2) Người dùng không có quyền truy cập vào scala.reflect.internal.Trees.Tree, chỉ scala.reflect.runtime.universe.Tree, vì vậy plugin sẽ cần dịch giữa hai.
Đó chắc chắn là một ý tưởng khủng khiếp - nhưng là một bài tập tuyệt vời;) - bạn sẽ nghĩ về việc tìm kiếm trong việc xâm nhập macro trong thiên đường. –