Ein Polyglot ist ein Programm, das in zwei oder mehr verschiedenen Programmiersprachen ausgeführt werden kann.
Welche allgemeinen Tipps haben Sie für die Erstellung von Polyglots oder für die Auswahl von Sprachen, mit denen Polyglots für eine bestimmte Aufgabe leicht geschrieben werden können?
Bitte posten Sie die Tipps, die in den meisten Situationen angewendet werden könnten. Das heißt, sie sollten nicht nur in Polyglots zweier spezifischer Sprachen arbeiten. (Sie können einfach eine Antwort auf eine Polyglot-Frage posten, wenn Sie einen zu spezifischen Tipp haben.) Sie können jedoch Funktionen einer Sprache einführen, die das Arbeiten mit vielen Sprachen erleichtern oder das Hinzufügen zu vorhandenen Polyglots erleichtern.
Bitte posten Sie einen Tipp pro Antwort. Sie können auch eine Bearbeitung vorschlagen, wenn ein sprachspezifischer Tipp auch für eine andere Sprache gilt.
Teilen und erobern
Wenn Sie einen Polyglot in einer großen Anzahl von Sprachen schreiben, können Sie nicht unbedingt alle Kontrollflüsse der Sprache sofort voneinander trennen. Daher müssen Sie einige der Sprachen für eine gewisse Zeitspanne "polyglot" machen, damit in allen Sprachen derselbe Code ausgeführt werden kann. Dabei sind zwei Hauptregeln zu beachten:
Der Kontrollfluss in zwei beliebigen Sprachen sollte entweder sehr ähnlich oder sehr unterschiedlich sein . Der Versuch, eine große Anzahl von verschachtelten Kontrollabläufen zu verarbeiten, ist ein Rezept, das Verwirrung stiftet und es schwierig macht, Ihr Programm zu ändern. Stattdessen sollten Sie den Arbeitsaufwand begrenzen, indem Sie sicherstellen, dass alle Programme, die sich am selben Ort befinden, aus demselben Grund vorhanden sind und problemlos so lange parallel ausgeführt werden können, wie Sie dies benötigen. Wenn sich eine Sprache von den anderen stark unterscheidet, soll ihre Ausführung so schnell wie möglich an einen anderen Ort verschoben werden, damit Sie nicht versuchen müssen, Ihren Code gleichzeitig an zwei verschiedene syntaktische Modelle anzupassen.
Suchen Sie nach Möglichkeiten, eine Sprache oder eine Gruppe ähnlicher Sprachen voneinander zu trennen. Arbeiten Sie von größeren Gruppen bis hin zu kleineren Gruppen. Sobald Sie eine Gruppe ähnlicher Sprachen an einem bestimmten Punkt im Programm haben, müssen Sie sie irgendwann aufteilen. Zu Beginn des Programms können Sie beispielsweise die Sprachen, die
#
als Kommentarmarker verwendet werden, von Sprachen trennen, die andere Kommentarmarker verwenden. Vielleicht haben Sie später einen Punkt, an dem alle Sprachenf(x)
Syntax für Funktionsaufrufe verwenden, Befehle mit Semikolons trennen und ähnliche syntaktische Ähnlichkeiten aufweisen. Zu diesem Zeitpunkt könnten Sie etwas viel Sprachspezifischeres verwenden, um sie zu teilen, z. B. die Tatsache, dass Ruby und Perl keine Escape-Sequenzen in''
Strings verarbeiten, aber Python und JavaScript.Im Allgemeinen sollte der logische Ablauf Ihres Programms als Baum enden und sich wiederholt in Gruppen von Sprachen aufteilen, die einander ähnlicher sind. Dies erschwert es meistens, den Polyglot gleich zu Beginn vor dem ersten Split zu schreiben. Je mehr sich der Steuerungsfluss verzweigt und die Sprachen, die zu einem bestimmten Zeitpunkt ausgeführt werden, immer ähnlicher werden, desto einfacher wird Ihre Aufgabe, da Sie eine erweiterte Syntax verwenden können, ohne dass die beteiligten Sprachen zu Syntaxfehlern führen.
Ein gutes Beispiel ist die Menge {JavaScript, Ruby, Perl, Python 3}; Alle diese Sprachen akzeptieren Funktionsaufrufe in Klammern und können Anweisungen durch Semikolons trennen. Sie alle unterstützen auch eine
eval
Anweisung, mit der Sie den Datenfluss auf tragbare Weise steuern können. (Perl ist die beste dieser Sprachen, um sich frühzeitig von der Gruppe abzuspalten, da es eine andere Syntax für Variablen als die anderen hat.)quelle
Code in String-Literalen ausblenden
In den meisten Sprachen führt ein String-Literal alleine entweder nichts aus oder führt etwas aus, das leicht rückgängig gemacht werden kann (z. B. das Aufschieben des Strings auf den Stapel). Die Syntax von Zeichenfolgenliteralen ist ebenfalls relativ unstandardisiert, insbesondere für die alternativen Syntaxen, die viele Sprachen verwenden, um Zeichenfolgen mit eingebetteten Zeilenumbrüchen zu verarbeiten. Zum Beispiel hat Python
""" ... """
, Perlq( ... )
und Lua[[ ... ]]
.Es gibt zwei Hauptverwendungen von diesen. Zum einen können Sie Abschnitte, die für verschiedene Sprachen bestimmt sind, verschachteln, indem Sie einen String am Ende des ersten Abschnitts einer Sprache beginnen und am Anfang des zweiten Abschnitts fortsetzen: Es sollte ziemlich einfach sein, das versehentliche Schließen des Strings aufgrund der Vielfalt von zu vermeiden Zeichenkettenbegrenzer zwischen verschiedenen Sprachen. Das andere ist, dass viele Zeichenfolgenbegrenzer als Befehl in anderen Sprachen von Bedeutung sind (oftmals mehr als Kommentarmarkierungen), sodass Sie so etwas wie
x = [[4] ]
eine harmlose Zuweisung in Sprachen ausführen können, die die JSON-Notation für Listen verwenden, die jedoch gestartet werden eine Zeichenfolge in Lua (und ermöglicht es Ihnen somit, den Lua-Code vom Rest zu trennen, vorausgesetzt, er "springt" effektiv zum nächsten]]
).quelle
Programm beenden
Sie können das Programm abrupt in einer Sprache beenden, sodass der Code in einer anderen Sprache ignoriert wird.
Grundsätzlich kann also dieses Format verwendet werden
Wo
end_program_in_languageN
ist der Befehl zum Beenden des Programms.Zum Beispiel in meiner Antwort in Was bringst du zum Erntedankfest? Ich beendete das Programm in Dip und schrieb dann Code für eine andere Sprache, V, damit der Dip-Interpreter ihn ignorierte.
Aber dann haben nicht alle Sprachen einen Befehl, der das Programm einfach so beenden kann. Wenn jedoch eine solche Sprache die Funktion hat, sollte sie mit Bedacht verwendet werden.
Wie von @LuisMendo vorgeschlagen, können Sie einen Fehler erstellen (sofern dies zulässig ist), um das Programm zu beenden, wenn in der Sprache noch kein "Programm beenden" integriert ist.
quelle
Variable oder Code in String-Literalen
Literale in doppelten Anführungszeichen sind in vielen Sprachen meist harmlos. In einigen Sprachen können sie jedoch auch Code enthalten.
In Bash können Sie Folgendes verwenden
`...`
(es beendet das Programm nicht):In Tcl können Sie Folgendes verwenden
[...]
:In PHP können Sie Folgendes verwenden
${...}
(dies erzeugt einen Fehler in Bash, der nach dem Bash-Code angezeigt werden muss):In Ruby können Sie Folgendes verwenden
#{...}
:Es könnte auch andere geben.
Diese Grammatiken sind nicht kompatibel. Das heißt, Sie können den gesamten Code dieser Sprachen in einer Zeichenfolge an einem harmlosen Ort ablegen. Und es wird einfach den nicht erkannten Code in anderen Sprachen ignorieren und sie als Zeichenfolgeninhalt interpretieren.
In vielen Fällen können Sie dort auch leicht ein doppeltes Anführungszeichen auskommentieren und einen traditionelleren Polyglot erstellen.
quelle
Variables Aliasing
Dies ist wahrscheinlich einer der bislang einfachsten (IMO) wichtigsten Tricks, zumal er so viele Sprachen erreichen kann.
Beispiel:
Dies funktioniert nicht nur in Javascript, sondern auch in Python, Ruby usw. Weitere Beispiele später, wenn ich an andere denke. Kommentarvorschläge / Nachbearbeitungen sind natürlich willkommen.
quelle
alert
fürprint
Python normalerweise kürzer ist (nur 3), da die Kommentarsyntax von JS//
problemlos in ein Python-Programm eingearbeitet werden kann, während Pythons#
nicht in JS eingearbeitet werden kann.#
-basierte KommentareDieser Tipp ist eine Teilmenge der Exploit-Kommentarsymbole und Blockquotes in mindestens einer Sprache
Bei der Erstellung von mehrsprachigen Polyglots, insbesondere produktionsfertigen Sprachen im Gegensatz zu Esolangs, kann es hilfreich sein, die Sprachen zu betrachten, die
#
in Block- oder einzeiligen Kommentaren verwendet werden.#
, und die folgenden Zeichen sind sehr unterschiedlich#
.#
als Zeilenkommentar, was bedeutet, dass etwas, das einen Blockkommentar in einer Sprache beginnen könnte, nur ein gewöhnlicher Kommentar in einer anderen Sprache ist, was das Einfügen erleichtert.Hier ist eine kurze zusammenfassende Liste der Sprachen, die
#
in einem Blockkommentar verwendet werden (nicht erschöpfend):Weitere Beispiele finden Sie unter Rosetta-Code .
Hier ist ein schnelles und einfaches Beispiel als Demonstration:
quelle
#- ... -#
.Arithmetische Operatordifferenzen
Bei ähnlichen Sprachen oder einfachen Polyglotten ist es manchmal nützlich, nach Unterschieden in der Rechenleistung der Sprachen zu suchen. Dies liegt daran, dass die meisten (nicht-esoterischen) Sprachen Infix-Arithmetikoperatoren haben und Arithmetik eine schnelle und einfache Möglichkeit ist, einen Unterschied einzuführen.
Zum Beispiel:
^
ist bitweises XOR in einigen Sprachen und Potenzierung in anderen/
ist in einigen Sprachen eine Ganzzahldivision und in anderen eine Gleitkommadivision-1/2
ist-1
in einigen Sprachen (abgerundet) und0
in anderen (auf Null gerundet)-1%2
ist-1
in einigen Sprachen und1
in anderen--x
ist in einigen Sprachen ein No-Op (doppelte Verneinung) und in anderen ein Pre-Decrement1/0
gibt Unendlichkeit in einigen Sprachen und Fehler in anderen1<<64
gibt 0 in einigen Sprachen (Überlauf) und36893488147419103232
in anderenquelle
x=1;["JS","Python"][--x]
, das den Namen der Sprache zurückgibt, in der es ausgeführt wird (zwischen JS und Python).Benutze Brainfuck
So ziemlich alle BF-Implementierungen werfen Zeichen aus, die nicht
+-<>[].,
zu unseren Gunsten sind.Aufgrund dieser Funktion ist BF wahrscheinlich eine der am einfachsten zu bearbeitenden Sprachen, sofern Sie zuerst den BF-Teil schreiben. Sobald Sie Ihren BF Code geschrieben haben , aus, es ist nur eine Frage der Modellierung , was andere Code , den Sie haben rund um die BF - Struktur.
Hier ist ein wirklich einfaches Beispiel:
Dies erhöht und gibt den Zeichencode "für immer" aus (abhängig von den Laufzeiteinstellungen). Wenn Sie nun einen zufälligen Code schreiben möchten, z. B. in JS, können Sie Folgendes tun:
Beachten Sie, wie der JS um den BF geformt ist.
Stellen Sie sicher, dass dies am besten funktioniert, wenn Sie wirklich darauf eingestellt sind, mit BF zu beginnen. Es ist anständig schwieriger, mit einer anderen Sprache zu beginnen und zu versuchen, BF zu integrieren.
quelle
[]
wie nötig einwickeln .x=>
ändert die Zelle, was in diesem Fall nicht wichtig ist, sondern nur sagen wollteVerwenden Sie Sprachen, in denen die meisten Zeichen keine Rolle spielen
Dies ist eine Verallgemeinerung des Punktes von Mama Fun Roll über BF . Ein Esolang, der die meisten Zeichen ignoriert, ist in Polyglots sehr nützlich. Ebenfalls nützlich: ein Esolang, in dem eine große Anzahl von Zeichen austauschbar ist. Einige Beispiele:
()[]{}<>
. (@
Verursacht manchmal einen Fehler, wenn der Interpreter versucht, ihn als Start eines Debug-Flags zu analysieren.)quelle
@
Fehler behoben .exec('''...\t\n\40''')
Beachten Sie verschachtelte Blockkommentare
Manchmal verwenden mehrere Sprachen dieselbe Syntax für Blockkommentare. Dies ist häufig ein Deal Breaker für die Erstellung eines Polyglots mit den beiden Sprachen. In seltenen Fällen erlaubt eine der Sprachen jedoch verschachtelte Blockkommentare, die zum Erstellen separater Codepfade missbraucht werden können.
Betrachten Sie zum Beispiel diesen Polyglot:
Nim und Lily verwenden
#[
und]#
, um Blockkommentare zu beginnen und zu beenden, aber nur Nim erlaubt verschachtelte Blockkommentare.Lily betrachtet den zweiten
#[
als Teil des einzelnen Blockkommentars und den ersten]#
als Abschluss des Blockkommentars. (Die#
folgende Print-Anweisung von Lily ist ein Zeilenkommentar, der Nims Code verbirgt.)Nim sieht den alternativ
#[]#
als verschachtelten (wenn auch leeren) Blockkommentar undprint("Lily")#
als äußeren Blockkommentar.quelle
Ich bin mir nicht sicher, ob das zählt, aber ...
Verwandle alles mit einer Shebang-Linie in ein gültiges
perl
ProgrammNach dieser Antwort und der Perl - Dokumentation, wenn Sie eine Datei übergeben , dass beginnt mit einer Shebang - Zeile zu
perl
, ruft sie das entsprechende Programm, um sie auszuführen. Zum Beispiel dieswird vom Python-Interpreter ausgeführt, wenn Sie anrufen
perl filename.py
.quelle
perl
, wird es nicht zu einem Perl-Programm.perl
"? Klingt nach einem guten Philosoraptor Meme ...Rufen Sie nicht vorhandene Funktionen auf und beenden Sie sie, während Sie ihre Argumente auswerten
Viele Programmiersprachen können einen beliebigen Bezeichner gefolgt von einem Klammerpaar mit einem Ausdruck darin analysieren:
Manchmal kann die Form der fraglichen Kennung festgelegt werden, da Code für eine andere Sprache benötigt wird, die Sie verwenden. Dies kann zunächst zu Problemen führen, wenn der Bezeichner keiner Funktion entspricht, die die Sprache tatsächlich hat.
In vielen Programmiersprachen werden jedoch die Argumente einer Funktion ausgewertet, bevor sie prüfen, ob die Funktion tatsächlich vorhanden ist (z. B. Lua). Sie können diese Art von Konstrukt also trotzdem verwenden. Alles, was Sie brauchen, ist, das Programm irgendwo innerhalb der Argumente der Funktion zu beenden.
Hier ist ein Beispiel für einen DC / Lua-Polyglot:
c2pq
ist ein DC-Programm zum Drucken und Beenden von 2; Lua sieht dies als den Namen einer Funktion an, aber es kann verhindert werden, dass Lua einen Fehler macht, indem ein Exit-Befehl in das Argument eingefügt wird. Der große Vorteil dieser Konstruktion ist, dass sie im Gegensatz zu einer Anweisung (c2pq =
) nicht automatisch mit Sprachen inkompatibel ist, in denen Variablennamen mit einem Siegel beginnen. Die Syntax von Funktionsnamen ist in allen Sprachen einheitlicher als die von Variablennamen.quelle