Développer un langage dynamique


11

J'ai créé plusieurs compilateurs écrits à la main pour des langages très simples mais maintenant je veux m'essayer au développement d'un langage dynamique, similaire à un Python ou Ruby simplifié. Cependant, il m'a été facile de comprendre comment fonctionnent les compilateurs. Les compilateurs primitifs ne font que traduire. Mais je ne peux pas faire ça si la langue est dynamique. Je dois écrire un interprète ou une machine virtuelle qui garde la trace des informations au moment de l'exécution et me met beaucoup plus de travail.

En bref, y a-t-il des ressources que je devrais vérifier étant donné que je sais comment fonctionnent les compilateurs mais que je souhaite migrer vers la création d'un interprète? Il existe quelques machines virtuelles pour les langages dynamiques, mais je n'ai aucun problème avec le mien. C'est juste pour mon expérience personnelle.

Je cherche des informations sur la façon de passer d'un compilateur à un interprète. Si j'ai déjà fait un compilateur pour la langue X mais maintenant quoi écrire un interprète, que faut-il faire et y a-t-il des ressources qui vont au cours du processus?

Je ne veux pas de ressources étendues ou abstraites sur le fonctionnement des compilateurs ou des machines virtuelles. J'ai plein de manuels sur le sujet. Toutes les ressources que j'ai trouvées en ligne supposent que vous avez 0 expérience et vous commencent donc par une analyse lexicale ou syntaxique ou elles sont extrêmement abstraites. J'ai un compilateur qui fonctionne, mais je veux maintenant le transformer en interprète et ajouter des fonctionnalités dynamiques au langage.

Je n'ai pas pu trouver de ressources sur ce processus, il peut être de portée trop limitée, ou de ressources sur le "back end" d'un interprète sans être trop théorique c'est pourquoi j'ai posté ici.


1
Il y a des tonnes de ressources comme ça. Notez que la ligne entre le compilateur et l'interpréteur est plus floue que vous ne le pensez; le compilateur C # 4.0 prend en charge la programmation dynamique, comme le font un certain nombre d'autres compilateurs.
Robert Harvey

@RobertHarvey Oui, ce que je demande, c'est des ressources pour créer mon propre temps d'exécution / interprète / machine virtuelle. L'interprète .Net est beaucoup trop compliqué pour moi de baser le mien!
Austin Henley


1
Et consultez cette question SO , il y a quelques commentaires avec des références à d'autres questions qui sont assez intéressantes ...
yannis

Réponses:


4

Apprenez d'abord à implémenter des interprètes. Je recommande PLAI (langages de programmation: application et interprétation) . Il arrive rapidement à la chair d'interprétation sans s'attarder trop sur la syntaxe.

Pour votre langage, vous pourrez réutiliser la bibliothèque frontale du compilateur (analyseur, principalement) et la bibliothèque d'exécution (GC, structures de données, opérations primitives, etc.).

Bien sûr, vous pouvez également implémenter un langage dynamique avec un compilateur qui produit du code qui manipule (certaines) les mêmes structures de données que vous utiliseriez dans un interpréteur. Par exemple, dans un interpréteur, vous pouvez implémenter des variables globales sous forme de table de hachage indexée sur des chaînes. Dans un compilateur, vous compileriez des références de variables globales dans le code qui effectue la recherche en utilisant la même table. En revanche, vous pourriez compiler des variables lexicales dans une représentation plus efficace (arguments "natifs" et références de structure de fermeture).


5

Si vous voulez apprendre les bases de l'implémentation d'un interpréteur pour un langage dynamique, je ne peux pas imaginer un meilleur endroit pour commencer que les origines du tout premier langage de programmation interprété dynamique: Lisp.

Dans son article original de 1960 , John McCarthy a défini 5 fonctions primitives nécessaires à un Lisp. Bien sûr, McCarthy ne voulait que son article sur Lisp comme un exercice académique; c'est un étudiant diplômé qui a implémenté l' evalassemblage et créé le premier interprète Lisp. Paul Graham identifie sept primitives : quote, atom, eq, cons, car, cdr et cond.

Le fait est que vous pouvez vraiment implémenter Lisp dans n'importe quelle langue; une fois que vous avez implémenté eval, il est facile de configurer un REPL et vous disposez d'un interprète interactif . Les gens se sont ennuyés ou ont été assez curieux pour implémenter Lisps en C, Java, Ruby, Python et bien d'autres langages. Et pas toujours exprès; il est important de se rappeler la dixième règle de Greenspun :

Tout programme C ou Fortran suffisamment compliqué contient une implémentation ad hoc, spécifiée de manière informelle, remplie de bogues et lente de la moitié de Common Lisp.

Je ne dis pas que votre objectif final devrait être une implémentation Lisp; mais l'homoiconicité a ses avantages lorsqu'on apprend à mettre en œuvre un langage dynamique; pourquoi faire face à des problèmes de syntaxe quand vous pouvez apprendre sur une langue dans laquelle la syntaxe idiomatique est identique à l'AST d'une langue qui utilise un lexer / analyseur?

Quoi qu'il en soit ... juste une suggestion. Mais c'est à juste titre que la plupart des grands langages de programmation depuis C ont au moins un peu de nature Lisp.


1
J'aimerais pouvoir accepter deux réponses. Merci, je pense que je vais vraiment implémenter un interpréteur Lisp. Il est facile à analyser, a une tonne de documentation et de code existant et devrait me donner une base pour travailler avec. Malheureusement, j'ai pris un cours de premier cycle qui utilisait Scheme et cela m'a fait arracher mes cheveux;)
Austin Henley

1
Je suis maintenant tenté de compiler ma langue dans mon propre dialecte de lisp!
Austin Henley


0

J'ai mis cela (~ 600 lignes de C #) dans le domaine public, qui prend en charge quote / list / apply / eval / test / etc, et permet de personnaliser facilement une syntaxe de type Lisp et / ou les constructions sémantiques:

https://repl.it/CdjV/3

Par exemple:

        var factorial = (Lambda)language.
            Evaluate
            (@"
                ( => ( n ) (
                        ? ( != n 0 )
                        ( * n ( this ( - n 1 ) ) )
                        1
                    )
                )
            ");

        var sw = new System.Diagnostics.Stopwatch();
        var n = 12;
        var r = 0;
        int k;
        sw.Start();
        for (k = 0; k < 10000; k++)
        {
            r = (int)factorial.Invoke(null, n);
        }
        sw.Stop();
        Console.WriteLine("{0}! = {1}", n, r);
        Console.WriteLine();
        Console.WriteLine("in {0} ms (for {1} times)", sw.ElapsedMilliseconds, k.ToString("0,0"));

«HTH,


0

En supposant que vous connaissiez un peu Scheme (par exemple avoir lu SICP ) ou Lisp, je recommande le livre Lisp In Small Pieces de Queinnec . Il explique plusieurs variantes d'interprètes et de compilateurs de type Lisp (y compris le bytecode ou le C).

Lisez également la programmation du langage de programmation de Scott , le dernier Dragon Book , le manuel du GC , les types et les langages de programmation de Pierce .

Je cherche des informations sur la façon de passer d'un compilateur à un interprète.

Ensuite, une évaluation partielle (et projections Futamura) et un style de passage de continuation pourraient être pertinents.

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.