Un terrain de jeu pour l’écriture de compilateurs

“Créez votre propre compilateur” est un didacticiel interactif qui montre étape par étape comment écrire votre propre compilateur simple qui transforme JavaScript en Lisp. Parallèlement, nous examinons ce qu’est réellement un compilateur et l’état de l’art qu’est Roslyn.

Les compilateurs sont importants, mais la plupart des gens utilisent quotidiennement leur langage de programmation et leurs outils préférés sans
penser trop à eux, en ignorant ce qui se passe sous les couvertures.

Cependant, jeter un coup d’œil dans cette boîte noire et apprendre à écrire un compilateur vous donne des super pouvoirs. Il vous permettra d’écrire des outils personnalisés, des langages min/DSL, de créer votre propre langage à part entière, ou comme dans “Créer votre propre compilateur”, de transformer un langage en un autre !

Un excellent exemple de la raison pour laquelle cette dernière, en d’autres termes la transpilation, s’est avérée indispensable est le cas de Babel. Étant donné que tous les navigateurs ne sont pas en mesure de gérer toutes les dernières fonctionnalités du langage Javascript, Babel traduit ce code Javascript le plus récent en une version rétrocompatible de JavaScript dans les navigateurs ou environnements actuels et anciens.

Un autre exemple encore est le cas de Typescript qui ajoute un typage optionnel (à ce sujet, assurez-vous également de vérifier Sorbet – Making Ruby Staticly Typed) à Javascript, agissant comme un sur-ensemble statiquement typé et meilleur de celui-ci. Le compilateur TypeScript analyse et compile le code TypeScript en JavaScript afin de fonctionner sur n’importe quel navigateur. Étant donné que le moteur de machine virtuelle qui exécute Javascript est là, pourquoi ne pas le réutiliser au lieu d’en créer un à partir de zéro pour prendre en charge notre propre langage ? C’est plus facile à convertir !

Fable, est encore un autre transpileur X-to-Javascript. Fable transpile F # vers ES2015 JavaScript afin que le code écrit en F # puisse s’exécuter partout où JavaScript s’exécute – le navigateur, Node.js, Electron, React Native ou généralement V8.

Mais l’application la plus populaire d’un compilateur est que les programmes traduisent d’un langage supérieur vers un langage de niveau inférieur afin de créer un programme exécutable ; voir C.

Chaque compilateur fonctionne en exécutant plusieurs phases bien définies, chaque phase prenant l’entrée de la précédente jusqu’à ce qu’elle produise finalement du code exécutable.

La première phase est la tokenisation par la partie appelée lexer. Il prend un flux de caractères et l’utilisation d’expressions régulières les regroupe selon la syntaxe du langage dans ce qu’on appelle les jetons – fonctions de mots clés, opérateurs, etc.

La phase suivante est l’analyse. L’analyseur prend le flux de jetons créé par le lexer et les représente dans une structure, l’arbre de syntaxe abstraite, quelque chose de beaucoup plus facile à utiliser.

La phase suivante est l’analyse sémantique où le compilateur considère les contraintes de syntaxe du langage et les types de données. Il s’assure que le code est bien formé et bien typé.

L’étape suivante consiste à optimiser le code mort AST – eliminator en utilisant des techniques comme le tree shaking par exemple. Le résultat de cette phase est la Représentation Intermédiaire ou RI. IR subit lui-même des optimisations spécifiques à l’architecture CPU cible pour produire du code machine.

La dernière étape consiste à produire un exécutable autonome (des runtimes qui fonctionnent avec du bytecode comme la JVM, fonctionnent avec IR au lieu de créer un exécutable), quelque chose d’habituel en programmation C mais avec les nouveaux outils maintenant disponibles, même les langages de haut niveau comme Java , sous GraalVM peut compiler en exécutables natifs.

La liste ci-dessus est bien sûr simplifiée, mais en général, les étapes à suivre pour prendre une source d’entrée et la transformer en sortie souhaitée sont

  • Lexification
  • Analyse
  • Construire un arbre de syntaxe abstraite (AST)
  • Génération de code IR pour l’AST donné
  • Optimisations sur le code IR généré
  • Générer du code machine

Ajoutez à celles-ci l’étape de définition de la syntaxe de votre nouveau langage de programmation, si vous souhaitez suivre cette voie.

Le terrain de jeu “Créer votre propre compilateur” facilite ce processus compliqué. Actualy est une procédure pas à pas annotée de “The Super Tiny Compiler” de Jamie Kyle, un simple compilateur écrit en Javascript. Le but du tutoriel est de compiler une instruction Lisp en Javascript. En cours de route, nous passons par les différentes étapes de l’analyse lexicale, de l’analyse syntaxique, de la transformation et de la génération de code.

Chaque étape est divisée en plusieurs étapes et chaque étape est accompagnée du code annoté de manière interactive. C’est un excellent moyen de se mouiller les pieds et de comprendre les concepts de pieds nus.

L’autre façon post-moderne de construire des compilateurs est de suivre la voie de Roslyn. Écrire un compilateur pour le langage dans ce langage ? Microsoft l’a fait avec la plate-forme de compilateur de pointe, Roslyn.

Quant à la question de savoir ce qu’est réellement Roslyn, quoi de mieux que d’obtenir la réponse faisant autorité d’un membre de l’équipe Roslyn, le célèbre gourou C# lui-même, Eric Lippert ? L’opportunité s’est présentée sous la forme d’une interview qu’il nous a accordée en 2014 :

VN : La définition officielle de Roslyn indique qu’il s’agit d’un “projet de réécriture complète des compilateurs et des services de langage Visual Basic et C# dans leur propre langage de code managé respectif ; Visual Basic est en cours de réécriture en Visual Basic et C# est en cours de réécriture en C#”.
Comment C# est-il réécrit en C# ?

EL : Quand j’étais chez Microsoft, j’ai vu tellement de gens écrire leurs propres petits parseurs C # ou IDE ou petits mini compilateurs ou autre, pour leurs propres besoins. C’est très difficile, cela prend du temps, cela coûte cher et c’est presque impossible à faire correctement. Roslyn change tout cela, en donnant à chacun une bibliothèque d’outils d’analyse pour C # et VB qui est correcte, très rapide et conçue spécifiquement pour améliorer la vie des constructeurs d’outils. Je suis très heureux que ce soit presque terminé! J’ai travaillé dessus pendant de nombreuses années et j’ai hâte de mettre la main sur la version finale.

Cliquez sur ce lien pour lire le reste des commentaires d’Eric.

Construire votre compilateur à l’aide de Roslyn vous offre des avantages distincts :

  • Amélioration massive des performances et mécanisme intégré de gestion des objets dynamiques. Fonctionnalité cruciale pour l’émission de code, l’analyse des assemblages et la structure du compilateur lui-même qui se traduisent par la portabilité des assemblages et la possibilité de l’intégrer avec des outils disponibles uniquement pour C # (analyse de code, extensions VS).
  • Capacité multiplateforme puisque Roslyn produit des bibliothèques de classes portables compatibles avec Mono et le . NET Core.
  • Intégration de Visual Studio et d’autres fonctionnalités, notamment la coloration du code, la coloration syntaxique et IntelliSense.

La magie!

Plus d’information

Créez votre propre compilateur

Articles Liés

C# Guru – Entretien avec Eric Lippert

Fable – Écrire des applications frontales pour le Web en F #

Sorbet – Rendre Ruby statiquement typé

Comment créer des langages légers pragmatiques

Prenez gratuitement les compilateurs avancés CS 6120 de Cornell

Pour être informé des nouveaux articles sur I Programmer, inscrivez-vous à notre newsletter hebdomadaire, abonnez-vous au flux RSS et suivez-nous sur Twitter, Facebook ou Linkedin.

Bannière

picobook

commentaires

ou envoyez votre commentaire à: comments@i-programmer.info

.

Leave a Comment

Your email address will not be published. Required fields are marked *