J'étudie les sujets des compilateurs et des interprètes de manière intensive. Je veux vérifier si ma compréhension de base est correcte, alors supposons ce qui suit:
J'ai une langue appelée "Foobish" et ses mots clés sont
<OUTPUT> 'TEXT', <Number_of_Repeats>;
Donc, si je veux imprimer 10 fois sur la console, j’écrirais
OUTPUT 'Hello World', 10;
Bonjour World.foobish-file.
Maintenant, j'écris un interprète dans la langue de mon choix - C # dans ce cas:
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);
}
}
}
}
Sur un niveau d'interprète très facile, l'interprète analysera le fichier script, etc. et exécutera le langage foobish de la même manière que l'implémentation de l'interprète.
Un compilateur créerait-il un langage machine qui fonctionne directement sur le matériel physique?
Donc, un interprète ne produit pas de langage machine, mais un compilateur le fait-il pour son entrée?
Est-ce que j'ai des malentendus dans la façon dont fonctionne les compilateurs et interprètes?
la source
Réponses:
Les termes "interprète" et "compilateur" sont beaucoup plus flous qu'avant. Il y a de nombreuses années, il était plus courant que les compilateurs produisent du code machine à exécuter ultérieurement, tandis que les interprètes "exécutaient" directement le code source. Donc, ces deux termes étaient bien compris à l'époque.
Mais aujourd'hui, il y a beaucoup de variations sur l'utilisation de "compilateur" et "interprète". Par exemple, VB6 "compile" en code d'octet (une forme de langage intermédiaire ), qui est ensuite "interprété" par VB Runtime. Un processus similaire a lieu en C #, ce qui produit CIL qui est ensuite exécuté par un compilateur juste-à-temps (JIT) qui, jadis, aurait été considéré comme un interprète. Vous pouvez "lyophiliser" la sortie du JIT dans un exécutable binaire en utilisant NGen.exe , dont le produit aurait été le résultat d'un compilateur de l'ancien temps.
La réponse à votre question n’est donc pas aussi simple qu’elle l’était.
Lectures complémentaires
Compilateurs vs interprètes sur Wikipédia
la source
Le résumé que je donne ci-dessous est basé sur "Compilateurs, principes, techniques et outils", Aho, Lam, Sethi, Ullman, (Pearson International Edition, 2007), pages 1 et 2, avec l’ajout de certaines de mes idées personnelles.
Les deux mécanismes de base pour le traitement d'un programme sont la compilation et l' interprétation .
La compilation prend en entrée un programme source dans une langue donnée et génère un programme cible dans une langue cible.
Si la langue cible est le code machine, il peut être exécuté directement sur un processeur:
La compilation implique la numérisation et la traduction de l’ensemble du programme d’entrée (ou du module) et ne nécessite pas son exécution.
L'interprétation prend en entrée le programme source et son entrée et produit la sortie du programme source
L'interprétation implique généralement le traitement (l'analyse et l'exécution) du programme, une instruction à la fois.
En pratique, de nombreux processeurs de langage utilisent une combinaison des deux approches. Par exemple, les programmes Java sont d'abord traduits (compilés) dans un programme intermédiaire (code octet):
la sortie de cette étape est ensuite exécutée (interprétée) par une machine virtuelle:
Pour compliquer encore les choses, la machine virtuelle Java peut effectuer une compilation juste à temps au moment de l'exécution afin de convertir le code octet dans un autre format, qui est ensuite exécuté.
En outre, même lorsque vous compilez en langage machine, un interpréteur exécutant votre fichier binaire est implémenté par le processeur sous-jacent. Par conséquent, même dans ce cas, vous utilisez un système hybride compilation + interprétation.
Ainsi, les systèmes réels utilisent une combinaison des deux. Il est donc difficile de dire si un processeur de langage donné est un compilateur ou un interprète, car il utilisera probablement les deux mécanismes à différentes étapes de son traitement. Dans ce cas, il serait probablement plus approprié d'utiliser un autre terme plus neutre.
Néanmoins, la compilation et l’interprétation sont deux types de traitement distincts, décrits dans les schémas ci-dessus,
Pour répondre aux questions initiales.
Pas nécessairement, un compilateur traduit un programme écrit pour une machine M1 en un programme équivalent écrit pour une machine M2. La machine cible peut être implémentée matériellement ou être une machine virtuelle. Conceptuellement, il n'y a pas de différence. L'important est qu'un compilateur examine un morceau de code et le traduise dans un autre langage sans l'exécuter.
Si, en produisant, vous faites référence à la sortie, un compilateur produit un programme cible qui peut être en langage machine, contrairement à un interprète.
la source
defined A && !defined B
.Non . Un compilateur est tout simplement un programme qui prend en entrée un programme écrit en langage A et produit en sortie un programme sémantiquement équivalent dans le langage B . La langue B peut être n'importe quoi, il n'est pas nécessaire qu'elle soit en langage machine.
Un compilateur peut compiler d'un langage de haut niveau à un autre langage de haut niveau (par exemple, GWT, qui compile Java vers ECMAScript), d'un langage de haut niveau à un langage de bas niveau (par exemple, Gambit, qui compile Scheme en C), d'un langage de haut niveau au code machine (par exemple, GCJ, qui compile Java en code natif), d'un langage de bas niveau à un langage de haut niveau (par exemple, Clue, qui compile le C en Java, Lua, Perl, ECMAScript et Common Lisp), d’un langage de bas niveau à un autre langage de bas niveau (par exemple, le SDK Android, qui compile le bytecode JVML en Daltik), d’un langage de bas niveau au code machine (par exemple, le compilateur C1X qui fait partie de HotSpot, qui compile le bytecode JVML en code machine), le code machine en un langage évolué (tout "décompilateur", également Emscripten, qui compile le code machine LLVM en ECMAScript),code machine en langage de bas niveau (par exemple, le compilateur JIT dans JPC, qui compile le code natif x86 en bytecode JVML) et le code natif en code natif (par exemple, le compilateur JIT dans PearPC, qui compile le code natif PowerPC en code natif x86).
Notez également que "code machine" est un terme très flou pour plusieurs raisons. Par exemple, certains processeurs exécutent de manière native le code octet JVM et des interpréteurs logiciels pour le code machine x86. Alors, qu'est-ce qui fait qu'un "code machine natif" mais pas l'autre? De plus, chaque langue est un code pour une machine abstraite pour cette langue.
Il existe de nombreux noms spécialisés pour les compilateurs qui remplissent des fonctions spéciales. Bien qu'il s'agisse de noms spécialisés, tous restent des compilateurs, mais des types de compilateurs particuliers:
Pas nécessairement. Il peut être exécuté dans un interprète ou dans une machine virtuelle. Il pourrait être ensuite compilé dans une langue différente.
Un interprète ne produit rien. Il ne fait que lancer le programme.
Un compilateur produit quelque chose, mais il ne doit pas nécessairement s'agir d'un langage machine, il peut s'agir de n'importe quel langage. Ce peut même être la même langue que la langue d'entrée! Par exemple, Supercompilers, LLC a un compilateur qui prend Java en entrée et produit une sortie Java optimisée. Il existe de nombreux compilateurs ECMAScript qui utilisent ECMAScript en entrée et produisent en sortie un ECMAScript optimisé, minimisé et obscurci.
Vous pouvez également être intéressé par:
la source
Je pense que vous devriez abandonner complètement la notion de "compilateur par rapport à interprète", car c'est une fausse dichotomie.
Le mot collectif pour rendre un langage de programmation abstrait utile dans le monde réel est implémentation .
Auparavant, une implémentation de langage de programmation consistait souvent en un compilateur (et le processeur pour lequel elle avait généré le code) ou en un interpréteur. Il est donc possible que ces deux types d’outils s’excluent mutuellement. Aujourd'hui, vous pouvez voir clairement que ce n'est pas le cas (et cela n'a jamais été le cas). Prendre une implémentation sophistiquée du langage de programmation et tenter de lui attribuer le nom de "compilateur" ou "interprète" vous mènera souvent à des résultats peu concluants ou incohérents.
Une seule implémentation de langage de programmation peut impliquer un nombre illimité de compilateurs et d'interprètes , souvent sous plusieurs formes (autonome, à la volée), un nombre illimité d'outils, tels que des analyseurs statiques et des optimiseurs , et un nombre illimité d'étapes. Il peut même inclure des implémentations complètes d'un nombre quelconque de langages intermédiaires (qui peuvent être sans rapport avec celui qui est implémenté).
Voici des exemples de schémas de mise en œuvre:
...etc.
la source
Bien que les lignes entre les compilateurs et les interprètes soient devenues floues au fil du temps, on peut toujours les distinguer en examinant la sémantique de ce que le programme devrait faire et du compilateur / interprète.
Un compilateur générera un autre programme (généralement dans un langage de niveau inférieur tel que le code machine) qui, si ce programme est exécuté, fera ce que votre programme devrait faire.
Un interprète fera ce que votre programme devrait faire.
Avec ces définitions, les endroits où cela devient flou sont les cas où votre compilateur / interprète peut être considéré comme faisant différentes choses en fonction de la façon dont vous le regardez. Par exemple, Python prend votre code Python et le compile en un bytecode Python compilé. Si ce bytecode Python est exécuté via un interpréteur de bytecode Python , il fait ce que votre programme était censé faire. Cependant, dans la plupart des situations, les développeurs Python pensent que ces deux étapes doivent être exécutées en une seule étape. Ils choisissent donc de considérer l' interpréteur CPython comme une interprétation de leur code source. Le fait qu'il ait été compilé en cours de route est considéré comme un détail d'implémentation . De cette façon, tout est une question de perspective.
la source
Voici une simple homonymie conceptuelle entre les compilateurs et les interprètes.
Considérez 3 langages: le langage de programmation , P (dans lequel le programme est écrit); langue du domaine , D (pour ce qui se passe avec le programme en cours d'exécution); et langue cible , T (une troisième langue).
Conceptuellement,
un compilateur traduit P en T afin que vous puissiez évaluer T (D); tandis que
un interprète évalue directement P (D).
la source