Comment créer un langage de programmation.

N'ayez crainte, ma question est plus axée qu'elle n'en a l'air.

a marqué ce sujet comme résolu.

Salutation ^^ ,

La question du "comment créer un langage de programmation" trotte dans ma tête depuis belle lurettes et je me suis récemment décidé à en comprendre le fonctionnement, puis à en créer un. Je ne suis pour l’instant qu’à l’étape de la compréhension.

J’ai premièrement cherché à apprendre quelles étaient les langages existants et leurs utilités, puis les paradigmes et enfin les compilateurs. En étudiant le sujet des langages existants, j’ai remarqué que certain d’on Rust avait utilisé "LLVM" pour créer leur compilateur, j’ai donc fais mes recherches et j’en tire la conclusion que : LLVM est un framework pour compilateur qui attend le front-end et qui s’occupe du back-end (génération du code intermédiaire, optimisation de ce dernier et génération du code).

Toutefois, créer un compilateur ne suffit pas à créer un langage de programmation. C’est pourquoi j’ai approfondie mes recherches et le résultat de ces dernières est prévisible : il faut créer sa syntaxe et son mode de fonctionnement (implémentation de la création de fonction, de classe si le paradigme comporte l’orienté objet, de la déclaration de fonction, de module, de boucles, etc.)

Et à propos de ça, je n’ai rien trouvé de concret, c’est comme ci jamais personne ne s’était posé cette question. Je m’en remet par conséquent à vous pour répondre aux questions suivantes :

1. Lors de la création du langage, doit on prévoir deux répertoires distincts pour le compilateur et le langage en lui même (syntaxe, sémantique) ?

2. Si un répertoire comportant la sémantique et la syntaxe doit belle et bien exister, à quoi ressemblerait son architecture et comment programmer une syntaxe / sémantique ?

3. Pour créer le front-end du compilateur qui accompagnera mon langage, vers quelle ressource je peux me tourner pour apprendre à en créer un?

4. Lorsque mon langage sera créé, pour exécuter un programme écrit en mon langage je vais devoir utiliser mon compilateur, mais comment ? Je dois avoir créé une commande attendant le nom d’un fichier pour que mon compilateur le compile ? Et si c’est le cas, je dois ajouter le mot clé de mon compilateur au PATH ?

Cordialement, b4b4.

+0 -0

Salut,

Ta question est en effet très vaste :D

Comme tu commences à le sentir, il y a deux très grandes parties dans la création d’un langage :

  • comment concevoir un langage (chercher programming language theory sur Google pour trouver des ressources - il y en a beaucoup, mais c’est assez compliqué de trouver des bonnes introductions. Certaines universités mettent leurs cours en ligne)
  • comment exécuter un programme sur une machine (en gros compilé ou interprété).

Donc tu commences par écrire une grammaire pour décrire la syntaxe de ton langage. Ensuite tu as besoin d’un frontend (tokenizer/parser). C’est considéré "la plus simple" car automatisable. Il existe de nombreux framework pour générer des parseurs de grammaires (yacc ou flex par exemple). Ensuite tu dois écrire soit un backend, soit un interpréteur, qui sert à transformer la représentation de ton programme en actions concrètes. On dirait presque que c’est simple comme ça, mais ça devient rapidement très long et très compliqué selon ce que tu veux faire :D en cherchant "Compiler tutorial" tu trouves pas mal de ressources pour voir à quoi ça ressemble en pratique sur des exemples simples.

J’espere que j’ai répondu à tes questions,

Salut,

LLVM est un framework pour compilateur qui attend le front-end et qui s’occupe du back-end (génération du code intermédiaire, optimisation de ce dernier et génération du code).

Pour corriger un peu ça, LLVM pourrait plutôt être vu comme un langage assembleur de haut niveau. C’est un peu un oxymore, mais l’idée est littéralement d’exposer un langage plutôt proche de la machine mais qui abstrait l’architecture concrete. En pratique, les compilateurs qui s’appuient sur LLVM (Rust que tu as mentionné mais aussi par example clang) passent par plusieurs représentations intermédiaires du code qui sont optimisées jusqu’à passer la main à LLVM qui s’occupe de la dernière couche entre la représentation qu’elle accepte jusqu’au langage machine ciblé. LLVM est un acronyme pour low level virtual machine, c’est une couche faiblement (par rapport à un langage typique) abstraite par rapport au matériel ciblé.

Pour ce qui est de la conception d’un langage, c’est un domaine de recherche actif (donc il y a bien des gens qui se posent la question et planchent dessus, et les questions qui se posent sont rapidement assez subtiles…). Clairement la question de la conception des langages de programmation a encore plein de sous-questions qui sont complètement ouvertes !

Lors de la création du langage, doit on prévoir deux répertoires distincts pour le compilateur et le langage en lui même (syntaxe, sémantique) ?

La question est un peu étrange. Tu vas classiquement avoir cinq grosses étapes assez distinctes lors de la compilation d’un programme :

  • la tokenization : tu lis ton fichier d’entrée et tu le transformes en une succession d’objets qui ont un sens logique pour ton langage (exemple, transformer let a = 4; en une suite de tokens du genre [Keyword(let), Ident(a), Equal, LiteralInteger(4), Semicolon]) ;
  • une analyse syntaxique pour transformer la liste de tokens en une représentation interne selon la grammaire de ton langage (une grammaire est un truc qui donne un sens à des suites de tokens, typiquement la suite de tokens précédente pourrait être remplacée par une liste d’instructions du genre [Declare(a), Assign(a, Integer(5))] (c’est très naïf comme exemple bien sûr) ;
  • une analyse sémantique pour vérifier que le code écrit a du sens en plus d’être grammaticalement valable (genre tu n’utilises pas une variable avant de l’avoir déclarée et initialisée) ;
  • plein d’optimisations, avec potentiellement plusieurs représentations internes successives ;
  • la génération de code machine (là par exemple Rust s’appuie sur LLVM, GCC a son implémentation, certains langages comme Python ou Java visent une machine virtuelle plutôt que du matériel, etc).

Ces étapes sont assez indépendantes les une des autres, donc en général on va avoir tendance à les isoler dans leur propre répertoires mais ça c’est une question d’organisation du code assez orthogonale à celle du design d’un langage.

Lorsque mon langage sera créé, pour exécuter un programme écrit en mon langage je vais devoir utiliser mon compilateur, mais comment ? Je dois avoir créé une commande attendant le nom d’un fichier pour que mon compilateur le compile ? Et si c’est le cas, je dois ajouter le mot clé de mon compilateur au PATH ?

Ça aussi c’est une considération assez orthogonale, et c’est le soucis de l’utilisateur du langage plutôt que de son développeur. Mais en effet tu vas classiquement avoir un exécutable qui sera appelé en lui filant des fichiers sources.

Pour créer le front-end du compilateur qui accompagnera mon langage, vers quelle ressource je peux me tourner pour apprendre à en créer un?

Il y a "write yourself a scheme" qui est une bonne introduction au problème.

Cela dit certaines de tes questions sont relativement "naïves" par rapport à d’autres, du coup quel sont tes connaissances générales en programmation ? J’ai l’impression que tu as les yeux un peu plus gros que le ventre parce qu’il y a un fort contraste de difficulté entre par exemple ta question sur le PATH et celles sur le design d’une syntaxe et d’une sémantique pour un langage…

+3 -0

je tiens a rajouter mais ca peut paraître evident : faut aussi bien maitrises le langage de programmation dont tu creer le compilateur. Si tu n’as pas les competences requis dans ce langage Ca ne servira a rien si tu veux faire un bon compilateur, il faudra connaitre aussi le langage dans ton compilateur dans lequel passe. Ce que tu peux faire aussi c’est justement créer un compilateur pour s’améliorer mais je ne te garantirai rien si tu réussira a faire un compilateur d’un langage complet et maintenable

+0 -0

Merci Fantasio et Adri1,

Je répond à tes intérogations @Adri1:

quel sont tes connaissances générales en programmation ?

Je programme beaucoup avec des technologies webs tel que Django et je maîtrise les langages PHP, (HTML et CSS) et le SQL. Je fais aussi beaucoup de Python et j’ai de maigres connaisances en C++ (très maigre) et JavaScript. Rust sera mon prochain car il me permettra nottament de développer un langage de programmation, et bien d’autres choses pour lesquels je vous épargnerai les détails, du moins, jusqu’à ce que ça se retrouve au coeur d’une de mes futurs questions que je viendrai poser ici.

J’ai l’impression que tu as les yeux un peu plus gros que le ventre parce qu’il y a un fort contraste de difficulté entre par exemple ta question sur le PATH et celles sur le design d’une syntaxe et d’une sémantique pour un langage…

Oui, j’ai conscience que mes questions, du moins certaines parraisent naïves comme tu l’as dis plus haut mais, une fois de plus, comme tu l’as énoncé au début de ta réponse, "donc il y a bien des gens […] et les questions qui se posent sont rapidement assez subtiles…". Je pense que ma questions rentre dans ce cas de figure. La question de la grammaire ou de l’architecture que pourrait avoir mon avoir mon code sont des questions qui à contrario de votre interprétation, on toute leur importance à mes yeux.

Pour finir, vous n’avez pas réellement répondu à l’une de mes questions qui vous demandait si la grammaire de mon langage se trouverai dans le même répertoire que celui du compilateur. Par là j’entend, "Est-ce que ces deux choses sont suffisament différentes pour être développé chacunes de leur côté ou bien son elles justement complémentaire et méritent d’être développé dans un même ensemble, de sorte que lorsque il parraitra sur GitHub, il y ai le tout".

Cordialement, b4b4.

Rust sera mon prochain car

bon je te conseille ce cours alors : rust book

si la grammaire de mon langage se trouverai dans le même répertoire que celui du compilateur

oui dans le meme repo / project

tu peux regarder celui de Rust , ou de Python(c’est un interpreteur mais ce sera la meme chose pour le compilateur)

+0 -0

Oui, j’ai conscience que mes questions, du moins certaines parraisent naïves comme tu l’as dis plus haut mais, une fois de plus, comme tu l’as énoncé au début de ta réponse, "donc il y a bien des gens […] et les questions qui se posent sont rapidement assez subtiles…". Je pense que ma questions rentre dans ce cas de figure. La question de la grammaire ou de l’architecture que pourrait avoir mon avoir mon code sont des questions qui à contrario de votre interprétation, on toute leur importance à mes yeux.

Sans vouloir te vexer, je parlais de gens qui ont littéralement des doctorats en poche et qui font de la recherche (au sens académique du terme, pas une recherche Google) sur ce sujet en réfléchissant sur des questions connexes dont tu (et moi aussi d’ailleurs) ignores même l’existence. Je ne doute absolument pas que tu trouves ces questions de design d’un langage importantes et intéressantes (et c’est très bien d’être curieux !), mon message tenait plutôt à souligner que pouvoir les aborder sereinement demande un peu (beaucoup) plus de bagage en informatique que celui que l’on peut inférer que tu as d’après certaines de tes questions.

Pour finir, vous n’avez pas réellement répondu à l’une de mes questions qui vous demandait si la grammaire de mon langage se trouverai dans le même répertoire que celui du compilateur. Par là j’entend, "Est-ce que ces deux choses sont suffisament différentes pour être développé chacunes de leur côté ou bien son elles justement complémentaire et méritent d’être développé dans un même ensemble, de sorte que lorsque il parraitra sur GitHub, il y ai le tout".

Rien ne t’empêche d’avoir ton parseur sur gitlab, ta grammaire sur bitbucket, et le reste du compilateur sur Github si tu as envie, mais étant donné qu’ils ont besoin de se parler de toute façon, ces composants vont dépendre les uns des autres. En pratique, tu as intérêt à garder tout ensemble jusqu’à ce que certain composants deviennent trop gros. Comme tu parles d’implémenter ça en Rust, lorsqu’un des composants devient trop gros, tu peux utiliser la notion de workspace pour séparer les composants dans des crates différentes au sein du même dépôt Git. C’est ce que fait Rust lui-même (note que la stdlib de Rust est aussi dans le même dépôt!). Mais tu as le temps de voir venir avant d’avoir un projet assez gros pour en arriver à ces considérations.

Peut être le meilleur conseil serait de commencer par des petits tutoriels, ça te permettrait de sentir les différents problèmes à petite échelle pour construire une compréhension du système.

Tes questions sont tres abstraites et il y a beaucoup d’approches avant d’aboutir concrètement à un compilateur ou interpréteur, je pense que toucher à des systèmes existants te permettrait de clarifier ta vision du problème :)

Salut,

En soi, un langage c’est juste des mots auxquels on donne un sens et qui permettent de former des phrases (qui doivent être conformes à une grammaire qu’on a également donnée). Donc créer un langage de programmation, c’est juste créer des mots et une grammaire et leur donner un sens… C’est même pas la peine de toucher à un ordi pour ça !

Je dis ça un peu en rigolant, mais c’est une étape importante (et intéressante) et il y a notamment de la recherche en informatique sur ce sujet (allez, on va par exemple citer ce billet), par exemple pour créer des langages de programmation avec des « bonnes » propriétés et de bonnes fonctionnalités. Si cet aspect t’intéresse, il te faudra creuser un peu dans la théorie, regarder ce qui se fait du côté de la sémantique des langages de programmation, etc.

Une fois que tu as ton langage, tu voudras peut-être l’implémenter. Et là encore, tu as plusieurs étapes, mais les autres ont déjà traité tout ça plus haut. Personnellement, faire de l’analyse lexicale et tout, c’est pas un truc qui m’attire trop (même si écrire un parser est une expérience intéressante), mais faire l’étape d’interprétation/de compilation m’intéresse déjà plus, on peut faire des optimisations, on peut « s’amuser » à vérifier que ce qu’on fait est bien correct (allez, on va citer ça cette fois), etc.

Pour commencer plutôt tranquillement sur les deux notions, tu peux écrire un programme pour gérer des expressions arithmétiques. Parser un 2 + (3 + 2 x 4) c’est pas si simple que ça au début. Ensuite, tu pourras rajouter de la complexité en rajoutant des variables, donc traiter un code de ce genre.

X = 3
2 + (3 + 2 x X)

On a déjà un bon petit projet avec ça, n’est-ce-pas ? Pour la suite, je vais cette fois citer ça que tu pourras également suivre et que tu trouveras certainement intéressant.

+1 -0
Connectez-vous pour pouvoir poster un message.
Connexion

Pas encore membre ?

Créez un compte en une minute pour profiter pleinement de toutes les fonctionnalités de Zeste de Savoir. Ici, tout est gratuit et sans publicité.
Créer un compte