Nous avons beaucoup de langages de programmation. Chaque langue est analysée et sa syntaxe vérifiée avant d'être traduite en code afin qu'un arbre de syntaxe abstraite (AST) soit construit.
Nous avons cet arbre de syntaxe abstrait, pourquoi ne stockons-nous pas cet arbre de syntaxe au lieu 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 son choix (avec la grammaire dépourvue de contexte appropriée) et revenir à AST une fois terminé. Cela éliminerait donc le débat sur les questions de style de codage (où placer le {et}, où mettre les espaces, l'indentation, etc.)
Quels sont les avantages et les inconvénients de cette approche?
language-agnostic
Calmarius
la source
la source
Réponses:
Espace et commentaires
Généralement, un AST n'inclut pas les espaces, les fins de ligne et les commentaires.
Formatage significatif
Vous avez raison de dire que dans la plupart des cas, il s’agit d’un élément positif (élimine le formatage des guerres saintes), il existe de nombreux cas où le formatage du code original confère une certaine signification, comme dans les littéraux de chaîne multiligne et les "paragraphes de code" (séparant les blocs de texte). déclarations avec une ligne vide).
Code qui ne peut pas être compilé
Bien que de nombreux analyseurs résistent très bien à la syntaxe manquante, le code comportant des erreurs entraîne souvent un arbre de syntaxe très étrange, ce qui est très utile jusqu'à ce que l'utilisateur recharge le fichier. Avez-vous déjà fait une erreur dans votre IDE et tout d’un coup l’ensemble du fichier a des "gribouillis"? Imaginez comment cela serait rechargé dans une autre langue.
Peut-être que les utilisateurs ne commettent pas de code imparable, mais ils ont certainement besoin de sauvegarder localement.
Il n'y a pas deux langues qui correspondent parfaitement
Comme d'autres l'ont souligné, il n'y a presque pas deux langues qui présentent une parité parfaite des caractéristiques. Le plus proche que je puisse penser est VB et C #, ou JavaScript et CoffeeScript, mais même dans ce cas, VB possède des fonctionnalités telles que les littéraux XML qui n'ont pas tout à fait l'équivalent en C #, et la conversion de JavaScript à CoffeeScript peut générer beaucoup de littéraux JavaScript.
Expérience personnelle:Cela est en fait nécessaire dans une application logicielle que j'écris, car les utilisateurs doivent entrer des expressions "anglais simplifié" qui sont converties au format JS en arrière-plan. Nous n’avions envisagé que de stocker la version JS, mais n’avions trouvé aucun moyen acceptable de le charger et de le décharger de manière fiable. "version analysée parfaitement ou pas.
la source
En effet, c'est une idée raisonnable. Microsoft avait un 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, l'AST peut être rendu dans différentes vues en fonction des préférences de différents programmeurs pour des choses comme l'espacement, etc. Mais stocker un AST est excessif pour ce scénario; écrivez simplement une jolie imprimante. Lorsque vous chargez un fichier dans votre éditeur, exécutez la jolie imprimante pour le placer dans le format de votre choix, puis revenez au format d'origine lorsque vous l'enregistrez.
La seconde est plus intéressante. Si vous pouvez stocker l'arbre de syntaxe abstraite, la modification d'une modification par code ne devient pas textuelle mais plutôt syntaxique. Les refactorisations dans lesquelles le code est déplacé deviennent beaucoup plus faciles à comprendre. L’inconvénient est bien sûr que l’écriture des algorithmes tree-diff n’est pas vraiment triviale et doit souvent être faite langue par langue. Les différences de texte fonctionnent pour presque toutes les langues.
La troisième ressemble plus à ce que Simonyi envisageait pour la programmation intentionnelle: les concepts fondamentaux communs aux langages de programmation sont ceux qui sont sérialisés, ce qui donne différentes vues de ces concepts dans des langages différents. Bien que ce soit une belle idée, le fait déplorable est que les détails des langues sont suffisamment différents pour qu’une approche au plus petit dénominateur commun ne fonctionne pas vraiment.
En bref, c’est une belle idée, mais c’est une énorme charge de travail supplémentaire pour un bénéfice relativement modeste. C'est pourquoi presque personne ne le fait.
la source
Vous pourriez faire valoir que c'est exactement ce que le code d'octet est dans .NET. Le programme de réflecteur de redgate de Infact convertit le code d'octet dans 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 et qui n'ont aucune représentation dans d'autres langues. Cela se produit dans .NET, C ++ étant le seul langage .NET ayant accès aux 7 niveaux d'accès.
En dehors de l'environnement .NET, cela devient beaucoup plus compliqué. 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 en Java qui reflétait la même exécution d'instructions puisqu'elles résolvent des problèmes similaires de manière très différente.
la source
J'aime un peu votre idée, mais vous surestimez de manière significative la facilité avec laquelle il est facile de traduire langue. Si cela était aussi simple, vous n’auriez même pas besoin de stocker l’AST, puisqu’il serait toujours possible d’analyser le langage X dans l’AST puis de passer de AST à la langue Y.
Cependant, je souhaite que les spécifications du compilateur pensent un peu plus à exposer une partie de l'AST via une sorte d'API. Des éléments tels que la programmation orientée aspect, le refactoring et l'analyse de programme statique pourraient être implémentés via une telle API, sans que l'implémenteur de ces fonctionnalité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 d'un programmeur pour représenter un programme est constituée d'un ensemble de fichiers contenant des chaînes.
la source
Je pense que les points les plus saillants sont ceux:
Il n'y a aucun avantage. Vous avez dit que cela voudrait dire que tout le monde pourrait utiliser son langage animal de compagnie. Mais ce n'est pas vrai - utiliser une représentation d'arbre de syntaxe ne résoudrait que 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 même pas là complètement.
C'est problématique. Vous avez gagné la liberté de langage, mais vous avez perdu la liberté d’outils. Vous ne pouvez plus lire ni éditer le code dans un éditeur de texte, ni même dans aucun IDE. Vous dépendez d'un outil spécifique qui énonce votre représentation AST pour lire et éditer le 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, on avait presque l'impression que la langue pouvait décoller, mais cela dépendait entièrement du fournisseur, au point que vous ne pouviez afficher que le code dans l'EDI, car il avait été enregistré dans un format propriétaire non textuel. Grosse erreur.
la source
astyle
ou UnniversalIndent. Pas besoin de formats binaires arcanes.Je pense que si vous stockez à la fois le texte et l'AST, vous n'avez rien ajouté d'utile, car le texte existe déjà dans une langue et l'AST peut être rapidement reconstruit à partir du texte.
D'autre part, si vous ne stockez que l'AST, vous perdez des éléments tels que des commentaires qui ne peuvent pas être récupérés.
la source
Je pense que l'idée est intéressante en théorie mais pas très pratique puisque différents langages de programmation supportent des constructions différentes, certaines n'ayant pas d'équivalent 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 beaucoup de langues ont des sucres syntaxiques qui traduisent en gros blocs de code du même langage ou même que des éléments qui n'existent pas du tout dans les autres. Voici un exemple pourquoi l'approche AST ne fonctionnera pas:
La langue X a un mot-clé K traduit, en AST, en 4 énoncés: S1, S2, S3 et S4. L'AST est maintenant traduit en langue Y et un programmeur change de position S2. Maintenant que se passe-t-il avec la traduction vers X? Le code est traduit en 4 instructions au lieu d'un mot clé unique ...
Le dernier argument contre l'approche AST concerne les fonctions de la plate-forme: que se passe-t-il lorsqu'une fonction est intégrée à la plate-forme? Comme la variable Environment.GetEnvironmentVariable de .NET. Comment traduisez-vous?
la source
Il existe un système construit autour de cette idée: JetBrains MPS . Un éditeur est un peu étrange, ou juste différent, mais en général ce n’est pas un gros problème. Le plus gros problème est, bien que ce n'est pas un texte plus, de sorte que vous ne pouvez pas utiliser des outils en texte normal - d' autres éditeurs,
grep
,sed
, fusion et outils diff, etc.la source
Il existe en fait plusieurs produits, généralement appelés "établis de langage", qui stockent les AST et présentent, dans leurs éditeurs, une "projection" de l'AST dans une langue particulière. Comme @ sk-logic l'a dit, le système MPS de JetBrains est l'un de ces systèmes. Un autre est Intentional Workbench d'Intentional Software.
Le potentiel d'assemblages de langues semble très élevé, en particulier dans le domaine des langues spécifiques à un domaine, car vous pouvez créer une projection spécifique à un domaine. Par exemple, Intentional présente un DSL relatif à l’électricité, projeté sous forme de schéma de circuit - bien plus facile et plus précis à discuter et à critiquer pour un expert du domaine qu’un circuit décrit dans un langage de programmation textuel.
En pratique, les ateliers de travail sur les langues ont été lents à comprendre car, à part le travail sur DSL, les développeurs préféreraient probablement travailler dans un langage de programmation général et familier. Lorsqu'ils sont comparés à un éditeur de texte ou à un IDE de programmation, les ateliers de langage ont une surcharge et leurs avantages ne sont pas aussi évidents. Aucun des ateliers de langage que j'ai vus ne s'est étiré au point de pouvoir facilement étendre ses propres IDE. Autrement dit, si les ateliers de langue sont excellents pour la productivité, pourquoi les outils de l'atelier de langage ne deviennent-ils pas meilleurs -et-mieux à des taux de plus en plus rapides?
la source
Vous avez lu dans mes pensées.
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 le Scheme (un dialecte de Lisp) dans mes études de premier cycle, je n'avais jamais vraiment acquis une appréciation de celui-ci. Ce cours m'a permis de mieux comprendre Lisp et ses dialectes.
Problèmes avec ce que vous proposez:
il est difficile / lent de composer un AST dans un environnement graphique. Après tout, la plupart d’entre nous pouvons taper plus vite que nous ne pouvons déplacer une souris. Et pourtant, une question qui se pose est "comment écrivez-vous du code de programme avec une tablette?" Taper sur une tablette est lent / fastidieux, comparé à un clavier / ordinateur portable avec un clavier matériel. Si vous pouviez créer un AST en glissant-déposant des composants d'une palette sur un canevas, sur un grand écran tactile, la programmation sur tablette pouvait devenir une réalité.
peu / aucun de nos outils existants ne supporte cela. Nous avons des décennies de développement dans la création d'EDI de plus en plus complexes et d'éditeurs de plus en plus intelligents. Nous avons tous ces outils pour reformater le texte, comparer du texte, rechercher du texte. Où se trouvent les outils permettant d'effectuer l'équivalent d'une recherche d'expression régulière 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 telle sorte que les mots soient différents mais que la signification sémantique soit la même et que ces outils diff rencontrent des problèmes. De tels outils, développés pour opérer sur des AST au lieu de texte, vous permettraient de vous rapprocher de la signification sémantique. Ce serait une bonne chose.
Bien que la transformation du code source du programme en AST soit relativement bien comprise (nous avons des compilateurs et des interprètes, n'est-ce pas?), la transformation d'un AST en code de programme n'est pas aussi bien comprise. Multiplier deux nombres premiers pour obtenir un grand nombre composé est relativement simple, mais il est beaucoup plus difficile de factoriser un grand nombre composé en nombres premiers. c'est là où nous en sommes avec l'analyse vs la décompilation des AST. C'est là que les différences entre les langues deviennent un problème. Même dans une langue donnée, il existe plusieurs façons de décompiler un AST. Itérer dans une collection d'objets et obtenir un résultat, par exemple. Utilisez une boucle for, en parcourant un tableau? Ce serait compact et rapide, mais il y a des limites. Utilisez un itérateur de quelque sorte, opérant sur une collection? Cette collection pourrait être de taille variable, ce qui ajoute de la flexibilité aux dépens (possibles) de la vitesse. Carte / Réduire? Plus complexe, mais implicitement parallélisable. Et ce n'est que pour Java, selon vos préférences.
Avec le temps, les efforts de développement seront déployés et nous développerons à l'aide d'écrans tactiles et d'AST. Taper deviendra moins une nécessité. Je vois cela comme une progression logique de l'endroit où nous sommes, en regardant comment nous utilisons les ordinateurs, aujourd'hui, cela résoudra le problème # 1.
Nous travaillons déjà avec des arbres. Lisp est simplement des AST en série. XML (et HTML, par extension) n'est qu'un arbre sérialisé. Pour effectuer une recherche, nous avons déjà quelques prototypes: XPath et CSS (pour XML et HTML, respectivement). Lorsque des outils graphiques nous permettant de créer des sélecteurs et des modificateurs de style CSS sont créés, nous avons résolu une partie de # 2. Lorsque ces sélecteurs pourront être étendus pour prendre en charge les expressions rationnelles, nous serons plus proches. Je cherche toujours un bon outil de comparaison graphique pour comparer deux documents XML ou HTML. Alors 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 là, pas encore.
La seule façon pour moi de pouvoir décompiler ces AST en langage de programmation serait de rechercher un objectif. Si je modifie du code existant, l'objectif peut être atteint par un algorithme qui rend mon code modifié aussi semblable que possible au code de départ (diff textuel minimal). Si j'écris du code à partir de zéro, l'objectif pourrait être le code le plus petit et le plus strict (probablement une boucle for). Ou bien ce pourrait être un code qui se parallélise le plus efficacement possible (probablement une carte / réduction ou quelque chose impliquant le CSP). Ainsi, le même AST pourrait donner lieu à un code considérablement différent, même dans le même langage, en fonction de la manière dont les objectifs ont été définis. Développer un tel système résoudrait le problème # 3. Ce serait un calcul complexe, ce qui signifie que nous aurions probablement besoin d'une sorte d'arrangement client-serveur,
la source
Si votre intention est d'éliminer le débat sur les styles de formatage, vous souhaitez peut-être 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 son enregistrement, reformatez le style choisi par l'équipe les usages.
C'est assez facile 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 points d'ancrage pour transformer automatiquement un fichier dans votre propre style lors du chargement et pour le transformer en style d'équipe lors de la sauvegarde.
la source
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. Le bytecode Java et le code intermédiaire .NET fonctionnent comme un AST.
la source
c'est une bonne idée mais chaque langue AST est différente des autres.
la seule exception que je connaisse concerne VB.NET et C #, où Microsoft affirme qu’il s’agit du "même langage avec une syntaxe différente". Même les autres langages .NET (IronPython, F #, peu importe) sont différents au niveau AST.
Même chose avec les langages JVM, ils visent 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 «à couches minces», 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 que cela aurait été défini comme un "décompilateur" Java-à-Xtend qui crée par magie des abstractions de niveau supérieur à partir de code Java existant, vous ne pensez pas?
la source