Pourquoi les compilateurs auto-hébergés sont-ils considérés comme un rite de passage pour de nouvelles langues?


30

J'ai entendu dans un certain nombre d'endroits maintenant que les gens s'attendent à ce que les langues utilisent, ou du moins aient, un compilateur auto-hébergé afin de mériter le respect.

Je suis curieux de savoir pourquoi c'est. Un compilateur semble être un logiciel très important à écrire, et j'imagine que toutes les langues ne sont pas bien adaptées à leur création. Ne serait-il pas plus judicieux de consacrer l'effort à travailler sur quelque chose qui donnera de meilleurs résultats?


17
"Un compilateur semble être un logiciel très important à écrire, et j'imagine que toutes les langues ne sont pas bien adaptées pour les créer.": Je considérerais cela comme une très bonne raison d'essayer d'écrire un compilateur dans une nouvelle langue, à savoir prouver que la langue est à la hauteur.
Giorgio

13
À moins qu'il ne s'agisse d'un langage spécifique, un langage qui n'est pas bien adapté pour écrire un compilateur n'est probablement pas bien adapté à ce que je veux faire non plus.
CodesInChaos

3
AFAIK, ce n'est pas toujours le cas de Fortran. Plusieurs compilateurs Fortran (par exemple gfortrande GCC ...) ne sont pas codés en Fortran.
Basile Starynkevitch

Réponses:


29

Ne serait-il pas plus judicieux de consacrer l'effort à travailler sur quelque chose qui donnera de meilleurs résultats?

Comme ça?

Ce qui est bien avec les compilateurs, c'est qu'ils n'ont pas beaucoup de dépendances. Cela en fait de bons candidats pour une nouvelle langue qui n'a probablement pas encore de bibliothèque standard très large ou diversifiée.

Mieux encore, ils nécessitent une variété de choses, tout en étant bien étudiés. La variété permet de s'assurer que votre exemple teste différentes parties de la langue. Être bien étudié signifie que vous avez d'autres compilateurs à comparer - ainsi que donner plus de crédit aux types académiques que vous savez ce que vous faites.

Et bien que les compilateurs semblent une tonne de travail, ils sont assez petits dans le grand schéma des choses. Si les implémenteurs de langage ne peuvent même pas faire quelque chose qu'ils ont fait auparavant dans le nouveau langage, comment vont-ils faire des choses nouvelles? Comment vont-ils gérer les trucs vraiment gros comme les bibliothèques standard ou un IDE?


Juste comme note latérale, je voudrais mentionner qu'en dépit d'être gentil, il y a toujours une variété de raisons pour lesquelles un compilateur peut être écrit dans une autre langue. Par exemple, la plupart des moteurs javascript ne sont pas écrits en javascript. Il y a plusieurs raisons à cela: intégration avec d'autres logiciels, liaison à des bibliothèques / dépendances existantes, outils supérieurs, performances, code hérité ... Parfois, l'auto-compilation du langage est agréable, mais il est toujours logique de maintenir le compilateur de base dans un autre. Pourtant, le langage en lui-même a du sens. C'est juste que vous ne pouvez généralement pas vous permettre de réaménager un écosystème entier.
dagnelies

2
@arnaud Et le fait qu'un compilateur Javascript nécessite un environnement Javascript, qui ne peut pas être écrit en Javascript car Javascript nécessite un environnement Javascript, <répétez paradoxalement> , car un environnement Javascript n'est pas fourni par le système d'exploitation (et si était, il ne serait pas écrit en Javascript).
Qix

3
@Qix en.wikipedia.org/wiki/Bootstrapping_%28compilers%29 Mais surtout il n'y a aucune raison de l'utiliser. Il est largement connu comme un langage médiocre, les navigateurs s'en sortent sans l'utiliser pour la compilation car ils contrôlent la situation :), tandis que les autres n'ont pas le choix sur le Web.
Den

3
Je ne suis pas sûr de la revendication «ne pas avoir beaucoup de dépendances». Cela pourrait être vrai pour le frontal du compilateur . Mais dès que vous avez un AST, lancer votre propre optimiseur et générateur de code ne semble pas être une voie prometteuse. Mis à part le fait que les techniques d'optimisation modernes nécessitent des moteurs logiques formels sophistiqués pour lesquels on pourrait vouloir utiliser une bibliothèque tierce, il n'y a aucune raison de réinventer la roue pour chaque nouveau langage au lieu de s'appuyer sur une base de force industrielle comme GCC ou LLVM.
5gon12eder

30

Le but d'avoir un compilateur dans le langage en cours de compilation fait souvent partie de la pratique de « manger sa propre nourriture pour chien ». Cela montre au monde que vous considérez que le langage, le compilateur et l'écosystème des modules et outils de support sont "assez bons pour un travail sérieux" ou "prêts pour la production".

Cela a également pour effet vertueux de forcer les personnes les plus proches du langage, du compilateur et de la conception d'exécution à faire face directement aux effets de toutes les décisions qu'ils ont prises et des priorités de développement qu'ils ont choisies - les verrues et tout. Cela conduit souvent à un groupe de base qui non seulement comprend l'environnement linguistique en théorie, mais qui possède une vaste expérience pratique de l'utilisation du langage / des outils dans le creuset de conditions difficiles et réelles.


1
pour être complet: manger votre propre nourriture pour chien ; voir chien nourri (adj.) ou dogfooding (verbe)
Qix

17

Les gens créent de nouveaux langages à usage général pour une raison principale: ils détestent au moins une chose sur toutes les autres langues. C'est pourquoi tant de langues ne décollent pas. Vous avez une bonne idée d'un langage qui améliorerait votre vie de programmation, mais vous devez faire la première implémentation dans un langage qui vous agace d'au moins une façon. L'auto-hébergement signifie que vous n'avez plus à travailler dans cet ancien langage ennuyeux. C'est pourquoi les créateurs d'une langue travaillent vers cette étape et la voient comme une étape majeure.

Beaucoup de fonctionnalités linguistiques semblent bonnes sur papier, mais lorsque vous vous en servez pour les utiliser dans un vrai projet, vous commencez à voir leurs limites. Par exemple, de nombreuses langues ne disposent pas au départ d'un support décent Unicode. La réalisation d'un grand projet permet de garantir qu'un grand nombre de ces types de situations ont été rencontrées et traitées, et un compilateur auto-hébergé est aussi bon qu'un projet. C'est pourquoi les gens autres que les créateurs de la langue y voient une étape majeure.

Cela ne signifie pas que c'est la seule étape importante à noter. Il existe des fonctionnalités qui ne sont pas exercées par un compilateur, telles que l'intégration de bases de données, les interfaces graphiques, la mise en réseau, etc.


J'ai l'impression qu'une langue (native) est une langue quand elle peut se compiler et qu'un noyau linux pourrait y être porté (car elle englobe la plupart / toutes les tâches nécessaires au fonctionnement de la plupart des systèmes d'exploitation modernes).
Qix

Un support Unicode décent n'est cependant pas vraiment nécessaire pour écrire un compilateur.
Paŭlo Ebermann

11

Steve Yegge a écrit un excellent article de blog qui, quelque peu indirectement, traite de cela.

Gros point n ° 1: les compilateurs englobent à peu près tous les aspects de l'informatique. Il s'agit d'un cours de niveau supérieur, car vous devez connaître toutes les autres choses que vous apprenez dans le programme d'informatique juste pour commencer. Structures de données, recherche et tri, performances asymptotiques, coloration graphique? Tout est là-dedans.

Il y a une raison pour laquelle Knuth travaille sur son monumental (et sans fin) "Art of Computer Programming" depuis plusieurs décennies, même s'il a commencé comme (juste) un manuel de compilation. De la même manière que Carl Sagan a dit "Si vous voulez faire une tarte aux pommes à partir de zéro, vous devez d'abord inventer l'univers", si vous souhaitez écrire un compilateur, vous devez d'abord traiter presque tous les aspects de l'informatique.

Cela signifie que si le compilateur est auto-hébergé, il est à peu près sûr de pouvoir faire ce dont j'ai besoin, peu importe ce que je fais. Inversement, si vous n'avez pas écrit de compilateur dans votre langage, il y a de fortes chances qu'il manque quelque chose de vraiment important pour quelqu'un, car les implémenteurs de langage n'ont jamais eu à écrire un programme qui les obligerait à réfléchir à tous ces problèmes.

Gros point n ° 2: à partir de 30 000 pieds, un nombre surprenant de problèmes ressemblent à des compilateurs.

Les compilateurs prennent un flux de symboles, déterminent leur structure selon certaines règles prédéfinies spécifiques au domaine et les transforment en un autre flux de symboles. Cela semble assez général, n'est-ce pas? Ben ouais.

Que vous soyez dans l'équipe Visual C ++ ou non, vous vous retrouverez très souvent à faire quelque chose qui ressemble à une partie d'un compilateur. Je le fais littéralement tous les jours.

Contrairement à la plupart des autres professions, les programmeurs n'utilisent pas seulement des outils, mais construisent leurs propres outils. Un programmeur qui ne peut pas (en raison du manque de compétences ou du manque d'outils utilisables pour construire d'autres outils) écrire des outils sera à jamais handicapé, limité aux outils que quelqu'un d'autre fournit.

Si un langage n'est "pas bien adapté à la création" de programmes qui peuvent prendre un flux de symboles, leur appliquer des règles et le transformer en un autre flux de symboles, cela ressemble à un langage assez limité, et pas un qui serait utile pour moi.

(Heureusement, je ne pense pas qu'il existe de nombreux langages de programmation qui ne conviennent pas à la transformation de symboles. C est probablement l'un des pires langages de ce type utilisé aujourd'hui, mais les compilateurs C sont généralement auto-hébergés, de sorte que personne n'a jamais été arrêté.)

Une troisième raison pour laquelle je terminerai, par expérience personnelle, non mentionnée par Yegge (parce qu'il n'écrivait pas sur "pourquoi s'auto-héberger"): cela fait sortir les bugs. Lorsque vous écrivez un compilateur, cela signifie que chaque fois que vous le construisez (pas seulement chaque fois que vous l' exécutez ), vous dépendez de lui pour fonctionner et pour fonctionner correctement sur une base de code de taille décente (le compilateur lui-même).

Ce mois-ci, j'utilise un compilateur non auto-hébergé relativement nouveau et célèbre (vous pouvez probablement deviner lequel), et je ne peux pas passer 2 jours sans commettre de faute. Je me demande combien les concepteurs devaient réellement l'utiliser.


8

Si vous voulez qu'un compilateur pour la langue X soit auto-hébergé, vous devez d'abord l'implémenter dans une autre langue, disons Y, de sorte qu'il prenne une entrée pour la langue X et crache du code assembleur, ou du code intermédiaire, ou même code objet de la machine sur laquelle le compilateur s'exécute. Vous souhaitez que la langue Y soit aussi similaire que possible à la langue X, car à un moment donné, vous traduirez du code écrit en Y en X.

Mais vous ne voulez pas écrire plus de compilateur dans le langage Y que nécessaire, donc pour commencer, vous n'implémentez qu'un sous-ensemble du langage - éliminant les constructions redondantes. Dans le cas d'un langage de type «C», while mais no for or do while . si mais pas de cas ou tertiaire op. Pas de structures, d'unions ou d'énumérations. Etc. Il vous reste juste assez de langue pour écrire un analyseur et un générateur de code rudimentaire pour la langue X. Ensuite, vérifiez la sortie. Encore.

Une fois que cela fonctionne, vous pouvez réécrire la source du compilateur qui a été écrite dans la langue Y dans la langue X et compiler la source de la langue X à l'aide du compilateur écrit dans la langue Y. La sortie sera un nouveau compilateur écrit dans la nouvelle langue X qui compile le langage X, c'est-à-dire qu'il est maintenant auto-hébergé. Cependant, il n'est pas complet car vous n'avez implémenté qu'un sous-ensemble de la langue dans la langue Y.

Alors maintenant, vous ajoutez les fonctionnalités manquantes, en testant chacune (ou un groupe de fonctionnalités) pour qu'elles génèrent du code correct. c'est-à-dire une fois que la fonctionnalité est implémentée dans le compilateur, vous pouvez écrire des programmes de test en utilisant les nouvelles fonctionnalités, les compiler et les tester, mais vous ne devriez pas encore les utiliser dans la source du compilateur. Une fois les nouvelles fonctionnalités vérifiées, vous pouvez ensuite utiliser ces nouvelles fonctionnalités dans la source du compilateur lui-même - en remplaçant peut-être une partie du code original écrit dans le sous-ensemble de langage - recompiler la source du compilateur en utilisant la version avec les nouvelles fonctionnalités.

Vous avez maintenant un mécanisme pour ajouter de nouvelles fonctionnalités au langage - et, une fois que la génération de code pour les fonctionnalités a été vérifiée correctement, elles peuvent être utilisées dans la prochaine génération du compilateur lui-même.

Il y a environ 60 ans, lorsque les ordinateurs sont arrivés sur la scène (et plus tard lorsque les microprocesseurs sont arrivés pour la première fois), il n'y avait pas d'autres langues Y adaptées pour implémenter le compilateur initial. Ainsi, les premiers compilateurs devaient être écrits en code assembleur, puis lorsque suffisamment de compilateur était en cours d'exécution, le code assembleur serait remplacé par la version écrite dans un nouveau langage. Pas d'assembleur non plus? L'ensemble du processeur a baissé d'un autre niveau, l'assembleur étant initialement écrit en code machine .


2

Est-il possible de produire un langage de programmation qui n'est pas bien conçu pour écrire un compilateur mais qui est bien conçu pour un autre but?

En regardant un langage comme SQL, je suppose que la réponse est oui. Mais les langues de cette nature ne sont pas d'usage général.


1
Accepté: écrire un compilateur C en SQL.
Qix

2

Qui dit ça? ... de toute façon, c'est juste une opinion. Certains pourraient être d'accord, d'autres non, il n'y a pas de bien ou de mal ici. Certaines langues ont des compilateurs écrits en eux-mêmes, d'autres non. Peu importe.

Néanmoins, je pense que c'est un bon exercice / preuve de concept si un langage est capable de "s'auto-compiler" ... c'est juste ... agréable ... et cela prouve que le langage est adapté pour faire des choses complexes.

Je voudrais également mentionner qu'en dépit de sa gentillesse, il existe encore diverses raisons pour lesquelles un compilateur peut être écrit dans une autre langue. Par exemple, la plupart des moteurs javascript ne sont pas écrits en javascript. Il y a plusieurs raisons à cela: intégration avec d'autres logiciels, liaison à des bibliothèques / dépendances existantes, outils supérieurs, performances, code hérité ... Parfois, l'auto-compilation du langage est agréable, mais il est toujours logique de maintenir le compilateur de base dans un autre. Pourtant, le langage en lui-même a du sens. C'est juste que vous ne pouvez généralement pas vous permettre de réaménager un écosystème entier.


2

Clang est écrit en C ++. Il ne serait pas trop difficile de réécrire le compilateur Clang Objective-C dans Objective-C, mais alors ce serait tout à fait inutile. Tout changement dans le compilateur C ++ devrait être refait dans Objective-C et vice versa. Alors pourquoi?

Il y a maintenant un compilateur Clang Swift. Ce compilateur pourrait sûrement être réécrit dans Swift. Mais à quoi cela servirait-il? Pour démontrer que le langage est suffisamment puissant pour y écrire un compilateur? Personne ne se soucie si vous pouvez écrire des compilateurs dans Swift. Les gens ne les soins si vous pouvez écrire des interfaces utilisateur à Swift, et vous démontrable peut.

Si vous avez un compilateur bien testé qui peut facilement être adapté pour compiler différentes langues, il est tout à fait inutile de le réécrire dans différentes langues, à moins que la réécriture dans une langue différente ne facilite le travail avec le compilateur. Et s'il était logique d'écrire Clang dans Swift, par exemple, alors les compilateurs Clang C, C ++ et Objective-C seraient tous écrits en Swift.

Il y a des choses plus importantes à faire que de prouver que vous pouvez écrire un compilateur dans un langage de programmation.


1

Cela montre que le langage est capable de traiter des chaînes complexes et de se traduire dans une autre langue / de s'interpréter lui-même.

Dans le processus de création d'un compilateur (le premier grand projet), il y aura un problème qui viendra au premier plan.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.