184 votes

Comment un compilateur peut-il se compiler?

Je fais des recherches sur CoffeeScript sur le site Web http://coffeescript.org/ et le texte

Le compilateur CoffeeScript est lui-même écrit en CoffeeScript

Comment un compilateur peut-il se compiler ou qu'est-ce que cette déclaration signifie?

236voto

Ben N Points 2567

La première édition d'un compilateur ne peut pas être générée par l'ordinateur à partir d'un langage de programmation spécifique; votre confusion est compréhensible. Une version ultérieure du compilateur avec plus de fonctionnalités de la langue (avec source réécrit dans la première version de la nouvelle langue) pourraient être construits par le compilateur. Cette version peut ensuite compiler le prochain compilateur, et ainsi de suite. Voici un exemple:

  1. La première CoffeeScript compilateur est écrit en Ruby, la production de la version 1 de CoffeeScript
  2. Le code source de la CS compilateur est réécrit en CoffeeScript 1
  3. L'original du CS compilateur compile le nouveau code (écrit dans CS 1) dans la version 2 du compilateur
  4. Des modifications sont apportées au compilateur de code source pour ajouter de nouvelles fonctionnalités de langage
  5. La deuxième CS compilateur (le premier écrit en CS) compile la version révisée du nouveau code source dans la version 3 du compilateur
  6. Répétez les étapes 4 et 5 pour chaque itération

Note: je ne suis pas sûr exactement comment CoffeeScript versions sont numérotées, qui était juste un exemple.

Ce processus est généralement appelé amorçage. Un autre exemple de l'amorçage est un compilateur rustc, le compilateur pour la Rouille de la langue.

61voto

200_success Points 963

Dans le livre des Réflexions sur la Confiance la Confiance, Ken Thompson, l'un des initiateurs de Unix, écrit un fascinant (et lisible) aperçu de la façon dont le compilateur C compile lui-même. Des concepts similaires peuvent être appliquées à CoffeeScript ou toute autre langue.

L'idée d'un compilateur qui établit son propre code ressemble vaguement à un quine: source code qui, lorsqu'il est exécuté, produit en sortie le code source d'origine. Voici un exemple d'un CoffeeScript quine. Thompson a donné cet exemple de C quine:

char s[] = {
    '\t',
    '0',
    '\n',
    '}',
    ';',
    '\n',
    '\n',
    '/',
    '*',
    '\n',
    … 213 lines omitted …
    0
};

/*
 * The string s is a representation of the body
 * of this program from '0'
 * to the end.
 */

main()
{
    int i;

    printf("char\ts[] = {\n");
    for(i = 0; s[i]; i++)
        printf("\t%d,\n", s[i]);
    printf("%s", s);
}

Ensuite, vous pourriez vous demander comment le compilateur est enseigné qu'une séquence d'échappement comme '\n' représente le code ASCII 10. La réponse est que, quelque part dans le compilateur C, il y a une routine qui interprète les chaînes de caractères, contenant certaines conditions comme ça, à reconnaître barre oblique inverse séquences:

…
c = next();
if (c != '\\') return c;        /* A normal character */
c = next();
if (c == '\\') return '\\';     /* Two backslashes in the code means one backslash */
if (c == 'r')  return '\r';     /* '\r' is a carriage return */
…

Donc, nous pouvons en ajouter une condition pour le code ci-dessus...

if (c == 'n')  return 10;       /* '\n' is a newline */

... pour produire un compilateur sait qu' '\n' représente ASCII 10. Il est intéressant de noter, que le compilateur, et de tous les compilateurs compilé par elle, "les savons" que la cartographie, donc dans la prochaine génération du code source, vous pouvez modifier cette dernière ligne en

if (c == 'n')  return '\n';

... et il va faire la bonne chose! L' 10 vient de le compilateur, et n'a plus besoin d'être explicitement définie dans le compilateur de code source.1

C'est un exemple de langage C fonctionnalité qui a été mis en œuvre dans le code C. Maintenant, répétez ce processus pour chaque fonctionnalité du langage, et vous avez un "auto-hébergement" compilateur un compilateur C qui est écrit en C.


1 Le plot twist décrit dans ce document est que depuis que le compilateur peut être "enseigné" faits comme cela, il peut aussi être mal-appris à générer trojaned exécutables dans une manière qui est difficile à détecter, et un tel acte de sabotage peut persister dans tous les compilateurs produite par les tarés du compilateur.

29voto

Jörg W Mittag Points 153275

Vous avez déjà eu une très bonne réponse, cependant, je veux vous offrir un point de vue différent, qui nous l'espérons être instructif pour vous. Nous allons tout d'abord établir deux faits que nous pouvons tous les deux d'accord sur:

  1. La CoffeeScript compilateur est un programme qui permet de compiler des programmes écrits en CoffeeScript.
  2. La CoffeeScript compilateur est un programme écrit en CoffeeScript.

Je suis sûr que vous pouvez être d'accord que les deux #1 et #2 sont remplies. Maintenant, regardez les deux états. Voyez-vous maintenant qu'il est tout à fait normal pour la CoffeeScript compilateur pour être en mesure de compiler les CoffeeScript compilateur?

Le compilateur ne se soucie pas de ce qu' il compile. Tant que c'est un programme écrit en CoffeeScript, il peut le compiler. Et la CoffeeScript compilateur lui-même se trouve être un tel programme. La CoffeeScript compilateur ne se soucie pas que c'est la CoffeeScript compilateur lui-même, il est en cours de compilation. Tous voit il est certains CoffeeScript code. Période.

Comment un compilateur compiler lui-même, ou ce que fait cette déclaration signifie?

Oui, c'est exactement ce que cela signifie, et j'espère que vous pouvez voir maintenant comment cette affirmation est vraie.

9voto

Polygnome Points 4766

Comment un compilateur compiler lui-même, ou ce que fait cette déclaration signifie?

Il veut dire exactement. Tout d'abord, quelques points à considérer. Il y a quatre objets, nous avons besoin de regarder:

  • Le code source de tout arbitraire CoffeScript programme
  • L' (produits) de l'assemblée de tout arbitraire CoffeScript programme
  • Le code source du compilateur CoffeScript
  • L' (produits) de l'assemblée de la CoffeScript compilateur

Maintenant, il devrait être évident que vous pouvez utiliser l'assembly généré le fichier exécutable de l'CoffeScript compilateur pour compiler tout arbitraire CoffeScript programme, et de générer de l'assemblée pour que programme de.

Maintenant, la CoffeScript compilateur lui-même est juste un arbitraire CoffeScript programme, et ainsi, il peut être compilé par le CoffeScript compilateur.

Il semble que votre confusion vient du fait que lorsque vous créez votre propre langue, vous n'avez pas avoir un compilateur pourtant, vous pouvez l'utiliser pour compiler votre compilateur. Cela semble sûrement comme un poulet-oeuf problème, non?

Introduire le processus appelé amorçage.

  1. Vous écrire un compilateur en un déjà existant de la langue (dans le cas de CoffeScript, l'original, le compilateur a été écrit en Ruby) qui permet de compiler un sous-ensemble de la nouvelle langue
  2. Vous écrire un compilateur qui permet de compiler un sous-ensemble de la nouvelle langue dans la nouvelle langue elle-même. Vous pouvez uniquement utiliser les fonctionnalités de langage le compilateur à partir de l'étape ci-dessus permet de compiler.
  3. Vous utilisez le compilateur à partir de l'étape 1 pour compiler le compilateur à partir de l'étape 2. Cela vous laisse avec une assemblée qui a été écrit à l'origine dans un sous-ensemble de la langue, et qui est en mesure de compiler un sous-ensemble de la nouvelle langue.

Maintenant, vous devez ajouter de nouvelles fonctionnalités. Disons que vous avez mis en œuvre qu' while-boucles, mais aussi souhaitez for-boucles. Ce n'est pas un problème, puisque vous pouvez réécrire for-boucle de telle manière que c'est un while-boucle. Cela signifie que vous ne pouvez utiliser while-boucles dans le code source de votre compilateur, depuis l'assemblée, vous avez à portée de main ne peut compiler ces. Mais vous pouvez créer des fonctions à l'intérieur de votre compilateur qui peut pase et compiler for-boucles avec elle. Ensuite, vous utilisez l'assemblée que vous avez déjà, et de compiler la nouvelle version de compilateur. Et maintenant, vous avez un assemblage d'un compilateur qui peut également analyser et de compiler for-boucles! Vous pouvez maintenant aller vers le fichier source de votre compilateur, et réécrire while-boucles que vous ne voulez pas en for-boucles.

Rincez et répétez jusqu'à ce que toutes les fonctionnalités de la langue que l'on souhaite peut être compilé avec le compilateur.

while et for étaient évidemment que des exemples, mais cela fonctionne pour toute nouvelle fonctionnalité que vous souhaitez. Et ensuite, vous êtes dans la situation CoffeScript est maintenant: Le compilateur compile lui-même.

Il ya beaucoup de littérature. Réflexions sur la Confiance la Confiance est un classique pour tous ceux qui s'intéressent à ce sujet devrait lire au moins une fois.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X