Cela a commencé comme une question SO mais j'ai réalisé que c'était assez peu conventionnel et basé sur la description réelle sur les sites Web, il pourrait être mieux adapté aux programmeurs.se puisque la question a beaucoup de poids conceptuel.
J'ai appris le clang LibTooling et c'est un outil très puissant capable d'exposer l'intégralité du "nitty gritty" du code de manière conviviale, c'est-à-dire de manière sémantique , et non en devinant non plus. Si clang peut compiler votre code, alors clang est certain de la sémantique de chaque caractère à l'intérieur de ce code.
Permettez-moi maintenant de prendre un peu de recul.
Il existe de nombreux problèmes pratiques qui se posent lorsque l'on s'engage dans la métaprogrammation de modèles C ++ (et en particulier lorsque l'on s'aventure au-delà des modèles sur le territoire de macros intelligentes mais terrifiantes). Pour être honnête, pour de nombreux programmeurs, y compris moi-même, de nombreuses utilisations ordinaires des modèles sont également quelque peu terrifiantes.
Je suppose qu'un bon exemple serait les chaînes de compilation . C'est une question qui remonte à plus d'un an maintenant, mais il est clair que le C ++ à l'heure actuelle ne facilite pas la tâche des simples mortels. Bien que regarder ces options ne soit pas suffisant pour me causer des nausées, cela me laisse néanmoins confiant quant à la capacité de produire un code machine magique et efficace au maximum pour s'adapter à toutes les applications fantaisistes que j'ai pour mon logiciel.
Je veux dire, avouons-le, les gens, les chaînes sont assez simples et basiques. Certains d'entre nous veulent juste un moyen pratique d'émettre du code machine qui a certaines chaînes "intégrées" beaucoup plus que ce que nous obtenons en le codant de manière simple. Dans notre code C ++.
Entrez clang et LibTooling, qui expose l'arbre de syntaxe abstraite (AST) du code source et permet à une application C ++ personnalisée simple de manipuler correctement et de manière fiable le code source brut (à l'aide Rewriter
) aux côtés d'un riche modèle sémantique orienté objet de tout dans l'AST. Il gère beaucoup de choses. Il connaît les extensions de macro et vous permet de suivre ces chaînes. Oui, je parle de transformation ou de traduction de code source à source.
Ma thèse fondamentale ici est que clang nous permet maintenant de créer des exécutables qui eux-mêmes peuvent fonctionner comme les étapes de préprocesseur personnalisées idéales pour notre logiciel C ++, et nous pouvons implémenter ces étapes de métaprogrammation avec C ++. Nous sommes simplement contraints par le fait que cette étape doit prendre en entrée du code C ++ valide et produire en sortie du code C ++ plus valide. De plus, quelles que soient les autres contraintes auxquelles votre système de construction s'applique.
L'entrée doit être au moins très proche du code C ++ valide car, après tout, clang est le frontal du compilateur et nous ne faisons que fouiner et être créatifs avec son API. Je ne sais pas s'il est possible de définir une nouvelle syntaxe à utiliser, mais il est clair que nous devons développer les moyens de l'analyser correctement et de l'ajouter au projet clang pour ce faire. Attendre plus, c'est avoir quelque chose dans le projet Clang qui est hors de portée.
Pas de problème. J'imagine que certaines fonctions macro sans opération peuvent gérer cette tâche.
Une autre façon de voir ce que je décris est d'implémenter des constructions de métaprogrammation à l'aide du runtime C ++ en manipulant l'AST de notre code source (grâce à clang et son API) au lieu de les implémenter en utilisant les outils plus limités disponibles dans le langage lui-même. Cela présente également des avantages clairs en termes de performances de compilation (les en-têtes lourds en modèles ralentissent la compilation proportionnellement à la fréquence à laquelle vous les utilisez. Beaucoup de choses compilées sont ensuite soigneusement adaptées et jetées par l'éditeur de liens).
Cela, cependant, se fait au prix de l'introduction d'une ou deux étapes supplémentaires dans le processus de construction et également de la nécessité d'écrire des logiciels (certes) un peu plus verbeux (mais au moins c'est du runtime C ++ simple) dans le cadre de notre outil. .
Ce n'est pas tout. Je suis à peu près certain qu'il existe un espace beaucoup plus grand de fonctionnalités qui peut être obtenu en générant du code qui est extrêmement difficile ou impossible avec les fonctionnalités du langage de base. En C ++, vous pouvez écrire un modèle ou une macro ou une combinaison folle des deux, mais dans un outil de clang, vous pouvez modifier les classes et les fonctions de TOUTE manière que vous pouvez réaliser avec C ++, au moment de l' exécution , tout en ayant un accès complet au contenu sémantique, en plus du modèle et des macros et tout le reste.
Je me demande donc pourquoi tout le monde ne le fait pas déjà. Est-ce que cette fonctionnalité de clang est si nouvelle et que personne ne connaît l'énorme hiérarchie des classes de l'AST de clang? Ça ne peut pas être ça.
Peut-être que je sous-estime un peu la difficulté de cela, mais faire une "manipulation de chaîne au moment de la compilation" avec un outil de clang est presque criminellement simple. C'est verbeux, mais c'est incroyablement simple. Tout ce qui est nécessaire est un tas de fonctions macro sans opération qui correspondent aux std::string
opérations réelles réelles . Le plugin clang implémente cela en récupérant tous les appels de macro sans opération pertinents et effectue les opérations avec des chaînes. Cet outil est ensuite inséré dans le cadre du processus de génération. Pendant la génération, ces appels de fonction macro sans opération sont automatiquement évalués dans leurs résultats, puis réinsérés en tant que vieilles chaînes de compilation simples dans le programme. Le programme peut ensuite être compilé comme d'habitude. En fait, ce programme résultant est également beaucoup plus portable, ne nécessitant pas de nouveau compilateur sophistiqué prenant en charge C ++ 11.