Como o primeiro compilador C ++ pode ser escrito em C ++?

48

Stroustrup afirma que o Cfront, o primeiro compilador C ++, foi escrito em C ++ ( Stroustrup FAQ ).

No entanto, como é possível que o primeiro compilador C ++ seja escrito em C ++?

O código que compõe o compilador também precisa ser compilado e, portanto, o primeiro compilador C ++ não poderia ter sido escrito em C ++, poderia?

Pacerier
fonte

Respostas:

57

A chave está aqui:

O primeiro compilador C ++ (Cfront) foi escrito em C ++. Para criar isso, usei C para escrever um pré-processador "C com classes" em C. "C com classes" era um dialeto em C que se tornou o ancestral imediato do C ++. Esse pré-processador traduziu as construções "C com Classes" (como classes e construtores) para C. Era um pré-processador tradicional que não entendia todo o idioma, deixou a maior parte do tipo de verificação para o compilador C fazer e traduziu individualmente constrói sem conhecimento completo. Eu então escrevi a primeira versão do Cfront em "C with Classes".

Portanto, a primeira versão do Cfront não foi escrita em C ++, e sim na linguagem intermediária. A capacidade de criar compiladores e pré-processadores C diretamente em C levou a muitas das inovações (e falhas de segurança maciças ) em C. Então, você escreve seu novo pré-professor que transforma seu código "C com Classes" em C direto (porque C direto pode fazer qualquer coisa) e então você usa "C com Classes" para escrever um compilador C ++ (não que você não possa fazê-lo em C, isso levaria algum tempo) e, em seguida, você usa esse compilador C ++ para escrever um compilador mais eficiente / completo em C ++. Entendi?

Christopher Bibbs
fonte
5
+1 por incluir um link para um dos meus contos favoritos de coisas que podem ser feitas (e não deveriam).
jwernerny
3
O compilador foi escrito em código C ++ válido, mas utilizou apenas alguns dos recursos completos do C ++, os quais eram suportados pelo pré-processador "C with Classes". Ele usava um subconjunto do idioma completo, portanto também compilou o resultado (a primeira versão de trabalho do Cfront). Depois de executar esta etapa de "inicialização", ele provavelmente nunca precisou usar o pré-processador novamente.
Joeytwiddle
2
@ jwernerny - eu sempre achei esse artigo insatisfatório. Ele examina a parte mais difícil e não trivial: "O bug corresponderia ao código no comando 'login' do UNIX. O código de substituição compilaria incorretamente o comando de login para que aceitasse a senha criptografada pretendida ou uma senha conhecida específica. " Mas como isso seria feito? Alguma vez foi realmente demonstrado?
detly
3
"levou a muitas das inovações (e falhas de segurança massivas) em C": Até onde eu sei, esses truques podem ser usados ​​em qualquer idioma, não apenas em C. Portanto, qualquer outro idioma pode ter as mesmas falhas de segurança.
Giorgio
2
@detly: Parece trivial agora, mas em 1983 foi um novo ataque tornado viável pela falta de diversidade na implementação. Naquela época, confiávamos mais nos binários, em parte porque compilar tudo da fonte era uma provação muito maior do que é agora.
Blrfl
17

Foi inicializado. Assim que um recurso C ++ foi adicionado ao cfront, o cfront também poderia usá-lo a partir desse ponto (mas não para implementar esse mesmo recurso). Isso funcionou porque o cfront tinha a capacidade de converter código C ++ em código C. Portanto, se alguma nova plataforma surgir, você poderá usar o cfront em outra plataforma para converter o cfront de C ++ em C e, em seguida, usar o compilador C da nova plataforma para concluir a compilação de C para código de objeto.

David Schwartz
fonte
9

Eu acho que BS responde a essa pergunta:

O primeiro compilador C ++ (Cfront) foi escrito em C ++. Para criar isso, usei C para escrever um pré-processador "C com classes" em C. "C com classes" era um dialeto em C que se tornou o ancestral imediato do C ++. Esse pré-processador traduziu as construções "C com Classes" (como classes e construtores) para C. Era um pré-processador tradicional que não entendia todo o idioma, deixou a maior parte do tipo de verificação para o compilador C fazer e traduziu individualmente constrói sem conhecimento completo.

Eu então escrevi a primeira versão do Cfront em "C with Classes". O Cfront era um compilador tradicional que completava a sintaxe e a verificação semântica da fonte C ++. Para isso, ele tinha um analisador completo, construiu tabelas de símbolos e uma representação interna completa da árvore de cada classe, função, etc. Também fez alguma otimização no nível da fonte em sua representação interna da árvore das construções C ++ antes da saída C. C gerado, não confiou em C para nenhuma verificação de tipo. Simplesmente usava C como montador. O código resultante foi incrivelmente rápido.

Primeiro, ele criou algo que chamou de "C com Classes" implementado por um simples pré-processador em C. Era basicamente C ++, mas o pré-processador fez pouca ou nenhuma verificação. Ele então usou isso para escrever o Cfront, a versão mais poderosa do tradutor de C ++ em C, completa com verificação de tipo, tabelas de símbolos etc.

Mike Dunlavey
fonte
11
Então, basicamente, quando compilamos um programa C ++, ele é convertido em C; depois, depois de convertido em C, ele é compilado novamente em código de máquina?
Pacerier 02/09/11
@ Pacerier: Originalmente, sim, mas agora não acho.
Mike Dunlavey
Eu não entendo bem o seu comentário. você quer dizer agora que existem compiladores que pulam a segunda etapa e simplesmente pegam a fonte C ++ e compilam com o código da máquina?
Pacerier
7
@ Pacerier: Bem, eles não vão diretamente para a linguagem assembly ou para o código da máquina. Geralmente, eles primeiro vão para uma representação intermediária independente da máquina (triplos ou quádruplos) e analisam isso para otimização. A partir disso, eles geram código de montagem ou de máquina. Se você escolher um livro sobre design de compilador (Aho & Ullman) , tenho certeza de que o achará interessante.
precisa saber é o seguinte
11
É importante notar que o C ++ que ele estava construindo também era uma fração da linguagem que existe agora. Não possuía modelos, nenhuma nova biblioteca, usava apenas a conversão C e, se bem me lembro, não tinha exceções.
Gort the Robot
2

Acrescentarei esta resposta, já que nenhuma resposta abordou esse aspecto.

Tecnicamente, você não precisa de software para compilar código. Contanto que você tenha as especificações necessárias do compilador, poderá fazer a compilação real manualmente. Não é assim que o primeiro compilador C ++ foi compilado. Só estou dizendo que é possível.

Compare com a linguagem assembly. Quando eles foram usados ​​nos primeiros dias, não havia software de montagem para converter o código de montagem em código de máquina. Foi feito à mão, mas a linguagem assembly deu aos programadores uma melhor visão geral.

Klutt
fonte