I - Introduction à la compilation et à l interprétation



Documents pareils
Évaluation et implémentation des langages

Cours 1 : La compilation

INTRODUCTION A JAVA. Fichier en langage machine Exécutable

Éléments de programmation et introduction à Java

Logiciel Libre Cours 3 Fondements: Génie Logiciel

Institut Supérieure Aux Etudes Technologiques De Nabeul. Département Informatique

Éléments d informatique Cours 3 La programmation structurée en langage C L instruction de contrôle if

Quelques éléments de compilation en C et makefiles

Cours d Algorithmique et de Langage C v 3.0

Cours 1 : Introduction Ordinateurs - Langages de haut niveau - Application

L informatique en BCPST

Environnements de développement (intégrés)

UE Programmation Impérative Licence 2ème Année

Programmation C. Apprendre à développer des programmes simples dans le langage C

INITIATION AU LANGAGE C SUR PIC DE MICROSHIP

Seance 2: En respectant la méthode de programmation par contrat, implémentez les autres fonctions de jeu.

Cours 1 : Introduction. Langages objets. but du module. contrôle des connaissances. Pourquoi Java? présentation du module. Présentation de Java

Algorithme. Table des matières

Cours 1 : Qu est-ce que la programmation?

Traduction des Langages : Le Compilateur Micro Java

Info0101 Intro. à l'algorithmique et à la programmation. Cours 3. Le langage Java

Chapitre I Notions de base et outils de travail

LES OUTILS D ALIMENTATION DU REFERENTIEL DE DB-MAIN

Le langage C++ est un langage de programmation puissant, polyvalent, on serait presque tenté de dire universel, massivement utilisé dans l'industrie

TP1. Outils Java Eléments de correction

Manuel d utilisation 26 juin Tâche à effectuer : écrire un algorithme 2

Cours 1: Java et les objets

Annexe : La Programmation Informatique

Programmation Web. Madalina Croitoru IUT Montpellier

Chapitre 10 Arithmétique réelle

PARAGON - Sauvegarde système

Mise en œuvre des serveurs d application

Introduction à la programmation orientée objet, illustrée par le langage C++ Patrick Cégielski

Introduction aux concepts d ez Publish

Optimisation de logiciels de modélisation sur centre de calcul

Machines virtuelles. Brique ASC. Samuel Tardieu Samuel Tardieu (ENST) Machines virtuelles 1 / 40

LANGAGUE JAVA. Public Développeurs souhaitant étendre leur panel de langages de programmation

Cours Bases de données

SSTIC Désobfuscation automatique de binaires. Alexandre Gazet. Yoann Guillot. Et autres idyles bucoliques...

Travaux pratiques. Compression en codage de Huffman Organisation d un projet de programmation

La mémoire. Un ordinateur. L'octet. Le bit

eduscol Ressources pour la voie professionnelle Français Ressources pour les classes préparatoires au baccalauréat professionnel

Anne Tasso. Java. Le livre de. premier langage. 10 e édition. Avec 109 exercices corrigés. Groupe Eyrolles, , ISBN :

De quoi avez-vous besoin pour ce manuel?

Architectures web/bases de données

INTERNET est un RESEAU D ORDINATEURS RELIES ENTRE EUX A L ECHELLE PLANETAIRE. Internet : interconnexion de réseaux (anglais : net = réseau)

Nom de l application

Bien architecturer une application REST

Machines virtuelles Cours 1 : Introduction

programmation S initier à la la Avec des exemples en C, C++, C#, Java et PHP Avec des exemples en C, C++, C#, Java et PHP Claude Delannoy

Générer du code à partir d une description de haut niveau

Grandes lignes ASTRÉE. Logiciels critiques. Outils de certification classiques. Inspection manuelle. Definition. Test

La dernière base de données de Teradata franchit le cap du big data grâce à sa technologie avancée

Cours d introduction à l informatique. Partie 2 : Comment écrire un algorithme? Qu est-ce qu une variable? Expressions et instructions

Cours intensif Java. 1er cours: de C à Java. Enrica DUCHI LIAFA, Paris 7. Septembre Enrica.Duchi@liafa.jussieu.fr

Chapitre 1 Qu est-ce qu une expression régulière?

Modèle de cahier des charges pour un appel d offres relatif à une solution de gestion des processus métier (BPM)

Conservation des documents numériques

Devenez un véritable développeur web en 3 mois!

Cours d Algorithmique-Programmation 2 e partie (IAP2): programmation 24 octobre 2007impérative 1 / 44 et. structures de données simples

Créer le schéma relationnel d une base de données ACCESS

INFORMATIQUE & WEB. PARCOURS CERTIFICAT PROFESSIONNEL Programmation de sites Web. 1 an 7 MODULES. Code du diplôme : CP09

Manuel de System Monitor

Ecrire pour le web. Rédiger : simple, concis, structuré. Faire (plus) court. L essentiel d abord. Alléger le style. Varier les types de contenus

Table des matières PRESENTATION DU LANGAGE DS2 ET DE SES APPLICATIONS. Introduction

AUVRAY Clément (168187) HOMBERGER Alexandre (186897) GLADE. Langages, outils et méthodes pour la programmation avancée Page 1 sur 12

Cours Langage C/C++ Programmation modulaire

Algorithmique et Programmation, IMA

EPREUVE OPTIONNELLE d INFORMATIQUE CORRIGE

CH.3 SYSTÈMES D'EXPLOITATION

Comment reproduire les résultats de l article : POP-Java : Parallélisme et distribution orienté objet

Python - introduction à la programmation et calcul scientifique

Serveur d Applications Web : WebObjects

Rebol, un langage «différent»

BABEL LEXIS : UN SYSTÈME ÉVOLUTIF PERMETTANT LA CRÉATION, LE STOCKAGE ET LA CONSULTATION D OBJETS HYPERMÉDIAS

DOSSIER SOLUTION CA ERwin Modeling. Comment gérer la complexité des données et améliorer l agilité métier?

Intelligence Artificielle et Systèmes Multi-Agents. Badr Benmammar

IV- Comment fonctionne un ordinateur?

ASP 3.0 Professionnel

Retrouver de vieux programmes et jouer sur VirtualBox

Université de Bangui. Modélisons en UML

Plateforme de capture et d analyse de sites Web AspirWeb

Introduction aux Systèmes et aux Réseaux, Master 2 CCI

Les outils actuels permettent-ils d automatiser la production de cartes? De quels outils dispose-t-on?

GOL502 Industries de services

UltraBackup NetStation 4. Guide de démarrage rapide

Présentation du PL/SQL

Bases de programmation. Cours 5. Structurer les données

ISO/CEI NORME INTERNATIONALE

ACTIVITÉ DE PROGRAMMATION

Unix/Linux I. 1 ere année DUT. Université marne la vallée

Programmer en JAVA. par Tama

RÉUSSIR L AUTOMATISATION DU PROCESSUS DE TEST FONCTIONNEL

Module d anonymisation

Langage et Concepts de ProgrammationOrientée-Objet 1 / 40

Vulgarisation Java EE Java EE, c est quoi?

Introduction à Windows Script Host DescoDev

RTDS G3. Emmanuel Gaudin

Transcription:

I - Introduction à la compilation et à l interprétation Étienne M. Gagnon et Jean Privat 2009 2013 UQAM Les langages de programmation permettent aux programmeurs d écrire leurs programmes avec une notation plus naturelle pour l humain que le code machine binaire exécuté par les processeurs. Les premiers langages de programmation développés, les langages assembleurs, n offrent qu une simple couche d abstraction sur le code machine sous-jacent ; ils permettent d exprimer les instructions avec des codes symboliques et les adresses de mémoire avec des étiquettes. Évidemment, les langages de programmation ont continué à évoluer, souvent en augmentant la distance entre la notation textuelle utilisée par le programmeur et le code machine. L avènement du génie logiciel a influencé d avantage la conception des langages de programmation pour y introduire des notions de robustesse, d expressivité, d évolutivité, etc. et protéger les programmeurs d un certain nombre d erreurs. L exécution d un programme écrit avec un langage de programmation ne peut pas être directement effectuée par le processeur. Une première solution à ce problème consiste à préalablement traduire le programme source en code machine à l aide d un compilateur. La seconde solution consiste à décoder le programme source et à en exécuter le code au fur et à mesure à l aide d un interpréteur. Outre les compilateurs et les interpréteurs, de nombreux programmes doivent pouvoir lire et transformer toute sorte de fichiers. Par exemple, un navigateur Web doit pouvoir analyser l information d une page Web codée en langage de description HTML. Un extracteur automatique de documentation, comme javadoc ou doxygen, doit pouvoir lire le code source d un programme, en extraire les commentaires et générer la documentation des classes sous la forme d une collection de fichiers HTML ou d un document Copyright 2009-2013, Étienne M. Gagnon et Jean Privat. Tous droits réservés. 1

1 DÉFINITIONS PDF. Et plus généralement, la majorité des programmes doivent être capable de lire leurs propres fichiers de configuration. Des définitions plus précises du compilateur et de l interpréteur sont données à la Section 1. La structure interne d un compilateur est présentée à la Section 2 et celle d un interpréteur à la Section 3. 1 Définitions 1.1 Compilateur En français, compiler, probablement du latin compilare 1, signifie réunir des documents sur un même sujet à partir de diverses sources. En informatique, un compilateur est un programme qui accepte du code source en entrée et qui produit du code destination équivalent en sortie, tel qu illustré à la figure 1. Compilation Code source Code destination FIGURE 1 Compilateur 1.1.1 Compilateur traditionnel Le plus connu des types de compilateur est le compilateur de langage de programmation traditionnel. Celui-ci accepte un ou plusieurs fichiers de code source constituant un programme en entrée et produit, en sortie, un ou plusieurs fichiers binaires formés d instructions pour un processeur. Ces fichiers binaires peuvent ensuite être exécutés sur l ordinateur. Ceci est illustré à la figure 2. Un exemple est le compilateur gcc pour le langage C. Lorsque le programmeur lance la commande gcc main. c o main 1. Qui lit eralement signifie piller, comme dans pillage et mise-à-sac, mais est construit sur con- (ensemble) et pilare (compresser). 2

1 DÉFINITIONS 1.1 Compilateur FOR A = 1 TO 9 B = B + A NEXT A Code source Compilateur 01100100100 11101110110111 10110010110001 10000011010110 Code binaire exécutable Données Code binaire exécutable Résultats FIGURE 2 Compilateur traditionnel et exécution. le compilateur lit le fichier main.c ainsi que les autres fichiers sources référencés par celui-ci (même indirectement), et produit un fichier binaire main pouvant être exécuté directement sur la machine. Le système de compilation du langage C est en réalité plus complexe que ne le laisse imaginer la commande précédente. Chaque fichier file.c d un programme C est en premier donné en entrée à un préprocesseur qui traite les directives de pré-traitement contenues dans le fichier source, telles que #include et #define, et produit du code C sans directives en sortie. Ce code est ensuite envoyé au compilateur C qui le traduit en code assembleur. Par la suite, le code assembleur est donné en entrée à un assembleur qui le traduit en code binaire et le stocke dans un fichier objet file.o. Finalement, l éditeur de liens combine les fichiers *.o et produit un fichier exécutable dans un format approprié, tel que EXE sous WINDOWS et ELF sous LINUX. Il suffit d ajouter l option -v à la ligne de commande de gcc pour visualiser ces différentes étapes illustrées à la figure 3. Un utilisateur peut choisir de n effectuer que les premières phases du système de compilation. L option -E de gcc n invoque que le préprocesseur et génère un gros fichier.c pur (gros car chaque directive #include est remplacée par le contenu complet du fichier inclus), l option -S invoque le préprocesseur et le compilateur C et génère un fichier assembleur (.s) et l option -c invoque toutes les phases sauf l édition de lien et génère un fichier en langage machine (.o) non exécutable en soit. Il est intéressant de noter que le préprocesseur et l assembleur sont des compilateurs ; ils traduisent du code source en code destination équivalent. Dans gcc, le préprocesseur et l assembleur sont même des programmes 3

1.1 Compilateur 1 DÉFINITIONS *.h fichier.c *.o préprocesseur compilateur C éditeur de liens assembleur fichier.o programme.exe FIGURE 3 Compilation d un programme C séparés (respectivement cpp et as) qui sont utilisés par le programme gcc mais qui pourraient tout aussi bien être exécutés directement par l utilisateur. Le compilateur C ne constitue qu un élément du système de compilation d un programme C. Il traduit du code C pur 2 en code assembleur. Un autre exemple de compilateur est le compilateur javac du langage JAVA. Le système de compilation d un programme Java est bien plus simple que celui d un programme C. Il n y a ni préprocesseur, ni assembleur, ni éditeur de liens. Les fichiers *.class générés par javac sont des fichiers binaires formés d instructions pour un processeur virtuel. L exécution d un programme JAVA compilé n est donc pas effectuée directement par le processeur de l ordinateur, mais plutôt par une machine virtuelle, un programme qui réalise l exécution des instructions du processeur virtuel. 1.1.2 Compilateur source à source Un compilateur source à source est un programme qui accepte du code source en entrée et qui génère du code source équivalent (dans le même langage ou dans un autre) en sortie. Ce type de compilateur est d une grande utilité pour les programmeurs. Un exemple type est un compilateur qui lit une description de schéma de données en XML et qui produit un ensemble de classes (fichiers sources) en langage JAVA pour encapsuler l accès à une base de données avec un modèle objet. Un autre exemple est le 2. Code C ne contenant pas directives de pré-traitement. 4

1 DÉFINITIONS 1.1 Compilateur préprocesseur C qui transforme du code C avec directives de pré-traitement en code C sans directive de pré-traitement. Un compilateur source à source est un extraordinaire outil de génie logiciel. Les avantages d utiliser un tel compilateur plutôt que d écrire le code répétitif à la main sont nombreux : 1. Il est très facile de faire des erreurs dans l écriture de code répétitif et, pire, il est difficile de trouver ces erreurs à la lecture du code. 2. En cas d évolution ou de correction d erreur, il suffit d intervenir à un seul endroit dans le compilateur source à source plutôt qu à chaque apparition du patron dans le code. Ceci peut réduire considérablement le temps de développement requis pour appliquer et tester l évolution ou la correction. 3. Finalement, il est généralement plus stimulant de développer un petit compilateur à l aide d outils que d écrire du code répétitif. Lors de la conception d un nouveau langage de programmation, la compilation source à source peut servir à créer rapidement un compilateur prototype ciblant un langage de programmation existant. Il existe même des compilateurs optimisants qui font de la compilation source à source. Le compilateur SMARTEIFFEL, par exemple, traduit les programmes EIFFEL en code source C portable (ou en code-octet JAVA). Ainsi, SMARTEIFFEL peut cibler tous les systèmes qui possèdent un compilateur C sans nécessiter le développement de générateurs de code distincts pour les divers processeurs et systèmes d exploitation. C est le système de compilation C, sur chaque système, qui prend en charge les lourdes tâches de génération de code machine selon les exigences architecturales et d édition de liens. 1.1.3 Décompilateur Un décompilateur est un compilateur particulier qui fait le travail inverse d un compilateur. Il prend en entrée un ou plusieurs fichiers binaires et produit en sortie un programme équivalent dans le langage de programmation original. En général le résultat de la décompilation n est pas identique au programme original. En effet la compilation traditionnelle n est pas réversible car lors de la compilation traditionnelle de l information non nécessaire au fonctionnement du programme est perdue. Par exemple les commentaires et les noms des variables locales ont disparus. De plus, plus le compilateur 5

1.2 Interpréteur 1 DÉFINITIONS est optimisant, plus celui-ci risque d avoir transformé des morceaux du programme en des équivalents plus efficaces. Par exemple certaines structures de contrôles complexes peuvent avoir été transformées en des structures plus simples (de la même façon qu une boucle for peut être transformée en une boucle while voire juste en quelques goto). Les décompilateurs sont généralement utilisés dans un cadre de rétroingénierie pour étudier ou comprendre un programme dont le code source est indisponible. L objectif peut être, par exemple, de trouver ou d analyser des bogues, de réaliser un portage sur une architecture différente, de vérifier son fonctionnement ou d en analyser la sécurité comme, par exemple, chercher la présence de postes dérobées (backdoors). L option --disassemble de de la commande objdump Unix permet de transformer un programme machine en code assembleur (on parle alors de désassembleur). Plusieurs décompilateurs existent pour d autres langages comme le C ou le Java. En pratique, la décompilation est un problème difficile car en plus du travail habituel d un compilateur, le décompilateur doit trouver le moyen de retrouver (ou de fabriquer) un maximum d information non nécessaire au fonctionnement du programmes mais nécessaire à la compréhension du programme par un humain. Au niveau légal, la plupart des licences de logiciels propriétaires en interdisent la décompilation. Dans certains pays elles est illégale ou seulement autorisée à des fin d interopérabilité. Certains logiciels sont même parfois compilés avec des compilateurs obfuscateurs de code dont l objectif est de rendre plus difficile la décompilation du code produit : un décompilateur arrivera à produire un programme équivalent dans le langage d origine mais il sera relativement incompréhensible pour un humain. 1.2 Interpréteur Un interpréteur est un programme qui accepte du code source en entrée et qui accompli ce qui est spécifié dans le code source, tel qu illustré à la figure 4. 1.2.1 Interpréteur traditionnel Le plus connu des types d interpréteur est l interpréteur de langage de programmation traditionnel. Plusieurs interpréteurs traditionnels fonctionnent en mode interactif où le programmeur écrit le code source et l interpréteur exécute ce code dès qu il est entré. 6

1 DÉFINITIONS 1.2 Interpréteur Code source FOR A = 1 TO 9 B = B + A NEXT A Interpréteur Résultats Données FIGURE 4 Interpréteur Plusieurs langages de programmation sont interprétés. Les programmes RUBY, par exemple, sont lus et directement exécutés par l interpréteur de ce langage. Typiquement, l exécution d un programme RUBY est lancée avec la commande ruby fichier.rb. Le programme ruby est l interpréteur de ce langage. Il lit le fichier fichier.rb et exécute le programme sur le champ 3. La plupart des interpréteurs peuvent être aussi interactifs. C est-à-dire qu ils exécutent le programme au fur et à mesure que le programmeur le saisit et non pas d un coup à la fin de la lecture. Cela permet au programmeur de choisir l instruction suivante à écrire en fonction du résultat (ou de l erreur) qu a produit la instruction précédente. Le mode interactif d un interpréteur est un outil pratique pour apprendre à utiliser un nouveau langage ou pour tester simplement le comportement de petites séquences d instructions. La plupart des interpréteurs sont également réflexifs. C est-à-dire qu ils peuvent dynamiquement manipuler et exécuter des morceaux de code source. Ainsi, dans de nombreux langages, l instruction eval(s) permet d évaluer la chaîne de caractères s en tant que code source sachant que la valeur de s peut avoir été calculée dynamiquement. Habituellement les interprètes de commandes des systèmes d exploitation (shells) sont considérées comme des interpréteurs à part entière. Ils sont généralement utilisés en mode interactif mais il est habituel d écrire ou d exécuter des programmes pour ces interpréteurs (script shells). 3. Sur un système de type UNIX correctement configuré, la commande./fichier.rb lancera automatiquement l interpréteur. 7

1.3 Compilateur optimisant et interpréteur hybride 1 DÉFINITIONS 1.2.2 Machine virtuelle et émultateur Une machine virtuelle est un interpréteur qui exécute des programmes codés en langage binaire plutôt qu en langage texte. La machine virtuelle de JAVA, par exemple, lit les fichiers de classe *.class et les exécute. Un émulateur est une machine virtuelle particulière qui exécute des programmes codés en langage binaire pour une plate-forme physique existante (processeur, matériel et système d exploitation). Par exemple le programme DOSBox permet d exécuter sur un très grand nombre de plate-forme, des programmes compilés pour le système d exploitation DOS avec un processeur x86 en simulant, au besoin, une carte vidéo, une carte son ou un lecteur de CD-ROM. 1.3 Compilateur optimisant et interpréteur hybride Certains langages peuvent facilement être catégorisés comme étant destinés soit à la compilation (C, C++, PASCAL, ADA), soit à l interprétation (PERL, RUBY, PYTHON, JAVASCRIPT). D autres langages imposent un mode de développement et d exécution mixte ; c est le cas du langage JAVA où le code source est clairement destiné à la compilation, mais où l exécution requiert une machine virtuelle 4. Évidemment, il y a des langages qui se prêtent aussi bien à l interprétation qu à la compilation ; c est le cas du langage BASIC. Un des avantages majeurs de l utilisation d un compilateur est la rapidité d exécution du code. Le code compilé est directement exécuté par le processeur, sans intermédiaire. De plus, la compilation du programme a été effectuée avant le lancement de l exécution. Les compilateurs optimisants en profitent pour analyser le code plus profondément, augmentant ainsi le temps de compilation, afin de produire du code machine plus efficace. À l autre bout du spectre, les interpréteurs doivent analyser le code source, détecter les erreurs et interpréter les instructions du programme continuellement lors de l exécution d un programme ; et tout recommencer à chaque fois à chaque nouvelle exécution. Typiquement, la rapidité d exécution d un programme compilé est de 10 à 100 fois supérieure à celle du même programme interprété. Pour cette raison, les interpréteurs se sont complexifiés au fil des ans. Afin d améliorer la performance, certains interpréteur intègrent un compilateur juste à temps qui compile le code source d une fonction en code 4. La fonctionnalité de chargement dynamique des classes empêche la compilation pure du code JAVA, sans interprétation. 8

1 DÉFINITIONS 1.4 Problème de l amorçage machine lors de la première invocation de celle-ci. Généralement, le temps perdu à compiler le code est amplement compensé par le temps gagné avec l exécution directe, par le processeur, du code machine généré. Les interpréteurs de pointe les plus efficaces vont encore plus loin. Ils sont complètement hybrides. Il incluent un moteur d interprétation et usent également de modèles statistiques sophistiqués pour ne compiler, spéculativement, que le code qui en vaut la peine avec un compilateur optimisant intégré. Ces interpréteurs hybrides réussissent parfois l exploit de surpasser la vitesse d exécution d un même programme précompilé avec un compilateur optimisant traditionnel. En effet, un compilateur optimisant traditionnel doit générer du code adapté pour toutes les utilisations du programme alors qu un interpréteur hybride peut se concentrer spécifiquement et agressivement sur l exécution en cours. 1.4 Problème de l amorçage Toute introduction à la compilation doit aborder le problème classique de l amorçage (anglais : bootstrap). Le problème de l amorçage est un vrai problème pratique mais un faux problème théorique. Le faux problème théorique est le suivant : un compilateur (ou un interpréteur) est un programme. Donc il doit être doit être exécuté à l aide d un compilateur (ou d un interpréteur), qui lui-même doit être exécuté à l aide d un compilateur (ou d un interpréteur), et ainsi infiniment. Ce faux problème théorique a déjà été identifié par Spinoza au 17ème Siècle en remplaçant «programme» par «outil» et «compilateur» par «forge», ou se retrouve encore aujourd hui dans l éculé problème de l œuf et de la poule. Le vrai problème pratique, par contre, est sans doute plus intéressant : comment développer et exécuter un nouveau compilateur ou un interpréteur. Traditionnellement, en utilisant un autre compilateur. Ainsi de nombreux interpréteurs et compilateurs sont implémentés dans un autre langage disposant compilateur (en C par exemple) et sont compilées de la même façon que tout programme dans de langage. Certains compilateur sont dit autogènes : c est-à-dire qu ils sont implémentés dans le langage qu ils compilent. C est le cas de gcc qui est implémenté en C. En général, la version suivante d un compilateur autogène est simplement compilée à l aide de la version précédente du compilateur 5. La 5. Puis traditionnellement recompilée avec lui-même un certain nombre de fois. 9

2 STRUCTURE D UN COMPILATEUR première version d un compilateur compilateur autogène est compilée soit à l aide d un compilateur concurrent, soit à l aide d un compilateur primitif écrit dans un autre langage. Le dernier cas pratique du problème de l amorçage concerne l exécution d un programme sur une nouvelle architecture matérielle. Dans ce cas là, on utilise généralement un compilateur croisé (ou cross compiler en Anglais), c est-à-dire un compilateur capable de générer du code binaire pour une architecture différente de celle qui exécute le compilateur. Le résultat d une compilation croisée doit alors être installé sur l architecture cible pour pouvoir être exécuté. À noter les compilateurs croisés sont fréquemment utilisés pour générer des exécutables pour des plates-formes qui n ont pas les moyens de disposer d un compilateur autonome (comme les plates-formes embarquées). Précision Dans le reste du texte, le terme compilateur sera utilisé pour désigner un compilateur non-optimisant et le terme interpréteur désignera un interpréteur non-hybride. 2 Structure d un compilateur Pour accomplir son travail, un compilateur doit lire le code source, vérifier sa validité et, enfin, générer le code destination lorsqu il n y a pas d erreur ou afficher les erreurs détectées. La figure 5 donne une vue générale de la structure interne d un compilateur. Lorsque le code source est textuel, le compilateur doit analyser la séquence des caractères du code source pour extraire l information structurée qu elle contient 6. L utilisation de la théorie des langages pour s attaquer à ce problème a mené à diviser cette tâche en deux : l analyse lexicale et l analyse syntaxique. L analyse de l information structurée (reconstituée ou non) permet de détecter des erreurs, s il y a lieu, et de calculer des informations dérivées nécessaires à la génération de code. C est ce qu on appelle l analyse sémantique 7. 6. Les compilateurs qui acceptent du code source déjà structuré sont dispensés du travail de reconstitution. 7. La sémantique du code, c est le sens ou la signification du code. 10

2 STRUCTURE D UN COMPILATEUR 2.1 Analyse lexicale Source texte Source structuré Analyseur lexical Structures de données Analyseur syntaxique Analyseur sémantique Générateur de code Compilateur Code destination FIGURE 5 Structure d un compilateur Finalement, l étape de génération de code se sert des informations extraites et calculées précédemment pour émettre du code destination équivalent au code source lu. 2.1 Analyse lexicale L analyse lexicale consiste à diviser la longue séquence de caractères du fichier source en jetons (ou lexème). Un jeton est une petite sous-séquence significative de caractères. Cela peut être un mot clé, une ponctuation, une espace, un identifiant, un nombre ou toute autre entité significative. Généralement, les langages utilisent deux types de jetons : les jetons utiles à l analyse syntaxique (tels les identifiants et les nombres) et les jetons ignorés (tels les espaces et les commentaires). Les jetons ignorés sont éliminés par l analyseur lexical. Seule la séquence des jetons utiles est envoyée à l analyseur syntaxique. Par exemple, la séquence d octets «for i = 1 to 10 loop» peut produire la séquence de jetons suivante : mot clé «for», identifiant «i», symbole d égalité, entier littéral 1, mot clé «to», etc. 11

2.2 Analyse syntaxique 2 STRUCTURE D UN COMPILATEUR 2.2 Analyse syntaxique Le rôle de l analyse syntaxique est de reconstituer la structure syntaxique de la séquence des jetons utiles reçue de l analyseur lexical. Le plus simple est d expliquer l analyse syntaxique à l aide d une analogie. La reconstitution de la structure syntaxique d une longue séquence de mots en langue française identifie le verbe et les autre éléments des phrases, l organisation des phrases en paragraphes, l organisation des paragraphes en sections, l organisation des sections en chapitres et l organisation des chapitres en livre. La structure obtenue par analyse syntaxique est naturellement arborescente et est appelée arbre syntaxique ; elle est envoyée à l analyseur sémantique. La figure 6 donne l exemple de l analyse syntaxique de la phrase «le chat dort.». le chat dort. article définit nom commun verbe groupe nominal phrase groupe verbal point FIGURE 6 Arbre syntaxique de la phrase «le char dort». Les feuilles sont des mots ou des symboles de ponctuation, les autres nœuds sont des concepts grammaticaux. 2.3 Analyse sémantique L analyse sémantique consiste à vérifier la cohérence de l information structurée obtenue de l analyseur syntaxique (ou directement du code source structuré). L analyse sémantique peut également inclure le calcul d informations sémantiques additionnelles (tel que le calcul de la quantité de mémoire nécessaire à stocker une variable). Voici un exemple qui illustre une phrase syntaxiquement correcte mais sémantiquement erronée : «Le crayon mange une pomme». Syntaxiquement, tout va bien ; on trouve un groupe sujet, un verbe et un groupe 12

3 STRUCTURE D UN INTERPRÉTEUR 2.4 Génération de code complément. Sur le plan sémantique, il y a un problème : un crayon, ça ne mange pas. Par exemple, lors de la compilation d un programmation, c est l analyse sémantique qui détermine qu une affectation est illégale car les types ne correspondent pas ou qui détecte qu une variable locale est utilisée avant d être initialisée. 2.4 Génération de code Le générateur de code se sert des informations et des structures obtenues et créées par les analyseurs lexical, syntaxique et sémantique pour émettre le code destination. Quand le langage à compiler est de haut niveau, la génération de code peut se faire en plusieurs étapes. Chacune traduisant le programme vers un langage de moindre niveau d abstraction. C est particulièrement vrai pour les compilateurs optimisants dans lesquels chacune des optimisations est généralement spécifique à une étape particulière. D une certaine façon, dans le cadre d un système de compilation C, les phases de pré-traitement et d assemblage peuvent être considérée comme des étapes intermédiaires entre le langage de haut niveau qui est le C avec des directives de précompilation et le langage de bas niveau qui est le code machine du processeur. Toutefois, même l étape proprement dite de compilation C, qui traduit du code C pur en assembleur, se fait à l interne en utilisant des langages intermédiaires. 3 Structure d un interpréteur La structure interne d un interpréteur est presque identique à la structure d un compilateur expliquée à la Section 2. La seule différence, c est que le générateur de code est remplacé par un exécuteur de code comme le montre la figure 7. L interpréteur est réflexif si l exécuteur de code peut interpréter directement du code source nouveau, qui peut être soit extrait des données du programme, soit dynamiquement construit sous une forme manipulable par le langage interprété, comme une chaîne de caractères par exemple. Ceci est représenté sur la figure par la flèche entre l exécuteur de code et l analyseur lexical. Dans le cadre des interpréteurs interactifs, la structure principale est une boucle, appelée read-eval-print, où l exécution d une instruction est suivie 13

3 STRUCTURE D UN INTERPRÉTEUR par la lecture, l analyse et l exécution de l instruction suivante. Données Source texte Source structuré Analyseur lexical Structures de données Analyseur syntaxique Analyseur sémantique Exécuteur de code Résultats Interpréteur FIGURE 7 Structure d un interpréteur Tout comme le générateur de code dans le cadre d un compilateur, l exécuteur de code se sert des informations et des structures obtenues et créées par les analyseurs lexical, syntaxique et sémantique pour réaliser les tâches décrites dans le code source. Toutefois, l interpréteur doit également maintenir des structures de données additionnelles permettant de représenter l état d exécution du programme. Dans le cas des interpréteur mixtes, l interprétation peut se faire non pas sur le code source originel mais sur une représentation intermédiaire. C est par exemple le cas des interpréteurs PERL et PYTHON qui compilent à l interne le code source en un code binaire puis interprètent ce code binaire. Toutefois, ce travail de compilation est à recommencer à chaque nouvelle exécution d un programme (sauf si l interpréteur peut sérialiser ce code binaire et le réutiliser lors des exécutions suivantes, ce propose l interpréteur PYTHON avec les fichiers *.pyc). De plus, un interpréteur mixte disposant d un compilateur juste-à-temps peut choisir compiler des morceaux de code source (ou plus vraisemblablement de code binaire intermédiaire) en code binaire machine directement exécutables par le processeur physique. 14

4 EXERCICES 4 Exercices 1. Identifiez cinq langages de programmation compilés. Pour chacun des langages, identifiez les systèmes d exploitation et les processeurs actuellement supportés. 2. Identifiez cinq langages de programmation interprétés. Pour chacun des langages, identifiez les systèmes d exploitation et les processeurs actuellement supportés. 3. Identifiez cinq langages de programmation pour chacun desquels il existe au moins un compilateur et un interpréteur. 15