Sie müssen einen Dolmetscher für eine coole Sprache namens Huhn schreiben !
Sie sollten ein Chicken-Programm aus einer Datei, Standardeingaben, Programm- oder Funktionsargumenten oder was auch immer für Ihre Sprache am bequemsten ist, sowie aus Eingaben in das Programm lesen.
Sie sollten das Ergebnis der Interpretation des Programms gemäß der Chicken-Sprachspezifikation ausdrucken oder zurückgeben.
Weitere Beschreibung der Sprache .
Hühnchen-Programmübersicht
Chicken arbeitet mit einem einzigen Stapel, der sein gesamtes Speichermodell zusammensetzt. Während der Ausführung von Anweisungen werden vom Programm Werte aus dem Stapel verschoben und entfernt. Es gibt jedoch auch Anweisungen, mit denen das Programm andere Teile des Stapels nach Belieben ändern kann.
Der Stapel enthält drei Segmente:
- Die Register bei den Indizes 0 und 1. Index 0 ist eine Referenz auf den Stapel selbst, und Index 1 ist eine Referenz auf die Benutzereingabe. Wird meistens für Anweisung 6 verwendet (siehe unten).
- Der geladene Code: Für jede Codezeile befindet sich in diesem Segment eine Zelle, die die Anzahl der "Hühner" in der Zeile enthält. Dies wird am Ende mit einer 0 (Opcode zum Beenden des Programms) aufgefüllt.
- Der eigentliche Programmstapel, in dem Werte während der Programmausführung verschoben / verschoben werden. Beachten Sie, dass die Segmente nicht isoliert sind. Dies bedeutet, dass es möglich ist, selbstmodifizierenden Code zu erstellen oder Code aus diesem Segment des Stapelbereichs auszuführen.
Das Huhn ISA
Der Befehlssatz von Chicken basiert auf der Häufigkeit, mit der das Wort "Huhn" in jeder Programmzeile erscheint. Eine leere Zeile beendet das Programm und gibt den obersten Wert im Stapel aus.
Der Hühnchen-Befehlssatz nach Anzahl der "Hühnchen" pro Zeile:
- Schieben Sie die wörtliche Zeichenfolge "Huhn" auf den Stapel
- Fügen Sie die beiden obersten Stapelwerte als natürliche Zahlen hinzu und geben Sie das Ergebnis an.
- Subtrahieren Sie die beiden obersten Werte als natürliche Zahlen und geben Sie das Ergebnis ein.
- Multiplizieren Sie die beiden obersten Werte als natürliche Zahlen und geben Sie das Ergebnis an.
- Vergleichen Sie zwei Spitzenwerte für Gleichheit, drücken Sie 1, wenn sie gleich sind, und 0, wenn dies nicht der Fall ist.
- Sehen Sie sich die nächste Anweisung an, um festzustellen, von welcher Quelle geladen werden soll: 0 Ladevorgänge vom Stapel, 1 Ladevorgänge von Benutzereingaben. Die Oberseite des Stapels zeigt auf die Adresse / den Index, die bzw. der aus der angegebenen Quelle geladen werden soll. Laden Sie diesen Wert und schieben Sie ihn auf den Stapel. Da dies ein doppelt breiter Befehl ist, überspringt der Befehlszeiger den Befehl, der zum Bestimmen der Quelle verwendet wird.
- Die Oberseite des Stapels zeigt auf die Adresse / den Index, in der / dem gespeichert werden soll. Der darunter liegende Wert wird abgelegt und im angegebenen Index im Stapel gespeichert.
- Die Oberseite des Stapels ist ein relativer Versatz, zu dem gesprungen werden kann. Wenn der Wert darunter wahr ist, springt das Programm um den Offset.
- Interpretiert die Oberseite des Stapels als ASCII und drückt das entsprechende Zeichen.
- (10 + N) Schiebt die Literalzahl n-10 auf den Stapel.
Beispiel
Angenommen, das Programm ist:
chicken chicken chicken chicken chicken chicken chicken chicken chicken chicken chicken
chicken chicken chicken chicken chicken chicken
(an empty line)
(Ein Katzenprogramm. Beachten Sie, dass die leere Zeile erforderlich ist, da die vorhergehende Zeile 6 "Huhn" enthält.)
Eingabe für das Chicken-Programm
Chicken
Ausgabe
Chicken
Die Referenzimplementierung von Chicken.js .
Fehlererkennung
Der Interpreter sollte einen Fehler hinterlassen und beenden, wenn in der Quelle ein Wort vorhanden ist, das nicht "Huhn" ist.
Viel Glück!
quelle
Antworten:
Ruby, 335 Bytes
Nimmt den Namen der Eingabedatei als Befehlszeilenargument und nimmt Benutzereingaben (für Anweisung Nr. 6) von STDIN entgegen.
Da Ruby "trueyy" (alles außer
false
undnil
) sich von Javascript "truety" (Ruby truey plus0
, leere Zeichenfolgen usw.) unterscheidet, kann es in einigen Fällen vorkommen, dass Programme, die auf einem JS-Interpreter einwandfrei funktionieren , in diesem Fall fehlschlagen wegen der Anweisung Nr. 8, z. B. wenn sie""
sich auf dem Stapel befindet. Ich habe jedoch den größten Fall behoben, der falsch ist0
.Funktioniert mit dem Testprogramm und dem Hello World-Programm auf der Chicken-Website.
Erläuterung
Der Interpreter startet sofort, indem er eine Regex-Übereinstimmung
/^(chicken|\s)*$/m
mit der gesamten Datei ($<.read
) ausführt , wodurch sichergestellt wird, dass die Datei nurchicken
Leerzeichen enthält. In Ruby gibt dieser Operator den Index für die Übereinstimmung zurück odernil
wenn er nicht gefunden wurde.Hier werden zwei Tricks zum Speichern von Bytes verwendet: Anstatt direkt abzugleichen
chicken
, wird der String-Ersetzungsoperator#{}
stattdessen verwendet, um diesen String auch einer Variablen für später zuzuweisen (spart 1 Byte) und wenn der Inhalt der Datei zur Verarbeitung in einer Variablen gespeichert wird Es werden zwei Zeilenumbrüche angehängt, damit dielines
Funktion später auf natürliche Weise ein Extra0
an das Ende des Befehlssatzes anhängen kann . (Zwei werden benötigt, da nachfolgende Zeilenumbrüche ignoriert werden, die für das Chicken-Programm erforderlich sind.)Der verwendete Fehler ist
NoMethodError: undefined method '+@' for nil:NilClass
, dass das Regex-Match in Parens eingewickelt und ein vorangestellt wird+
. Wenn die Datei mit dem Muster übereinstimmt, erhalten Sie+0
, was0
normal ausgewertet wird und fortgesetzt wird.Als nächstes wird der Stapel zusammengebaut. Die anfängliche Liste muss erstellt werden, bevor die Selbstreferenz auf den Stapel zugewiesen werden kann. Daher wird ein Platzhalter verwendet und dann ersetzt. Der Anweisungszeiger wird
1
anstelle von gesetzt,2
da in Ruby keine Post-Inkrement-Operatoren vorhanden sind.Schließlich wird der Lambda-Trick von @BassdropCumberwubwubwub verwendet, um zu bestimmen, was als nächstes auf den Stapel geschoben werden soll. Wenn eine Operation nichts auf den Stapel schiebt, gibt der Interpreter einfach einen zusätzlichen Wert ein, damit der Stapel gleich bleibt. (Dies spart Bytes gegenüber dem Hinzufügen einer Push-Operation zu jedem einzelnen Lambda.)
Ungolfed Code:
quelle
Javascript ES6, 398 Bytes
Ich bin mir sicher, dass dies das mit Abstand längste Golfspiel ist, das ich je gemacht habe, aber mein Gehirn erkennt nichts anderes als
chicken
zu diesem Zeitpunkt.Ich werde die Erklärung bearbeiten, wenn mein Gehirn wieder funktioniert. Hier ist eine etwas ungolfed Version für jetzt.
Gibt für alles, was nicht der Fall ist, einen Falsey-Wert (0) aus
chicken
Probieren Sie es hier aus
quelle
if(!/^(chicken\s?)+$/.test(a))throw'There are any words except "chicken".';
gleich zu Beginn Ihres Dolmetschers hinzufügen .stderr
oder das Programm mit einem Code ungleich Null zu beenden. Etwas, das zeigt, dass etwas nicht stimmt. In Javascript können Sie eine Ausnahme auslösen, ein Fehlerobjekt zurückgeben, eine Warnung anzeigen, mitconsole.erro()
oder Ähnlichem in die Konsole schreiben .