Warum gibt es keine automatisierten Übersetzer von einer Programmiersprache in eine andere? [geschlossen]

37

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?

serg
quelle
5
Denken Sie daran, dass "alle Sprachen" auch dumme Sprachen wie Oook! (Turing Vollständigkeit ist nicht die ganze Geschichte; Sie brauchen die syscalls auch in der Praxis.)
Donal Fellows
Dort sind einige. C-zu-Pascal- und Pascal-zu-C-Übersetzer waren an einem Punkt weit verbreitet. Wie die folgenden Antworten zeigen, war die Ausgabe normalerweise nicht so gut lesbar, ohne dass zumindest einige manuelle Eingriffe vorgenommen wurden. Und das sind relativ einfache Sprachen mit relativ einfachen Bibliotheken - es wäre wahrscheinlich unmöglich, die Arbeit für C ++ nach Haskell oder umgekehrt gut zu machen.
Steve314
Testen Sie Roslyn, den .net-Compiler, als Dienst, der C # in VB und umgekehrt übersetzen kann.
Daniel Little
2
Alle Compiler übersetzen eine PL in eine andere, sie garantieren jedoch nicht, dass der Code in der Ziel-PL einfach zu lesen ist
jk.
Nachdem ich die Genauigkeit der Google-Übersetzung gesehen habe, bin ich überzeugt, dass ich in meinem Leben einen universellen Übersetzer sehen werde. Ja, es wird eine herausfordernde Anstrengung sein und möglicherweise enormen Aufwand erfordern, wie im Fall der Analyse einer großen Codebasis wie Github oder Stackoverflow, aber dies wird passieren und die Nachfrage nach einem solchen Tool wird in den kommenden Jahren insbesondere jetzt zunehmen dass es eine gute Anzahl von Programmierern gibt, die AI und ML studieren. Möglicherweise gibt es nicht eine Person, die ein solches Werkzeug allein entwickelt. Man könnte jedoch einen Bot entwickeln, um Bots zu entwickeln, um dieses Problem anzugehen.
Ganesh Kamath - "Code Frenzy"

Antworten:

32

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.

Joeri Sebrechts
quelle
Es sieht so aus, als hätte jemand einen PHP-Java-Übersetzer erstellt und tatsächlich die PHP-Binärdatei eingebettet. Einverstanden, obwohl es Ihren Standpunkt nicht ändert. runtimeconverter.com/single-post/2017/09/15/…
user1122069 15.11.17
20

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:

  1. Der Code ist grundsätzlich nicht lesbar. MSIL (auch mit Debugging-Informationen) entfernt viele Informationen aus der Originalquelle, sodass die übersetzte Version keine 100% ige Wiedergabetreue aufweist (theoretisch sollte eine Konvertierung von C # -> MSIL-> C # den Originalcode zurückgeben, aber es Gewohnheit).
  2. Viele .NET-Sprachen haben ihre eigenen benutzerdefinierten Bibliotheken (z. B. die VB-Laufzeitbibliothek, die F # -Bibliothek usw.). Diese müssen bei der Konvertierung ebenfalls berücksichtigt (oder konvertiert) werden.

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.

Dean Harding
quelle
Viele der Metadaten aus der Originalquelle sind in der MSIL enthalten (einschließlich der XML-Kommentare und der Originalmethode, der Eigenschaften und der Mitgliedsnamen), daher denke ich, dass die Konvertierung nach C # nicht so unlesbar ist, wie Sie es sagen. Versuchen Sie, Teile des .NET-Frameworks zu zerlegen. es ist sehr gut lesbar. Natürlich könnte die Situation bei einer Umwandlung von F # in C # anders sein.
Robert Harvey
@Robert: XML-Kommentare sind nicht in der MSIL enthalten. Wenn Sie beispielsweise nachsehen 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.
Dean Harding
2
Ein Disassembler konvertiert die ausführbare Binärdatei des Computers zurück in einen Assembler für diesen bestimmten Prozessortyp (nicht alle auf der Welt sind x86-Prozessoren). Sie meinen wirklich einen Dekompiler, der den kompilierten Code zur Quelle zurückbringt. Dies ist eine schrecklich schwierige Aufgabe, da jeder Compiler von jedem Hersteller auf jeder Optimierungsstufe die Quellzeilen in eine andere binäre Ausgabeform konvertiert.
22.
20

Ist es zumindest theoretisch möglich, einen 100% korrekten Übersetzer zwischen allen Sprachen zu schreiben? Was sind die Herausforderungen in der Praxis?

  • Das Übersetzen von einer stärker strukturierten Sprache in eine weniger strukturierte Sprache, die noch vollständig ist, ist immer möglich.
    • Diese Behauptung ist rein technisch zu verstehen: Das übersetzte Programm liefert bei der Ausführung genau das gleiche Ergebnis.
    • Über die Lesbarkeit des übersetzten Codes oder die Beibehaltung der ursprünglichen Programmstrukturen wird nichts ausgesagt.
  • Das Übersetzen von einer weniger strukturierten Sprache in eine stärker strukturierte Sprache ist möglich, der übersetzte Code bleibt jedoch in seiner weniger strukturierten Form.
rwong
quelle
1
Du triffst den Nagel auf den Kopf. Lesen Sie den Code aus dem C-Backend von LLVM. Es ist technisch legaler C-Code, aber It Ain't Pretty (TM).
Dsimcha
1
@dsimcha: Lesbarkeit abgesehen davon, dass das C-Backend die Ausgabe so viel einfacher lesbar macht als das Debuggen oder Disassemblieren. Ich bin so froh, dass sie dieses Backend wieder zurückgebracht haben, nachdem es für kurze Zeit nicht mehr gewartet wurde.
JM Becker
10

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 ...

keppla
quelle
1
Gute Antwort. Man könnte hinzufügen, dass, wenn zwei Sprachen genau den gleichen Satz von Merkmalen und Redewendungen hätten, es möglich wäre, eine Sprache ziemlich effizient in eine andere zu übersetzen, aber die meisten Sprachen sind für den Zweck konzipiert, Merkmale und Redewendungen zu unterstützen, die ihrer Meinung nach nicht angemessen sind in anderen Sprachen unterstützt . Die mechanische Übersetzung von wartbarem Code ist manchmal praktikabel, wenn die Merkmale und Redewendungen in der Zielsprache eine Obermenge der in der Ausgangssprache sind, aber solche Situationen sind nicht besonders häufig.
Supercat
6

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.

Jerry Sarg
quelle
5

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 .

dsimcha
quelle
4

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.

scrwtp
quelle
Könnten Sie einige dieser Gruppen nennen?
Qwertie
4

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!

alexis
quelle
3

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:

  1. Wenn das Programm trivial ist, erhalten Sie möglicherweise ein anständiges Ergebnis. Aber wenn es so einfach ist, wozu ist es dann überhaupt sinnvoll, einen Übersetzer zu durchsuchen?
  2. Wenn das Programm nicht trivial ist, ist der Code von geringer Qualität.

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.

Maxpm
quelle
Ihre Analogie würde dann auch für die normale Kompilierung gelten, und wir wissen empirisch, dass dies nicht der Fall ist! Computer generieren (nicht schreiben) Code von guter Qualität. Was sie oft schlecht machen, ist die Lesbarkeit / Wartbarkeit. Wenn jemand einen solchen Prozess brauchte, den mir die Leute gelegentlich glauben, sind keine Probleme Showstopper. Wenn dem so ist, war die Übersetzung natürlich ursprünglich nie wichtig.
JM Becker
1

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.

indyK1ng
quelle
Ich denke, es gibt keine Notwendigkeit, vorhandene Bibliotheken zu kennen, es kann nur Bibliotheken übersetzen, wie es geht (vorausgesetzt, sie haben Quellen zur Verfügung).
Serg
1
Das erhöht dann tatsächlich die Komplexität des zweiten Problems. Vorausgesetzt, Sie haben Zugriff auf den Quellcode, um ihn zu übersetzen. So oder so ist es immer noch ziemlich undurchführbar.
indyK1ng
+1 Punkt über libs ist absolut gültig und es gibt IMMER libs.
Dan Rosenstark
1

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.

mike30
quelle