[JAVA] Lassen Sie uns den Unterschied zwischen Interpreter und Compiler anhand des Ben-Diagramms erklären

Ich habe seit vielen Jahren Mühe, den Unterschied zwischen Interpreten und Compilern zu erklären. Zu den Ursachen gehören verschiedene Dinge wie Missverständnisse, die durch die Verwechslung der Programmiersprache mit ihrem Verarbeitungssystem verursacht werden, solche, die durch den Unterschied zwischen dem Inneren und dem Äußeren des Verarbeitungssystems verursacht werden, und solche, die auf historischen Hintergrund zurückzuführen sind. Ich bin. Daher ist es schwierig, die Definitionen des Interpreters und des Compilers kurz zu beschreiben, und es wird angenommen, dass eine Struktur erstellt wurde, in der Missverständnisse zu Missverständnissen führen. Daher möchte ich in diesem Artikel den Unterschied zwischen dem Interpreter und dem Compiler anhand des Ben-Diagramms erläutern, um die Situation so weit wie möglich zu verbessern.

(Dieser Artikel wurde inspiriert von "Erklärung des Unterschieds zwischen Interpreten und Compilern unter Verwendung einer mathematischen Sprache - Qiita". .)

Vorausgesetztes Wissen

Zuerst werde ich kurz " Interpreter "und" Compiler" erklären. Dies sind die Konzepte, die mit dem "Verarbeitungssystem" der Programmiersprache verbunden sind, und sie unterscheiden sich in einfachen Worten in der Implementierungsmethode der Programmiersprache. Der Interpreter "" interpretiert "" und "" führt die Zielprogrammiersprache aus. Die Interpretation hier besteht darin, basierend auf der Semantik der Programmiersprache zu entscheiden, wie dies zu tun ist. Im Gegensatz zum Interpreter beinhaltet der Compiler keine "Ausführung" und übersetzt nur die Zielsprache in eine andere Sprache. Grundsätzlich kann jede Programmiersprache entweder als "Interpreter" oder als "Compiler" implementiert werden [^ 1].

Es scheint eine einfache und klare Definition zu sein, so viel zu schreiben, aber in Wirklichkeit ist das Obige die Definition von ** "breit definiert" **, und für die Klassifizierung anhand der Realität ist etwas mehr Einfallsreichtum erforderlich.

[^ 1]: Dieser Artikel setzt eine Programmiersprache voraus, die auf einem Neumann-Computer ausgeführt werden kann. Ich werde es in diesem Artikel nicht behandeln, da es verwirrend wird, Quantencomputer zu entwickeln.

Erklärung durch Ben-Diagramm

Als ich zum ersten Mal versuchte, es mit einem Diagramm zu erklären, war ich sehr besorgt darüber, wie ich es ausdrücken sollte, aber am Ende bekam ich das folgende Ben-Diagramm.

interpreter-compiler.png

Ich wollte es so einfach wie möglich schreiben, aber ich denke, es gibt einige Teile, in denen die Absicht schwer zu lesen ist, deshalb möchte ich es kurz erklären.

Compiler

Erstens bedeutet ein breiterer Compiler einfach eine "Übersetzung" in eine andere Programmiersprache, aber ein typisches Compiler-Image ist von einer Hochsprache in eine Niedrigsprache (Maschinensprache oder nahe an Maschinensprache), wie C- und Java-Compiler. Bytecode) wird übersetzt. Daher ist dieses Bild als "Compiler im engeren Sinne" definiert.

Als nächstes ist "Übersetzer" ein Verarbeitungssystem, das in dieselbe Programmiersprachenebene konvertiert. Es ist nicht eindeutig, "gleiche Ebene" zu sagen, aber wenn Sie nur drei Kategorien berücksichtigen, Maschinensprache, Bytecode und andere Hochsprachen, sind sie ungefähr gleich. Der Assembler übersetzt die Assemblersprache (Mnemonik) in eine Maschinensprache, die als Übersetzer betrachtet werden kann, da es sich fast um eine Eins-zu-Eins-Konvertierung auf derselben Ebene handelt [^ 2]. Der Parser bezieht sich in dieser Abbildung auf den Prozess der Konvertierung einer Programmiersprache in einen abstrakten Syntaxbaum (AST). Ich denke jedoch, dass der Parser auch als Übersetzer klassifiziert werden kann, wenn AST als eine Art formale Sprache angesehen wird. [^ 3]. Das Verarbeitungssystem von AltJS (TypeScript, CoffeeScript, Dart, PureScript, Elm, Scala.js, Opal ...) ist ebenfalls eine Art Übersetzer und wird oft als "Transpiler" bezeichnet. Diese Verarbeitungssysteme sind alternative Sprachen von JavaScript (Ursprung von AltJS), da die Konvertierungszielsprache auf JavaScript festgelegt ist.

[^ 2]: Der Assembler wird eigentlich nicht als "Übersetzer" oder "Compiler" bezeichnet, nur weil er konzeptionell als solcher klassifiziert werden kann. [^ 3]: Die Konvertierung in einen abstrakten Syntaxbaum ändert nichts an der Semantik der ursprünglichen Programmiersprache. Ich hatte das Gefühl, dass sie einem Übersetzer näher steht als einem Compiler, aber es ist keine allgemeine Interpretation.

Dolmetscher

Der Interpreter hat die Sprache ursprünglich direkt interpretiert und ausgeführt, wie das Verarbeitungssystem der frühen BASIC-Sprache. Daher wird der Interpreter dieses Bildes "Interpreter im engeren Sinne" genannt. Nur wenige Verarbeitungssysteme sind auf diese Weise in modernen High-End-Sprachen implementiert. Dies liegt daran, dass moderne High-End-Sprachen entwickelt wurden, um den Umgang mit Menschen zu erleichtern, und nicht für die direkte Computerausführung geeignet sind. Umgekehrt werden Sprachverarbeitungssysteme (JVMs) für Low-Level-Sprachen wie Java-Bytecodes anstelle von High-Level-Sprachen auch als "Bytecode-Interpreter" bezeichnet und fallen unter die Kategorie "Interpreter im engeren Sinne".

Wenn Sie ein modernes Hochsprachenverarbeitungssystem als Dolmetscher implementieren möchten, werden Sie mit ziemlicher Sicherheit einen "indirekten Dolmetscher" implementieren. Der Interpreter "indirekte Interpretation" ist eine Methode, um den ursprünglichen Quellcode vorübergehend in einen einfach auszuführenden Zwischenausdruck wie einen abstrakten Syntaxbaum (AST) oder Bytecode umzuwandeln und auszuführen. Dies ist ein typisches Verarbeitungssystem für sogenannte Lightwight Language / LL wie Python, Ruby und JavaScript. Wie einige von Ihnen vielleicht bereits bemerkt haben, bedeutet die Konvertierung in "Zwischendarstellung", dass eine potenziell compileräquivalente Verarbeitung im Interpreter implementiert ist. Dies ist der Grund, warum sich der Interpreter im weiteren Sinne und der Kreis der indirekten Interpretation mit dem Compiler im Ben-Diagramm überschneiden. Insbesondere in neueren Interpreter-Verarbeitungssystemen wird das Bytecode-Format, für das die Optimierungsforschung voranschreitet, häufig für die "Zwischendarstellung" verwendet und unter vollständiger Nutzung der für den Compiler entwickelten Technologie entwickelt.

Unterschiede im Erscheinungsbild je nach Blickwinkel, Blickwinkel und Gesichtsfeld

Die Aufteilung von Compiler und Interpreter ändert sich, wenn sich der Kontext wie Ansichtspunkt, Ansichtspunkt und Sichtfeld ändert. Wenn Sie beispielsweise mit dem aktuellen CRuby-Verarbeitungssystem (Ruby-Verarbeitungssystem in C-Sprache) erklären, wird das CRuby-Verarbeitungssystem aus Sicht des Benutzers der Ruby-Sprache als Interpreter erkannt. Dies liegt daran, dass der CRuby-Prozessor die Ruby-Sprache zu interpretieren und auszuführen scheint. Wenn Sie jedoch Ihren Ansichtspunkt innerhalb des CRuby-Verarbeitungssystems verschieben, ändert sich die angezeigte Szenerie. Im CRuby-Verarbeitungssystem wird zuerst der Prozess der Konvertierung der Ruby-Sprache in einen abstrakten Syntaxbaum ausgeführt und dann in den für das CRuby-Verarbeitungssystem eindeutigen Bytecode konvertiert. Danach arbeitet der für das CRuby-Verarbeitungssystem eindeutige Bytecode-Interpreter und führt den generierten Bytecode aus. Auf diese Weise werden, wenn Sie es von innen genauer betrachten, "Übersetzer" ausgeführt, der die Ruby-Sprache in AST konvertiert, und "Compiler im engeren Sinne, der AST in CRuby-Verarbeitungsbytecode konvertiert" und "CRuby-Verarbeitungsbytecode" ausgeführt Sie können sehen, dass der "Interpreter im engeren Sinne" funktioniert. Wenn Sie Ihre Perspektive weiter in den Bytecode-Interpreter verschieben, können Sie auch sehen, dass dort der JIT-Compiler ausgeführt wird [^ 4]. Wenn Sie diesmal Ihren Horizont erweitern, verfügt die Ruby-Sprache auch über ein Verarbeitungssystem namens JRuby, das auf JVM ausgeführt wird. JRuby wird mit einem "Pre-Compiler" (Ahead-Of-Time-Compiler) geliefert, mit dem Sie Ruby-Skripte im Voraus in Java-Bytecode "kompilieren" können.

Um ein Beispiel für Java zu geben, wurde Jshell aus Java 9 eingeführt. Da es sich um eine sogenannte REPL (Read-Eval-Print Loop) handelt, kann sie aus Anwendersicht als ** Interpreter-Verarbeitungssystem ** angesehen werden. Ich werde. Da Java 11 Java-Dateien sofort ausführen konnte, ist dies das korrekte Verhalten des Interpreters, und es ist die Ausführungsmethode, mit der leichte Programmiersprachen wie Ruby bisher gut umgehen konnten.

Auf diese Weise erfahren Programmiersprachen und ihre Verarbeitungssysteme derzeit eine große Entwicklung, Komplexität und Diversifizierung. Infolgedessen sind Interpreter und Compiler verschachtelt, haben eine mehrstufige Struktur und mehrere Verarbeitungssysteme. Daher ist es sehr wichtig, aus welchem Kontext Sie den "Compiler" oder "Interpreter" betrachten. Mit anderen Worten, was Sie als Dolmetscher aus Ihrer eigenen Sicht sehen, kann sich von anderen Sichtweisen unterscheiden. Daher sollten Sie den Kontext genau beachten, wenn Sie darüber sprechen.

[^ 4]: Der JIT-Compiler (experimentell) ist optional in Ruby 2.6 verfügbar.

Zusammenfassung

In diesem Artikel habe ich versucht, den Unterschied zwischen dem Interpreter und dem Compiler mithilfe des Ben-Diagramms zu erklären. Die Zusammenfassung ist wie folgt.

―― „Interpreter“ und „Compiler“ sind die Implementierungsmethoden des Sprachverarbeitungssystems und nicht mit der Programmiersprache verknüpft.

Bens Diagramm organisiert auch moderne Interpreten und Compiler auf rationale und intuitive Weise und respektiert gleichzeitig historische Interpretationen. Die Überlappung der Kreise soll auch ausdrücken, dass die obere Schicht die untere Schicht enthalten kann.

Wir hoffen, dass dieser Artikel Ihnen hilft, Ihre Interpreten und Compiler besser zu verstehen und neue Entdeckungen zu machen.

Verweise

Recommended Posts

Lassen Sie uns den Unterschied zwischen Interpreter und Compiler anhand des Ben-Diagramms erklären
Was ist der Unterschied zwischen einem Webserver und einem Anwendungsserver?
Was ist der Unterschied zwischen einer Aktion und einer Instanzmethode?
Überschreiben wir den Unterschied zwischen == (Identität) und der Methode equals (Äquivalenz).
[Ruby] Beziehung zwischen Elternklasse und Kinderklasse. Beziehung zwischen Klasse und Instanz.
Über den Unterschied zwischen irb und pry
[Java] Verstehe den Unterschied zwischen List und Set
[Rails / Active Record] Über den Unterschied zwischen create und create!
Verstehe den Unterschied zwischen abstrakten Klassen und Schnittstellen!
Was ist der Unterschied zwischen SimpleDateFormat und DateTimeFormatter? ??
Verstehe in 3 Minuten! Eine sehr grobe Erklärung des Unterschieds zwischen Sitzung und Cookie
[Ruby] Ich habe über den Unterschied zwischen each_with_index und each.with_index nachgedacht
[Rails] Ich habe den Unterschied zwischen Ressourcen und Ressourcen untersucht
Was ist der Unterschied zwischen Systemspezifikation und Funktionsspezifikation?
Unterschiede zwischen Klassen und Instanzen in Ruby
[Rails] Was ist der Unterschied zwischen Redirect und Rendering?
Vergleichen Sie den Unterschied zwischen Docker-Datei vor und nach Docker-Slim
[JAVA] Was ist der Unterschied zwischen Schnittstelle und Zusammenfassung? ?? ??
Was ist der Unterschied zwischen Überspringen und Ausstehend? [RSpec]
[Swift] UITextField hat mir den Unterschied zwischen Null und "" beigebracht.
Ich werde den Unterschied zwischen der Entwicklung von Android-Anwendungen und der Entwicklung von iOS-Anwendungen aus der Sicht von iOS-Ingenieuren erläutern
Unterschied zwischen vh und%
Unterschied zwischen i ++ und ++ i
[Rails] Was ist der Unterschied zwischen Bundle-Installation und Bundle-Update?
Unterschied zwischen Java und JavaScript (wie man den Durchschnitt findet)
[Java] Überprüfen Sie den Unterschied zwischen orElse und orElseGet mit IntStream
Der Unterschied zwischen der Programmierung mit Ruby-Klassen und der Programmierung ohne Ruby-Klassen