ruby - 为 DSL 翻译 block 和语句

标签 ruby dsl

我想编写一个简单的 Ruby DSL 来将一些语句和表达式翻译成另一种语言。一个基本的例子是:

some_function {
    t + 2
}

这里,t 不是 ruby​​ 变量,因此 block 不能(也不能!)由 Ruby 求值。所以我最好的选择是使用解析输出(或 AST)自己进行翻译。为此,我可以使用 ParseTree 和 ruby​​2ruby。但是,我还有其他想要使用的结构,例如:

1.upto(10) {|x|
    some_function {
        t + x
    }
}

在这里,我有一个局部变量,我需要获取它的值才能进行翻译。但是,在执行 block 评估的函数中,我无权访问调用 block 的局部变量。如果它是一个全局变量 ($x),我可以检查它的名称是否存在于 global_variables 数组中,在最坏的情况下使用 eval,但如果可能的话,我怎么能对局部变量这样做呢?

更新:

只是为了清理事情。就像我最初所说的那样,我正在使用 ruby​​2ruby(因此使用 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/

相关文章:

android - 使用 aws-ruby-sdk 通过 AWS SNS 向多个平台发送消息

ruby-on-rails - 单表继承查找问题

ruby - 使用不同的参数多次运行 rspec 测试套件

android - Gradle:找不到 DSL 方法:minSdkVersion/targetSdkVersion/compileSdkVersion/buildToolsVersion

python - 在 Tkinter.Tcl() 中使用 Python 函数

ruby-on-rails - 所有 Rails url 都返回错误 500

Ruby:Titleize:如何忽略较小的词,如 'and' 、 'the' 、 'or 等

spring - 如何在 Groovy 中使用 Spring DSL 基于环境(dev、qa、prod)注入(inject)依赖?

image-processing - 用于 Clojure 图像合成的 DSL

.net - 在为规则引擎创建 DSL 时使用什么技术?