Как написать компилятор C на C?

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

В предисловии к первому изданию K & R можно найти следующее утверждение (стр. Xi):

Операционная система, компилятор C и, по сути, все прикладные программы UNIX (включая все программное обеспечение, используемое для подготовки этой книги) написаны на C.

(мой акцент)

Вот что я не понимаю: разве компилятор C не должен компилироваться, прежде чем он сможет скомпилировать любой C-код? И если этот компилятор C написан на C, не компилирует ли он уже существующий компилятор C?

Единственный выход из этой бесконечно регрессионной головоломки (или проблемы с курицей и яйцом) заключается в том, что компилятор C, написанный на C, который относится к K & R, был фактически скомпилирован с уже существующим компилятором C, написанным на языке, отличном от C Компилятор C, написанный на C, затем заменил последний.

Или я полностью отключен?

Ответ 1

Он назвал Bootstrapping, цитируя из Википедии:

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

  1. Внедрение интерпретатора или компилятора для языка X на языке Y. Никлаус Вирт сообщил, что написал первый компилятор Pascal в Fortran.
  2. Другой интерпретатор или компилятор для X уже написан на другом языке Y; это то, как Scheme часто загружается.
  3. Более ранние версии компилятора были написаны в подмножестве X, для которого существовал какой-то другой компилятор; это как некоторые надмножества Java, Haskell и исходного компилятора Free Pascal загружаются.
  4. Компилятор для X перекрестно скомпилирован из другой архитектуры, где существует компилятор для X; так как компиляторы для C обычно переносятся на другие платформы. Также это метод, используемый для Free Pascal после начальной загрузки.
  5. Написание компилятора в X; затем вручную скомпилировать его из источника (скорее всего, не оптимизированным образом) и запустить его в коде для получения оптимизированного компилятора. Дональд Кнут использовал это для своей системы программирования грамотного WEB.

И если вам интересно, вот первый источник компилятора C Dennis Richie.

Ответ 2

См. Раздел "Курица и яйцо" на странице Википедии:

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

  • Внедрение интерпретатора или компилятора для языка X на языке Y. Никлаус Вирт сообщил, что написал первый компилятор Pascal в Fortran.
  • Другой интерпретатор или компилятор для X уже написан на другом языке Y; это то, как Scheme часто загружается.
  • Более ранние версии компилятора были написаны в подмножестве X, для которого существовал какой-то другой компилятор; это как некоторые надмножества Java, Haskell и исходного компилятора Free Pascal загружаются.
  • Компилятор для X перекрестно скомпилирован из другой архитектуры, где существует компилятор для X; так как компиляторы для C обычно переносятся на другие платформы. Также это метод, используемый для Free Pascal после начальной загрузки.
  • Написание компилятора в X; затем вручную скомпилировать его из источника (скорее всего, не оптимизированным образом) и запустить его в коде для получения оптимизированного компилятора. Дональд Кнут использовал это для своей системы программирования грамотного WEB.

Ответ 3

Обычно первый компилятор написан на другом языке (непосредственно в ассемблере PDP11 в этом случае или в C для большинства "современных" языков). Затем этот первый компилятор используется для программирования компилятора, написанного на самом языке.

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

Ответ 4

Это совершенно обычное дело для компилятора, написанного на языке, который он компилирует. Одним из способов достижения этого было бы написать полный компилятор для языка L на каком-то другом языке, а затем написать новый компилятор для L в L. Более интересным подходом было бы написать минимальный компилятор для подмножества L в некотором на другом языке, а затем используйте это минимальное подмножество для улучшения компилятора, делая его менее минимальным, увеличивая доступное подмножество L. Таким образом, можно построить полный компилятор.