Lexer/Parser:
______________
La grammaire de notre langage est écrite pour le logiciel ANTLRv3.4. La grammaire actuelle est disponible dans "ANTLR/LP.g". Celle-ci intègre à la fois les éléments de lexer, de parser, ainsi que des règles de réécriture permettant déjà de simplifier l'arbre syntaxique obtenu en sortie.
La grammaire peut être transformée en Lexer/Parser C via la commande suivante: "java -jar antlr-3.4-complete-no-antlrv2.jar LP.g". Une version prégénérée à partir de la dernière grammaire se trouve à la racine, avec le code du compilateur.
Compilateur:
______________
Un makefile fourni à la racine de cette archive permet de compiler notre compilateur. Celui-ci suppose la présence des fichiers générés par ANTLR, du runtime C ANTLR (-lantlr3c) ainsi que du runtime C LLVM. Si nécessaire, une version précompilée du runtime C ANTLR est disponible dans './lib'. La compilation s'effectue via la commande:
make
Une commande "make clean" permet de nettoyer les fichiers temporaires générés.
Le compilateur peut se lancer en ligne de commande de la façon suivante:
./inspiration [flags] ./input.txt
Les flags de compilation suivant sont disponibles:
-dAST: Affichage de l'arbre syntaxique obtenu sur la sortie standard
-dLL: Affichage du code LLVM obtenu sur la sortie standard
-O0: Force le compilateur à désactiver les optimisations. Ce paramètre est transmis à llc/gcc
-On (n>=1): Active les optimisations (comportement par défaut). Ce paramètre est transmis à llc/gcc
-o filename: Enregistre le code LLVM généré dans 'filename' (préfixez de './' pour le dossier courant).
-c filename: Si une version binaire du runtime est disponible (voir ci-dessous), utilise les outils LLC et GCC (supposés disponibles et appelables) pour compiler le programme d'entrée en format natif à la machine courante et l'enregistre sous 'filename' (préfixez de './' pour le dossier courant).
-r: Si l'option -c a été sélectionnée, lance le programme compilé dans le même invite de commande
Runtime:
______________
Le runtime nécessaire à notre langage est divisé en 3 parties:
1) Les fonctions les plus primitives résident directement dans le code du compilateur, et leur code LLVM est généré en début de compilation.
2) Les fonctions primitives de plus haut niveau sont autant que possible implémentées directement dans notre langage. Leur présence dans l'unité de compilation est nécessaire à la compilation des opérations qui en découlent, le compilateur y faisant référence lors de la génération de code. Ce runtime est disponible sous la forme de "stdlib.insp", lequel inclue "libmath.insp", "libio.insp" et "libdebug.insp".
3) Certaines opératations nécessaires au runtime sont programmées en C++ et entourées d'un wrapper C connu du compilateur. Cette librairie doit-être compilée séparément au moyen du makefile founi dans le dossier './insstd' et de la commande 'make'. La bibliothèque dynamique résultante doit être accessible à la compilation ainsi qu'à l'exécution. Le moyen le plus simple de l'installer sur un système UNIX est de la placer dans '/usr/local/lib', et d'ajouter ce même chemin à la variable d'environnement $LD_LIBRARY_PATH. La commande 'make install' exécutée avec les droits suffisants automatise cette opération. Si nécessaire, une version précompilée se trouve à la racine de cette archive ('./libinsstd.so').