Ruby中运行时代码生成的最佳实践

时间:2012-09-20 01:46:35

标签: ruby compilation code-generation runtime-compilation

我最近开始使用解析器和解析器生成器及其在DSL设计中的用途。为了开始,并一举两得,我通过窃取peg.js的一些想法写了一个纯Ruby Ruby解析器DSL。区别在于peg.js会将语法编译为JavaScript,而我的库使用解释器模式结合Ruby提供的一些语法糖来完成纯Ruby中的所有操作。这增加了一些我想避免的非平凡的开销。

为了减少一些开销,我开始考虑编译一些生成为低级表示的解析表达式。我的一个想法是使用eval来评估某个对象的单例类中代码的字符串表示。这里有一些伪代码来演示这个过程:

# will be used to pass CompiledExpression instance to `eval`
def get_binding(instance)
  instance.instance_eval { binding }
end

# an instance of this class will be used with `eval` 
# to define an `execute` method
class CompiledExpression
  attr_reader :code_repr
  # need to instantiate with a string representation of 
  # the code we are going to use to define the `execute` method
  def initialize(code)
    @code_repr = code
  end
end

# create the instance and define `execute` for that instance
# by evaluating the code representation
compiled_expr = CompiledExpression.new

# first way
eval "class << self; def execute; " +
    "#{compiled_expr.code_repr}; end; end", get_binding(compiled_expr)

# second way
compiled_expr.instance_eval "class << self; " +
    "def execute; #{compiled_expr.code_repr}: end; end"

# third way
compiled_expr.singleton_class.class_eval "def execute; " + 
    "#{compiled_expr.code_repr}; end"

# fourth way
compiled_expr.instance_eval "def execute; " + 
    "#{compiled_expr.code_repr}; end"

我想知道是否有其他/更好的方法来完成这样的代码生成?我是新手,所以我可能会遗漏一些明显的东西。

1 个答案:

答案 0 :(得分:2)

我仍在尝试了解您要完成的任务,但是您可能有兴趣探索一些Ruby解析器/解析器生成器。

Treetop :我最熟悉的解析器,它是一个可以动态运行的peg解析器,或者将语法编译成纯Ruby解析器Treetop

Parslet :这是另一个peg解析器,它具有比Treetop更简单的设计和“更好”的错误报告。 Parslet

Citrus :另一个解析器,我不熟悉的解析器;我不认为这是一个 peg解析器。 Citrus