Как язык может быть интерпретирован сам по себе (например, Рубиниус)? - PullRequest
5 голосов
/ 30 мая 2010

Я уже некоторое время программирую на Ruby, используя только стандартную MRI-реализацию Ruby, но мне всегда было интересно узнать о других реализациях, о которых я так много слышал.

На днях я читал о Рубиниусе, переводчике на Ruby, написанном на Ruby. Я пытался найти его в разных местах, но мне было трудно понять, как именно это работает. У меня никогда не было большого опыта в написании компиляторов или написании языков, но мне действительно интересно это выяснить.

Как именно язык может быть интерпретирован сам по себе? Есть ли базовый шаг в компиляции, который я не понимаю, где это имеет смысл? Может ли кто-нибудь объяснить мне это, как будто я идиот (потому что это не слишком далеко от базы в любом случае)

Ответы [ 5 ]

8 голосов
/ 30 мая 2010

Это проще, чем вы думаете.

Rubinius не написан на 100% на Ruby, просто в основном.

С http://rubini.us/

Большой аспект популярных языков, таких как C и Java, заключается в том, что большинство функций, доступных программисту, написаны на самом языке. Цель Rubinius - добавить Ruby в этот список. Рубиисты могут легче добавлять функции в язык, исправлять ошибки и изучать, как работает язык. По возможности, Рубинус написан на Руби. Там, где это невозможно (пока), это C ++.

4 голосов
/ 30 мая 2010

Концепция, которую вы ищете: начальная загрузка компилятора .

По сути, начальная загрузка означает написание компилятора (или интерпретатора) для языка x на языке x . Это делается либо написанием базового компилятора на более низком уровне вручную (т.е. написанием компилятора C в ассемблере), либо использованием другого языка высокого уровня.

Подробнее о начальной загрузке см. В wikipedia . Ответ Грега относительно мета-циркулярных оценщиков также настоятельно рекомендуется, включая соответствующую главу в SICP.

2 голосов
/ 30 мая 2010

В случае Rubinius виртуальная машина написана на C ++ и имеет дело со всеми низкоуровневыми (связанными с операционной системой) вещами и базовыми операциями. У виртуальной машины есть собственный формат байт-кода (как и у JVM), и когда Rubinius запускается, он запускает виртуальную машину, которая выполняет байт-код. Однако большая часть стандартной библиотеки Rubinius (которая является частью языка Ruby) реализована на Ruby по сравнению с C (MRI) или Java (JRuby). Кроме того, компилятор байт-кода Rubinius также написан на Ruby. Так что да, в какой-то момент в начале они должны были использовать стандартный интерпретатор Ruby (MRI) для начальной загрузки Rubinius. Но это больше не должно иметь место (хотя я не уверен, что вам все еще это может понадобиться, поскольку его система сборки использует rake).

1 голос
/ 30 мая 2010

Предположим, что вы работаете с языком, скажем Lisp, хотя это не имеет значения. (Может быть C ++, Java, Ruby, что угодно.)

Хорошо, у вас есть реализация Lisp. Назовите эту реализацию Imp (только некоторые из придуманных сокращений для IMPlementation). Поскольку Imp сама по себе является программой, ваш компьютер может ее запустить. Теперь вы пишете свою собственную реализацию для Lisp, написанную на Lisp, и называете ее Circ. Circ - это просто программа, скомпилированная (или интерпретированная, если хотите) из кода на Лиспе. Ваш код написан так, что он читает в файл, анализирует его (обрабатывает его в значимые данные) и что-то делает с данными. Что это такое? В случае с Circ он выполняет данные.

Но как это получается?

Предположим, для простого случая, что код, который читает и анализирует Circ, представляет собой нечто простое, например, выполнение математических операций и вывод результата. Circ обрабатывает код в виде простых в использовании данных (хорошо для такого языка, как Lisp, с которого легко начать, но это не главное) и сохраняет его. Что ж, в Lisp вы можете написать код для сокращения чисел, поэтому код, написанный для Circ, может сделать то же самое, потому что он написан на Lisp. Таким образом, обработанные данные подключаются к некоторому коду дополнительной обработки ... и вуаля! У вас есть числовой результат! Затем ваша программа Circ выдаст результат.

То же самое можно сделать с более сложными вещами, чем простая математика. На самом деле вы можете компилировать / интерпретировать другие аспекты языка. Напишите достаточно этих «других аспектов» и склейте их вместе, вы получите компилятор для Lisp, написанный на Lisp.

Поскольку компилятор компилируется Imp, он может запускаться на вашей машине и presto! Вы сделали.

0 голосов
/ 30 мая 2010

Этот метод обычно называется мета-круговым оценщиком и был впервые введен несколько десятилетий назад в контексте Lisp.

Хорошее описание методики можно найти в Структура и интерпретация компьютерных программ , глава 4.

...