Як міг записати перший компілятор C ++ в C ++?


48

Stroustrup стверджує, що Cfront, перший компілятор C ++, був написаний на C ++ ( Stroustrup FAQ ).

Однак як можливо навіть перший компілятор C ++ записати на C ++?

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


6
en.wikipedia.org/wiki/Cfront висвітлює проблему трохи.
christofr

Відповіді:


57

Ключ тут:

Перший компілятор C ++ (Cfront) був написаний на C ++. Щоб побудувати це, я вперше застосував C, щоб записати "C з класами" -процесором C. "C з класами" - це діалект С, який став безпосереднім предком С ++. Цей препроцесор переклав на C. конструкти "C з класами" (наприклад, класи та конструктори). Це був традиційний препроцесор, який не розумів усі мови, залишив більшість перевірок типу для компілятора C і переклав окремі конструкції без повних знань. Тоді я написав першу версію Cfront у "C з класами".

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


5
+1 за включення посилання на одну з моїх улюблених казок про речі, які можна зробити (а не слід).
jwernerny

3
Компілятор був написаний дійсним кодом C ++, але використовував лише декілька повноцінних функцій C ++, тих, які підтримували препроцесор "C з класами". Він використовував підмножину повної мови, тому також компілював за результатом (перша робоча версія Cfront). Виконавши цей крок "завантаження", йому, ймовірно, ніколи більше не потрібно було використовувати препроцесор.
joeytwiddle

2
@jwernerny - цю статтю я завжди вважав незадовільною. Він переглядає найскладнішу і нетривіальну частину: "Помилка відповідатиме коду в команді" вхід "UNIX. Код заміни неправильно складе команду входу, щоб вона прийняла або призначений зашифрований пароль, або певний відомий пароль. " Але як це зробити? Чи було це колись насправді продемонстровано?
detly

3
"призвело до багатьох нововведень (і масивних дірок у безпеці) в C": Наскільки я знаю, ці хитрощі можна використовувати на будь-якій мові, а не лише на C. Отже, будь-яка інша мова може мати ті самі отвори в безпеці.
Джорджіо

2
@detly: Це зараз звучить тривіально, але в 1983 році це була нова атака, яка стала життєздатною через відсутність різноманітності в реалізації. Тоді ми довіряли бінарним файлам, частково тому, що компіляція всього з джерела була набагато більшим випробуванням, ніж зараз.
Blrfl

17

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


9

Я думаю, що BS відповідає на це питання:

Перший компілятор C ++ (Cfront) був написаний на C ++. Щоб побудувати це, я вперше застосував C, щоб записати "C з класами" -процесором C. "C з класами" - це діалект С, який став безпосереднім предком С ++. Цей препроцесор переклав на C. конструкти "C з класами" (наприклад, класи та конструктори). Це був традиційний препроцесор, який не розумів усі мови, залишив більшість перевірок типу для компілятора C і переклав окремі конструкції без повних знань.

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

Спочатку він створив щось, що він назвав "C з класами", реалізований простим препроцесором у C. Це був C ++, але препроцесор мало перевіряв або не перевіряв. Потім він використав це для написання Cfront, більш потужної версії перекладача C ++ на C, у комплекті з перевіркою типів, таблицями символів тощо.


1
так що в основному, коли ми компілюємо програму C ++, вона перетворюється на C, а після її перетворення в C вона знову компілюється в машинний код?
Pacerier

@Pacerier: Спочатку так, але зараз не думаю.
Майк Данлаве

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

7
@Pacerier: Ну, вони не переходять безпосередньо до мови складання чи машинного коду. Зазвичай вони спочатку переходять до машинного незалежного проміжного представлення (трійки або квадроцикли) і аналізують це для оптимізації. З цього вони генерують збірку або код машини. Якщо ви підберете книгу про дизайн компілятора (Aho & Ullman), я впевнений, що вам це буде цікаво.
Майк Данлаве

1
Важливо зазначити, що C ++, який він будував, також був частиною мови, яка існує зараз. У ньому не було шаблонів, нових бібліотек, використовувався лише C-кастинг, і якщо я пригадую правильно, не було винятків.
Gort the Robot

2

Я додам цю відповідь, оскільки жодна відповідь не охоплювала цей аспект.

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

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

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