Générer un langage C à partir d'une expression S avec Python

introduction

Remarques

――Veuillez le considérer comme une sorte de jeu. -Ce n'est pas l'histoire de Gauche's Are. ――L'auteur n'est pas très familier avec le langage C. Veuillez signaler tout point étrange.

Récemment, j'ai joué avec la création de Lisp avec Python.

C'était amusant avec ça, mais je n'étais pas motivé parce que ce n'était pas pratique, à part l'utiliser et ne pas l'utiliser, et je me demandais à quoi jouer ensuite. À ce moment-là, je me souviens avoir lu un article quelque part qui semble venir avec un transpilateur de langage S-type → C, et cela me paraissait intéressant, alors j'ai complètement détourné la partie lecteur de mon propre Lisp. Je l'ai implémenté en Python. L'original s'appelle CiSE (C dans S-Expression), mais celui implémenté cette fois est ** complètement différent **. Au fait, il a une saveur plutôt Common Lisp.

Publié sous le nom CLOP, donc si vous êtes intéressé, s'il vous plaît. Au fait, c'est un nom que je n'aime pas vraiment, alors je pourrais le changer si j'y pense. CiSE peut être cool.

Comment ça fonctionne

Le flux de génération du langage C à partir de l'expression S est le suivant.

  1. Conversion d'une expression S en une liste de chaînes de caractères
  2. Si le début de la liste est * une fonction prédéfinie *, appelez le reste comme argument
  3. Sinon, traitez-le comme une fonction * C *

Une * fonction prédéfinie * est, par exemple:

def aref(array, subscript):
    return f"{array}[{subscript}]"

Par exemple, (aref hoge fuga) est converti en["aref", "hoge", "fuga"](1), puis" hoge [fuga] "" est généré (2). est. A ce moment, si le premier élément de la liste n'est pas recherché, il est traité en fonction de c. Par exemple, (printf" bonjour ")produit" printf (\ "bonjour ") "` (3).

De plus, «+ hoge +» est converti en «HOGE», et «hoge-hoge» est converti en «hoge_hoge».

J'ai utilisé l'expression ** function ** telle que définie à l'avance, mais le fait est que c'est comme une macro. Les macros suivantes sont définies à l'avance dans CLOP.

* + - / 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

La plupart des noms sont tirés de Common Lisp ou C. C'est juste cela, donc vous pouvez presque imaginer ce que cela fait.

Si vous ne l'oubliez pas, vous devriez être capable de gérer presque toutes les fonctions du langage C.

Illustration

Hello, world!

hello.clop


(include stdio)

(defun int:main (void)
  (printf "Hello, world!\n")
  (return 0))

Je pense que je ne l'ai pas vu. Le type est déclaré avec des spécificateurs séparés par des deux-points, tels que ʻunsigned: int: hoge`. Vous pouvez convertir en langage C avec la commande suivante.

$ clop translate hello.clop --out hello.c

hello.c


#include <stdio.h>

int main (void)
{
  printf("Hello, world!\n");
  return 0;
}

macro

Vous pouvez utiliser des macros pour le moment. Cependant, CLOP n'est rien de plus qu'un ** list → convertisseur de chaînes ** après tout, il n'y a donc pas de fonction d'opération de liste. Par conséquent, vous ne pouvez pas utiliser de macros puissantes comme Common Lisp, mais vous pouvez écrire de manière plus flexible que les fonctions macro en langage C. Par exemple.

python


(defsyntax null (ptr)
  (eq ,ptr +null+))

Ceci est développé comme suit.

hoge == NULL // (null hoge)

Il est vraiment désagréable d'avoir des guillemets arrière même s'il n'y a pas de guillemets, mais si vous ajoutez des guillemets arrière, la valeur sera insérée à partir de l'argument donné au moment de l'expansion de la macro. C'est la même chose que la macro CPP, voici donc un exemple plus compliqué. Dans CLOP, vous pouvez utiliser des arguments d'option de type Common Lisp, des arguments de mot-clé et des arguments de longueur variable.

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

Si vous faites , @ hoge, le contenu de l'argument sera développé tel quel. (Une parenthèse peut être prise)

Vous pouvez écrire la définition de la macro dans un seul code source, mais vous pouvez également la extraire d'un autre fichier avec require. A ce moment, le fichier d'en-tête qui est ʻincludeest également extrait en même temps s'il n'est pas déjà inclus. De plus, à l'exception de la définition de macro et de l'inclusion, elle sera ignorée. Voici un exemple derequire the previous with-open-file.clop avec 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;
}

C'est un code effrayant, mais cela fonctionne bien. CLOP fait un usage intensif des expressions composées (comme ({hoge; fuge; ...})), ce qui peut la rendre terrible dans certains cas.

De côté

1. Avantages

Pensons aux avantages.

Sauf pour le troisième, c'est subtil.

2. Difficultés

J'ai senti que la syntaxe du langage C était compliquée. Je ne pense pas à l'écriture de C brut, mais lors de la génération à partir d'une expression S, j'étais assez inquiet de savoir où mettre les parenthèses et où appuyer sur le point-virgule. Compte tenu de cela, je pense que le pouvoir expressif de la formule S est incroyable.

Résumé

Implémentation d'Oreore CiSE en Python. Je pense qu'il y a un désir universel d'écrire des choses non-S dans le style S (par exemple, Hy). Et le langage C? Je voudrais toucher CiSE du chef de famille gauche, mais c'est dommage qu'il n'y ait pas beaucoup d'informations. (Peut-être que vous ne pouvez tout simplement pas le trouver. S'il vous plaît laissez-moi savoir si vous avez un bon document)

** Addenda ** Il y avait une telle chose. https://github.com/burtonsamograd/sxc

Recommended Posts

Générer un langage C à partir d'une expression S avec Python
Appeler le langage C depuis Python (python.h)
Générer une classe à partir d'une chaîne en Python
Next Python en langage C
API C en Python 3
Comment générer une séquence en Python et C ++
Étendre python en C ++ (Boost.NumPy)
Intégration du langage machine en langage C
Générer une vignette arrondie en Python
Essayez de créer un module Python en langage C
OCR à partir de PDF en Python
Recherche binaire en Python / C ++
Générer une distribution U en Python
Générer du code QR en Python
Générez 8 * 8 (64) cubes avec Blender Python
Générez Word Cloud à partir de données de cas d'essai avec python3
Obtenir des constantes de macro à partir du fichier d'en-tête C (++) (.h) en Python
Appeler C depuis Python avec DragonFFI
Test de module multi-instance en langage C
[Python] Générer un code QR en mémoire
Obtenir des données de Quandl en Python
100 Language Processing Knock Chapitre 1 en Python
Réaliser une classe d'interface en langage C
Générer le notebook Jupyter ".ipynb" en Python
Appeler popcount depuis Ruby / Python / C #
Introduction à Protobuf-c (langage C ⇔ Python)
Résoudre ABC036 A ~ C avec Python
Conseils pour appeler Python à partir de C
Exécuter du code Python à partir de l'interface graphique C #
Comment envelopper C en Python
Exécutez des scripts Python de manière synchrone à partir de C #
Python pour passer d'une autre langue
Résoudre ABC037 A ~ C avec Python
Segfo avec 16 caractères en langage C
Ecrire un test unitaire de langage C en Python
Appeler C / C ++ depuis Python sur Mac
Extraire des chaînes de fichiers avec Python
Appelez votre propre bibliothèque partagée en langage C à partir de Python à l'aide de ctypes
Générer une collection de première classe en Python
Liste de liens (list_head / queue) en langage C
Générer une URL signée AWS-S3 (limitée dans le temps) en Python
4 langage de comparaison de fermeture (Python, JavaScript, Java, C ++)
Algorithme en Python (ABC 146 C Dichotomy
Relancé de "pas d'accès Internet" en Python
Empêcher le double lancement de cron en Python
Implémenter le filtre FIR en langage Python et C
Générer automatiquement un commentaire de chaîne de document Python avec Emacs
Ecrire le fichier O_SYNC en C et Python
Module pour générer le mot N-gramme en Python
Télécharger des images à partir de la liste d'URL en Python
Obtenez le niveau de la batterie de SwitchBot avec Python
Communication socket par langage C et Python
Utilisation des fonctions C ++ de python avec pybind11
Convertir de Markdown en HTML en Python
Obtenez la probabilité de précipitation de XML avec Python
Exécutez Python en C ++ sur Visual Studio 2017
Obtenir l'historique des métriques de MLflow en Python
Langage C pour voir et se souvenir de la partie 2 Appeler le langage C à partir de la chaîne Python (argument)
[Langage C] Je souhaite générer des nombres aléatoires dans la plage spécifiée
Langage C pour voir et se souvenir de la partie 1 Appeler le langage C depuis Python (bonjour le monde)
Langage C pour voir et se souvenir de la partie 4 Appelez le langage C depuis Python (argument) double