[JAVA] Expliquons la différence entre l'interpréteur et le compilateur en utilisant le diagramme de Ben

J'ai du mal à expliquer la différence entre les interprètes et les compilateurs depuis de nombreuses années. Les causes incluent diverses choses telles que les malentendus causés par la confusion du langage de programmation avec son système de traitement, ceux causés par la différence entre l'intérieur et l'extérieur du système de traitement, et ceux dus au contexte historique. Je suis. Par conséquent, il est difficile de décrire brièvement les définitions de l'interpréteur et du compilateur, et on pense qu'une structure a été créée dans laquelle des malentendus provoquent des malentendus. Par conséquent, dans cet article, je voudrais expliquer la différence entre l'interpréteur et le compilateur en utilisant le diagramme de Ben afin d'améliorer la situation autant que possible.

(Cet article a été inspiré par "Expliquons la différence entre les interprètes et les compilateurs en utilisant un langage mathématique-Qiita". .)

Connaissances préalables

Tout d'abord, j'expliquerai brièvement " interpreter "et" compiler". Ce sont les concepts associés au "système de traitement" "du langage de programmation, et en termes simples, ils diffèrent par la méthode de mise en œuvre du langage de programmation. L'interpréteur «interprète» et «exécute» le langage de programmation cible. L'interprétation ici est de décider comment le faire en fonction de la sémantique du langage de programmation. Contrairement à l'interpréteur, le compilateur n'implique pas une «exécution», il ne fait que «traduire» la langue cible dans une autre langue. N'importe quel langage de programmation peut être implémenté en tant que "interpréteur" ou "compilateur" [^ 1].

Cela semble être une définition simple et claire d'écrire autant, mais en réalité, ce qui précède est la définition de ** "au sens large" **, et la classification basée sur la réalité demande un peu plus d'ingéniosité.

[^ 1]: Cet article suppose un langage de programmation qui peut être exécuté sur un ordinateur Neumann. Je ne le couvrirai pas dans cet article car il est déroutant de trouver l'informatique quantique.

Explication par diagramme de Ben

Quand j'ai essayé de l'expliquer pour la première fois avec un diagramme, j'étais très inquiet de savoir comment l'exprimer, mais à la fin, j'ai obtenu le diagramme Ben suivant.

interpreter-compiler.png

J'avais l'intention de l'écrire aussi facilement que possible, mais je pense qu'il y a certaines parties où l'intention est difficile à lire, alors j'aimerais l'expliquer brièvement.

compilateur

Premièrement, un compilateur plus large signifie simplement une «traduction» vers un langage de programmation différent, mais une image de compilateur typique va d'un langage de haut niveau à un langage de bas niveau (langage machine ou proche du langage machine), comme les compilateurs C et Java. Byte code) est traduit. Par conséquent, cette image est définie comme «compilateur au sens strict» ».

Ensuite, «traducteur» est un système de traitement qui convertit au même niveau de langage de programmation. Il est ambigu de dire «même niveau», mais si vous ne considérez que trois catégories, langage machine, code d'octet et autres langages de haut niveau, ils sont à peu près les mêmes. L'assembleur traduit le langage d'assemblage (mnémonique) en langage machine, qui peut être considéré comme un traducteur car il s'agit presque d'une conversion un-à-un au même niveau [^ 2]. L'analyseur fait référence au processus de conversion d'un langage de programmation en un arbre de syntaxe abstraite (AST) dans cette figure, mais je pense que l'analyseur peut également être classé comme un traducteur si AST est considéré comme une sorte de langage formel. [^ 3]. Le système de traitement d'AltJS (TypeScript, CoffeeScript, Dart, PureScript, Elm, Scala.js, Opal ...) est aussi une sorte de traducteur et est souvent appelé " transpiler ". Ces systèmes de traitement sont des langages alternatifs de JavaScript (origine d'AltJS) car la langue de destination de la conversion est fixée à JavaScript.

[^ 2]: L'assembleur n'est pas réellement appelé "traducteur" ou "compilateur" simplement parce qu'il peut être classé conceptuellement comme tel. [^ 3]: La conversion en un arbre de syntaxe abstrait ne change pas la sémantique du langage de programmation original, donc j'ai senti que c'était plus un traducteur qu'un compilateur, mais ce n'est pas une interprétation générale.

Interprète

L'interprète a initialement interprété et exécuté le langage directement, comme le système de traitement du premier langage BASIC. Par conséquent, l'interprète de cette image est appelé "" interprète au sens étroit "". Peu de systèmes de traitement sont mis en œuvre de cette manière dans les langages modernes haut de gamme. En effet, les langages modernes haut de gamme ont été conçus pour les rendre plus faciles à manipuler par les humains et ne sont pas adaptés à une exécution directe par ordinateur. Inversement, les systèmes de traitement du langage (JVM) pour les langages de bas niveau tels que les bytecodes Java plutôt que les langages de haut niveau sont également appelés «interprètes de bytecode» et relèvent de la catégorie des «interprètes au sens étroit».

Si vous souhaitez implémenter un système moderne de traitement du langage de haut niveau en tant qu'interprète, vous implémenterez presque certainement un «interpréteur d'interprétation indirect». L'interpréteur «d'interprétation indirecte» est une méthode de conversion temporaire du code source original en une expression intermédiaire facile à exécuter telle qu'un arbre de syntaxe abstraite (AST) ou un code d'octet et son exécution. C'est le cas pour les systèmes de traitement typiques de ce que l'on appelle Lightwight Language / LL tels que Python, Ruby et JavaScript. Comme certains d'entre vous l'ont peut-être déjà remarqué, la conversion en "représentation intermédiaire" signifie qu'un traitement potentiellement équivalent au compilateur est implémenté dans l'interpréteur. C'est la raison pour laquelle l'interpréteur au sens large et le cercle d'interprétation indirecte se chevauchent avec le compilateur dans le diagramme de Ben. Surtout dans les systèmes de traitement d'interpréteurs récents, le format de code d'octet, pour lequel les recherches d'optimisation progressent, est souvent adopté pour la «représentation intermédiaire», et il est développé en utilisant pleinement la technologie développée pour le compilateur.

Différences d'apparence en fonction du point de vue, du point de vue et du champ visuel

La division du compilateur et de l'interpréteur changera si le contexte tel que le point de vue, le point de vue et le champ de vision change. Par exemple, si vous expliquez avec le système de traitement CRuby récent (système de traitement Ruby écrit en langage C), le système de traitement CRuby est reconnu comme un interprète du point de vue de l'utilisateur du langage Ruby. C'est parce que le processeur CRuby semble interpréter et exécuter le langage Ruby. Cependant, si vous déplacez votre point de vue à l'intérieur du système de traitement CRuby, le décor que vous voyez changera. Dans le système de traitement CRuby, le processus de conversion du langage Ruby en un arbre de syntaxe abstraite est effectué en premier, puis il est converti en code d'octet unique au système de traitement CRuby. Après cela, l'interpréteur de code d'octet unique au système de traitement CRuby fonctionne et exécute le code d'octet généré. Si vous le regardez en détail de l'intérieur comme ceci, traducteur" qui convertit le langage Ruby en AST et ʻexécution du code d'octet du système de traitement CRuby et le "compilateur" au sens étroit qui convertit AST en code d'octet du système de traitement CRuby Vous pouvez voir que "l'interprète au sens étroit" fonctionne. Si vous déplacez votre perspective plus loin dans l'interpréteur de bytecode, vous pouvez également voir que le compilateur JITest en cours d'exécution ici [^ 4]. Si vous élargissez vos horizons cette fois, le langage Ruby dispose également d'un système de traitement appelé JRuby qui fonctionne sur JVM. JRuby est livré avec unpré-compilateur` (compilateur Ahead-Of-Time) qui vous permet de" compiler "des scripts Ruby en code octet Java à l'avance.

Pour donner un exemple de Java, Jshell a été introduit à partir de Java 9, et comme il s'agit d'un REPL (Read-Eval-Print Loop), il peut être considéré comme un ** système de traitement d'interpréteur ** du point de vue de l'utilisateur. Je vais. De plus, étant donné que Java 11 permet une exécution immédiate des fichiers java, c'est le comportement correct de l'interpréteur, qui est la méthode d'exécution pour laquelle les langages de programmation légers tels que Ruby ont été bons.

De cette manière, les langages de programmation et leurs systèmes de traitement subissent aujourd'hui une évolution, une complexité et une diversification majeures. En conséquence, les interpréteurs et les compilateurs sont imbriqués, ont une structure en plusieurs étapes et ont plusieurs systèmes de traitement, il est donc très important à partir de quel contexte vous regardez le "compilateur" ou "interpréteur". En d'autres termes, ce que vous voyez en tant qu'interprète de votre propre point de vue peut paraître différent des autres points de vue, vous devez donc porter une attention particulière au contexte lorsque vous en parlez.

[^ 4]: le compilateur JIT (expérimental) est disponible en option depuis Ruby 2.6.

Résumé

Dans cet article, j'ai essayé d'expliquer la différence entre l'interpréteur et le compilateur en utilisant le diagramme de Ben. Le résumé est le suivant.

―― «Interprète» et «compilateur» sont les méthodes d'implémentation du système de traitement du langage et ne sont pas liés au langage de programmation.

Le diagramme de Ben organise également des interprètes et des compilateurs modernes de manière rationnelle et intuitive, tout en respectant les interprétations historiques. Le chevauchement des cercles est également conçu pour exprimer que la couche supérieure peut comprendre la couche inférieure.

Nous espérons que cet article vous aidera à mieux comprendre vos interprètes et compilateurs et à faire de nouvelles découvertes.

Les références

Recommended Posts

Expliquons la différence entre l'interpréteur et le compilateur en utilisant le diagramme de Ben
Quelle est la différence entre un serveur Web et un serveur d'applications?
Quelle est la différence entre une action et une méthode d'instance?
Remplaçons la différence entre == (identité) et méthode equals (équivalence)
[Ruby] Relation entre la classe parent et la classe enfant. Relation entre classe et instance.
À propos de la différence entre irb et pry
[Java] Comprendre la différence entre List et Set
[Rails / Active Record] À propos de la différence entre créer et créer!
Comprenez la différence entre les classes abstraites et les interfaces!
Quelle est la différence entre SimpleDateFormat et DateTimeFormatter? ??
Comprenez en 3 minutes! Une explication très approximative de la différence entre session et cookie
[Ruby] J'ai réfléchi à la différence entre each_with_index et each.with_index
[Rails] J'ai étudié la différence entre les ressources et les ressources
Quelle est la différence entre System Spec et Feature Spec?
Différences entre les classes et les instances dans Ruby
[Rails] Quelle est la différence entre la redirection et le rendu?
Comparez la différence entre dockerfile avant et après docker-slim
[JAVA] Quelle est la différence entre interface et abstract? ?? ??
Quelle est la différence entre ignorer et en attente? [RSpec]
[Swift] UITextField m'a appris la différence entre nil et ""
Je vais expliquer la différence entre le développement d'applications Android et le développement d'applications iOS du point de vue des ingénieurs iOS
Différence entre vh et%
Différence entre i ++ et ++ i
[Rails] Quelle est la différence entre l'installation et la mise à jour du bundle?
Différence entre Java et JavaScript (comment trouver la moyenne)
[Java] Vérifiez la différence entre orElse et orElseGet avec IntStream
La différence entre la programmation qui utilise des classes Ruby et la programmation qui n'utilise pas