coldwa.st
Todos os guiasProgramaçãoWebDadosFerramentasBases de dadosHaskellConceitosCabal e buildsToolchainCompiladorDesempenhoEditor e HLS

Programação · Conceitos · Compilador

O que é um compilador?

Por ColdwastAtualizado em 23 jun 20268 min de leitura#compiler#concepts#haskell
Código-fonte C++ destacado com números de linha num editor escuro
Um código-fonte como este — variáveis, laços e condições escritos por uma pessoa — é a entrada que o compilador lê para transformá-la num programa que a máquina pode executar.

Você escreve um programa numa linguagem que sabe ler: palavras, indentação, nomes com significado. O processador da sua máquina não entende nada disso — ele executa instruções binárias cruas. A ferramenta que faz a ponte é o compilador. Este guia explica o que é um compilador, as etapas pelas quais ele passa, em que difere de um interpretador, e onde um compilador como o GHC se encaixa quando você escreve Haskell.

A definição curta

Um compilador é um programa que traduz código-fonte escrito numa linguagem para outra forma — normalmente o código de máquina que um computador pode executar diretamente. Você entrega os arquivos de texto que escreveu e ele produz um executável (ou um formato intermediário) que a máquina, ou um runtime, pode executar. A tradução acontece uma vez, antecipadamente, e o resultado roda sozinho, sem que o compilador esteja presente.

Como um compilador funciona, etapa por etapa

Um compilador não traduz num único salto. Ele percorre uma cadeia de etapas, cada uma passando o seu resultado para a seguinte:

  • Análise léxica (tokenização): o texto-fonte é dividido em pequenas unidades — palavras-chave, nomes, números, símbolos — chamadas tokens.
  • Análise sintática (parsing): os tokens são organizados numa árvore que reflete a estrutura do programa, segundo a gramática da linguagem.
  • Análise semântica: o compilador verifica se o programa faz sentido — nomes definidos, tipos coerentes, regras da linguagem respeitadas. É aqui que muitos dos seus erros são detectados.
  • Otimização: o compilador reescreve o programa num equivalente mais rápido ou menor sem mudar o que ele faz.
  • Geração de código: por fim ele emite a saída-alvo — código de máquina, ou uma representação intermediária que outra ferramenta vai finalizar.

Se alguma etapa encontrar um problema, você recebe um erro de compilação e nenhum programa é produzido. É o trato do compilador: ele se recusa a construir código quebrado, então toda uma classe de erros é capturada antes mesmo de o programa rodar.

Um desenvolvedor de fones de ouvido trabalhando numa mesa com um monitor e um notebook mostrando código numa sala azul-escura
Um desenvolvedor trabalhando: você escreve e edita o código-fonte, depois roda o compilador, que lê os seus arquivos e produz o programa executável.

Compilador vs interpretador

A outra abordagem comum é o interpretador, que lê o seu código-fonte e o executa diretamente, linha por linha, cada vez que o programa roda — nenhum executável separado é construído antecipadamente. Um compilador traduz o programa inteiro uma vez, no início, para uma forma que a máquina executa sozinha.

A diferença prática: programas compilados costumam iniciar e rodar mais rápido, porque a tradução e a otimização já aconteceram, e os erros aparecem em tempo de compilação. Programas interpretados são mais rápidos de testar e mais flexíveis, mas refazem o trabalho de tradução a cada execução. Muitas toolchains reais misturam as duas — compilam para uma forma intermediária e depois a executam numa máquina virtual.

Onde GHC e Haskell se encaixam

Quando você escreve Haskell, o compilador que usa é o GHC (o Glasgow Haskell Compiler). Ele lê os seus arquivos-fonte .hs, verifica os tipos a fundo, otimiza o resultado e produz um executável nativo que você pode rodar sozinho. O forte sistema de tipos do Haskell faz com que a etapa de análise semântica do GHC trabalhe muito por você: muitos bugs são reportados como erros de compilação em vez de quebrarem em tempo de execução. Para o passo a passo completo do uso, veja o nosso guia do compilador GHC e como instalar o Haskell com o GHCup.

Os comandos que você realmente encontra

  • Compilar um único arquivo: uma ferramenta como ghc Main.hs lê o seu fonte e produz um executável.
  • Construir um projeto: ferramentas de build como Cabal ou Stack conduzem o compilador através de muitos arquivos e dependências por você.
  • Verificar tipos sem um build completo: muitos compiladores oferecem um modo mais rápido que procura erros sem emitir um binário.

Na maior parte do tempo você não chama o compilador à mão — a sua ferramenta de build ou o seu editor faz isso e mostra os erros. Mas saber o que ele faz por baixo torna esses erros muito mais fáceis de ler.

Os compromissos honestos

Compiladores acrescentam um passo: você muda o código, espera o build, e depois executa. Num projeto grande essa espera pode incomodar, e por isso compiladores rápidos e builds incrementais importam. A recompensa é real: erros capturados cedo, saída otimizada e um único executável que você pode distribuir sem distribuir a sua toolchain. Para uma linguagem fortemente tipada como Haskell, essa verificação antecipada é grande parte do apelo — o compilador é uma rede de segurança, não apenas um tradutor.

Perguntas frequentes

O que é um compilador em termos simples?

Um compilador é um programa que traduz o código-fonte que você escreve para uma forma que o computador pode executar — normalmente código de máquina. Você dá os seus arquivos de texto e ele produz um executável que roda sozinho, sem que o compilador esteja presente. A tradução acontece uma vez, antecipadamente.

Qual é a diferença entre um compilador e um interpretador?

Um compilador traduz o programa inteiro uma vez, antecipadamente, para uma forma executável, então o resultado inicia e roda rápido. Um interpretador lê e executa o código-fonte diretamente a cada execução, sem um passo de build separado. Programas compilados costumam ser mais rápidos; os interpretados são mais rápidos de testar e mais flexíveis.

Quais são as etapas de um compilador?

Um compilador costuma percorrer a análise léxica (dividir o texto em tokens), a análise sintática (construir uma árvore de estrutura), a análise semântica (verificar nomes e tipos), a otimização (tornar o programa mais rápido ou menor) e a geração de código (emitir o código de máquina final ou uma forma intermediária). Um erro em qualquer etapa interrompe o build.

O GHC é um compilador?

Sim. O GHC, o Glasgow Haskell Compiler, é o compilador padrão do Haskell. Ele lê os seus arquivos-fonte .hs, verifica os tipos e os otimiza, e produz um executável nativo que você pode rodar sozinho. O forte sistema de tipos do Haskell faz com que o GHC capture muitos bugs como erros de compilação antes mesmo de o programa rodar.

Guia independente, mantido pela comunidade. coldwa.st é um site de recursos de programação; este artigo é um texto explicativo original e inédito sobre como os compiladores funcionam. As etapas descritas são padrão nos compiladores mais comuns; consulte a documentação do seu compilador para o comportamento exato.
Recomendado

Uma máquina Linux para compilar e executar o seu código

Compilar um projeto de verdade — construir o GHC, verificar os tipos de uma grande base de código Haskell e depois rodar o executável — é muito mais fácil numa máquina Linux de verdade do que num notebook. Um servidor na nuvem dá acesso root para instalar uma toolchain de compilação e construir a sua app num ambiente limpo. A Infomaniak — um provedor suíço que respeita a privacidade — oferece servidores na nuvem que você configura e acessa por SSH.

Ver Infomaniak Cloud →

Link de afiliado — apoia estes guias gratuitos.

Veja mais explicações claras no nosso índice de guias.