Начальная загрузка переводчика? - PullRequest
3 голосов
/ 24 марта 2012

Мы знаем, что компилятор может быть написан на его собственном языке, используя прием, известный как начальная загрузка.Мой вопрос заключается в том, может ли этот прием быть применен и к интерпретаторам?

Теоретически, ответ, конечно, да, но есть одно беспокойство, что интерпретация исходного кода будет становиться все более и более неэффективной, когда мы проходим черезитераций.Будет ли это серьезной проблемой?

Я запускаю очень динамичную систему, где программы будут постоянно меняться, так что это исключает компилятор.

Позвольте мне изложить это так:

Пусть i будут интерпретаторами.

Пусть L будут языками программирования.

  • Мы можем написать i1 в машинном коде (самый низкий уровень), чтобы интерпретировать L1.
  • Затем мы пишем i2 в L1, интерпретируя L2 - новый язык.
  • Затем пишем i3 в L2, интерпретируя L3 - другой новый язык.
  • и такon ...

Нам не нужен никакой компилятор, только интерпретаторы.Правильно?

Это может быть неэффективно.Это мой вопрос, и как его преодолеть, если он действительно неэффективен.

Ответы [ 4 ]

5 голосов
/ 24 марта 2012

Это не имеет смысла. Интерпретатор не создает двоичный файл, поэтому не может создать то, что может работать автономно. Где-то, в конечном счете, вам нужен двоичный файл, который является интерпретатором.

Пример начальной загрузки компилятора. Допустим, у нас есть два языка A (ssembler) и C. Мы хотим запустить компилятор C, написанный на C. Но у нас есть только ассемблер, с которого нужно начинать.

  1. Написать базовый компилятор C в A
  2. Написать компилятор C на C и скомпилировать с более ранним компилятором, написанным на A
  3. Теперь у вас есть компилятор C, который может компилироваться сам, вам больше не нужен A или оригинальный компилятор.

Более поздние пробеги становятся просто

  1. Компиляция программы C с использованием компилятора, написанного на C

Теперь предположим, что вместо этого у вас есть интерпретируемый язык, я назову его Y. Первая версия может называться Y1, следующая Y2 и так далее. Давайте попробуем его «загрузить».

Прежде всего, у нас нет ничего, что могло бы интерпретировать Y-программы, нам нужно написать базовый интерпретатор. Допустим, у нас есть компилятор C и мы написали интерпретатор Y1 на C.

  1. Написать интерпретатор Y1 на C, скомпилировать его
  2. Напишите интерпретатор Y2 в Y1, запустите его на интерпретаторе Y1, написанном на C
  3. Написать интерпретатор Y3 в Y2, запустить его на интерпретаторе Y2, работающем на интерпретаторе Y1 ... Написано на C.

Проблема в том, что вы никогда не можете избежать стека интерпретаторов, поскольку вы никогда не компилируете интерпретатор более высокого уровня. Так что вам всегда нужно будет скомпилировать и запустить тот первый интерпретатор версий, написанный на C. Вы никогда не сможете избежать этого, что, я думаю, является фундаментальной точкой процесса начальной загрузки компилятора. Вот почему я говорю, что ваш вопрос не имеет смысла.

2 голосов
/ 05 июня 2015

Ответ зависит от того, что интерпретируется.Если вы нацелены на виртуальную машину, которая интерпретирует байт-код, и ваш язык разрабатывается итеративно, в то время как байт-код не изменяется, то это не то, что вы потеряете производительность по пути.Существует множество примеров языков, которые загружаются на целевую виртуальную машину, которая не была разработана специально для этого языка, и они не испытывают значительного снижения производительности как прямой результат (например, Scala на JVM).

Например, используя JVM, вы написали бы первый компилятор на Java, который компилирует ваш исходный язык в байт-код JVM.Затем вы переписали бы свой компилятор, чтобы он делал то же самое, но на новом исходном языке.Результирующий байт-код может быть неразличим между ними.Обратите внимание, что это не то же самое, что написание интерпретатора на интерпретируемом языке, который будет становиться медленнее с каждой итерацией.

0 голосов
/ 27 марта 2012

Это предложение, похоже, не имеет смысла:

Я загружаю очень динамичную систему, в которой программы будут постоянно меняться, поэтому он исключает компилятор.

Неважно, есть ли у вас интерпретатор или компилятор: оба будут иметь дело с чем-то, что не изменяется, то есть с вашим языком. И даже если язык как-то «динамичен», тогда будет мета-язык, который исправлен. Скорее всего, у вас также есть какой-то низкоуровневый код или, по крайней мере, структура данных, с которой работает интерпретатор.

Вы могли бы сначала спроектировать и формализовать этот низкоуровневый код (каким бы он ни был) и написать какую-нибудь программу, которая может «запустить» это. Если у вас есть это, вы можете добавить стек интерпретаторов, и, пока все они производят этот код низкого уровня, эффективность не должна быть проблемой.

0 голосов
/ 24 марта 2012

Вы действительно можете, и это подход, который использует писк (и я верю многим другим мелочам). Вот один из подходов к этому: https://github.com/yoshikiohshima/SqueakBootstrapper/blob/master/README

...