Ich beschäftige mich intensiv mit den Themen von Übersetzern und Dolmetschern. Ich möchte überprüfen, ob mein Grundverständnis stimmt. Nehmen wir also Folgendes an:
Ich habe eine Sprache namens "Foobish" und ihre Stichwörter sind
<OUTPUT> 'TEXT', <Number_of_Repeats>;
Wenn ich also 10 Mal auf die Konsole drucken möchte, würde ich schreiben
OUTPUT 'Hello World', 10;
Hallo World.foobish-Datei.
Jetzt schreibe ich einen Dolmetscher in der Sprache meiner Wahl - in diesem Fall C #:
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);
}
}
}
}
Auf einer sehr einfachen Dolmetscherebene würde der Dolmetscher die Skriptdatei usw. analysieren und die Fobish-Sprache in der Art und Weise der Implementierung des Dolmetschers ausführen.
Würde ein Compiler eine Maschinensprache erstellen, die direkt auf der physischen Hardware ausgeführt wird?
Ein Interpreter erzeugt also keine Maschinensprache, aber macht ein Compiler dies für seine Eingabe?
Habe ich grundsätzliche Missverständnisse in Bezug auf die Arbeitsweise von Compilern und Dolmetschern?
quelle
Antworten:
Die Begriffe "Interpreter" und "Compiler" sind viel unschärfer als früher. Vor vielen Jahren war es üblich, dass Compiler Maschinencode für eine spätere Ausführung produzierten, während Interpreter den Quellcode mehr oder weniger direkt "ausführten". Also waren diese beiden Begriffe damals gut verstanden.
Aber heute gibt es viele Variationen bei der Verwendung von "Compiler" und "Interpreter". Beispielsweise "kompiliert" VB6 Bytecode (eine Form von Intermediate Language ), der dann von der VB-Runtime "interpretiert" wird. Ein ähnlicher Prozess findet in C # statt, das CIL erzeugt , das dann von einem Just-In-Time-Compiler (JIT) ausgeführt wird , der früher als Interpreter gedacht gewesen wäre. Sie können die Ausgabe des JIT in eine tatsächliche ausführbare Binärdatei "einfrieren", indem Sie NGen.exe verwenden , dessen Produkt früher das Ergebnis eines Compilers gewesen wäre .
Die Antwort auf Ihre Frage ist also bei weitem nicht mehr so einfach wie früher.
Weitere Lesungen
Compiler vs. Dolmetscher auf Wikipedia
quelle
Die folgende Zusammenfassung basiert auf "Compilers, Principles, Techniques, & Tools" von Aho, Lam, Sethi, Ullman (Pearson International Edition, 2007), Seite 1, 2, mit einigen eigenen Ideen.
Die beiden Grundmechanismen zur Abarbeitung eines Programms sind Kompilierung und Interpretation .
Beim Kompilieren wird ein Quellprogramm in einer bestimmten Sprache als Eingabe verwendet und ein Zielprogramm in einer Zielsprache ausgegeben.
Wenn es sich bei der Zielsprache um Maschinencode handelt, kann dieser direkt auf einem bestimmten Prozessor ausgeführt werden:
Beim Kompilieren wird das gesamte Eingabeprogramm (oder Modul) gescannt und übersetzt, ohne dass es ausgeführt wird.
Die Interpretation nimmt das Quellprogramm und seine Eingabe als Eingabe und erzeugt die Ausgabe des Quellprogramms
Bei der Interpretation wird das Programm normalerweise einzeln verarbeitet (analysiert und ausgeführt).
In der Praxis verwenden viele Sprachprozessoren eine Mischung aus beiden Ansätzen. Beispielsweise werden Java-Programme zunächst in ein Zwischenprogramm (Bytecode) übersetzt (kompiliert):
Die Ausgabe dieses Schritts wird dann von einer virtuellen Maschine ausgeführt (interpretiert):
Um die Sache noch komplizierter zu machen, kann die JVM zur Laufzeit eine Just-in-Time-Kompilierung durchführen, um Byte-Code in ein anderes Format zu konvertieren, das dann ausgeführt wird.
Auch wenn Sie in Maschinensprache kompilieren, wird Ihre Binärdatei von einem Interpreter ausgeführt, der vom zugrunde liegenden Prozessor implementiert wird. Daher verwenden Sie auch in diesem Fall eine Mischung aus Kompilierung und Interpretation.
Reale Systeme verwenden also eine Mischung aus beidem. Daher ist es schwierig zu sagen, ob ein bestimmter Sprachprozessor ein Compiler oder ein Interpreter ist, da er wahrscheinlich beide Mechanismen in verschiedenen Phasen seiner Verarbeitung verwendet. In diesem Fall wäre es wahrscheinlich sinnvoller, einen anderen, neutraleren Begriff zu verwenden.
Dennoch sind Kompilierung und Interpretation zwei unterschiedliche Arten der Verarbeitung, wie in den obigen Diagrammen beschrieben.
Um die ersten Fragen zu beantworten.
Nicht unbedingt übersetzt ein Compiler ein Programm, das für eine Maschine M1 geschrieben wurde, in ein äquivalentes Programm, das für eine Maschine M2 geschrieben wurde. Die Zielmaschine kann in Hardware implementiert sein oder eine virtuelle Maschine sein. Konzeptionell gibt es keinen Unterschied. Der wichtige Punkt ist, dass ein Compiler einen Teil des Codes betrachtet und in eine andere Sprache übersetzt, ohne ihn auszuführen.
Wenn Sie durch das Produzieren auf die Ausgabe verweisen, dann erzeugt ein Compiler ein Zielprogramm, das möglicherweise in Maschinensprache verfasst ist, ein Interpreter jedoch nicht.
quelle
defined A && !defined B
.Nein. Ein Compiler ist einfach ein Programm, das ein in Sprache A geschriebenes Programm als Eingabe verwendet und ein semantisch äquivalentes Programm in Sprache B als Ausgabe erzeugt . Sprache B kann alles sein, es muss nicht Maschinensprache sein.
Ein Compiler kann von einer Hochsprache zu einer anderen Hochsprache kompilieren (z. B. GWT, das Java zu ECMAScript kompiliert), von einer Hochsprache zu einer Niedrigsprache kompilieren (z. B. Gambit, das Schema zu C kompiliert). von einer Hochsprache zu Maschinencode (z. B. GCJ, der Java zu systemeigenem Code kompiliert), von einer Niedrigsprache zu einer Hochsprache (z. B. Clue, der C zu Java, Lua, Perl, ECMAScript und Common kompiliert Lisp), von einer einfachen Sprache zu einer anderen einfachen Sprache (z. B. dem Android SDK, das JVML-Bytecode zu Dalvik-Bytecode kompiliert), von einer einfachen Sprache zu Maschinencode (z. B. dem C1X-Compiler, der Teil von HotSpot ist, der JVML-Bytecode in Maschinencode übersetzt), Maschinencode in eine Hochsprache (ein beliebiger sogenannter "Decompiler", auch Emscripten, der LLVM-Maschinencode in ECMAScript übersetzt),Maschinencode in eine einfache Sprache (z. B. der JIT-Compiler in JPC, der nativen x86-Code in JVML-Bytecode kompiliert) und nativer Code in nativen Code (z. B. der JIT-Compiler in PearPC, der nativen PowerPC-Code in nativen x86-Code kompiliert).
Beachten Sie auch, dass "Maschinencode" aus mehreren Gründen ein sehr verschwommener Begriff ist. Beispielsweise gibt es CPUs, die JVM-Bytecode nativ ausführen, und es gibt Software-Interpreter für x86-Maschinencode. Also, was macht einen "nativen Maschinencode" aus, aber nicht den anderen? Außerdem ist jede Sprache Code für eine abstrakte Maschine für diese Sprache.
Es gibt viele spezielle Namen für Compiler, die spezielle Funktionen ausführen. Trotz der Tatsache, dass es sich um spezialisierte Namen handelt, handelt es sich bei allen immer noch um Compiler, nur um spezielle Arten von Compilern:
Nicht unbedingt. Es kann in einem Interpreter oder in einer VM ausgeführt werden. Es könnte weiter in eine andere Sprache übersetzt werden.
Ein Dolmetscher produziert nichts. Es wird nur das Programm ausgeführt.
Ein Compiler erzeugt etwas, aber es muss nicht unbedingt Maschinensprache sein, es kann jede Sprache sein. Es kann sogar die gleiche Sprache wie die Eingabesprache sein! Beispielsweise verfügt Supercompilers, LLC über einen Compiler, der Java als Eingabe und optimiertes Java als Ausgabe verwendet. Es gibt viele ECMAScript-Compiler, die ECMAScript als Eingabe verwenden und optimiertes, minimiertes und verschleiertes ECMAScript als Ausgabe erzeugen.
Das könnte Sie auch interessieren:
quelle
Ich denke, Sie sollten den Begriff "Compiler versus Interpreter" gänzlich streichen, da dies eine falsche Zweiteilung ist.
Das gemeinsame Wort, um eine abstrakte Programmiersprache in der realen Welt nützlich zu machen, ist Implementierung .
In der Vergangenheit bestand eine Programmiersprachenimplementierung häufig nur aus einem Compiler (und der CPU, für die der Code generiert wurde) oder nur aus einem Interpreter. Es sah also so aus, als ob sich diese beiden Arten von Tools gegenseitig ausschließen. Heute kann man deutlich sehen, dass dies nicht der Fall ist (und es war noch nie so). Wenn Sie versuchen, den Namen "Compiler" oder "Interpreter" in eine ausgefeilte Programmiersprache umzuwandeln, führt dies häufig zu nicht eindeutigen oder inkonsistenten Ergebnissen.
Eine einzelne Programmiersprachenimplementierung kann eine beliebige Anzahl von Compilern und Interpreten , häufig in mehreren Formen (eigenständig, im laufenden Betrieb), eine beliebige Anzahl anderer Tools wie statische Analysatoren und Optimierer sowie eine beliebige Anzahl von Schritten umfassen. Es kann sogar vollständige Implementierungen einer beliebigen Anzahl von Zwischensprachen enthalten (die nicht mit der zu implementierenden zusammenhängen können).
Beispiele für Implementierungsschemata sind:
...und so weiter.
quelle
Während die Grenzen zwischen Compilern und Interpreten im Laufe der Zeit verschwommen sind, kann man immer noch eine Grenze zwischen ihnen ziehen, indem man sich die Semantik dessen ansieht, was das Programm tun soll und was der Compiler / Interpreter tut.
Ein Compiler generiert ein anderes Programm (normalerweise in einer niedrigeren Sprache wie Maschinencode), das, wenn dieses Programm ausgeführt wird, das tut, was Ihr Programm tun soll.
Ein Dolmetscher wird tun, was Ihr Programm tun soll.
Mit diesen Definitionen sind die Stellen, an denen es unscharf wird, die Fälle, in denen Ihr Compiler / Interpreter je nach Ihrer Sichtweise unterschiedliche Aktionen ausführen kann. Zum Beispiel nimmt Python Ihren Python-Code und kompiliert ihn in einen kompilierten Python-Bytecode. Wenn dieser Python-Bytecode über einen Python-Bytecode- Interpreter ausgeführt wird , wird das getan, was Ihr Programm tun sollte. In den meisten Situationen denken die Python-Entwickler jedoch, dass beide Schritte in einem großen Schritt ausgeführt werden. Daher wird der CPython- Interpreter als Interpretation des Quellcodes angesehen und die Tatsache, dass er auf diesem Weg kompiliert wurde , wird als Implementierungsdetail angesehen . Auf diese Weise ist alles eine Frage der Perspektive.
quelle
Hier ist eine einfache konzeptionelle Disambiguierung zwischen Compilern und Interpreten.
Betrachten Sie 3 Sprachen: Programmiersprache , P (was das Programm geschrieben ist); Domänensprache D (für das, was mit dem laufenden Programm passiert); und Zielsprache , T (eine dritte Sprache).
Konzeptionell
Ein Compiler übersetzt P in T, so dass Sie T (D) auswerten können. wohingegen
Ein Interpreter wertet P (D) direkt aus.
quelle