我想编写一个简单的 Ruby DSL 来将一些语句和表达式翻译成另一种语言。一个基本的例子是:
some_function {
t + 2
}
这里,t 不是 ruby 变量,因此 block 不能(也不能!)由 Ruby 求值。所以我最好的选择是使用解析输出(或 AST)自己进行翻译。为此,我可以使用 ParseTree 和 ruby2ruby。但是,我还有其他想要使用的结构,例如:
1.upto(10) {|x|
some_function {
t + x
}
}
在这里,我有一个局部变量,我需要获取它的值才能进行翻译。但是,在执行 block 评估的函数中,我无权访问调用 block 的局部变量。如果它是一个全局变量 ($x),我可以检查它的名称是否存在于 global_variables 数组中,在最坏的情况下使用 eval,但如果可能的话,我怎么能对局部变量这样做呢?
更新:
只是为了清理事情。就像我最初所说的那样,我正在使用 ruby2ruby(因此使用 ParseTree)来获取与该 block 对应的 AST(使用 to_sexp)。但是在我的 block 中使用局部变量时,我遇到了以下情况:
[:dvar, :x]
因此,我需要从变量的名称中获取变量的值作为字符串/符号。而且我不能使用 method_missing 或 instance_eval,因为我想将整个表达式翻译成另一种语言或语法(如 RPN)。
尽管如此,另一种不基于 ParseTree 的解决方案还是受欢迎的,因为 Ruby 1.9 显然不完全支持它。
最佳答案
要获取变量值,请使用过程的绑定(bind):
def some_function(&block)
b = block.binding
p [b.eval("t"), b.eval("x")]
end
t = 1
1.upto(10) {|x|
some_function {
t + x
}
}
关于ruby - 为 DSL 翻译 block 和语句,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/843181/