Vorsichtsmaßnahmen
――Bitte betrachten Sie es als eine Art Spiel. -Es ist nicht die Geschichte von Gauche's Are. ――Der Autor ist mit der Sprache C nicht sehr vertraut. Bitte weisen Sie auf merkwürdige Punkte hin.
Vor kurzem habe ich damit gespielt, Lisp mit Python zu machen.
Das hat Spaß gemacht, aber ich war nicht motiviert, weil es nicht praktisch war, abgesehen davon, es zu benutzen und nicht zu benutzen, und ich fragte mich, was ich als nächstes spielen sollte. Zu dieser Zeit erinnere ich mich, dass ich irgendwo einen Artikel gelesen habe, in dem Gauche mit einem S-Typ → C-Sprachtranspiler zu kommen scheint, und es schien interessant zu sein, also habe ich den Leserteil meines eigenen Lisp vollständig abgelenkt. Ich habe es in Python implementiert. Das Original heißt CiSE (C in S-Expression), aber das diesmal implementierte ist ** ein völlig anderes **. Übrigens hat es einen eher Common Lisp Geschmack.
Veröffentlicht unter dem Namen CLOP. Wenn Sie also interessiert sind, bitte. Übrigens, es ist ein Name, den ich nicht wirklich mag, also könnte ich ihn ändern, wenn ich daran denken kann. CiSE kann cool sein.
Der Fluss der Erzeugung der C-Sprache aus dem S-Ausdruck ist wie folgt.
Eine * vordefinierte Funktion * ist zum Beispiel:
def aref(array, subscript):
return f"{array}[{subscript}]"
Zum Beispiel wird "(aref hoge fuga)" in "[" aref "," hoge "," fuga "]" (1) konvertiert und dann "hoge [fuga]" "erzeugt (2). ist. Wenn zu diesem Zeitpunkt das erste Element der Liste nicht nachgeschlagen wird, wird es als Funktion von c verarbeitet. Zum Beispiel erzeugt "(printf" Hallo ")" "printf (" Hallo ")" "(3).
Außerdem wird "+ hoge +" in "HOGE" und "hoge-hoge" in "hoge_hoge" konvertiert.
Ich habe den Ausdruck ** Funktion ** wie im Voraus definiert verwendet, aber der Punkt ist, dass er wie ein Makro ist. Die folgenden Makros werden im Voraus in CLOP definiert.
* + - / 1+ 1- < > and aref ash break cast cond continue
decf declare defconstant defenum defstruct defsyntax
defun defunion defvar eq for if incf include let logand
logior logxor mod not or progn return setf when while
Die meisten Namen stammen von Common Lisp. C Es ist nur das, so dass Sie sich fast vorstellen können, was es tut.
Wenn Sie es nicht übersehen, sollten Sie in der Lage sein, fast alle Funktionen der C-Sprache zu handhaben.
Hello, world!
hello.clop
(include stdio)
(defun int:main (void)
(printf "Hello, world!\n")
(return 0))
Ich glaube ich habe es nicht gesehen. Der Typ wird mit durch Doppelpunkte getrennten Bezeichnern deklariert, z. B. "unsigned: int: hoge". Sie können mit dem folgenden Befehl in die Sprache C konvertieren.
$ clop translate hello.clop --out hello.c
hello.c
#include <stdio.h>
int main (void)
{
printf("Hello, world!\n");
return 0;
}
Sie können vorerst Makros verwenden. CLOP ist jedoch nichts anderes als ein ** Listen → String-Konverter **, sodass es keine Listenoperationsfunktion gibt. Daher können Sie keine leistungsstarken Makros wie Common Lisp verwenden, aber Sie können flexibler als Makrofunktionen in C-Sprache schreiben. Zum Beispiel.
python
(defsyntax null (ptr)
(eq ,ptr +null+))
Dies wird wie folgt erweitert.
hoge == NULL // (null hoge)
Es ist wirklich unangenehm, Anführungszeichen zu haben, obwohl es keine Anführungszeichen gibt. Wenn Sie jedoch Anführungszeichen hinzufügen, wird der Wert aus dem Argument eingefügt, das zum Zeitpunkt der Makroerweiterung angegeben wurde. Dies ist dasselbe wie das CPP-Makro, daher hier ein komplizierteres Beispiel. In CLOP können Sie Common Lisp-ähnliche Optionsargumente, Schlüsselwortargumente und Argumente variabler Länge verwenden.
with-open-file.clop
(include stdio)
(defsyntax null (ptr)
(eq ,ptr +null+))
(defsyntax with-open-file ((stream filespec &optional (mode "w")) &body body)
(let ((FILE*:,stream (fopen ,filespec ,mode)))
(if (null ,stream)
(perror "Failed to open file")
(progn
,@body
(fclose ,stream)))))
Wenn Sie , @ hoge
tun, wird der Inhalt des Arguments so wie er ist erweitert. (Eine Klammer kann genommen werden)
Sie können die Makrodefinition in einen einzigen Quellcode schreiben, aber Sie können sie auch mit require
aus einer anderen Datei ziehen. Wenn zu diesem Zeitpunkt die Header-Datei "include" noch nicht enthalten ist, wird sie gleichzeitig abgerufen. Beachten Sie, dass alle außer der Makrodefinition und dem Include übersprungen werden.
Hier ist ein Beispiel für "erfordern" die vorherige "with-open-file.clop" mit "main.clop".
main.clop
(include stdio)
(require with-open-file)
(defun int:main (void)
(with-open-file (fd "hello.txt")
(fprintf fd "Hello, world!\n"))
(return 0))
$ clop translate main.clop --out main.c
main.c
#include <stdio.h>
int main (void)
{
({
FILE* fd = fopen("hello.txt", "w");
fd == NULL? (perror("Failed to open file")) : (({
fprintf(fd, "Hello, world!\n");
fclose(fd);
}));
});
return 0;
}
Es ist ein gruseliger Code, aber er funktioniert gut. CLOP verwendet häufig zusammengesetzte Ausdrücke (wie ({hoge; fuge; ...})
), was es in einigen Fällen schrecklich machen kann.
Lassen Sie uns über die Vorteile nachdenken.
Mit Ausnahme des dritten ist es subtil.
Ich hatte das Gefühl, dass die Syntax der C-Sprache kompliziert war. Ich denke nicht, wenn ich rohes C schreibe, aber als ich aus dem S-Ausdruck generierte, war ich ziemlich besorgt darüber, wo ich Klammern setzen und wo ich Semikolon drücken sollte. Angesichts dessen finde ich die Ausdruckskraft der S-Formel erstaunlich.
Oreore CiSE in Python implementiert. Ich denke, es gibt eine gewisse Anzahl universeller Wünsche, Dinge im Nicht-S-Stil im S-Stil zu schreiben (zum Beispiel Hy). Was ist mit C-Sprache? Ich würde gerne CiSE von der Hauptfamilie Gauche berühren, aber es ist schade, dass es nicht viele Informationen gibt. (Vielleicht können Sie es einfach nicht finden. Bitte lassen Sie mich wissen, wenn Sie ein gutes Dokument haben.)
** Nachtrag ** Da war so etwas. https://github.com/burtonsamograd/sxc
Recommended Posts