Estudo intensamente os tópicos de compiladores e intérpretes. Quero verificar se meu entendimento básico está correto, então vamos assumir o seguinte:
Eu tenho um idioma chamado "Foobish" e suas palavras-chave são
<OUTPUT> 'TEXT', <Number_of_Repeats>;
Então, se eu quiser imprimir no console 10 vezes, escreveria
OUTPUT 'Hello World', 10;
Olá, arquivo World.foobish.
Agora, escrevo um intérprete no idioma de minha escolha - C # neste caso:
using System;
namespace FoobishInterpreter
{
internal class Program
{
private static void Main(string[] args)
{
analyseAndTokenize(Hello World.foobish-file)//Pseudocode
int repeats = Token[1];
string outputString = Token[0];
for (var i = 0; i < repeats; i++)
{
Console.WriteLine(outputString);
}
}
}
}
Em um nível de intérprete muito fácil, o intérprete analisaria o arquivo de script etc. e executaria a linguagem foobish no caminho da implementação do intérprete.
Um compilador criaria uma linguagem de máquina que é executada diretamente no hardware físico?
Portanto, um intérprete não produz linguagem de máquina, mas um compilador faz isso por sua entrada?
Tenho algum mal-entendido da maneira básica como os compiladores e intérpretes funcionam?
fonte
Respostas:
Os termos "intérprete" e "compilador" são muito mais confusos do que costumavam ser. Muitos anos atrás, era mais comum os compiladores produzirem código de máquina a ser executado posteriormente, enquanto os intérpretes mais ou menos "executavam" o código-fonte diretamente. Então esses dois termos eram bem entendidos na época.
Mas hoje existem muitas variações no uso de "compilador" e "intérprete". Por exemplo, o VB6 "compila" o código de bytes (uma forma de linguagem intermediária ), que é então "interpretada" pelo VB Runtime. Um processo semelhante ocorre no C #, que produz o CIL que é então executado por um JIT (Just-In-Time Compiler) que, antigamente, era considerado um intérprete. Você pode "congelar" a saída do JIT em um executável binário real usando o NGen.exe , cujo produto teria sido o resultado de um compilador nos velhos tempos.
Portanto, a resposta para sua pergunta não é tão direta quanto era antes.
Leitura adicional
Compiladores vs. Intérpretes na Wikipedia
fonte
O resumo a seguir é baseado em "Compiladores, Princípios, Técnicas e Ferramentas", Aho, Lam, Sethi, Ullman, (Pearson International Edition, 2007), páginas 1, 2, com a adição de algumas idéias minhas.
Os dois mecanismos básicos para processar um programa são compilação e interpretação .
A compilação recebe como entrada um programa de origem em um determinado idioma e gera um programa de destino em um idioma de destino.
Se o idioma de destino for um código de máquina, ele poderá ser executado diretamente em algum processador:
A compilação envolve a varredura e tradução de todo o programa de entrada (ou módulo) e não envolve a execução.
A interpretação toma como entrada o programa de origem e sua entrada e produz a saída do programa de origem
A interpretação geralmente envolve o processamento (análise e execução) do programa, uma instrução de cada vez.
Na prática, muitos processadores de linguagem usam uma mistura das duas abordagens. Por exemplo, os programas Java são primeiro traduzidos (compilados) em um programa intermediário (código de bytes):
a saída desta etapa é então executada (interpretada) por uma máquina virtual:
Para complicar ainda mais, a JVM pode executar a compilação just-in-time no tempo de execução para converter o código de bytes em outro formato, que é então executado.
Além disso, mesmo quando você compila a linguagem de máquina, há um intérprete executando seu arquivo binário que é implementado pelo processador subjacente. Portanto, mesmo neste caso, você está usando um híbrido de compilação + interpretação.
Portanto, sistemas reais usam uma mistura dos dois, por isso é difícil dizer se um determinado processador de linguagem é um compilador ou um intérprete, porque provavelmente usará os dois mecanismos em diferentes estágios de seu processamento. Nesse caso, provavelmente seria mais apropriado usar outro termo mais neutro.
No entanto, compilação e interpretação são dois tipos distintos de processamento, conforme descrito nos diagramas acima,
Para responder às perguntas iniciais.
Não necessariamente, um compilador converte um programa gravado para uma máquina M1 em um programa equivalente gravado para uma máquina M2. A máquina de destino pode ser implementada em hardware ou ser uma máquina virtual. Conceitualmente, não há diferença. O ponto importante é que um compilador analisa um pedaço de código e o traduz para outro idioma sem executá-lo.
Se, ao produzir uma referência à saída, um compilador produz um programa de destino que pode estar na linguagem de máquina, um intérprete não.
fonte
defined A && !defined B
.No. Um compilador é simplesmente um programa que toma como entrada de um programa escrito numa linguagem Um e produz como saída um programa semanticamente equivalentes em linguagem B . A linguagem B pode ser qualquer coisa, não precisa ser uma linguagem de máquina.
Um compilador pode compilar de uma linguagem de alto nível para outra linguagem de alto nível (por exemplo, GWT, que compila Java para ECMAScript), de uma linguagem de alto nível para uma linguagem de baixo nível (por exemplo, Gambit, que compila Esquema para C), de uma linguagem de alto nível para código de máquina (por exemplo, GCJ, que compila Java para código nativo), de uma linguagem de baixo nível para uma linguagem de alto nível (por exemplo, Clue, que compila C para Java, Lua, Perl, ECMAScript e Common Lisp), de um idioma de baixo nível para outro idioma de baixo nível (por exemplo, o Android SDK, que compila bytecode JVML para Dalvik bytecode), de um idioma de baixo nível para código de máquina (por exemplo, o compilador C1X que faz parte do HotSpot, que compila bytecode JVML para código de máquina), código de máquina para uma linguagem de alto nível (qualquer "descompilador", também Emscripten, que compila código de máquina LLVM para ECMAScript),código de máquina para linguagem de baixo nível (por exemplo, o compilador JIT no JPC, que compila o código nativo x86 no JVML bytecode) e código nativo para o código nativo (por exemplo, o compilador JIT no PearPC, que compila o código nativo do PowerPC para o código nativo x86).
Observe também que "código de máquina" é realmente um termo confuso por vários motivos. Por exemplo, existem CPUs que executam nativamente o código de bytes da JVM e existem intérpretes de software para o código de máquina x86. Então, o que faz um "código de máquina nativo", mas não o outro? Além disso, todo idioma é código para uma máquina abstrata para esse idioma.
Existem muitos nomes especializados para compiladores que executam funções especiais. Apesar de serem nomes especializados, todos ainda são compiladores, apenas tipos especiais de compiladores:
Não necessariamente. Pode ser executado em um intérprete ou em uma VM. Poderia ser compilado para outro idioma.
Um intérprete não produz nada. Apenas executa o programa.
Um compilador produz algo, mas não precisa necessariamente ser linguagem de máquina, pode ser qualquer idioma. Pode até ser o mesmo idioma que o idioma de entrada! Por exemplo, Supercompilers, LLC possui um compilador que usa Java como entrada e produz Java otimizado como saída. Existem muitos compiladores ECMAScript que aceitam ECMAScript como entradas e produzem ECMAScript otimizado, minimizado e ofuscado como saída.
Você também pode estar interessado em:
fonte
Eu acho que você deve abandonar completamente a noção de "compilador versus intérprete", porque é uma dicotomia falsa.
A palavra coletiva para tornar útil uma linguagem de programação abstrata no mundo real é implementação .
No passado, uma implementação de linguagem de programação geralmente consistia em apenas um compilador (e a CPU para a qual gerou o código) ou apenas um intérprete - portanto, pode parecer que esses dois tipos de ferramentas são mutuamente exclusivos. Hoje, você pode ver claramente que esse não é o caso (e nunca foi assim). Tomar uma implementação sofisticada de linguagem de programação e tentar empurrar o nome "compilador" ou "intérprete" para ele geralmente leva a resultados inconclusivos ou inconsistentes.
Uma única implementação de linguagem de programação pode envolver qualquer número de compiladores e intérpretes , geralmente de várias formas (autônomo, em movimento), qualquer número de outras ferramentas, como analisadores e otimizadores estáticos , e várias etapas. Pode até incluir implementações inteiras de qualquer número de idiomas intermediários (que podem não estar relacionados ao que está sendo implementado).
Exemplos de esquemas de implementação incluem:
...e assim por diante.
fonte
Embora as linhas entre compiladores e intérpretes tenham se tornado confusas ao longo do tempo, ainda é possível traçar uma linha entre eles, observando a semântica do que o programa deve fazer e o que o compilador / intérprete faz.
Um compilador irá gerar outro programa (normalmente em uma linguagem de nível inferior, como código de máquina) que, se esse programa for executado, fará o que seu programa deve fazer.
Um intérprete fará o que seu programa deve fazer.
Com essas definições, os locais onde fica confuso são os casos em que seu compilador / intérprete pode fazer coisas diferentes, dependendo de como você o vê. Por exemplo, o Python pega seu código Python e o compila em um bytecode Python compilado. Se esse bytecode do Python for executado através de um interpretador de bytecode do Python , ele fará o que seu programa deveria fazer. Na maioria das situações, no entanto, os desenvolvedores de Python pensam que essas duas etapas estão sendo executadas em uma grande etapa; portanto, optam por pensar no interpretador CPython como interpretando seu código-fonte, e o fato de ele ter sido compilado ao longo do caminho é considerado um detalhe da implementação. . Desta forma, é tudo uma questão de perspectiva.
fonte
Aqui está uma simples desambiguação conceitual entre compiladores e intérpretes.
Considere três idiomas: linguagem de programação , P (em que o programa está escrito); linguagem de domínio , D (para o que se passa com o programa em execução); e idioma alvo , T (algum terceiro idioma).
Conceitualmente,
um compilador converte P em T para que você possa avaliar T (D); enquanto que
um intérprete avalia diretamente P (D).
fonte