Чи можливо створити «завантажений» перекладач, незалежний від оригінального перекладача?


21

Згідно з Вікіпедією, термін "завантажувальний" в контексті написання компіляторів означає :

В інформатиці завантажувальний процес - це процес написання компілятора (або асемблера) на мові програмування джерела, яку він має намір компілювати. Застосування цієї методики веде до самостійного розміщення компілятора.

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

Ви пишете свій перший варіант інтерпретатора в мові X , і інтерпретатор для нової мови , який ви створюєте, називається Y . Ви спочатку використовуєте компілятор мови X для створення виконуваного файлу. Тепер ви можете інтерпретувати файли , написані на новому мовою Y , використовуючи інтерпретатор , написаний на мові X .

Тепер, наскільки я розумію, щоб бути в змозі «початкового завантаження» інтерпретатора ви писали на мові X , вам потрібно переписати інтерпретатор в мові Y . Але от заковика: навіть якщо ви переписати весь інтерпретатор в мові Y , ви все ще будете мати потребу в оригінальний інтерпретатор ви писали на мові X . Оскільки для запуску інтерпретатора мовою Y , вам доведеться інтерпретувати вихідні файли. Але що саме буде інтерпретувати вихідні файли? Ну, звичайно, це не може бути нічого, тому ви змушені все-таки використовувати перший перекладач.

Незалежно від того, скільки нових перекладачів ви пишете мовою Y , вам завжди доведеться використовувати перший перекладач, написаний на X, для тлумачення наступних перекладачів. Це, здається, є проблемою просто через природу перекладачів.

Однак , на зворотній стороні, ця стаття у Вікіпедії про перекладачів насправді говорить про перекладачів, що займаються власною організацією . Ось невеликий уривок, який є релевантним:

Самоперекладач - це перекладач мови програмування, написаний мовою програмування, який може інтерпретувати себе; приклад - перекладач BASIC, написаний на BASIC. Самоперекладачі пов’язані з самостійними організаторами хостингу.

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

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

Тепер згадана вище стаття посилається на іншу статтю, в якій Вікіпедія наводить кілька прикладів передбачуваних перекладачів, що розміщуються на власному хостингу . При більш детальному огляді, здається, що основна "інтерпретація" частини багатьох тих перекладачів, що займаються самоврядуванням (особливо деякі більш поширені, такі як PyPy або Rubinius), насправді написана іншими мовами, такими як C ++ або C.

То чи можливо те, що я описую вище? Чи може самостійний перекладач не залежати від свого початкового господаря? Якщо так, то як би це було зроблено?

Відповіді:


24

Коротка відповідь: ви маєте рацію в своїх підозрах, вам завжди потрібен або інший перекладач, написаний на X, або компілятор з Y на якусь іншу мову, для якої у вас уже є перекладач. Інтерпретатори виконують, компілятори перекладають лише з однієї мови на іншу, в якийсь момент у вашій системі повинен бути перекладач… навіть це лише CPU.

Незалежно від того, скільки нових перекладачів ви пишете мовою Y , вам завжди доведеться використовувати перший перекладач, написаний на X, для тлумачення наступних перекладачів. Це, здається, є проблемою просто через природу перекладачів.

Правильно. Що ви можете зробити, це написати компілятор від Y до X (або іншу мову , для якого у вас є перекладач), і ви навіть можете зробити це в Y . Тоді ви можете запустити ваш компілятор Y, написаний на Y, на Y- інтерпретаторі, написаному X (або на Y- інтерпретаторі, написаному на Y, на Y- інтерпретаторі, написаному на X , або на Y- інтерпретаторі, написаному на Y, на Y- інтерпретаторі, написаному на Y працює на Y інтерпретатора, написаний X , або… ad infinitum), щоб скласти свій Y- інтерпретатор, написаний від Y до X , щоб потім можна було виконати його на X- інтерпретаторі. Таким чином, ви позбулися свого інтерпретатора Y, написаного на X , але тепер вам потрібен перекладач X (ми знаємо, що у нас його вже є, хоча в іншому випадку ми не змогли запустити перекладача X, написаного Y ), і ви довелося спочатку написати Y- to- X- компілятор .

Однак , на зворотній стороні, стаття Вікіпедії про перекладачів насправді розповідає про перекладачів, що займаються власною організацією. Ось невеликий уривок, який є релевантним:

Самоперекладач - це перекладач мови програмування, написаний мовою програмування, який може інтерпретувати себе; приклад - перекладач BASIC, написаний на BASIC. Самоперекладачі пов’язані з самостійними організаторами хостингу.

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

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

Правильно. Зауважте, що у статті Вікіпедії прямо написано, що вам потрібна друга реалізація вашої мови, і вона не говорить про те, що ви можете позбутися першої.

Тепер згадана вище стаття посилається на іншу статтю, в якій Вікіпедія наводить кілька прикладів передбачуваних перекладачів, що розміщуються на власному хостингу. При більш детальному огляді, здається, що основна "інтерпретація" частини багатьох тих перекладачів, що займаються самоврядуванням (особливо деякі більш поширені, такі як PyPy або Rubinius), насправді написана іншими мовами, такими як C ++ або C.

Знову правильно. Це справді погані приклади. Візьмемо, наприклад, Рубіній. Так, це правда, що частина Rubyus у Rubinius розміщена самостійно, але це компілятор, а не інтерпретатор: він компілює у вихідний код Ruby до байт-коду Rubinius. Частина інтерпретатора OTOH не є власною організацією: вона інтерпретує байт-код Рубінія, але він написаний на C ++. Так, називаючи Rubinius «резидентних перекладач» є неправильним: резидентних частина не є перекладачем , а перекладач частина не резидентних .

PyPy схожий, але ще більш невірний: він навіть не написаний в Python в першу чергу, він написаний на RPython, що є іншою мовою. Він синтаксично схожий на Python, семантично "розширений підмножина", але він насправді є мовою статичного типу приблизно на тому ж рівні абстракції, що і Java, і його реалізація є компілятором з декількома зворотними пакетами, який компілює RPython у вихідний код C, ECMAScript вихідний код, байт-код CIL, байт-код JVM або вихідний код Python.

То чи можливо те, що я описую вище? Чи може самостійний перекладач-хост бути незалежним від свого початкового хоста? Якщо так, то як би це було зроблено?

Ні, не самостійно. Вам або потрібно буде зберегти оригінального перекладача або написати компілятор і скласти свій самоперекладач.

Там є деякі мета-кругової віртуальні машини, такі як Кляйн (написано в Самості ) і Максін (написаний на Java). Однак зауважте, що тут визначення "мета-кругової" все ж відрізняється: ці VM не написані мовою, яку вони виконують. Однак вихідний код Self / Java VM фактично компілюється в байт-код Self / JVM і потім виконується ВМ, тому до моменту його виконання він знаходиться на мові, яку він виконує. Phew.

Зауважте також, що це відрізняється від таких віртуальних машин, як SqueakVM та RVM Jikes . Jikes написаний на Java, а SqueakVM написаний на сленгу (статично набраний синтаксичний і семантичний підмножина Smalltalk приблизно на тому ж рівні абстракції, що і асемблер високого рівня), і обидва отримують статичний збір до нативного коду до їх запуску. Вони не бігають всередину себе. Однак ви можете запускати їх зверху (або поверх іншого Smalltalk VM / JVM). Але це не є "мета-круговим" у цьому сенсі.

Максін і Клейн, OTOH робитибігати всередину себе; вони виконують свій власний байт-код, використовуючи власну реалізацію. Це справді розум! Це дозволяє отримати декілька цікавих можливостей оптимізації, наприклад, оскільки VM виконує себе разом із користувацькою програмою, він може вбудовувати дзвінки з користувацької програми в VM і навпаки, наприклад, дзвінок до сміттєзбірника або розподільник пам'яті може бути вбудований у користувача код і відбивні зворотні дзвінки в коді користувача можуть бути вписані в VM. Крім того, усі розумні прийоми оптимізації, які роблять сучасні віртуальні машини, де вони переглядають програму, що виконує, та оптимізують її залежно від фактичного навантаження та даних, VM може застосувати ті самі хитрощі до себе під час виконання користувацької програми під час користувацької програми виконується конкретне навантаження. Іншими словами, VM вузькоспеціалізованих себе за щоконкретна програма, що працює на цьому робочому навантаженні.

Однак, зауважте, я обійшов вживання слова "перекладач" вище і завжди використовував "виконувати"? Ну, ці віртуальні віртуальні машини не побудовані навколо інтерпретаторів, вони побудовані навколо (JIT) компіляторів. Пізніше до Maxine був доданий перекладач, але вам завжди потрібен компілятор: вам потрібно запустити VM один раз над іншим VM (наприклад, Oracle HotSpot у випадку Maxine), щоб VM міг (JIT) компілювати себе. У випадку з Maxine він буде JIT компілювати власну фазу завантаження, потім серіалізувати цей скомпільований нативний код до зображення VM завантажувальної машини та наклеїти дуже простий завантажувач спереду (єдиний компонент VM, написаний на C, хоча це просто для зручності , це може бути і на Java). Тепер ви можете використовувати Maxine для виконання себе.


Так . Я ніколи не знав, що світ перекладачів, які влаштовують гості, був таким клейким! Дякуємо, що дали хороший огляд.
Крістіан Дін

1
Ха-ха, ну чому світ повинен бути меншим, ніж концепція? ;-)
Йорг W Міттаг

3
Я думаю, що одна з проблем полягає в тому, що люди часто грають швидко і вільно з іншими мовами. Наприклад, Рубінія зазвичай називають "Рубі в Рубі", але це лише половина історії. Так, строго кажучи , компілятор Ruby в Rubinius написаний на Ruby, але VM, який виконує байт-код, не є. І ще гірше: PyPy часто називають "Python in Python", за винятком того, що там насправді немає жодного рядка Python. Вся справа написана в RPython, який призначений для знайомства з програмістами Python, але це не Python . Так само SqueakVM: це не написано у Smalltalk, це…
Jörg W Mittag

… Написано в сленгу, що, на думку людей, які насправді закодували його, у своїх можливостях абстракції навіть гірше, ніж C. Єдина перевага, яку має Сленг, - це те, що це належний підмножина Smalltalk, а це означає, що ви можете розробити його (і запустити, а головне налагодити VM) потужний ID ID Smalltalk.
Йорг W Міттаг

2
Просто додати ще одне ускладнення: Деякі інтерпретовані мови (наприклад, FORTH та, можливо, TeX) здатні записати зображення, що завантажується в операційну систему, як виконуваний файл. У цьому сенсі такі системи можуть працювати без оригінального перекладача. Наприклад, я одного разу написав перекладач FORTH, використовуючи 16-бітну версію FORTH, щоб "перехресно" інтерпретувати 32-бітну версію для іншого процесора та працювати в іншій ОС. (Зауважте, мова FORTH включає власний асемблер, тому "FORTH VM" (який, як правило, складає лише 10 або 20 інструкцій машинного коду), можна записати в самому FORTH.)
alephzero

7

Ви правильно зазначаєте, що інтерпретатор, що хостинг, все ще вимагає, щоб інтерпретатор запускався сам, і його не можна завантажувати в тому ж сенсі, що і компілятор.

Тим НЕ менше, резидентних мову це не те ж саме , як самоприйняття перекладача. Зазвичай побудувати інтерпретатора простіше, ніж створити компілятор. Тому для впровадження нової мови ми можемо спершу застосувати перекладача на незв'язаній мові. Тоді ми можемо використовувати цей перекладач для розробки компілятора для нашої мови. Потім мова розміщується самостійно, оскільки компілятор інтерпретується. Потім компілятор може компілювати себе, а потім може вважатися повністю завантаженим.

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

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

Випадок, який насправді зустрічається досить часто, - це здатність мови впливати на власний синтаксичний аналіз, наприклад, як макроси, що оцінюються за час розбору. Оскільки мова макросів є такою ж, як і мова, що обробляється, вона, як правило, набагато більше функціональної, ніж виділена або обмежена мова макросів. Однак правильно зазначити, що мова, яка виконує розширення, є дещо іншою мовою, ніж мова після розширення.

Коли використовуються «справжні» власні перекладачі, це зазвичай робиться з міркувань освіти або дослідження. Наприклад, впровадження інтерпретатора для схеми всередині схеми - це класний спосіб викладання мов програмування (див. SICP).

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