J'ai entendu parler de l'idée d'amorcer un langage, c'est-à-dire d'écrire un compilateur / interpréteur pour le langage en lui-même. Je me demandais comment cela pouvait être accompli et j'ai regardé un peu autour de moi, et j'ai vu quelqu'un dire que cela ne pouvait être fait que par l'un ou l'autre
- écrire un compilateur initial dans une langue différente.
- coder à la main un compilateur initial dans Assembly, ce qui semble être un cas particulier du premier
Pour moi, ni l'un ni l'autre ne semblent réellement bootstrap sur un langage dans le sens où ils ont tous deux besoin d'un soutien extérieur. Existe-t-il un moyen d'écrire un compilateur dans son propre langage?
Réponses:
Vous devez avoir un langage existant pour écrire votre nouveau compilateur. Si vous écriviez un nouveau compilateur, disons, C ++, vous l'écririez simplement en C ++ et le compileriez d'abord avec un compilateur existant. D'un autre côté, si vous créez un compilateur pour un nouveau langage, appelons-le Yazzleof, vous devrez d'abord écrire le nouveau compilateur dans un autre langage. En général, ce serait un autre langage de programmation, mais ce n'est pas obligatoire. Il peut s'agir d'un assemblage ou, si nécessaire, d'un code machine.
Si vous étiez allez démarrer un compilateur pour Yazzleof, vous généralement pas écrire un compilateur pour le langage complet au départ. Au lieu de cela, vous écririez un compilateur pour Yazzle-lite, le plus petit sous-ensemble possible du Yazzleof (enfin, un assez petit sous-ensemble au moins). Ensuite, dans Yazzle-lite, vous écririez un compilateur pour le langage complet. (Évidemment, cela peut se produire de manière itérative au lieu d'un saut.) Puisque Yazzle-lite est un sous-ensemble approprié de Yazzleof, vous avez maintenant un compilateur qui peut se compiler.
Il existe un très bon article sur l'amorçage d'un compilateur à partir du niveau le plus bas possible (qui sur une machine moderne est essentiellement un éditeur hexadécimal), intitulé Bootstrapping un simple compilateur à partir de rien . Il peut être trouvé à https://web.archive.org/web/20061108010907/http://www.rano.org/bcompiler.html .
la source
L'explication que vous avez lue est correcte. Il y a une discussion à ce sujet dans Compilers: Principles, Techniques, and Tools (the Dragon Book):
la source
Une super intéressante discussion de c'est sous Unix co-créateur Ken Thompson de Turing Award conférence.
Il commence par:
et continue à montrer comment il a écrit une version du compilateur Unix C qui lui permettrait toujours de se connecter sans mot de passe, car le compilateur C reconnaîtrait le programme de connexion et ajouterait un code spécial.
la source
La façon dont j'ai entendu parler est d'écrire un compilateur extrêmement limité dans un autre langage, puis de l'utiliser pour compiler une version plus compliquée, écrite dans le nouveau langage. Cette seconde version peut ensuite être utilisée pour se compiler, et la version suivante. Chaque fois qu'il est compilé, la dernière version est utilisée.
C'est la définition du bootstrapping:
EDIT: L' article de Wikipedia sur l'amorçage du compilateur couvre le concept mieux que moi.
la source
Regardez l' épisode 61 du podcast Software Engineering Radio (2007-07-06) qui traite des composants internes du compilateur GCC, ainsi que du processus de bootstrap de GCC.
la source
Donald E. Knuth a en fait construit WEB en y écrivant le compilateur, puis en le compilant manuellement en code assembleur ou machine.
la source
Si je comprends bien, le premier interpréteur Lisp a été amorcé en compilant manuellement les fonctions du constructeur et le lecteur de jetons. Le reste de l'interprète a ensuite été lu à partir de la source.
Vous pouvez vérifier vous - même en lisant le papier McCarthy original, récursives Fonctions des expressions symboliques et leur calcul par la machine, la partie I .
la source
Une autre alternative est de créer une machine bytecode pour votre langage (ou d'utiliser une machine existante si ses fonctionnalités ne sont pas très inhabituelles) et d'écrire un compilateur en bytecode, soit dans le bytecode, soit dans la langue de votre choix en utilisant un autre intermédiaire - tel qu'un boîte à outils d'analyseur qui génère l'AST au format XML, puis compile le XML en bytecode en utilisant XSLT (ou un autre langage de correspondance de modèle et une représentation arborescente). Cela ne supprime pas la dépendance à une autre langue, mais pourrait signifier qu'une plus grande partie du travail d'amorçage se termine dans le système final.
la source
C'est la version informatique du paradoxe de la poule et de l'œuf. Je ne peux pas penser à un moyen de ne pas écrire le compilateur initial en assembleur ou dans un autre langage. Si cela avait pu être fait, j'aurais dû que Lisp l'aurait fait.
En fait, je pense que Lisp est presque qualifié. Découvrez son entrée Wikipédia . Selon l'article, la fonction Lisp eval pourrait être implémentée sur un IBM 704 en code machine, avec un compilateur complet (écrit en Lisp lui-même) qui verrait le jour en 1962 au MIT .
la source
Chaque exemple d'amorçage d'un langage auquel je peux penser ( C , PyPy ) a été réalisé après qu'un compilateur fonctionne. Il faut commencer quelque part, et réimplémenter un langage en lui-même nécessite d'abord d'écrire un compilateur dans un autre langage.
Sinon, comment cela fonctionnerait-il? Je ne pense pas qu'il soit même conceptuellement possible de faire autrement.
la source
Certains compilateurs ou systèmes bootstrap gardent à la fois le formulaire source et le formulaire objet dans leur référentiel:
ocaml est un langage qui possède à la fois un interpréteur de bytecode (ie un compilateur vers le bytecode Ocaml) et un compilateur natif (vers x86-64 ou ARM, etc ... assembleur). Son référentiel svn contient à la fois le code source (fichiers
*/*.{ml,mli}
) et la forme bytecode (fichierboot/ocamlc
) du compilateur. Ainsi, lorsque vous le construisez, il utilise d'abord son bytecode (d'une version précédente du compilateur) pour se compiler. Plus tard, le bytecode fraîchement compilé est capable de compiler le compilateur natif. Ainsi, le référentiel Ocaml svn contient à la fois les*.ml[i]
fichiers source et leboot/ocamlc
fichier bytecode.Le compilateur rust télécharge (en utilisant
wget
, vous avez donc besoin d'une connexion Internet fonctionnelle) une version précédente de son binaire pour se compiler.MELT est un langage de type Lisp pour personnaliser et étendre GCC . Il est traduit en code C ++ par un traducteur amorcé. Le code C ++ généré du traducteur est distribué, de sorte que le référentiel svn contient à la fois les
*.melt
fichiers source et les fichiersmelt/generated/*.cc
"objet" du traducteur.Le système d'intelligence artificielle CAIA de J.Pitrat est entièrement auto-générateur. Il est disponible sous la forme d'une collection de milliers de
[A-Z]*.c
fichiers générés (également avec undx.h
fichier d'en-tête généré ) avec une collection de milliers de_[0-9]*
fichiers de données.Plusieurs compilateurs Scheme sont également bootstrapés. Scheme48, Poulet Scheme, ...
la source