Об утверждении "Ваш рубиновый код никогда не переводится на машинный язык"

Я читаю книгу "Рубин под микроскопом" и не понимаю процитированную часть во второй главе:

Из того, что я понял, процесс запуска программы ruby ​​примерно такой:

  • Прочитайте файл и токенизируйте его

  • Используя правила грамматики, преобразуйте эти токены в инструкции в дереве абстрактного синтаксиса.

  • Проходя по узлам, преобразуйте их в байт-код YARV (этот шаг называется компиляцией?).

И этот последний меня беспокоит

  • "Ruby никогда не компилирует ваш код Ruby вплоть до машинного языка. [...] Ruby интерпретирует инструкции байт-кода".

Мой вопрос: для того, чтобы эти инструкции байт-кода были поняты и выполнены, не нужно ли мне переводить их в ассемблер / машинный код раньше? Если нет, то как машина понимает их?

2 ответа

"Ruby никогда не компилирует ваш код Ruby вплоть до машинного языка. [...] Ruby интерпретирует инструкции байт-кода".

Эта цитата - если не прямо неверно - ужасно вводит в заблуждение.

Во-первых, Ruby - это язык программирования. Языки программирования ничего не компилируют и не интерпретируют. Компиляторы и интерпретаторы делают это. Языки программирования - это просто набор абстрактных математических правил и ограничений.

Во-вторых, существует множество различных реализаций Ruby: Rubinius, JRuby, IronRuby, MacRuby, MRuby, Topaz, Cardinal, Opal, MagLev, YARV,… И все они работают по-разному. Например, Rubinius компилирует байт-код Ruby в Rubinius, затем собирает некоторую статистику при интерпретации этого байт-кода, а затем использует эту статистику для компиляции байт-кода в эффективный, производительный, машинный код. JRuby интерпретирует JRuby AST и одновременно собирает статистику, затем компилирует JRuby AST в компилятор IRuby IR, использует статистику для ее оптимизации, а затем компилирует ее далее в байт-код JVM. То, что JVM делает с этим байт-кодом, зависит от конкретной реализации JVM, но большинство JVM в конечном итоге компилируют байт-код JVM в эффективный, производительный, машинный код. Opal компилирует код Ruby в код ECMAScript, и большинство реализаций ECMAScript в конечном итоге скомпилируют исходный код ECMAScript в эффективный, производительный, машинный код.

В-третьих, что означает "машинный язык"? Байт-код YARV - это машинный язык машины YARV, не так ли? Существуют процессоры, которые могут выполнять байт-код JVM напрямую, означает ли это, что байт-код JVM является машинным языком? На JVM работают интерпретаторы, которые могут интерпретировать объектный код x86. Означает ли это, что объектный код x86 не является машинным языком? Что делать, если я запускаю интерпретатор x86 поверх IKVM (JVM, работающей поверх.NET) поверх.NET на компьютере ARM? Что такое машинный язык тогда?

Итак, резюмируем:

  • Ruby - это язык, а не реализация, утверждение даже не имеет смысла.
  • Большинство реализаций Ruby (Rubinius, Topaz, MacRuby, MagLev) или, по крайней мере, могут (JRuby, IronRuby, Opal, Cardinal) заканчиваются собственным машинным кодом.
  • Термин "машинный язык" в любом случае плохо определен.

Мой вопрос: для того, чтобы эти инструкции байт-кода были поняты и выполнены, не нужно ли мне переводить их в ассемблер / машинный код раньше?

Нет, переводчик понимает и выполняет их. Если бы он перевел их во что-то еще, это был бы компилятор, а не интерпретатор.

Компилятор переводит, но не запускается. Переводчик работает, но не переводит. Вам нужен где-то интерпретатор, вы не можете запустить программу только с помощью компилятора. Компилятор просто переводит программу с одного языка на другой язык. Период. Если вы действительно хотите запустить программу, вам нужен переводчик. Этот интерпретатор может быть реализован аппаратно, в этом случае мы называем его "ЦП", но он все еще просто интерпретатор.

См. Также Понимание различий: традиционный интерпретатор, JIT-компилятор, JIT-интерпретатор и AOT-компилятор в Programmers.SE.

Если нет, то как машина понимает их?

Это не так. Переводчик их понимает. Он понимает их так же, как их понимает компилятор, за исключением того, что вместо генерации кода, соответствующего семантике входной программы, он выполняет код, соответствующий семантике входной программы.

См. Также Переводчик производит машинный код? и как работает переводчик? на программистов.SE.

Нет, утверждение, в котором вы находитесь в затруднительном положении, говорит само за себя. Интерпретатор байтового кода Ruby выполняет вычисления от имени байтового кода и передает результаты (в большинстве случаев) в следующий набор байтовых кодов, который должен быть оценен.

Это сложнее, чем это, но воспринимайте это как уровень обработки между байтовым кодом Ruby и собственной машиной.

Другие вопросы по тегам