Computadores digitais não entendem as línguas que os humanos falam. Em vez disso, eles usam uma linguagem binária chamada código de máquina ou linguagem de máquina. O código de máquina consiste em uma seqüência de instruções simples do computador com cada instrução expressa como uma seqüência de dígitos ou bits binários (ou seja, 1’s e 0’s). Diferentes computadores – tipicamente “falam” ou “entendem” diferentes línguas de máquina. Por exemplo, um computador pode representar a operação ADD como 10011111
enquanto outro pode representar as mesmas operações como 000110
. Não só os bit-patterns tipicamente são diferentes de um tipo de computador para o próximo, mas mesmo assim o número de bits usados para representar uma operação pode ser diferente.
Outras vezes, quando um programa é executado, o sistema operacional (por exemplo, Windows, Linux, OS X, etc.) atua como um ambiente host que fornece serviços para o programa. Infelizmente, como o programa acessa esses serviços é tão diferente de um sistema operacional para o próximo. Como resultado das diferenças entre a linguagem da máquina e os requisitos do sistema operacional, os programas escritos na linguagem da máquina são mais focados no sistema que executa o programa do que em como o programa resolve um problema. Além disso, também significa que não é possível mover o código da máquina entre computadores diferentes sem fornecer algum tipo de serviço de tradução – geralmente na forma de uma máquina virtual.
Os programas escritos em linguagem de máquina são lentos, tediosos e propensos a erros. A solução foi desenvolver linguagens de programação de nível superior que focassem mais no problema e menos no sistema (o hardware e o sistema operacional) rodando o programa (veja Figura 2). Mas os computadores normalmente não executam programas escritos em linguagens de alto nível, então deve haver alguma forma de traduzir um programa escrito em uma linguagem de alto nível em linguagem de máquina. Dois tipos de programas de computador executam a tradução necessária: compiladores e interpretadores.
Um compilador é um programa que traduz outros programas escritos em uma linguagem de programação de alto nível como C ou C++ em código de máquina ou linguagem de máquina.Outras linguagens como Java e C# tomam um caminho diferente: Programas escritos nestas linguagens são compilados para uma representação intermediária (uma representação que fica em algum lugar entre a linguagem de alto nível e a linguagem de máquina) que é freqüentemente chamada de código de máquina virtual. O código da máquina virtual torna-se então a entrada para outro programa chamado interpretador ou máquina virtual (VM, um programa que simula uma CPU de hardware). Algumas linguagens, como Javascript e Perl, são completamente interpretadas, ou seja, não são compiladas mas interpretadas diretamente.
Cada abordagem para executar um programa escrito em uma linguagem de programação de alto nível tem vantagens e desvantagens. Programas escritos em linguagens totalmente compiladas (por exemplo, C e C++) executam mais rápido que programas escritos em linguagens parcialmente compiladas (por exemplo, Java e C#) e executam muito mais rápido que programas escritos em linguagens totalmente interpretadas (por exemplo, Javascript e Perl). Para dar alguma idéia da diferença de performance, digamos que um programa C++, uma vez compilado, executa no tempo 1.0. Um programa equivalente escrito em uma linguagem que é compilada e depois interpretada, geralmente será executado no tempo 3 a 10. O mesmo programa executado como uma linguagem puramente interpretada será executado em um tempo de cerca de 100. Implementações contemporâneas do Java e C# VMs usam um intérprete just in time (JIT) que compila parte do código virtual para o código da máquina enquanto o processa. Os processadores JIT reduzem o tempo de execução para cerca de 1,5 vezes o dos sistemas de linguagem puramente compilados. A linguagem de programação Python é um pouco diferente: A parte principal de um programa Python é interpretada mas é relativamente pequena e por isso tem um impacto mínimo no tempo de execução em geral. A maioria das bibliotecas Python, onde o programa passa a maior parte do seu tempo, são escritas em C, por isso os programas Python correm quase tão rápido como um programa equivalente em C.
Por outro lado, os programas executáveis produzidos por um compilador puro não podem ser transferidos entre plataformas diferentes (por exemplo, não se pode correr um programa Windows num computador Apple), enquanto os programas escritos em linguagens interpretadas são mais facilmente movidos entre computadores diferentes. Esta portabilidade é alcançada fornecendo uma VM ou um intérprete para cada plataforma (combinação de hardware e sistema operacional). Intérpretes e VMs são programas que são escritos em idiomas puramente compilados, portanto não são portáveis, mas os programas que eles processam são.