Die meisten Programmiersprachen sind Turing-vollständig, was bedeutet, dass jede Aufgabe, die in einer Sprache gelöst werden kann, in einer anderen oder sogar auf einem Turing-Computer gelöst werden kann. Warum gibt es dann keine automatischen Übersetzer, die Programme aus einer bestimmten Sprache in eine andere Sprache konvertieren können? Ich habe einige Versuche für zwei Sprachen gesehen, aber sie funktionieren immer nur mit einer begrenzten Teilmenge einer Sprache und können kaum für die Konvertierung realer Projekte verwendet werden.
Ist es zumindest theoretisch möglich, einen 100% korrekten Übersetzer zwischen allen Sprachen zu schreiben? Was sind die Herausforderungen in der Praxis? Gibt es Übersetzer, die arbeiten?
Antworten:
Das größte Problem ist nicht die eigentliche Übersetzung des Programmcodes, sondern die Portierung der Plattform-API.
Betrachten Sie einen PHP-Java-Übersetzer. Die einzige Möglichkeit, dies zu tun, ohne einen Teil der PHP-Binärdatei einzubetten, besteht darin, alle PHP-Module und -APIs in Java neu zu implementieren. Dies beinhaltet die Implementierung von über 10.000 Funktionen. Im Vergleich dazu ist die eigentliche Übersetzung der Syntax kinderleicht. Und selbst nach all dieser Arbeit hätten Sie keinen Java-Code, sondern eine Art Monstrosität, die zufällig auf der Java-Plattform ausgeführt wird, die aber innen wie PHP strukturiert war.
Aus diesem Grund kommen nur solche Tools in den Sinn, bei denen es darum geht, Code zu übersetzen, um ihn bereitzustellen, und nicht, um ihn anschließend zu warten. Googles GWT "kompiliert" Java in JavaScript. Facebooks HipHop kompiliert PHP in C.
quelle
Wenn Sie ein Zwischenformat haben, können Sie etwas implementieren, das ein Programm in Sprache X in dieses Format und von diesem Format in Sprache Y übersetzt. Implementieren Sie diese Konvertierungen für alle Sprachen, die Sie interessieren, und Sie sind fertig.
Weißt du was? Ein solches Format gibt es bereits: Assembly. Der Compiler führt bereits die Konvertierung "Language X to Assembly" und die Disassemblierung der Konvertierung "Assembly to Language Y" durch.
Assembler ist keine so gute Sprache für die umgekehrte Konvertierung, aber MSIL ist eigentlich nicht so schlecht. Laden Sie Reflector herunter und Sie werden sehen, dass Sie eine .NET-Assembly in eine Reihe verschiedener Sprachen zerlegen können (und Plugins bieten noch mehr). Es ist also durchaus möglich, ein Programm in C # zu nehmen, es in eine DLL (dh MSIL) zu kompilieren und es dann mit Reflector in VB, C ++ / CLI, F # und eine ganze Reihe anderer zu zerlegen. Natürlich funktionieren auch alle anderen Umbauten. Nehmen Sie eine F # -Datei, kompilieren Sie sie in eine DLL und konvertieren Sie sie mit Reflector in C #.
Die zwei großen Probleme, die Sie finden werden, sind natürlich:
Es gibt wirklich nichts um # 2 herum, aber Sie könnten wahrscheinlich mit einigen zusätzlichen Annotationen in der MSIL (über Attribute, vielleicht) um # 1 herumkommen. Das wäre natürlich zusätzliche Arbeit.
quelle
Microsoft.NET\Framework\v2.0.50727\en
, können Sie die gesamte XML-Dokumentation für die Systembibliotheken anzeigen. Dies ist, was Reflector (et al.) Verwendet, um die Kommentare anzuzeigen. Die Konvertierung ist nicht unlesbar. Ich habe nur gesagt, dass es keine 100% ige Treue ist, die Sie von einer Übersetzung auf Quellenebene erwarten können.quelle
Warum sollten Sie ein Programm konvertieren wollen?
Beide Sprachen, die Quell- und die Zielsprache, werden sowieso zu (virtuellem) Maschinencode kompiliert *, sodass aus technischen Gründen kein Compiler für eine andere Hochsprache erforderlich ist.
Sprachen sind für Menschen. Die implizite Anforderung für Ihre Frage lautet also: 'Warum gibt es keinen Übersetzer, der lesbaren Code generiert ? ' Und die Antwort lautet (imho): Wenn es zwei Sprachen gibt, die sich ausreichend unterscheiden, werden die Arten des 'lesbaren Codes' geschrieben unterscheidet sich in einer Weise, die nicht nur die Übersetzung der Algorithmen erfordert, sondern unterschiedliche Algorithmen verwendet.
Vergleichen Sie beispielsweise eine typische Iteration in C und eine in Lisp. Oder Pythons 'one best way' mit idiomatischem Rubin.
Hier tauchen die gleichen Probleme auf, die Sie in echten Sprachen haben: Sie übersetzen "Es regnet Katzen und Hunde" in etwas mit der Bedeutung "Es strömt wie aus Eimern", wenn Sie vom Englischen ins Deutsche übersetzen, das können Sie nicht übersetze Wort für Wort, aber du musst nach der Bedeutung suchen.
Und 'Sinn' ist kein einfaches Konzept, an dem man arbeiten kann.
*) na ja, es gibt coffeescript ...
quelle
Es ist theoretisch möglich, aber meistens unbrauchbar. Fast jede Kombination von Quell- und Zielsprache ist möglich, aber in den meisten Fällen möchte niemand das Ergebnis sehen oder verwenden.
Eine ganze Reihe von Compilern zielt auf C ab, einfach weil C-Compiler für nahezu jede vorhandene Plattform verfügbar sind (und es gibt automatische Compiler-Generatoren, mit denen Sie einen Prozessor entwerfen und automatisch einen C-Compiler generieren können, der auf Ihren neuen Prozessor abzielt). Natürlich gibt es auch eine ganze Reihe von Implementierungen, die auf die von verschiedenen virtuellen Maschinen wie .NET, JVM, C-- und LLVM verwendeten Sprachen abzielen.
Der entscheidende Punkt ist jedoch, dass es nur dann wirklich nützlich ist, wenn Sie das Ziel als eine Assemblersprache behandeln, die nur als Schritt im Kompilierungsprozess verwendet wird. Insbesondere möchten Sie im Allgemeinen nicht, dass ein normaler Programmierer dieses Ergebnis liest oder damit arbeitet. es ist normalerweise nicht gut lesbar.
quelle
FWIW, es gibt einen Übersetzer von Java nach D. Er heißt TioPort und wurde in einem ziemlich ernsthaften Versuch verwendet, SWT nach D zu portieren. Das Hauptproblem, auf das er gestoßen ist, war, dass es notwendig gewesen wäre, massive Teile der Java-Standardbibliothek zu portieren .
quelle
Während es sich nicht um eine Code-Übersetzung an sich handelt, zeigt das Konzept der Sprach-Workbenches , wie so etwas wie ein 100% korrekter Übersetzer zwischen allen Sprachen implementiert werden kann.
In unserem derzeitigen Ansatz wird der Quellcode in einem Textformat gespeichert. Während der Kompilierung werden diese lesbaren Textdateien in einer abstrakten Syntaxbaumdarstellung analysiert, die wiederum zum Generieren von Bytecode oder Maschinencode verwendet wird. Diese abstrakte Darstellung ist jedoch temporär und für den Compiler intern.
Beim Ansatz der Language Workbench ist eine ähnliche abstrakte Syntaxbaumdarstellung das permanente, gespeicherte Artefakt. Basierend auf dieser abstrakten Darstellung werden sowohl der Maschinencode als auch der Text-Quellcode generiert. Eine der Konsequenzen einer solchen Methode besteht darin, dass die abstrakte Darstellung des Programms tatsächlich sprachunabhängig ist und zum Generieren von Textcode in jeder implementierten Sprache verwendet werden kann. Das bedeutet, dass eine Person frei an verschiedenen Aspekten des Systems mit der Sprache arbeiten kann, die sie als am besten geeignet erachtet, oder dass jedes Mitglied des Teams an dem freigegebenen Projekt in der Sprache arbeiten kann, mit der sie am besten vertraut ist.
Soweit mir bekannt ist, ist die Technologie noch lange nicht für die Mainstream-Entwicklung geeignet, es arbeiten jedoch mehrere Gruppen unabhängig voneinander daran. Es ist schwer zu sagen, ob einer von ihnen seine Versprechen einhält, aber es wäre interessant, dies zu sehen.
quelle
Es gibt einige automatische Übersetzer. Wenn Sie kompilierbaren Code anstelle von lesbarem Code erstellen möchten, ist dies durchaus möglich und gelegentlich nützlich, nur nicht sehr häufig. Bekanntlich war der erste C ++ - Compiler eigentlich kein Compiler, sondern übersetzte C ++ in eine (wirklich komplizierte) C-Quelle, die dann vom C-Compiler kompiliert wurde. Viele Compiler können Assembler-Code auf Anfrage generieren. Anstatt jedoch Assembler-Text auszuspucken und ihn dann in Maschinencode zu übersetzen, können sie normalerweise Maschinencode direkt generieren.
Bei einer vollständigen Spezifikation von Sprache A ist es im Prinzip nicht so schwer, ein Programm zu schreiben, das seine Anweisungen in einer Sprache B ausdrückt. Aber normalerweise wählt jeder, der sich die Mühe macht, etwas wirklich Niedriges für "Sprache B": Maschinencode , oder heutzutage Bytecode: Jython ist eine Implementierung von Python, die Java-Bytecode generiert, der von der Java-VM interpretiert wird. Sie müssen keine Java-Klassenhierarchien ausschreiben und kompilieren!
quelle
Dies geschieht die ganze Zeit.
Jeder Compiler übersetzt die "Primärsprache" wie C ++ in die native Assemblersprache der Maschine oder den architekturunabhängigen Bytecode bei interpretierten Sprachen.
Ich stelle mir aber vor, dass du nicht darüber sprichst. Sie möchten wahrscheinlich einen Übersetzer, der C ++ in etwas wie Java oder Python konvertiert. Was ist der Sinn davon? Bestenfalls hat das Endergebnis die exakt gleiche Effizienz wie die ursprüngliche Quelle. (Praktisch wird es viel schlimmer sein.)
Wenn Code nur übersetzt werden soll, damit Sie ihn als eine Sprache lesen können, die Sie verstehen, würde ein solcher Übersetzer das Gegenteil des gewünschten Effekts bewirken. Sie werden mit einer Menge kryptischen, unintuitiven und unlesbaren Codes zurückgelassen.
Dies liegt daran, dass nur die einfachsten Dinge direkt von einer Sprache in eine andere übersetzt werden. Oft erfordert das, was in einer Sprache einfach ist, massive Bibliotheken für eine andere - oder ist überhaupt unmöglich. Deshalb:
Am Ende besteht die einzige Möglichkeit, guten Code zu schreiben, darin, ihn tatsächlich zu schreiben. Computer können - zumindest noch nicht - Menschen in Bezug auf Lesbarkeit, Best Practices und elegante Lösungen einfach nicht vergleichen.
Kurz gesagt, es lohnt sich einfach nicht.
quelle
Es gibt keine Sprachübersetzer für Programmiersprachen, da die Programmiersprachen unglaublich komplex sind. Obwohl dies hypothetisch möglich ist, gibt es viele Herausforderungen.
Die erste Herausforderung liegt lediglich in den akzeptablen Praktiken der Sprache. Das Konvertieren zwischen zwei objektorientierten Sprachen wie Java und C ++ ist unglaublich komplex und beide basieren auf C. Das Übersetzerprogramm muss die Standardbibliotheken für beide Sprachen perfekt kennen und die Unterschiede im Verhalten kennen. Sie müssten ein umfangreiches Wörterbuch erstellen, und selbst dann würden die Unterschiede in den Programmierstilen von Programmierer zu Programmierer bedeuten, dass Sie raten müssten, wie einige Änderungen vorgenommen werden sollen.
Sobald Sie die Syntaxübersetzung abgeschlossen haben, müssen Sie herausfinden, wie Sie ein Konstrukt in der ersten Sprache in ein Konstrukt in der zweiten Sprache konvertieren. Dies ist in Ordnung, wenn Sie ein Objekt in C ++ in ein Objekt in Java umwandeln (das ist vergleichsweise einfach), aber was machen Sie mit Ihren C ++ - Strukturen? Oder die Funktionen außerhalb der C ++ - Klassen? Die Entscheidung, wie damit umgegangen werden soll, kann schwierig sein, da dies zu einem anderen Problem führen kann, nämlich der Erstellung eines Blob-Objekts. Der Blob ist ein Antimuster, das häufig genug ist.
Dies ist keine vollständige Liste der Probleme, aber dies sind nur zwei und sie sind große Probleme. Einer meiner Professoren erwähnte, dass jemand seinen Arbeitgeber davon überzeugt habe, dass er in den 80er Jahren einen von Maschinencode auf C umstellen könne, aber das hat dann nicht funktioniert. Ich bezweifle, dass es jemals einen geben wird, der vollständig funktioniert.
quelle
Der Zweck des Kompilierens besteht darin, etwas Nützliches für den Computer zu erhalten. dh etwas, das laufen kann. Warum zu etwas kompilieren, das möglicherweise sogar höher ist als das, in dem Sie es geschrieben haben?
Ich mag die Strategie von .NET besser. Kompilieren Sie alles in eine gemeinsame Sprache. Dies bietet den Vorteil, dass die Sprachen kommunizieren können, ohne (N ^ 2) -N sprachübergreifende Compiler erstellen zu müssen.
Wenn Sie beispielsweise 10 Programmiersprachen hätten, müssten Sie nur 10 Compiler unter dem .NET-Modell schreiben, und sie könnten alle miteinander kommunizieren. Wenn Sie alle möglichen sprachübergreifenden Compiler erstellt hätten, müssten Sie 90 Compiler schreiben. Das ist viel zusätzliche Arbeit für wenig Nutzen.
quelle