Não pretendo escrever um compilador no futuro próximo; Ainda assim, estou bastante interessado nas tecnologias de compilador e em como essas coisas podem ser melhoradas.
Começando com linguagens compiladas, a maioria dos compiladores possui dois níveis de erro: avisos e erros, o primeiro sendo coisas não fatais que você deve corrigir e erros indicando na maioria das vezes que é impossível produzir máquina (ou byte) código da entrada.
Porém, esta é uma definição bastante fraca. Em algumas linguagens como Java, alguns avisos são simplesmente impossíveis de serem eliminados sem o uso da @SuppressWarning
diretiva. Além disso, o Java trata certos problemas não fatais como erros (por exemplo, código inacessível em Java aciona um erro por um motivo que eu gostaria de saber).
O C # não tem os mesmos problemas, mas possui alguns. Parece que a compilação ocorre em várias passagens, e uma falha na passagem impedirá a execução de outras passagens. Por esse motivo, a contagem de erros que você obtém quando sua compilação falha geralmente é subestimada. Em uma corrida, pode-se dizer que você tem dois erros, mas depois de corrigi-los, você poderá obter 26 novos.
Escavar em C e C ++ simplesmente mostra uma combinação ruim das deficiências de diagnóstico da compilação de Java e C # (embora possa ser mais preciso dizer que Java e C # apenas seguiram seu caminho com metade dos problemas cada). Alguns avisos realmente deveriam ser erros (por exemplo, quando nem todos os caminhos de código retornam um valor) e ainda são avisos porque, suponho, no momento em que eles escreveram o padrão, a tecnologia do compilador não era boa o suficiente para fazer esse tipo de coisa. verificações obrigatórias. Na mesma linha, os compiladores geralmente buscam mais do que o padrão diz, mas ainda usam o nível de erro de aviso "padrão" para obter descobertas adicionais. E, frequentemente, os compiladores não relatam todos os erros que podem encontrar imediatamente; pode levar algumas compilações para se livrar de todas elas. Sem mencionar os erros enigmáticos que os compiladores C ++ gostam de cuspir,
Agora, adicionando que muitos sistemas de compilação são configuráveis para relatar falhas quando os compiladores emitem avisos, obtemos uma mistura estranha: nem todos os erros são fatais, mas alguns avisos devem; nem todos os avisos são merecidos, mas alguns são explicitamente suprimidos sem menção adicional de sua existência; e algumas vezes todos os avisos se tornam erros.
Os idiomas não compilados ainda têm sua parcela de relatórios de erros ruins. Erros de digitação no Python não serão relatados até que o código seja realmente executado, e você nunca poderá realmente chutar mais de um erro de cada vez, porque o script interromperá a execução depois de encontrar um.
O PHP, por seu lado, possui vários níveis de erro mais ou menos significativos e exceções. Os erros de análise são relatados um de cada vez, os avisos geralmente são tão ruins que devem abortar seu script (mas não por padrão), os avisos geralmente mostram problemas sérios de lógica, alguns erros não são ruins o suficiente para interromper o script, mas ainda assim e, como de costume no PHP, existem algumas coisas realmente estranhas lá embaixo (por que diabos precisamos de um nível de erro para erros fatais que não são realmente fatais?, E_RECOVERABLE_E_ERROR
estou falando com você).
Parece-me que todas as implementações de relatórios de erro do compilador que consigo pensar estão quebradas. O que é uma pena, pois todos os bons programadores insistem em como é importante lidar corretamente com os erros e, no entanto, não conseguem ter suas próprias ferramentas para fazê-lo.
Qual você acha que deve ser o caminho certo para relatar erros do compilador?
Respostas:
Sua pergunta não parece ser sobre como relatamos erros do compilador - é sobre a classificação dos problemas e o que fazer com eles.
Se começarmos assumindo, por enquanto, que a dicotomia de aviso / erro está correta, vamos ver o quão bem podemos construir em cima disso. Algumas ideias:
Diferentes "níveis" de aviso. Muitos compiladores implementam isso (por exemplo, o GCC tem muitas opções para configurar exatamente o que será avisado), mas precisa de trabalho - por exemplo, relatando a gravidade de um aviso relatado e a capacidade de definir "avisos" são erros "apenas para avisos acima de uma gravidade especificada.
Classificação sã de erros e avisos. Um erro só deve ser relatado se o código não atender à especificação e, portanto, não puder ser compilado. Instruções inacessíveis, embora provavelmente um erro de codificação, devam ser um aviso , não um erro - o código ainda é "válido" e há instâncias legítimas em que alguém gostaria de compilar com código inacessível (modificações rápidas para depuração, por exemplo) .
Agora, eu discordo de você sobre:
Fazendo um esforço extra para relatar todos os problemas. Se houver um erro, isso interrompe a compilação. A compilação está quebrada. A compilação não funcionará até que esse erro seja corrigido. Portanto, é melhor relatar esse erro imediatamente, em vez de "continuar", a fim de tentar identificar tudo o mais "errado" no código. Especialmente quando muitas dessas coisas provavelmente são causadas pelo erro inicial de qualquer maneira.
Seu exemplo específico de um aviso de que deve ser um erro. Sim, provavelmente é um erro de programador. Não, não deve quebrar a compilação. Se eu souber que a entrada da função é tal que ela sempre retornará um valor, devo poder executar a compilação e fazer alguns testes sem precisar adicionar essas verificações extras. Sim, deve ser um aviso. E uma maldita alta gravidade nisso. Mas não deve quebrar a compilação por si só, a menos que seja compilado com avisos de erros.
Pensamentos?
fonte
Um problema que você levantou foi o relatório incompleto de erros - por exemplo, o relatório de 2 erros e, quando você os corrige, recebe muito mais.
Isso é (em grande parte) um compromisso por parte do escritor do compilador. Dependendo do que erro que você fez, é muito fácil para o compilador para começar a interpretar mal o que você faz tem mal o suficiente para que ele começa a relatar erros que têm muito pouco a ver com a realidade. Apenas por exemplo, considere um erro de digitação simples em que você tem algo parecido em
itn x;
vez deint x;
. A menos que você tenha feito algo queitn
signifique algo, isso será relatado como um erro. Tudo bem, mas agora considere o que acontece a seguir - o compilador analisa muito código que tenta usarx
como variável. A) deve parar e permitir que você conserte isso; ou B) vomitar 2000 erroserror: "x": undeclared identifier
ou algo nessa ordem? Considere outra possibilidade:Este é outro erro de digitação bastante óbvio - obviamente deve ser um em
{
vez de um[
. O compilador pode lhe dizer essa parte com bastante facilidade - mas deve reportar um erro por algo comox=1;
dizer algo comoerror: statement only allowed inside a function
?Observe que esses são problemas bastante triviais - problemas muito piores são fáceis de encontrar (especialmente, como a maioria de nós sabe, quando você entra em modelos C ++). O ponto principal é que o gravador do compilador geralmente fica impedido de tentar comprometer entre relatar erros falsos (ou seja, relatar algo como um erro, mesmo que esteja bom) e deixar de relatar erros reais. Existem algumas regras práticas que a maioria segue para tentar evitar erros excessivos em qualquer direção, mas quase nenhuma delas está perto da perfeição.
Um outro problema que você mencionou foi Java e
@SupressWarning
. Isso é bem diferente do acima - seria bastante trivial de corrigir. A única razão pela qual não foi corrigido é que isso não se encaixa no "caráter" básico do Java - ou seja, na opinião deles, "isso não é um bug, é um recurso". Mesmo que seja geralmente uma piada, nesse caso as pessoas envolvidas são tão equivocadas que realmente acreditam que é verdade.O problema que você menciona em C e C ++ com caminhos de código que não retornam um valor não é realmente permitir compiladores primitivos. É para permitir décadas de código existente , alguns dos quais ninguém quer consertar, tocar ou mesmo ler. É antigo e feio, mas funciona, e ninguém quer nada além de continuar trabalhando. Para melhor ou pior, os comitês de idiomas estão praticamente presos em manter essa compatibilidade com versões anteriores, então eles continuam permitindo coisas que ninguém realmente gosta - mas algumas pessoas (pelo menos pensam que precisam).
fonte
csc
desiste.