Clem ist eine minimale stapelbasierte Programmiersprache mit erstklassigen Funktionen. Ihr Ziel ist es, einen Dolmetscher für die Clem-Sprache zu schreiben. Es sollte richtig alle Beispiele auszuführen , die in der Referenzimplementierung enthalten, die verfügbar ist hier .
- Wie üblich gelten Standardlücken .
- Der kleinste Eintrag nach Byte-Anzahl gewinnt.
Die Clem-Sprache
Clem ist eine stapelbasierte Programmiersprache mit erstklassigen Funktionen. Der beste Weg, um Clem zu lernen, besteht darin, den clem
Interpreter ohne Argumente auszuführen . Es wird im interaktiven Modus gestartet, sodass Sie mit den verfügbaren Befehlen spielen können. Geben Sie zum Ausführen der Beispielprogramme Folgendes ein: clem example.clm
Beispiel ist der Name des Programms. Dieses kurze Tutorial sollte ausreichen, um Ihnen den Einstieg zu erleichtern.
Es gibt zwei Hauptfunktionsklassen. Atomfunktionen und zusammengesetzte Funktionen. Zusammengesetzte Funktionen sind Listen, die aus anderen zusammengesetzten Funktionen und atomaren Funktionen bestehen. Beachten Sie, dass eine zusammengesetzte Funktion sich nicht selbst enthalten kann.
Atomfunktionen
Die erste Art der Atomfunktion ist die Konstante . Eine Konstante ist einfach ein ganzzahliger Wert. Zum Beispiel -10. Wenn der Interpreter auf eine Konstante stößt, schiebt er sie auf den Stapel. Lauf clem
jetzt. Geben Sie -10
an der Eingabeaufforderung ein. Das solltest du sehen
> -10
001: (-10)
>
Der Wert 001
beschreibt die Position der Funktion im Stapel und (-10)
ist die gerade eingegebene Konstante . Geben Sie nun +11
an der Eingabeaufforderung ein. Das solltest du sehen
> +11
002: (-10)
001: (11)
>
Beachten Sie, dass (-10)
die zweite Position im Stapel erreicht wurde und (11)
jetzt die erste belegt. Das ist die Natur eines Stapels! Sie werden feststellen, dass dies -
auch der Dekrementierungsbefehl ist. Wann immer -
oder +
vor einer Zahl, bezeichnen sie das Vorzeichen dieser Zahl und nicht den entsprechenden Befehl. Alle anderen atomaren Funktionen sind Befehle . Insgesamt gibt es 14:
@ Rotate the top three functions on the stack
# Pop the function on top of the stack and push it twice
$ Swap the top two functions on top of the stack
% Pop the function on top of the stack and throw it away
/ Pop a compound function. Split off the first function, push what's left,
then push the first function.
. Pop two functions, concatenate them and push the result
+ Pop a function. If its a constant then increment it. Push it
- Pop a function. If its a constant then decrement it. Push it
< Get a character from STDIN and push it to the stack. Pushes -1 on EOF.
> Pop a function and print its ASCII character if its a constant
c Pop a function and print its value if its a constant
w Pop a function from the stack. Peek at the top of the stack. While it is
a non-zero constant, execute the function.
Wenn Sie an der Eingabeaufforderung einen Befehl eingeben, wird der Befehl ausgeführt. Geben Sie #
an der Eingabeaufforderung (den Befehl duplicate) ein. Das solltest du sehen
> #
003: (-10)
002: (11)
001: (11)
>
Beachten Sie, dass (11) dupliziert wurde. Geben Sie nun %
an der Eingabeaufforderung den Befehl drop ein. Das solltest du sehen
> %
002: (-10)
001: (11)
>
Um einen Befehl in den Stapel zu verschieben, schließen Sie ihn einfach in Klammern ein. Geben Sie (-)
an der Eingabeaufforderung ein. Dadurch wird der Dekrementierungsoperator auf den Stapel verschoben. Das solltest du sehen
> (-)
003: (-10)
002: (11)
001: (-)
>
Zusammengesetzte Funktionen
Sie können auch mehrere atomare Funktionen in Klammern setzen, um eine zusammengesetzte Funktion zu bilden. Wenn Sie an der Eingabeaufforderung eine zusammengesetzte Funktion eingeben, wird diese auf den Stapel verschoben. Geben Sie ($+$)
an der Eingabeaufforderung ein. Das solltest du sehen
> ($+$)
004: (-10)
003: (11)
002: (-)
001: ($ + $)
>
Technisch gesehen ist alles auf dem Stapel eine zusammengesetzte Funktion. Einige der zusammengesetzten Funktionen auf dem Stapel bestehen jedoch aus einer einzelnen Atomfunktion (in diesem Fall werden wir sie der Einfachheit halber als Atomfunktionen betrachten). Bei der Bearbeitung zusammengesetzter Funktionen auf dem Stapel ist der .
Befehl (Verkettung) häufig hilfreich. Geben Sie .
jetzt ein. Das solltest du sehen
> .
003: (-10)
002: (11)
001: (- $ + $)
>
Beachten Sie, dass die erste und die zweite Funktion auf dem Stapel verkettet wurden und dass die zweite Funktion auf dem Stapel in der resultierenden Liste an erster Stelle steht. Um eine Funktion auszuführen, die sich auf dem Stapel befindet (egal ob atomar oder zusammengesetzt), müssen wir den w
Befehl (while) ausgeben . Der w
Befehl öffnet die erste Funktion auf dem Stapel und führt sie wiederholt aus, solange die zweite Funktion auf dem Stapel eine Konstante ungleich Null ist. Versuchen Sie vorherzusagen, was passieren wird, wenn wir tippen w
. Geben Sie nun ein w
. Das solltest du sehen
> w
002: (1)
001: (0)
>
Hast du das erwartet? Die zwei Zahlen, die oben auf dem Stapel sitzen, wurden addiert und ihre Summe bleibt erhalten. Versuchen wir es nochmal. Zuerst lassen wir die Null fallen und drücken eine 10 durch Eingabe %10
. Das solltest du sehen
> %10
002: (1)
001: (10)
>
Jetzt geben wir die gesamte Funktion in einem Schuss ein, aber %
am Ende fügen wir ein zusätzliches hinzu , um die Null loszuwerden. Geben Sie (-$+$)w%
an der Eingabeaufforderung ein. Das solltest du sehen
> (-$+$)w%
001: (11)
>
(Beachten Sie, dass dieser Algorithmus nur funktioniert, wenn die erste Konstante auf dem Stapel positiv ist.)
Saiten
Saiten sind ebenfalls vorhanden. Sie sind meistens syntaktischer Zucker, können aber sehr nützlich sein. Wenn der Interpreter auf eine Zeichenfolge stößt, schiebt er jedes Zeichen vom letzten zum ersten auf den Stapel. Geben Sie ein %
, um die 11 aus dem vorherigen Beispiel zu löschen. Geben Sie nun 0 10 "Hi!"
an der Eingabeaufforderung ein. Das 0
fügt einen NULL-Terminator ein und das 10
fügt ein neues Zeilenzeichen ein. Das solltest du sehen
> 0 10 "Hi!"
005: (0)
004: (10)
003: (33)
002: (105)
001: (72)
>
Geben Sie ein (>)w
, um Zeichen vom Stapel zu drucken, bis der NULL-Terminator angezeigt wird. Das solltest du sehen
> (>)w
Hi!
001: (0)
>
Schlussfolgerungen
Hoffentlich sollte dies ausreichen, um Ihnen den Einstieg in den Dolmetscher zu erleichtern. Das Sprachdesign sollte relativ einfach sein. Lassen Sie mich wissen, wenn etwas furchtbar unklar ist :) Einige Dinge wurden absichtlich vage gelassen: Werte müssen signiert sein und mindestens 16 Bit, der Stapel muss groß genug sein, um alle Referenzprogramme usw. auszuführen. Viele Details wurden nicht geschnitzt hier draußen, weil eine vollständige Sprachspezifikation unerschwinglich groß wäre (und ich habe noch keine geschrieben: P). Im Zweifelsfall ahmen Sie die Referenzimplementierung nach.