Для завантаження все ще потрібна зовнішня підтримка


96

Я чув про ідею завантаження мови, тобто написання компілятора / інтерпретатора для самої мови. Мені було цікаво, як це можна зробити, і трохи озирнувся навколо, і побачив, як хтось каже, що це може зробити лише хтось із них

  • написання початкового компілятора іншою мовою.
  • ручне кодування початкового компілятора в Assembly, що здається приватним випадком першого

Мені здається, що жодне з них насправді не завантажує мову в тому сенсі, що їм обом потрібна зовнішня підтримка. Чи є спосіб насправді написати компілятор власною мовою?


Я не дуже досвідчений у таких речах, але я вважаю, що початковий компілятор повинен бути написаний іншою мовою. Я абсолютно впевнений , що «самонастроювання», з посиланням на укладачів, просто відноситься до написання на компілятор для мови на мові це означало для компіляції, а не писали перший компілятор для мови в мові це означало для компіляції.
jdd

1
Дякую за інформацію всім. Якщо пояснити ідею спочатку написати обмежений компілятор, а потім створити поверх цього, тоді ідея завантаження буде більш зрозумілою. У цьому семестрі я беру на уроки компіляторів, на вирішення яких багато в чому вплинув пост Стіва Єгге про те, наскільки важливим є клас у компіляторах , і я щойно придбав копію книги Dragon за посиланням Amazon, яка раніше була настільки модернізована для SO.
pbh101

1
Дивіться також подібне запитання: Впровадження компілятора само по собі
Urban Vagabond

Відповіді:


107

Чи є спосіб насправді написати компілятор власною мовою?

Ви повинні мати якусь існуючу мову, щоб писати новий компілятор. Якщо ви писали новий, скажімо, компілятор C ++, ви просто написали б його на C ++ і спочатку скомпілювали з існуючим компілятором. З іншого боку, якщо ви створювали компілятор для нової мови, назвемо його Yazzleof, вам спочатку потрібно було б написати новий компілятор іншою мовою. Як правило, це була б інша мова програмування, але це не обов’язково. Це може бути монтажний або, якщо потрібно, машинний код.

Якщо ви були збираєтеся самонастроювання компілятора для Yazzleof, ви взагалі не написати компілятор для повного мови на початковому етапі. Замість цього ви повинні написати компілятор для Yazzle-lite, найменшого можливого підмножини Yazzleof (ну, принаймні , досить маленького підмножини). Тоді в Yazzle-lite ви б написали компілятор для повної мови. (Очевидно, це може відбуватися ітеративно, а не одним стрибком.) Оскільки Yazzle-lite є належним підмножином Yazzleof, тепер у вас є компілятор, який може скомпілювати себе.

Існує дуже хороший запис про завантаження компілятора з найнижчого можливого рівня (який на сучасній машині в основному є шістнадцятковим редактором) під назвою Bootstrapping простий компілятор з нічого . Її можна знайти за адресою https://web.archive.org/web/20061108010907/http://www.rano.org/bcompiler.html .


19

Пояснення, яке ви прочитали, є правильним. Про це йдеться в Compilers: Principles, Techniques and Tools (The Dragon Book):

  • Написати компілятор C1 для мови X на мові Y
  • Використовуйте компілятор C1, щоб написати компілятор C2 для мови X мовою X
  • Зараз C2 - це повністю самостійне середовище хостингу.

7

Надзвичайно цікаве обговорення цього - у лекції співавтора Unix Кена Томпсона про нагороду Тьюрінга .

Він починає з:

Те, що я збираюся описати, є однією з багатьох проблем "курки та яєць", які виникають, коли компілятори написані рідною мовою. З цією простотою я буду використовувати конкретний приклад із компілятора C.

і продовжує показувати, як він написав версію компілятора Unix C, яка завжди дозволяла йому входити без пароля, оскільки компілятор C розпізнавав програму входу та додавав спеціальний код.

Другий шаблон спрямований на компілятор C. Замінний код - програма самовідтворення Stage I, яка вставляє обидва троянських коня в компілятор. Для цього потрібен етап навчання, як на прикладі етапу II. Спочатку ми компілюємо змінене джерело із звичайним компілятором C, щоб створити помилковий двійковий файл. Ми встановлюємо цей двійковий файл як офіційний C. Тепер ми можемо видаляти помилки з джерела компілятора, і новий двійковий файл буде повторно вставляти помилки щоразу, коли він буде скомпільований. Звичайно, команда входу залишатиметься помилкою без будь-яких слідів у джерелі.


9
Це не по темі .. Цікаво, але заплутано, а не відповідь на запитання.
blueshift

5

Я чув, як писати надзвичайно обмежений компілятор іншою мовою, а потім використовувати його для складання більш складної версії, написаної новою мовою. Потім цю другу версію можна використовувати для самокомпіляції та наступну версію. Щоразу, коли він компілюється, використовується остання версія.

Ось визначення завантаження:

процес простої системи, що активує більш складну систему, яка служить тій самій меті.

EDIT: Стаття Вікіпедії про завантаження компілятора висвітлює концепцію краще за мене.




3

Наскільки я розумію, перший інтерпретатор Lisp був завантажений шляхом ручного компілювання функцій конструктора та зчитувача маркерів. Решту перекладача тоді прочитали з джерела.

Ви можете перевірити себе, прочитавши оригінальну McCarthy папір, рекурсивні функції символічних виразів та їх обчислення з допомогою машини, частина I .


Що сталося з частинами 2 і 3? ... Як я не помітив, що @Wing розмістив те саме за 3 роки до мене? Я глупак. Принаймні я пов'язав цей документ (з допомогою).
luser droog

2

Інша альтернатива - створити машину байт-коду для вашої мови (або використовувати існуючу, якщо її особливості не дуже незвичні) і написати компілятор для байт-коду, або в байт-коді, або на потрібній мові, використовуючи інший проміжний - наприклад, набір інструментів синтаксичного аналізатора, який виводить AST як XML, а потім компілює XML в байт-код за допомогою XSLT (або іншої мови, що відповідає мові та представлення на основі дерева). Це не знімає залежності від іншої мови, але може означати, що більша частина роботи із завантаження потрапляє в остаточну систему.


2

Це версія інформаційного парадоксу про курку та яйце. Я не можу придумати способу не написати початковий компілятор на асемблері чи будь-якій іншій мові. Якби це могло бути зроблено, я міг би це зробити Лісп.

Насправді, я думаю, Лісп майже відповідає вимогам. Перевірте його запис у Вікіпедії . Згідно зі статтею, функція Lisp eval може бути реалізована на IBM 704 в машинному коді, а повний компілятор (написаний на самому Lisp) з’явився в 1962 році на MIT .


2

Кожен приклад завантаження мови, яку я можу згадати ( C , PyPy ), був зроблений після того, як з’явився робочий компілятор. Ви повинні десь починати, і для перетворення мови само по собі потрібно спочатку написати компілятор іншою мовою.

Як інакше це могло б працювати? Я не думаю, що навіть концептуально можливо вчинити інакше.


4
Принаймні перший компілятор Lisp був завантажений із використанням існуючого інтерпретатора Lisp . Тож не інша мова семантично, а інша реалізація мови.
Кен

0

Деякі завантажувані компілятори або системи зберігають як вихідну форму, так і об'єктну форму у своєму сховищі:

  • ocaml - це мова, яка має як інтерпретатор байт-коду (тобто компілятор для байт-коду Ocaml), так і власний компілятор (для x86-64 або ARM тощо ... асемблер). Його сховище svn містить як вихідний код (файли */*.{ml,mli}), так і boot/ocamlcформу байт-коду (файл ) компілятора. Отже, коли ви будуєте, він спочатку використовує його байт-код (попередньої версії компілятора) для компіляції. Пізніше щойно скомпільований байт-код зможе скомпілювати власний компілятор. Тож репозиторій Ocaml svn містить як *.ml[i]вихідні файли, так і boot/ocamlcфайл байт-коду.

  • У іржу завантаження компілятора ( з використанням wget, так що вам потрібно підключення до Інтернету робочий) попередню версію двійкового файлу компілюватиметься.

  • MELT - це мова, схожа на Lisp, для налаштування та розширення GCC . Він перекладається на код C ++ за допомогою завантажувального перекладача. Створений код перекладача C ++ поширюється, тому репозиторій svn містить як *.meltвихідні файли, так і melt/generated/*.cc"об'єктні" файли перекладача.

  • Система штучного інтелекту CAIA J.Pitrat повністю генерується самостійно. Він доступний як колекція тисяч [A-Z]*.cгенерованих файлів (також із сформованим dx.hзаголовком) із колекцією тисяч _[0-9]*файлів даних.

  • Декілька компіляторів схем також завантажуються. Схема48, Схема курки, ...

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.