Come potrebbe essere scritto il primo compilatore C ++ in C ++?


48

Stroustrup afferma che Cfront, il primo compilatore C ++, è stato scritto in C ++ ( Stroustrup FAQ ).

Tuttavia, come è possibile che il primo compilatore C ++ sia scritto in C ++?

Anche il codice che compone il compilatore deve essere compilato, e quindi il primo compilatore C ++ non avrebbe potuto essere scritto in C ++, vero?


6
en.wikipedia.org/wiki/Cfront tratta leggermente il problema.
christofr,

Risposte:


57

La chiave è proprio qui:

Il primo compilatore C ++ (Cfront) è stato scritto in C ++. Per costruirlo, per prima cosa ho usato C per scrivere un preprocessore da "C con classi" a C. "C with Classes" era un dialetto C che divenne l'antenato immediato del C ++. Quel preprocessore tradusse i costrutti "C con classi" (come classi e costruttori) in C. Era un preprocessore tradizionale che non capiva tutto il linguaggio, lasciava la maggior parte del controllo del tipo da compilare per il compilatore C e traduceva il singolo costruisce senza conoscenza completa. Ho quindi scritto la prima versione di Cfront in "C with Classes".

Quindi la prima versione di Cfront non è stata scritta in C ++, piuttosto nel linguaggio intermedio. La possibilità di creare compilatori e preprocessori C direttamente in C ha portato a molte delle innovazioni (e enormi buchi di sicurezza ) in C. Quindi scrivi il tuo nuovo preprosessor che trasforma il tuo codice "C con classi" in C dritto (perché C dritto può fare qualsiasi cosa) e poi usi "C with Classes" per scrivere un compilatore C ++ (non che non potresti farlo in C, ci vorrebbe un po 'di tempo) e poi usi quel compilatore C ++ per scrivere un compilatore più efficiente / completo in C ++. Fatto?


5
+1 per aver incluso un link a uno dei miei racconti preferiti di cose che possono essere fatte (e non dovrebbero).
jwernerny,

3
Il compilatore è stato scritto in un codice C ++ valido, ma ha utilizzato solo alcune delle funzionalità C ++ complete, quelle che erano supportate dal preprocessore "C con classi". Ha usato un sottoinsieme dell'intero linguaggio, quindi ha anche compilato il risultato (la prima versione funzionante di Cfront). Dopo aver eseguito questo passaggio "bootstrap", probabilmente non ha mai avuto bisogno di utilizzare nuovamente il preprocessore.
joeytwiddle,

2
@jwernerny - Ho sempre trovato quell'articolo insoddisfacente. Esamina la parte più difficile e non banale: "Il bug corrispondeva al codice nel comando 'login' di UNIX. Il codice di sostituzione avrebbe compilato erroneamente il comando di login in modo che potesse accettare la password crittografata o una password nota specifica. " Ma come si farebbe? È mai stato effettivamente dimostrato?
detenere il

3
"ha portato a molte delle innovazioni (e enormi buchi di sicurezza) in C": Per quanto ne so questi trucchi possono essere utilizzati in qualsiasi lingua, non solo in C. Quindi qualsiasi altra lingua può avere le stesse falle di sicurezza.
Giorgio,

2
@detly: adesso sembra banale, ma nel 1983 si è trattato di un nuovo attacco reso possibile dalla mancanza di diversità di implementazione. Allora ci fidavamo di più dei binari, in parte perché compilare tutto dalla fonte era una prova molto più grande di quanto lo sia ora.
Blrfl,

17

È stato avviato. Non appena una funzionalità C ++ è stata aggiunta a cfront, allora cfront potrebbe anche utilizzare quella funzione da quel punto in poi (ma non per implementare quella funzione). Questo ha funzionato perché cfront ha avuto la possibilità di convertire il codice C ++ in codice C. Quindi, se uscisse una nuova piattaforma, potresti usare cfront su un'altra piattaforma per convertire cfront da C ++ a C, quindi utilizzare il compilatore C della nuova piattaforma per completare la compilazione da C a codice oggetto.


9

Penso che BS risponda a questa domanda:

Il primo compilatore C ++ (Cfront) è stato scritto in C ++. Per costruirlo, per prima cosa ho usato C per scrivere un preprocessore da "C con classi" a C. "C with Classes" era un dialetto C che divenne l'antenato immediato del C ++. Quel preprocessore tradusse i costrutti "C con classi" (come classi e costruttori) in C. Era un preprocessore tradizionale che non capiva tutto il linguaggio, lasciava la maggior parte del controllo del tipo da compilare per il compilatore C e traduceva il singolo costruisce senza conoscenza completa.

Ho quindi scritto la prima versione di Cfront in "C with Classes". Cfront era un compilatore tradizionale che eseguiva la sintassi completa e il controllo semantico del sorgente C ++. Per questo, aveva un parser completo, costruiva tabelle di simboli e costruiva una rappresentazione ad albero interna completa di ogni classe, funzione, ecc. Inoltre, faceva un'ottimizzazione a livello di sorgente sulla sua rappresentazione ad albero interna dei costrutti C ++ prima di produrre C. La versione che generato C, non si basava su C per alcun controllo del tipo. Ha semplicemente usato C come assemblatore. Il codice risultante è stato incredibilmente veloce.

In primo luogo ha creato qualcosa che ha chiamato "C con classi" implementato da un semplice preprocessore in C. Era sostanzialmente C ++, ma il preprocessore ha fatto poco o nessun controllo. Ha quindi usato quello per scrivere Cfront, la versione più potente del traduttore di C ++ in C, completa di controllo del tipo, tabelle dei simboli, ecc.


1
quindi fondamentalmente quando compiliamo un programma C ++, viene convertito in C, quindi dopo che viene convertito in C, viene nuovamente compilato in codice macchina?
Pacerier,

@Pacerier: in origine sì, ma non ora penso.
Mike Dunlavey,

non capisco bene il tuo commento. vuoi dire che ora ci sono compilatori che saltano il secondo passaggio e prendono semplicemente il sorgente C ++ e compila il codice macchina?
Pacerier,

7
@Pacerier: Beh, non vanno direttamente al linguaggio assembly o al codice macchina. Di solito vanno prima a una rappresentazione intermedia indipendente dalla macchina (triple o quadruple) e la analizzano per l'ottimizzazione. Da ciò generano assembly o codice macchina. Se prendi un libro sul design del compilatore (Aho & Ullman) sono sicuro che lo troverai interessante.
Mike Dunlavey,

1
È importante notare che il C ++ che stava costruendo era anche una frazione del linguaggio che esiste ora. Non aveva modelli, né nuove librerie, utilizzava solo il casting C e, se ricordo bene, non aveva eccezioni.
Gort the Robot,

2

Aggiungerò questa risposta poiché nessuna risposta ha coperto questo aspetto.

Tecnicamente non hai bisogno di software per compilare il codice. Finché si dispone delle specifiche del compilatore necessarie, è possibile eseguire manualmente la compilazione effettiva. Non è così che è stato compilato il primo compilatore C ++. Sto solo dicendo che è possibile.

Confronta con il linguaggio assembly. All'inizio, non esistevano software di assemblaggio per convertire il codice di assemblaggio in codice macchina. È stato fatto a mano, ma il linguaggio assembly ha dato ai programmatori una migliore visione d'insieme.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.