web-dev-qa-db-fra.com

Pourquoi ne stockons-nous pas l'arbre de syntaxe au lieu du code source?

Nous avons beaucoup de langages de programmation. Chaque langue est analysée et la syntaxe vérifiée avant d'être traduite en code, de sorte qu'un arbre de syntaxe abstraite (AST) est construit.

Nous avons cet arbre de syntaxe abstrait, pourquoi ne stockons-nous pas cet arbre de syntaxe à la place du code source (ou à côté du code source)?

En utilisant un AST au lieu du code source. Chaque programmeur d'une équipe peut sérialiser cet arbre dans la langue de leur choix (avec la grammaire libre de contexte appropriée) et analyser à AST lorsqu'ils sont terminés. Cela éliminerait donc le débat sur les questions de style de codage (où mettre les {et}, où mettre les espaces, l'indentation, etc.)

Quels sont les avantages et les inconvénients de cette approche?

115
Calmarius

Pourquoi ne stockons-nous pas cet arbre de syntaxe au lieu du code source? Chaque programmeur dans une équipe peut sérialiser cet arbre dans n'importe quelle langue, il le souhaite et l'analyser à AST quand il a terminé.

En effet, c'est une idée raisonnable. Microsoft avait n projet de recherche dans les années 1990 pour faire presque exactement cela .

Plusieurs scénarios me viennent à l'esprit.

Le premier est plutôt trivial; comme vous le dites, vous pourriez avoir le AST rendu dans différentes vues en fonction des préférences des différents programmeurs pour des choses comme l'espacement et ainsi de suite. Mais stocker un AST est exagéré pour ce scénario; écrivez-vous simplement une jolie imprimante. Lorsque vous chargez un fichier dans votre éditeur, exécutez la jolie imprimante pour le mettre dans votre format préféré, puis revenez au format d'origine lorsque vous l'enregistrez.

Le second est plus intéressant. Si vous pouvez stocker l'arborescence de syntaxe abstraite, une modification de code ne devient pas textuelle mais plutôt syntaxique. Les refactorisations où le code est déplacé deviennent beaucoup plus faciles à comprendre. L'inconvénient est bien sûr que l'écriture des algorithmes d'arbre-diff n'est pas exactement triviale et doit souvent être effectuée sur une base par langue. Le texte diff fonctionne pour presque toutes les langues.

Le troisième ressemble plus à ce que Simonyi envisageait pour la programmation intentionnelle: que les concepts fondamentaux communs aux langages de programmation sont ceux qui sont sérialisés, puis vous avez différentes vues de ces concepts rendues dans différents langages. Bien que ce soit une belle idée, le fait est que les langues sont suffisamment différentes dans leurs détails pour qu'une approche au plus petit dénominateur commun ne fonctionne pas vraiment.

Donc, en bref, c'est une belle idée, mais c'est une énorme quantité de travail supplémentaire pour un avantage relativement faible. C'est pourquoi presque personne ne le fait.

48
Eric Lippert

Vous pourriez faire valoir que c'est exactement ce que le code d'octet est dans .NET. Le programme de réflecteur d'Infact redgate convertit le code d'octet en une gamme de langages de programmation .NET.

Cependant, il y a des problèmes. La syntaxe est spécifique à la langue dans la mesure où il y a des choses que vous pouvez représenter dans une langue qui n'ont aucune représentation dans d'autres langues. Cela se produit dans .NET avec C++ étant le seul langage .NET qui a accès aux 7 niveaux d'accès.

En dehors de l'environnement .NET, cela devient beaucoup plus délicat. Chaque langue commence alors à avoir son propre ensemble de bibliothèques associées. Il ne serait pas possible de refléter une syntaxe générique à la fois en C et Java qui reflétait la même exécution d'instructions car elles résolvent des problèmes simulaires de manières très différentes.

20
Michael Shaw

Je pense que les points les plus saillants sont ceux-ci:

  • Il n'y a aucun avantage. Vous avez dit que cela signifierait que tout le monde pourrait utiliser la langue de son animal de compagnie. Mais ce n'est pas vrai - l'utilisation d'une représentation d'arborescence de syntaxe éliminerait uniquement les différences syntaxiques, mais pas les différences sémantiques. Cela fonctionne dans une certaine mesure pour des langages très similaires - tels que VB et C #, ou Java et Scala. Mais pas même complètement).

  • C'est problématique. Vous avez acquis la liberté de langage, mais vous avez perdu la liberté des outils. Vous ne pouvez plus lire et modifier le code dans un éditeur de texte, ni même aucun IDE - vous dépendez d'un outil spécifique qui parle votre AST représentation pour la lecture et l'édition du code. Il n'y a rien gagné ici.

    Pour illustrer ce dernier point, jetez un œil à RealBasic, qui est une implémentation propriétaire d'un puissant dialecte BASIC. Pendant un certain temps, il semblait presque que la langue pouvait décoller, mais elle dépendait complètement du fournisseur, au point que vous ne pouviez afficher le code que dans leur IDE car il a été enregistré dans un format propriétaire non textuel. Grande erreur .

14
Konrad Rudolph

J'aime un peu votre idée, mais vous surestimez considérablement la facilité de traduction d'une langue à l'autre. Si c'était aussi simple, vous n'auriez même pas besoin de stocker l'AST, car vous pourriez toujours analyser la langue X dans le AST puis passer de AST to langue Y.

Cependant, je souhaite que les spécifications du compilateur réfléchissent un peu plus à l'exposition d'une partie de la AST via une sorte d'API. Des choses comme la programmation orientée aspect, la refactorisation et l'analyse de programme statique pourraient être implémentées via une telle API, sans que l'implémenteur de ces capacités doive refaire une grande partie du travail déjà implémenté par les rédacteurs du compilateur.

Il est étrange de voir combien de fois la structure de données du programmeur pour représenter un programme est un groupe de fichiers contenant des chaînes.

13
psr

Je pense que si vous stockez à la fois le texte et l'AST, vous n'avez pas vraiment ajouté quoi que ce soit d'utile, car le texte est déjà là dans une langue, et le AST peut être rapidement reconstruit à partir de le texte.

D'un autre côté, si vous ne stockez que l'AST, vous perdez des choses comme les commentaires qui ne peuvent pas être récupérés.

6
Tesserex

Il existe un système construit autour de cette idée: JetBrains MPS . Un éditeur est un peu bizarre, ou juste différent, mais en général ce n'est pas un gros problème. Le plus gros problème est, eh bien, qu'il ne s'agit plus d'un texte, vous ne pouvez donc pas utiliser les outils de texte normaux - autres éditeurs, grep, sed, merge et outils de diff, etc.

5
SK-logic

Il existe en fait plusieurs produits, généralement connus sous le nom d '"ateliers de langue" qui stockent les AST et présentent, dans leurs éditeurs, une "projection" de la AST retour dans une langue particulière. Comme @ sk-logic a déclaré, le MPS de JetBrains est l'un de ces systèmes. Un autre est Intentional Software's Intentional Workbench.

Le potentiel pour les ateliers linguistiques semble très élevé, en particulier dans le domaine des langues spécifiques au domaine, car vous pouvez créer une projection spécifique au domaine. Par exemple, Intentional présente une DSL relative à l'électricité qui se projette comme un schéma de circuit - beaucoup plus facile et plus précis pour un expert du domaine à discuter et à critiquer qu'un circuit décrit dans un langage de programmation textuel.

Dans la pratique, les établis de langage ont été lents à se développer car, à part le travail DSL, les développeurs préféreraient probablement travailler dans un langage de programmation général et familier. Comparés en tête-à-tête avec un éditeur de texte ou un IDE de programmation, les ateliers de langue ont des tonnes de frais généraux et leurs avantages ne sont pas aussi clairs. Aucun des ateliers linguistiques que j'ai vus ne s'est lui-même amorcé au point de pouvoir facilement étendre ses propres IDE - c'est-à-dire, si les ateliers linguistiques sont excellents pour la productivité, pourquoi les outils de l'atelier linguistique ne sont-ils pas devenus meilleurs -et mieux à des taux de plus en plus rapides?

5
Larry OBrien

Je pense que l'idée est intéressante en théorie mais pas très pratique car différents langages de programmation prennent en charge différentes constructions dont certaines n'ont pas d'équivalents dans d'autres langages.

Par exemple, X ++ a une instruction 'while select' qui ne pourrait pas être écrite en C # sans beaucoup de code supplémentaire (classes supplémentaires, logique supplémentaire, etc.). http://msdn.Microsoft.com/en-us/library/aa558063.aspx

Ce que je dis ici, c'est que de nombreux langages ont des sucres syntaxiques qui se traduisent en gros blocs de code du même langage ou même des éléments qui n'existent pas du tout dans d'autres. Voici un exemple pour lequel l'approche AST ne fonctionnera pas:

La langue X a un mot clé K qui est traduit, en AST en 4 instructions: S1, S2, S3 et S4. Le AST est maintenant traduit en langue Y et un programmeur change S2. Maintenant que se passe-t-il avec la traduction en X? Le code est traduit en 4 instructions au lieu d'un seul mot-clé ...

Le dernier argument contre l'approche AST sont les fonctions de la plateforme: que se passe-t-il lorsqu'une fonction est incorporée dans la plateforme? Comme Environment.GetEnvironmentVariable de .NET. Comment la traduisez-vous?

4
Victor Hurdugaci

Vous avez lu mon esprit.

Lorsque j'ai suivi un cours sur les compilateurs, il y a quelques années, j'ai découvert que si vous prenez un AST et le sérialisez, avec la notation préfixe au lieu de la notation infixe habituelle, et utilisez des parenthèses pour délimiter des instructions entières , vous obtenez LISP. Alors que j'avais appris sur Scheme (un dialecte de LISP) dans mes études de premier cycle, je ne l'avais jamais vraiment apprécié. J'ai définitivement acquis une appréciation pour LISP et ses dialectes, à la suite de cela cours.

Problèmes avec ce que vous proposez:

  1. il est difficile/lent de composer un AST dans un environnement graphique. Après tout, la plupart d'entre nous peuvent taper plus vite que nous ne pouvons déplacer une souris. Et pourtant, une question émergente est "comment écrivez-vous code de programme avec une tablette? "Taper sur une tablette est lent/lourd, par rapport à un clavier/ordinateur portable avec un clavier matériel. Si vous pouviez créer un AST en faisant glisser et en déposant des composants d'une palette sur une toile sur un grand appareil à écran tactile, la programmation sur une tablette pourrait devenir une réalité.

  2. peu/aucun de nos outils existants ne le supportent. Nous avons des décennies de développement pour créer des IDE de plus en plus complexes et des éditeurs de plus en plus intelligents. Nous avons tous ces outils pour reformater le texte, comparer le texte, rechercher du texte. Où sont les outils qui peuvent faire l'équivalent d'une recherche d'expressions régulières dans un arbre? Ou un diff de deux arbres? Toutes ces choses se font facilement avec du texte. Mais ils ne peuvent que comparer les mots. Modifiez un nom de variable, de sorte que les mots soient différents mais que la signification sémantique soit la même, et ces outils de diff rencontrent des problèmes. De tels outils, développés pour fonctionner sur les AST au lieu du texte, vous permettraient de vous rapprocher de la comparaison du sens sémantique. Ce serait une bonne chose.

  3. tout en transformant le code source du programme en un AST est relativement bien compris (nous avons des compilateurs et des interprètes, n'est-ce pas?), en transformant un AST en programme le code n'est pas si bien compris. Multiplier deux nombres premiers pour obtenir un grand nombre composite est relativement simple, mais il est beaucoup plus difficile de factoriser un grand nombre composite en nombres premiers; c'est là que nous en sommes avec l'analyse par rapport à la décompilation des AST. où les différences entre les langues deviennent un problème. Même dans une langue particulière, il existe plusieurs façons de décompiler un AST. Itérer à travers une collection d'objets et obtenir une sorte de résultat, par exemple. Utiliser une boucle for, itérer à travers un tableau? Ce serait compact et rapide, mais il y a des limites. Utiliser un itérateur quelconque, fonctionnant sur une collection? Cette collection peut être de taille variable, ce qui ajoute de la flexibilité aux dépens (possibles) de la vitesse. Map/Reduce? Plus complexe , mais implicitement parallélisable. Et c'est juste pour Java, selon vos préférences.

Avec le temps, l'effort de développement sera étendu et nous développerons en utilisant des écrans tactiles et des AST. La dactylographie deviendra moins une nécessité. Je vois cela comme une progression logique de l'endroit où nous en sommes, en regardant comment nous utilisons les ordinateurs, aujourd'hui, cela résoudra # 1.

Nous travaillons déjà avec des arbres. LISP est simplement des AST sérialisés. XML (et HTML, par extension) n'est qu'un arbre sérialisé. Pour faire la recherche, nous avons déjà quelques prototypes: XPath et CSS (pour XML et HTML, respectivement). Lorsque des outils graphiques sont créés qui nous permettent de créer des sélecteurs et des modificateurs de style CSS, nous aurons résolu une partie de # 2. Lorsque ces sélecteurs pourront être étendus pour prendre en charge les expressions rationnelles, nous serons plus proches. Toujours à la recherche d'un bon outil de comparaison graphique pour comparer deux documents XML ou HTML. Au fur et à mesure que les gens développent ces outils, le n ° 2 sera résolu. Les gens travaillent déjà sur de telles choses; ils ne sont tout simplement pas encore là.

La seule façon que je peux voir pour être en mesure de décompiler ces AST en texte de langage de programmation serait quelque chose de chercher des objectifs. Si je modifie le code existant, l'objectif pourrait être atteint par un algorithme qui rend mon code modifié aussi similaire que possible au code de départ (diff textuel minimal). Si j'écris du code à partir de zéro, l'objectif peut être le code le plus petit et le plus serré (probablement une boucle for). Ou il peut s'agir d'un code qui se parallélise le plus efficacement possible (probablement une carte/réduction ou quelque chose impliquant CSP). Ainsi, le même AST pourrait entraîner un code significativement différent, même dans le même langage, en fonction de la façon dont les objectifs ont été fixés. Le développement d'un tel système résoudrait # 3. Ce serait complexe sur le plan des calculs, ce qui signifie que nous aurions probablement besoin d'une sorte d'arrangement client-serveur, permettant à votre tablette portable de décharger beaucoup de travail sur un serveur cloud.

4
Meower68

--- Deux autres projets intéressants à noter concernant le codage dans l'arbre de syntaxe abstraite sont Tree-Sitter qui fait maintenant partie de l'éditeur de texte Atom et Github. Il analyse votre code en temps réel dans un AST. Cela vous permet de faire des choses très intéressantes, comme quelque chose que son créateur appelle "étendre la sélection" où vous pouvez continuer à cliquer sur un mot et il mettra en évidence le texte lié à des niveaux de plus en plus élevés de le AST car il comprend cette structure .:

enter image description here

Il existe également le langage de programmation nison qui ne stocke pas le code source dans des fichiers texte. Au lieu de cela, il analyse les fichiers texte, supprime tous les détails de sorte que vous vous retrouvez avec une version très abstraite de votre code, puis il hache cela. Ce "code" est ensuite accessible en utilisant le hachage, pas le nom de fichier. Cela conduit à de nombreux avantages intéressants comme plus de builds, plus de conflits de dépendance, et vous pouvez facilement changer les noms des variables/fonctions/etc sans changer la base de code.

Ces deux projets vous permettent de coder à un niveau d'abstraction un peu plus loin du texte brut et plus près de l'AST.

2
BarrettNashville

Il est difficile de lire et de modifier un AST, au lieu du code source.

Cependant, certains outils liés au compilateur permettent d'utiliser l'AST. Java bytecode et .NET Intermediate code fonctionnent comme un AST.

1
umlcat

Si votre intention est d'éliminer le débat sur les styles de formatage, alors peut-être que vous voulez un éditeur qui lit dans un fichier source, le formate selon vos préférences personnelles pour l'affichage et l'édition, mais lors de l'enregistrement, reformate au style choisi l'équipe les usages.

C'est assez simple si vous utilisez un éditeur comme Emacs. Changer le style de formatage d'un fichier entier est un travail à trois commandes.

Vous devriez également pouvoir créer les crochets pour transformer automatiquement un fichier en votre propre style lors du chargement, et le transformer en style d'équipe lors de l'enregistrement.

1
Gustav Bertram

c'est une bonne idée; mais le AST de chaque langue est différent de tous les autres).

la seule exception que je connaisse concerne VB.NET et C #, où Microsoft soutient qu'ils sont "exactement le même langage avec une syntaxe différente". Même d'autres langages .NET (IronPython, F #, peu importe) sont différents au niveau AST.

Même chose avec les langages JVM, ils ciblent tous le même bytecode, mais les constructions de langage sont différentes, ce qui en fait des langages différents et des AST différents.

Même les langages "couche mince", comme CoffeScript et Xtend partagent une grande partie de la théorie des langages sous-jacents (JavaScript et Java, respectivement); mais introduisez des concepts de niveau supérieur qui sont (ou devraient être) conservés au niveau AST.

si Xtend pouvait être reconstruit à partir d'un Java AST, je pense qu'il aurait été défini comme un "décompilateur" Java vers Xtend qui crée comme par magie des abstractions de niveau supérieur à partir de Java code, vous ne pensez pas?

0
Javier