2015-12-20 20 views
3

对于MRI 1.9+和Rubinius实现,Ruby源代码被编译为字节码,然后该VM解释该字节码。在使用解释器从命令行运行Ruby脚本时,我想知道这个机制的细节。Ruby解释器是否以懒惰的方式编译为字节码?怎么样?

  • 解释器是否先编译脚本中所需的所有相关源文件,然后运行一切?还是执行一些代码,然后在需要时以一种懒惰的方式编译其他文件?
  • 如果是后者(我怀疑),这个过程是通过文件还是通过一段代码完成的?
  • 在哪一点停止执行字节码并再次运行编译过程?
  • 这个过程是否与MRI到Rubinius不同?

例如,如果我跑“红宝石my_main_script.rb”,这需要其他3个RB源文件(这个文件本身没有任何要求),我想象中的可能性是:

  • A:解释器解析my_main_script.rb和3个文件。然后解析后,它将所有AST树编译为字节码。然后它继续使用VM运行字节码。

  • B:Ruby解析my_main_script.rb并将其编译为字节码。然后它运行字节码。当遇到对另一个文件中某个方法的调用时,它首先解析并编译该文件,并继续执行。如果是这种情况,我想详细了解这一点。

  • Ç:红宝石解析和编译根据一些从一些my_main_script.rb一段代码(unkwnon我)的标准,它运行的字节码,然后解析和 - 编译需要时的另一块。这个过程和“需要时”状态检测方法是我理解的有趣的东西。


更新30/03/16

我写了这个小实验的脚本来尝试检查,如果B是正确答案:

class RubyVM 
    class InstructionSequence 
    class << self 
     alias :old_compile_file :compile_file 
     def compile_file(code, opt) 
     puts "Injecting code..." 
     old_compile_file(code, opt) 
     end 
     alias :old_compile :compile 
     def compile(code) 
     puts "Injecting code..." 
     old_compile(code) 
     end 
    end 
    end 
end 

require_relative 'say_hi' 

“say_hi.rb '只包含行'puts'hello'“。 如果B是正确的答案,不应该输出以下内容?

Injecting code... 
hello 

它只是输出 “你好” ......

+0

你能提供一个示例脚本,然后解释如何该脚本会在不同的两种理论来执行?就像,如果“解释程序先编译脚本中所需的所有相关源文件,然后运行所有内容”,那么结果如何?如果“它执行一些代码,然后同时需要一个懒惰的方式编译其他文件”,将是什么样子? –

+0

@kitkat完成!希望它有帮助 – lucianolev

+0

谢谢,这是完美的! –

回答

2

对我来说,B是正确答案。

Ruby允许我们通过autoload动态加载我们的代码,并以代码的形式执行字符串(eval),因此它必须能够随时解析和执行代码。

因此首先它会改变所有的主程序YARV指令所需的文件,但如果您使用autoloadeval这些文件/代码将在稍后改变。

有关该过程的一个非常良好的开端是Ruby under a microscope

+0

我已经做了一个脚本来检查这是否属实,但我无法确认。请检查我的问题更新。顺便说一句,我已经在显微镜下阅读了Ruby,但无法找到答案。 – lucianolev

相关问题