Чому C ++ писати компілятор?


14

Мені було цікаво, чому C ++ - хороший вибір для написання компілятора. Звичайно, для цієї мети добре також і C, оскільки багато компіляторів написано або на C, або на C ++, але мене цього часу більше цікавить C ++. Будь-які вагомі причини? Я шукав це в Інтернеті, але не можу знайти жодних вагомих причин.


3
"Багато компіляторів написано [...] на C ++" - будь-які посилання? Котрий? Що ви думаєте, що C ++ частіше використовується для побудови компілятора, ніж інші популярні мови?
Док Браун

6
@DocBrown Ну, Clang і MSVC написані здебільшого на C ++, у gcc зараз є трохи C ++, Java JVM написано на C ++ stackoverflow.com/questions/410320/what-is-java-written-in, а також суперпопулярний. кому / питання / 136136 / ...
Klaim

@DocBrown DMD посилальний компілятор для D написаний на C ++
ratchet freak

3
Хто каже, що це вдалий вибір ??
Філ

1
@Phil Ви думаєте, що вони зробили цей вибір, не враховуючи альтернатив? Це не "хороший" вибір, це "ефективний" вибір.
Клаїм

Відповіді:


24

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


11
Наскільки я знаю, багато логіки всередині компілятора має функціональний характер (перетворює складні структури даних в інші структури даних), тому я не впевнений, чи об’єктно-орієнтовані засоби (які більш орієнтовані на програмування у великому розмірі , архітектурні аспекти) приносять реальну перевагу конструкції компілятора wrt в стиль процедурного програмування. Всього мої 2 копійки.
Джорджіо

5
@Giorgio Наявність об'єктів допомагає в багатьох інших аспектах написання компілятора. Наприклад, є багато стану, з яким компілятор повинен мати справу при оптимізації, і такий тип матеріалів добре піддається OOP. Крім того, програмування OOP та функціоналу може бути досить безкоштовним, тому те, що алгоритми можуть бути в основному функціональними, не означає, що об’єкти не допоможуть.
Олексі

3
@ Джорджіо та Олексі: Я можу підтвердити вас обох. Я написав компілятор з Haskell для справжньої світової мови. Це було дійсно гарне пристосування. Але іноді я пропускав якусь ОО навколо. Якби мені довелося написати іншого компілятора, я б точно вибрав Haskell, але це справді особливий випадок. Я б не вибрав Haskell без вагань для інших типів проектів.
хустка

27
Чому для створення коду потрібно мати мову зі стороною "низького рівня"? Я не бачу, як ці двоє пов'язані будь-яким чином.
phant0m

5
Вам не потрібна "сторона низького рівня" для створення коду більше, ніж потрібні ідентифікатори Unicode, щоб можна було писати японський текст у файл.
дан04,

17

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

  • Java-компілятор Sun написаний на Java
  • Компілятор Scala написаний на Scala
  • Моно компілятор C # написано на C #
  • Компілятор Squick Smalltalk написаний на Smalltalk
  • ... і багато іншого

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


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

1
@Krelp Я погоджуюся, що справа не в об'єктивній технічній причині, але вона насправді не "подобається" - це просто вважається деяким обрядом проходження мови - "чи достатньо зрілим, щоб можна було слугувати мовою власної реалізації. компілятор ".
Дуб

1
Java-компілятор Sun пишеться на C ++: stackoverflow.com/questions/410320/what-is-java-written-in
Klaim

12
@Зверніть, що ви плутаєте два продукти тут. Один з них - компілятор Java Java ( javacкомандний рядок), який компілює Java в Java-байт-код. Він написаний на Java - я його багато разів змінював, і ви можете переглядати його джерела Java в Інтернеті . Інший - це щойно введений компілятор, вбудований у JVM Hotspot, який компілює Java Bytecode до рідного машинного коду. Як і більшість JVM, він написаний на C ++, але це не компілятор Java - насправді він нічого не знає про мову Java.
Дуб

@Oak, абсолютно правильно! Іншими словами, JVM! = Javac
Пол Дрейпер

6

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

  • CoffeeScript компілюється в JavaScript, компілятор записується в CoffeeScript.
  • Сценарій # компілює C # в JavaScript, компілятор записується, якщо я добре пам’ятаю, C #.
  • тощо.

Мова, яку ви вибрали для написання компілятора, залежить від контексту. Наприклад, працюючи над проектом, який компілює мову, похідну від PHP, до рідного PHP-коду, я використав суміш PHP та C #, щоб написати компілятор, тому що це мало сенсу для мене з огляду на мої навички. Інша людина обрала б Python, або Java та PHP, або C ++ з трохи JavaScript, або що б там не було.

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

Зауважте, що для того, щоб бути більш вигадливим , ви можете вибрати мову джерела для написання компілятора. Це сталося з компілятором CoffeeScript та багатьма іншими компіляторами. Він також популярний серед IDE: одна з перших Visual Studio була побудована за допомогою тієї ж Visual Studio.


5
Самостійний хостинг не є вигадливим, це важлива властивість для перенесення компілятора.

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

6

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

Трохи залежить від мови, яку ви збираєте. Для маленьких, простих мов C і Pascal працюють досить непогано. Якщо ви збираєтеся скласти щось велике і складне, ваш компілятор також стає великим і складним - у цьому випадку додаткові функції організації C ++ для організації та роботи з більшими програмами очевидно знадобляться. Однак це не дуже специфічно для компіляції, а лише функції, корисні для великих програм загалом.

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


2
AST = Абстрактне синтаксичне дерево, RE = Регулярні вирази
хаотичний3рівноваги

5

Компілятори можуть бути реалізовані на будь-якій сучасній мові. Однак одна з найважливіших вимог компілятора - бути швидким.

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


11
Ще одна важлива вимога - правильність створеного коду - я скоріше маю повільний компілятор, якому я можу довіряти, ніж швидкий, який генерує неправильний код.

2
Хоча, безумовно, можна дуже сильно оптимізувати C ++, там досить багато… ну… менше, ніж оптимальний код C ++.
стипендіати

2
@DonalFellows Поверніть це навпаки: можна писати менше оптимального коду будь-якою мовою, але є оптимізації, які неможливо включити іншими мовами, ніж C ++ (крім Assembler. Я не включаю C через відсутність структури високого рівня, що дозволяють більш сильно розшивати).
Клаїм

@ user1249 - Немає причини, що швидкість коду С ++ зробить його будь-яким рудим баггі. Я вважаю за краще швидкий, правильний компілятор, ніж повільний, правильний компілятор.
gnasher729

3

Я підозрюю, що основним мотиватором їх використання є те, що вихід Lex / Yacc / Bison знаходиться (в першу чергу) в C. Оскільки це було стандартним для давніх часів, воно набирає обертів.

Не те, що це особливо вагомі причини ...


Насправді це мене не влаштовує, але дякую за спробу.
Кобра

Це не відповідає на питання "чому вибрати C ++ над C для побудови компілятора".
Док Браун

3
Це зовсім не вагома причина. Аналогічні інструменти для Lex та Yacc існують для багатьох платформ. Наприклад, PLY та ANTLR.
user16764

Більш того, більшість популярних компіляторів у реальному світі (я досить впевнений, наприклад, Кланг та GCC) використовують рукописні парсери.

@delnan: Так, але вони, ймовірно, почали використовувати створений, щоб вивести речі з землі. Ручне генерація аналізатора - це крок оптимізації, якого ви насправді не хочете робити, поки не зможете довести, що інші речі працюють.
Мартін Йорк

1

У мене є досвід цієї справи. Я написав компілятори на C і C ++. Основна відмінність C і C ++ полягає в тому, що C не має динамічного управління пам'яттю в автоматичному режимі. Весь керування пам'яттю на C повинен виконуватись явно. Написання компілятора багато стосується обробки рядків та управління масивом. У C ви змушені думати про розмір кожної рядка та кожного заявленого масиву, а також перевіряйте індекси під час доступу до цих об'єктів (якщо ви хочете, щоб ваш код був безпечним та стабільним). У C ви, звичайно, можете мати динамічне управління пам'яттю, але нічого не є автоматичним. Вам потрібно чітко розподілити та звільнити пам'ять за допомогою malloc () та free (), зберегти розмір динамічних об'єктів у відокремлених змінних, щоб бути впевненим, що ви не отримуєте доступ до них поза межами.

У C ++ у вас можуть бути ті самі механізми, але це дійсно ефективний час розробки, тому що все ваше управління пам’яттю може бути інкапсульовано в межах конструкторів і деструкторів, до яких не потрібно чітко викликати. Тож компілятор виділяє і звільняє ресурси для вас. Розмір ваших динамічних об'єктів також може бути капсульований, якщо ви створюєте свої власні класи, а індекси можна перевірити на граничний доступ шляхом перевантаження оператора []. Ці абстракції допомагають зробити ваш код більш чистим, легшим для розуміння та налагодження та, безумовно, робить швидшим розвиток.

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


0

Проект CompCert - це дослідницький компілятор C, який пишеться не на C або C ++, а більше на Ocaml та Coq.

Зверніть увагу, що C ++ використовувався для перекладу на C (у Cfront ). Тепер ви можете використовувати передній частині GCC до Gimple , потім скинути Gimple в якусь базу даних, а потім написати Gimple своєму перекладачу асемблера. Але юридичні причини ( виняток із бібліотеки виконання GCC ) вимагає, щоб такий компілятор був відкритим кодом. Поцікавтесь у свого адвоката деталями, я не юрист. Старі варіанти GCC написані на мові C (+ декілька мов, що належать до домену), а для деяких варіантів C ++ - це передній край. OpenWatcom може бути компілятором C ++, написаним на C (я залишаю вам це перевірити).

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

Дивіться також це та те, що відповідає на два пов’язані питання.

Якщо мені в 2020 році було доручено написати компілятор C (або C ++) з нуля (працює на Linux, можливо, якийсь крос-компілятор ), я, мабуть, не напишу його на C ++. Я б подумав написати це за допомогою Ocaml , Go або Rust . І я міг би базувати його на Frama-C, якщо це дозволять. Якщо потрібно ввести код у C або C ++, я спершу кодую бібліотеку сміттєзбірника для цього, ймовірно, якийсь рівень стійкості - дуже корисний для оптимізації цілої програми - і тоді я б розглядав підхід метапрограмування (генеруючи більшу частину коду С або С ++ компілятор з моїми спеціальними інструментами, можливо, Bismon або RefPerSys якщо це дозволено).

Ви можете знайти деякі (більш-менш відкриті джерела) компіляторів C, кодовані в Common Lisp або Python (наприклад, ShivyC або nqcc ). Загляньте також у ZetaC .

Зауважте, що останні версії GCC технічно не кодуються в чистому C ++, це десяток мов, специфічних для домену, які беруть участь у GCC (декілька з них є Turing-завершеними ). Дивіться також мій старий проект GCC MELT .

Я не здивуюся, якщо в майбутніх версіях GCC в них буде вбудований якийсь інтерпретатор Python або Guile (наприклад, як заміна менеджеру пропусків GCC).

Погляньте також на проект MILEPOST GCC .

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