Quem transforma o código escrito em software é outro software, conhecido como um implementador de linguagens. Leia a nossa série Poliglota com 24 capítulos (posts) para se tornar um especialista no assunto. Este é o quarto e fala sobre os diferentes tipos de implementadores. O primeiro, que explica a série, está aqui.
Nos dois primeiros posts explicamos o que é uma linguagem de programação e quais são seus elementos. Por várias vezes, falamos de um programa que transforma o código escrito em um programa executável. Chegou a hora de falar mais sobre isso.
1. O que é um implementador de linguagens?
Os diferentes tipos de software que convertem o código escrito em um programa executável são chamados de implementadores. Eles implementam uma linguagem de programação no sentido de torná-la utilizável para que programadores possam escrever e gerar programas.
Existem 3 métodos de implementação possíveis para uma linguagem de programação:
- compilação
- interpretação pura
- uma combinação de ambos (híbrido)
De forma que um implementador de linguagens pode ser um compilador, um interpretador ou possuir as duas implementações (híbrido). Já vamos explicar cada um, mas antes temos uma pergunta.
Como assim eles transformam o código em um programa? Eu posso escrever meu código no bloco de notas do Windows, chamo o implementador de linguagens e a mágica acontece?
Em alguns casos pode ser feito exatamente assim, considerando que a mágica é feita pelo implementador. Contudo, existem formas mais práticas do que escrever o código no bloco de notas e depois chamar o implementador de linguagens e já falaremos disso. Primeiro, vamos entender as diferenças entre eles.
2. Compilador
O implementador de linguagens mais comum é o compilador. Ele traduz o código para um formato executável pelo computador, gerando um novo software. Depois de traduzido, o programa roda muito rápido quando comparado com um programa interpretado, de modo que a compilação é o método mais rápido pensando na execução.
Um compilador possui várias tarefas internas, como analisar o código e conferir suas regras, depois ligar todos os recursos que o software precisa e, finalmente, gerar o arquivo executável com todos seus outros arquivos necessários . Ele atua sobre o código e faz bastante coisa. Porém, um programador dificilmente usa “só” o compilado.
2.1. IDE
Quando escrevo só o compilador, penso, por exemplo, no GCC, um compilador que implementa as linguagem C, C++, Objective-C, Fortran, Ada e Go. Nesse caso você escreve o código no editor que quiser e chama o comando executável gcc usando o prompt do sistema. É possível usar um bom editor de códigos, como o Sublime Text e Notepad++, porém é pouco comparado com uma ferramenta de software que tem tudo isso integrado, ou seja, o compilador, o editor de código e outros vários recursos. Essas ferramentas completas de software são chamadas de IDE (Integrated Development Enviroment) que, em português, quer dizer ambiente de desenvolvimento integrado.
Eclipse é, talvez, o IDE mais utilizado atualmente. Ele é gratuito, aceita muitos plugins e implementa diferentes linguagens. O Visual Studio é outro IDE famoso. Não é correto falar que o Visual Studio é só um compilador. Ele tem um compilador, mas possui muito mais, por isso o conceito de ambiente integrado de desenvolvimento. Quando falamos só ferramenta de desenvolvimento fica um termo mais genérico. Ela pode ser só o editor, só o compilador, qualquer software que seja usado no processo de gerar um novo pode ser considerado uma ferramenta de desenvolvimento de software.
2.2. Tipos de erros
O processo para gerar um software em um compilador segue o fluxo:
- Código é escrito pelo programador.
- Programador manda o compilador compilar o código.
- Se o código estiver ok, o compilador gera um arquivo executável e o novo software estará pronto para ser usado.
- Se o código não estiver ok, o compilador mostra o erro e sua linha e aborta a compilação.
Código estar ok significa que ele obedece todas as regras sintáticas da linguagem. Se algum erro ocorrer durante a compilação, dizemos que houve um erro em tempo de compilação. Esse tipo de erro está relacionado a sintaxe da linguagem e é fácil de encontrar (o compilador fala a linha do código que possui o erro) e corrigir. Pode ter sido um erro de digitação ou uma falta de atenção.
Agora, se o código compilou com sucesso e, durante a execução do programa gerado, ocorreu um erro, falamos que ele ocorreu em tempo de execução. Esse erro é difícil de encontrar. Pode ter sido um erro de lógica, um erro conceitual, um estouro de memória (quando o programa lota a memória RAM do equipamento), uma violação de acesso de memória (quando o programa tenta acessar um endereço na memória que não está reservado para ele) ou outros. Nessa situação, o compilador não informa a linha que possui o erro, normalmente fecha ou trava software, e mostra uma mensagem de erro como a figura abaixo.
2.2. Linguagens compiladas
As linguagens C, C++, C#, Objective-C, Fortran, Basic, Cobol, Pascal e outras são exemplos de linguagens compiladas. Para quem quiser saber mais, nesse link aqui tem uma lista bem completa, além do comentário feito em azul no começo que é muito bom. Vou traduzir aqui: “Essas são as linguagens tipicamente processadas por compiladores, embora, teoricamente, qualquer linguagem pode ser compilada ou interpretada”.
Essa afirmação é corretíssima e tira um pouco de peso nos rótulos que colocamos sobre linguagens quanto a sua implementação.
As primeiras implementações da linguagem Java eram todas híbridas. O código fonte em Java primeiro era compilado para seu formato intermediário, chamado de bytecode, depois ele era interpretado por uma máquina virtual java (JVM, de Java Virtual Machine), que é o interpretador. Existem agora sistemas que traduzem bytecode Java para código de máquina de forma a possibilitar uma execução mais rápida, ou seja, existem implementações de Java que são 100% compiladas. Portanto, Java pode ser uma linguagem híbrida (compilada e depois interpretada) ou compilada, depende do método de implementação.
3. Interpretador
A interpretação pura representa o oposto da compilação. Os programas são interpretados diretamente por outro software, chamado de interpretador. Não existe a etapa da tradução. O interpretador age como uma máquina virtual (pois é simulada em software) para a linguagem de programação. PHP e JavaScript são exemplos de linguagens puramente interpretadas.
3.1 Prós
Na hora de desenvolver, uma linguagem interpretada tem suas vantagens. A primeira delas é a facilidade de encontrar erros no código, tanto os sintáticos quanto os semânticos. Como não existe compilação, mas interpretação, o interpretador sempre sabe a descrição e a exata linha do erro. Isso é uma bela vantagem na hora de solucionar vários erros no dia a dia.
Outra vantagem de usar um interpretador como um implementador de linguagens é que não é preciso compilar e isso representa mais praticidade durante o desenvolvimento do software para testá-lo. É possível salvar o código e testá-lo imediatamente, sem essa etapa de tradução.
Considere que você escreveu um código em JavaScript dentro de um arquivo HTML e quer testar o código. É possível abrir um navegador, como o Google Chrome por exemplo, e rodar o arquivo HTML que contém o script de programação em JavaScript. Se você precisar rodar 100 vezes seu código no mesmo dia, isso não será um problema. Basta salvar o código e atualizar página para obter o novo resultado em segundos. Se você estivesse desenvolvendo o software em um compilador, você precisaria compilar 100 vezes. Cada compilação demandaria um tempo que não ocorre na interpretação.
Com a linguagem PHP o funcionamento é parecido. É possível escrever um arquivo com código PHP, salvá-lo e rodá-lo em um servidor que interpreta a linguagem PHP. Normalmente, um arquivo com programação PHP pode ser combinado com um HTML, porém, ao contrário de JavaScript, um navegador não interpreta PHP. Nesses casos, o servidor (como o Apache) interpreta o arquivo PHP, gera o arquivo HTML resultante e manda para o navegador. Parte do Facebook é programado com a linguagem PHP, por exemplo.
3.2. Contra
Contudo, segundo Sebesta (Sebesta, 2016), o tempo de execução de um sistema interpretado é de 10 a 100 vezes mais lento do que em métodos compilados. De fato, é um grande fator contra, mas que pode não ser crítico dependendo do propósito e uso do software. A linguagem PHP, por exemplo, mesmo sendo interpretada, é tida como uma das linguagens mais rápidas e eficientes para sistemas web.
4. Híbrido
O terceiro e último método é o híbrido, que representa um meio termo entre os compiladores e os interpretadores. Ele traduz (compila) os programas em linguagem de alto nível para uma linguagem intermediária projetada para facilitar a interpretação. Depois, usa um interpretador.
Perl é uma linguagem com um sistema híbrido e as primeiras implementações de Java, como já citei, eram todas híbridas.
Os Sistemas de implementação híbridos são mais rápidos do que a interpretação pura pelo fato de trabalharem com a etapa de compilação, porque as sentenças da linguagem fonte são decodificadas apenas uma vez. Em um interpretador puro, todas as linhas são interpretadas em todas as vezes que o programa é rodado. No modelo híbrido, o código compilado pode ser reutilizado, por isso algumas partes do código-fonte são decodificadas apenas uma vez, evitando repetir a mesma operação nas versões seguintes.
4.1. JIT
Um sistema de implementação Just-in-Time (JIT) inicialmente traduz os programas para uma linguagem intermediária. Então, durante a execução, compila os métodos da linguagem intermediária para linguagem de máquina quando esses são chamados. A versão em código de máquina é mantida para chamadas subsequentes. Sistemas JIT são bastante usados para programas
Java. As linguagens .NET também são todas implementadas com um sistema JIT.
4.2. Mundo perfeito
Analisando os prós e contras de cada implementador de linguagens, parece claro que ambos possuem vantagens complementares. O interpretador é melhor durante o desenvolvimento porque é preciso rodar o programa várias vezes até ele ficar pronto. Depois de pronto o código, o compilador é melhor porque é mais rápido.
Algumas vezes, um implementador pode fornecer tanto implementações compiladas quanto interpretadas para uma linguagem. Nesses casos, ele pode ser usado exatamente com os prós de cada abordagem. O interpretador é usado para desenvolver e depurar programas e, após um estado (relativamente) livre de erros ser alcançado, os programas são compilados para aumentar sua velocidade de execução.
Desta forma, uma linguagem de programação pode ser dita como compilada, interpretada ou compilada e interpretada (híbrida).
O próximo passo é entender quais são as principais linguagens de programação.