2015-12-20 5 views
3

Для реализации MRI 1.9+ и Rubinius исходный код Ruby скомпилирован в байт-код, а затем этот байт-код интерпретируется виртуальной машиной. Я хочу узнать подробности этого механизма при запуске Ruby-скрипта из командной строки с использованием интерпретатора.Является ли интерпретатор Ruby компиляцией байтового кода ленивым способом? Как?

  • Содержит ли интерпретатор все связанные исходные файлы, необходимые для первого скрипта, а затем запускает все? Или он выполняет какой-то код, а затем компилирует другие файлы, когда он нужен ленивым способом?
  • Если это последний (что я подозреваю), этот процесс выполняется файлом или блоком кода?
  • В какой момент он останавливает выполнение байтового кода и снова запускает процесс компиляции?
  • Отличается ли этот процесс от МРТ до Рубиния?

Например, если я бегу «рубиновый my_main_script.rb», который требует 3 других гь исходных файлов (и эти файлы сами по себе не имеют каких-либо требований), возможность я полагаю, было бы:

  • A: интерпретатор анализирует my_main_script.rb и 3 файла. После синтаксического анализа он компилирует все деревья AST в байт-код. Затем он запускает байт-код с использованием виртуальной машины.

  • B: Ruby разбирает my_main_script.rb и скомпилирует его в байтовый код. Затем он запускает байт-код. Когда вы сталкиваетесь с вызовом метода в других файлах, он сначала анализирует и компилирует эти файлы и продолжает выполнение. Если это так, я хотел бы разобраться в этом подробно.

  • C: Ruby разбирает и собирает некоторую часть кода из my_main_script.rb согласно некоторым (unkwnon мне) критерии, он запускает этот байт-код, а затем разбирает-и-компилирует другую часть, когда это необходимо. Этот процесс и то, что «когда нужно» метод обнаружения условий - это то, что мне было бы интересно понять.


Update 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, но если вы используете autoload или eval, эти файлы/код будут преобразованы позже.

Очень хорошая книга о том, что процесс является Ruby under a microscope

+0

Я сделал небольшой скрипт, чтобы проверить, правда ли это, но я не смог его подтвердить. Пожалуйста, проверьте мое обновление на вопрос. Кстати, я читал Руби под микроскопом, но на это не мог найти ответа. – lucianolev

 Смежные вопросы

  • Нет связанных вопросов^_^