2015-12-20 29 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

相關問題