Langages de haut niveau Eduardo Sanchez Ecole Polytechnique Fédérale de Lausanne Introduction ♦ Un assembleur est un programme traduisant en code machine un programme écrit à l'aide des mnémoniques ♦ Les langages d'assemblage représentent une deuxième génération de langages, après les langages machine. Toutefois, la différence entre les deux générations se situe simplement au niveau de la syntaxe, puisque les primitives sont les mêmes ♦ Le transfert d'un programme écrit en assembleur vers un autre processeur n'est pas une tâche aisée ♦ Une troisième génération de langages utilise des primitives de plus haut niveau, indépendantes de la machine. Les deux exemples les plus connus sont: • FORTRAN (Formula Translator), développé pour des applications scientifiques, et • COBOL (Common Business-Oriented Language), développé par l'US Navy pour des applications commerciales Page 2 Eduardo Sanchez Ecole Polytechnique Fédérale de Lausanne ♦ L'approche suivie par cette troisième génération était d'identifier un ensemble de primitives de haut niveau utilisables pour développer le logiciel ♦ Chacune de ces primitives devait pouvoir être implémentée comme une séquence des primitives de bas niveau disponibles dans les langages machine ♦ Un traducteur est ensuite nécessaire pour transformer les primitives de haut niveau en séquences d'instructions machine: c'est le compilateur ♦ Le premier compilateur a été écrit par Grace Hopper ♦ Un autre type de traducteur est l'interpréteur. Dans ce cas, les instructions machine sont exécutées au fur et à mesure qu'elles sont générées, au lieu d'être stockées dans un fichier pour une utilisation ultérieure Page 3 Eduardo Sanchez Ecole Polytechnique Fédérale de Lausanne ♦ Les problèmes de portabilité n'ont pas été tous résolus par les langages de troisième génération ♦ Certains de ces problèmes disparaissent avec une standardisation du langage, le plus souvent menée à bien par deux organisations: • ANSI (American National Standards Institute) et • ISO (International Organization for Standardization) ♦ Parfois les fabricants du compilateur ajoutent des "extensions" au langage qui le rendent incompatible avec d'autres produits ♦ Pour les générations suivantes, l'ambition s'est déplacée de la portabilité vers la communication avec l'ordinateur en utilisant des concepts abstraits. Ou, mieux encore, vers une découverte par l'ordinateur d'une partie de l'algorithme à exécuter Page 4 Eduardo Sanchez Ecole Polytechnique Fédérale de Lausanne Paradigmes de programmation LISP ML Scheme Smalltalk langages machine FORTRAN Basic COBOL Algol C APL Page 5 1960 C++ Visual Basic C# Java Ada Prolog 1970 orienté objet impératif Pascal GPSS 1950 fonctionnel déclaratif 1980 Eduardo Sanchez Ecole Polytechnique Fédérale de Lausanne 1990 2000 ♦ Ces paradigmes représentent des approches différentes pour construire des solutions aux problèmes. Plus que des paradigmes de programmation, on pourrait parler des paradigmes de développement de logiciel ♦ Paradigme impératif ou procédural: le processus de programmation est défini comme le développement d'une séquence de commandes qui manipulent des données pour produire le résultat souhaité. C'est-à-dire, on doit trouver l'algorithme donnant solution au problème et, ensuite, il doit être exprimé comme une séquence de commandes ♦ Avec le paradigme déclaratif, l'approche est différente: au lieu de décrire l'algorithme, le programmeur doit maintenant décrire le problème Page 6 Eduardo Sanchez Ecole Polytechnique Fédérale de Lausanne ♦ Pour le paradigme déclaratif, il faut trouver et implémenter un algorithme général de solution de problèmes. Si cela est fait, il suffit ensuite de décrire un problème donné en respectant un format compatible avec cet algorithme général pour obtenir sa solution ♦ Le paradigme fonctionnel voit le processus de développement de programmes comme l'interconnexion de "boîtes noires" prédéfinies. Chacune de ces boîtes est une fonction mathématique ♦ Les primitives d'un langage fonctionnel sont des fonctions élémentaires que le programmeur doit utiliser pour construire les fonctions plus complexes nécessaires pour résoudre le problème traité Page 7 Eduardo Sanchez Ecole Polytechnique Fédérale de Lausanne ♦ Exemple d'un programme fonctionnel pour calculer la moyenne d'une liste de nombres, utilisant les fonctions Add, Compter et Diviser: Entrée: Entrée: xx11,x ,x22,...,x ,...,xnn Add Add Compter Compter Diviser Diviser Sortie: Sortie: (x (x11+x +x22+...+x +...+xnn)/n )/n (Diviser (Add Nombres) (Compter Nombres)) Page 8 Eduardo Sanchez Ecole Polytechnique Fédérale de Lausanne ♦ Le paradigme orienté objets (OOP) voit les unités de données comme objets "actifs", contrairement aux unités passives vues par le paradigme impératif traditionnel ♦ Prenons, par exemple, une liste de noms. Le paradigme impératif voit cette liste comme une simple collection de données, et tout programme l'utilisant doit inclure un algorithme capable d'exécuter le traitement demandé. Pour le paradigme orienté objets, la liste est construite comme un objet composé par la liste elle-même plus une collection de procédures capables de la manipuler ♦ Les procédures à l'intérieur d'un objet, décrivant la façon de répondre aux messages adressés à l'objet, sont essentiellement des unités de programmation impérative Page 9 Eduardo Sanchez Ecole Polytechnique Fédérale de Lausanne Concepts de programmation ♦ Les concepts étudiés ici sont ceux des langages impératifs et orientés objets ♦ Trois catégories de phrases: • phrases déclaratives: définition des termes utilisés par la suite • phrases impératives: description des pas de l'algorithme • commentaires ♦ Les langages de haut niveau se réfèrent aux positions de mémoire par le biais des noms, contrairement aux adresses explicites utilisées par les langages machine. Ces noms sont les variables du programme ♦ Une variable doit être déclarée avant son utilisation. Cette déclaration doit donner également le type de la donnée, ce qui définit la façon de coder la donnée et les opérations qui peuvent l'utiliser Page 10 Eduardo Sanchez Ecole Polytechnique Fédérale de Lausanne ♦ Exemples des déclarations de variables: • Pascal: var Longueur, Largeur : real; Prix, Taxe, Total : integer; Symbole : char; • C, C++, C#, Java: float Longueur, Largeur; int Prix, Taxe, Total; char Symbole • FORTRAN: REAL Longueur, Largeur INTEGER Prix, Taxe, Total CHARACTER Symbole Page 11 Eduardo Sanchez Ecole Polytechnique Fédérale de Lausanne ♦ En plus de son type de donnée, une variable est souvent associée à une structure de données: c'est sa forme conceptuelle, son arrangement virtuelle. La disposition physique de la variable à l'intérieur de la mémoire est souvent différente ♦ Exemple d'un tableau (array): • Pascal: Employe: record Nom : packed array[1..8] of char; Age : integer; Evaluation: real end; • C: Employe struct {char Nom[8]; int Age; float Evaluation; } Employe; Page 12 Nom Eduardo Sanchez Ecole Polytechnique Fédérale de Lausanne Age Evaluation ♦ L'algorithme est décrit à l'aide des phrases impératives ♦ La phrase impérative de base est l'affectation, qui permet d'affecter une valeur à une variable (ou, plus précisément, de stocker une valeur dans la zone de mémoire réservée pour la variable) ♦ Exemple: • C, C++, C#, Java: z = x + y; • Ada, Pascal: z := x + y; Page 13 Eduardo Sanchez Ecole Polytechnique Fédérale de Lausanne ♦ Une phrase de contrôle altère la séquence d'exécution d'un programme ♦ Exemples en C, C++, C# et Java: B? s1 s2 B? s1 Page 14 Eduardo Sanchez Ecole Polytechnique Fédérale de Lausanne if B s1 else s2; while B s1; ♦ Un résultat surprenant de l'informatique théorique nous dit que le nombre de structures de contrôle nécessaires pour garantir à un langage de programmation qu'il est capable d'exprimer une solution à tout problème possédant une solution algorithmique est très petit ♦ Du choix des structures de contrôle d'un langage dépend en bonne partie la lisibilité des programmes. La programmation structurée est une méthodologie de programmation qui utilise une certaine famille de structures de contrôle afin de faciliter la lisibilité et la preuve des programmes Page 15 Eduardo Sanchez Ecole Polytechnique Fédérale de Lausanne Unités procédurales ♦ Une procédure est un ensemble d'instructions qui réalisent une tâche et qui peut être considéré comme une unité par d'autres unités du programme ♦ Lorsque les services de la procédure sont nécessaires, le programme lui passe le contrôle: on appelle la procédure unité appelante passage du contrôle à la procédure retour du contrôle Page 16 Eduardo Sanchez Ecole Polytechnique Fédérale de Lausanne procédure ♦ En général, une procédure possède une structure similaire à celle du programme principale, avec une partie déclarative suivie des phrases impératives qui décrivent l'algorithme ♦ Une variable déclarée dans une procédure est une variable locale, appelées ainsi par opposition aux variables globales du programme ♦ Les procédures sont écrites avec des termes génériques qui deviennent spécifiques au moment de l'appel: c'est les paramètres de la procédure ♦ Les termes utilisés pendant l'écriture de la procédure sont les paramètres formels. L'affectation spécifique donnée aux paramètres formels au moment de l'appel sont les paramètres réels Page 17 Eduardo Sanchez Ecole Polytechnique Fédérale de Lausanne ♦ Exemple de procédure: paramètre formel void PredictionPopulation (float TauxCroissance) { int Annee; variable locale Population[0] = 100.0; for (Annee = 0; Annee =< 10; Annee++) Population[Annee+1] = Population[Annee]*TauxCroissance); } paramètre réel PredictionPopulation (0.03); Page 18 Eduardo Sanchez Ecole Polytechnique Fédérale de Lausanne ♦ Le passage d'une donnée entre les paramètres formels et réels peut se faire de plusieurs façons, selon le langage ♦ Dans le passage par valeur, la procédure reçoit seulement une copie du paramètre réel: toute modification faite par la procédure sur le paramètre est ignorée par l'unité appelante ♦ Le passage par valeur est très peu efficace pour des données à très grande taille ♦ Dans le passage par référence, la procédure reçoit un accès direct au paramètre réel, en recevant son adresse. La procédure peut dans ce cas modifier la donnée de l'unité appelante Page 19 Eduardo Sanchez Ecole Polytechnique Fédérale de Lausanne ♦ Dans certains cas, le but de la procédure est de produire une valeur, plus que de réaliser une action: c'est une fonction ♦ Exemple de fonction: type de la valeur produite float VolumeCylindre (float Rayon, float Hauteur) { float Volume; Volume = 3.14 * Rayon * Rayon * Hauteur; return Volume; } valeur produite Cout = CoutPerUniteVol * VolumeCylindre(3.45, 12.7); Page 20 Eduardo Sanchez Ecole Polytechnique Fédérale de Lausanne