succès des langages - unice.frdeptinfo.unice.fr/~ol/m1i/cours-handout.pdf · puissance...

78
organisation 2. Étude de trois langages de programmation (C++, Caml et Icon) : Semaines 41 à 44 : C++ 2h de cours par semaine 2h de travaux pratiques par semaine Semaines 45 à 47 : Caml et Icon : 1h30 de cours par semaine : deux séances par langage 1h30 de travaux pratiques par semaine : deux séances par langage Langages et paradigmes – p.3/311 organisation 3. Semaines 48 à 2 : Mini-projet groupes de 5 un sujet différent par groupe le sujet est à traiter dans les trois langages 4. Semaine 3 : Conclusion présentation des mini-projets (écrite et orale) cours de synthèse et conclusion Langages et paradigmes – p.4/311 Langages et paradigmes Master d’informatique, première année Olivier Lecarme Université de Nice-Sophia Antipolis Langages et paradigmes – p.1/311 Organisation de cet enseignement Il est organisé en plusieurs périodes : 1. Semaines 41 à 45 : Introduction générale 2h de cours par semaine : 2h de travaux dirigés par semaine : lectures dirigées et commentées, exercices Langages et paradigmes – p.2/311

Upload: others

Post on 19-May-2020

1 views

Category:

Documents


0 download

TRANSCRIPT

organisation

2. Étude de trois langages de programmation (C++, Camlet Icon) :

Semaines 41 à 44 : C++2h de cours par semaine2h de travaux pratiques par semaine

Semaines 45 à 47 : Caml et Icon :1h30 de cours par semaine : deux séances parlangage1h30 de travaux pratiques par semaine : deuxséances par langage

Langages et paradigmes – p.3/311

organisation

3. Semaines 48 à 2 : Mini-projetgroupes de 5un sujet différent par groupele sujet est à traiter dans les trois langages

4. Semaine 3 : Conclusionprésentation des mini-projets (écrite et orale)cours de synthèse et conclusion

Langages et paradigmes – p.4/311

Langages et paradigmesMaster d’informatique, première année

Olivier Lecarme

Université de Nice-Sophia Antipolis

Langages et paradigmes – p.1/311

Organisation de cet enseignement

Il est organisé en plusieurs périodes :

1. Semaines 41 à 45 : Introduction générale2h de cours par semaine :2h de travaux dirigés par semaine : lectures dirigéeset commentées, exercices

Langages et paradigmes – p.2/311

nombre de langages

Variété des problèmes à résoudre :manipulation de données symboliquesstructures de données très complexesopérations complexes sur chaînes de caractèresprogrammation de bas niveau pour les systèmesd’exploitationreprésentation du raisonnement logiquenouveaux problèmes spécifiques

Langages et paradigmes – p.7/311

nombre de langages

Préférences personnelles :questions de goûts personnels principalementécrire bref ou écrire clair ?récursivité ou itération ?pointeurs explicites ou non ?sécurité ou liberté ?un seul langage « universel » ou plusieurs langagesspécialisés ?l’interactivité est-elle importante ?

Langages et paradigmes – p.8/311

Introduction et historique

1 Introduction et historique

1.1 Pourquoi tant de langages de

programmation ?

1.1.1 Nombre

Il existe plusieurs milliers de langages deprogrammation, et on continue d’en créer. Pourquoi?

Langages et paradigmes – p.5/311

nombre de langages

Évolution de la discipline :passage du langage machine au langaged’assemblage puis aux langages de haut niveauprogrès dans les formalismes de descriptionprogrès dans les techniques de compilationcourants nouveaux en méthodologie :programmation structurée, programmationmodulaire, programmation par objets, etc.

Langages et paradigmes – p.6/311

succès des langages

Facilité d’utilisation :facilité d’apprentissage pour un débutantrapidité des progrèsabsence de pièges et de surprises

Facilité d’implémentation :sur des machines peu coûteusesrapidité de construction d’une nouvelleimplémentationtransportabilité de l’implémentationabsence de freins légaux ou commerciaux

Langages et paradigmes – p.11/311

succès des langages

Qualité de l’implémentation :bonnes performances dès le débutrestrictions faites au langage pour le permettreconvivialité des outils annexes

Facteurs économiques et autres :support par un industriel puissant : Fortran, Cobol,PL/Isupport par un organisme public : Adacampagne publicitaire : Javaoccupation d’une niche spécifique : Prologdifficulté du changementinertie

Langages et paradigmes – p.12/311

Succès

1.1.2 Succès

Parmi les milliers de langages qui ont été définis etimplémentés, quelques centaines seulement sontencore utilisés, et quelques dizaines le sont demanière importante.

Langages et paradigmes – p.9/311

succès des langages

Qu’est-ce qui fait qu’un langage a du succès ?

Puissance d’expression :tout langage permet de tout exprimer, mais plus oumoins facilementcertaines caractéristiques ont une grandeimportance sur la facilité de programmationles possibilités d’abstraction sont les plusimportantes

Langages et paradigmes – p.10/311

catégories de langages

Modèle par objets :variante ou spécialisation du modèle de vonNeumannle calcul est décrit par les interactions entre objetsSimula 67, Smalltalk, Eiffel, C++, Java, etc.c’est le modèle le plus à la mode.

Langages et paradigmes – p.15/311

catégories de langages

Langages déclaratifs.Modèle fonctionnel :

fondé sur le lambda-calcul : un programme estune fonction qui fournit un résultat à partird’argumentsLisp, Scheme, ML, etc.c’est le modèle préféré des mathématiciens.

Modèle par flot de données :le calcul se fait par les données qui traversent desnœuds fonctionnelsId, Val, Sisalmodèle d’importance actuelle marginale.

Langages et paradigmes – p.16/311

Catégories de langages de programmation

1.2 Catégories de langages de programmation

Les catégories ont des limites floues. On nes’intéressera de toutes manières ici qu’aux « vrais »langages de programmation, en excluant leslangages d’assemblage, les macro-processeurs,etc.

Langages et paradigmes – p.13/311

catégories de langages

Langages « impératifs » ou procéduraux.Modèle de von Neumann :

le calcul est décrit par les changements d’état desvariablesFortran, Algol, Pascal, Basic, C, Ada, Icon, etc.c’est le modèle le plus répandu, en particulierparce qu’il est conforme à la structure desordinateurs.

Langages et paradigmes – p.14/311

pourquoi étudier

Comprendre les décisions de conception etd’implémentation pour mieux utiliser les langages :

Comprendre les caractéristiques obscures : on peutles ramener aux grands principes si on les connaît.Choisir parmi les différentes manières de faire lamême chose, en particulier en tenant compte descoûts :

passage par valeur de variables encombrantespassage par nomutilisation d’astuces pour améliorer lesperformancesévaluation des compromis entre encombrement etrapidité

Langages et paradigmes – p.19/311

pourquoi étudier

Simuler des caractéristiques manquantes :programmation structurée par discipline etcommentairesconventions de nommage pour imiter la modularitésimulation des générateurs à l’aide de fonctions etde variables statiquessimulation de la récursivité

Langages et paradigmes – p.20/311

catégories de langages

Modèle logique :le calcul est la tentative de trouver des données quisatisfont des équations logiquesProlog presque uniquementles tableurs ordinaires peuvent se rattacher à cemodèlemodèle résistant dans sa niche.

En fait, la plupart des langages fonctionnels incluent des mé-

canismes procéduraux, et on peut programmer de manière

fonctionnelle dans la plupart des langages procéduraux.

Langages et paradigmes – p.17/311

Pourquoi étudier les langages de programmation ?

1.3 Pourquoi étudier les langages de

programmation ?

Quelques raisons fondamentales :

position centrale dans l’informatique professionnellepermettre de choisir le langage le plus approprié auproblèmefaciliter l’apprentissage de nouveaux langagesdécouvrir les mécanismes et principes sous-jacentsaméliorer votre esprit critique

Langages et paradigmes – p.18/311

formalismes

Aspects sémantiques :utilisation de la langue naturelle la plus fréquenteexpression stéréotypée dans les documents denormalisationVienna Definition Language pour PL/Igrammaires de van Wijngaarden (grammaires àdeux niveaux) pour Algol 68 (effet néfaste)définition axiomatique pour PascalVienna Definition Method pour Modula-2à part Algol 68, la formalisation apparaît tardivementpeu d’influence sur la définition du langage

Langages et paradigmes – p.23/311

Normalisation des langages de programmation

1.5 Normalisation des langages de

programmation

1.5.1 Organismes de normalisation

Organismes nationaux :AFNOR en FranceDIN en AllemagneBSI au Royaume-Uni

ANSI et FBS aux États-Unis

Langages et paradigmes – p.24/311

pourquoi étudier

Appliquer les connaissances acquises à d’autressituations similaires :

langages de commande, shellsgénérateurs de rapportsoutils programmables (Emacs)fichiers de configuration et options de commandes

Langages et paradigmes – p.21/311

Formalismes de définition

1.4 Formalismes de définition des langages

Aspects lexicaux :en général non séparés de la syntaxedistinction entre symboles et représentation en Algol60 et Algol 68pas de formalisme spécifique

Aspects syntaxiques :forme normale de Backus à partir d’Algol 60notation originale mais sans descendance pourCobolextensions variées à BNF, sans uniformisation

Langages et paradigmes – p.22/311

Difficultés de la normalisation

1.5.3 Difficultés de la normalisation

lourdeur générale des mécanismes

intérêts contradictoires des participants

non-représentativité des participants

conflits entre précision et clarté

trop grande lenteur

Langages et paradigmes – p.27/311

Quelques exemples

1.5.4 Quelques exemples de normalisations

Fortranle premier exemple de normalisation de langage deprogrammationseul moyen d’évolution du langage après Fortran IVdominante : conserver la compatibilité avec lesprogrammes existants

PL/Inormalisation inutilesimple officialisation de la définition du langage parIBM

Langages et paradigmes – p.28/311

organismes

Organismes influents :

IEEE aux États-UnisGrandes associations (ACM)

Organismes internationaux :ISOCCITTIFIP

Langages et paradigmes – p.25/311

Rôle de la normalisation

1.5.2 Rôle de la normalisation

rassembler des définitions divergentes

clarifier la définition

faire évoluer le langage

définir un nouveau langage

Langages et paradigmes – p.26/311

exemples

Modula-2travail similaire à celui pour Pascal : propre à l’ISO,pas d’intervention de l’auteur du langagechoix malheureux de VDM comme formalismenorme ayant « tué » le langage

Langages et paradigmes – p.31/311

Tableau généalogique

1.6 Tableau généalogique des langages de

programmation

Langages et paradigmes – p.32/311

exemples

Algol 68 : la norme ISO est un pointeur sur le documentde l’IFIP

Pascalpremière normalisation d’un langage n’émanant pasd’une puissance économiqueconflit entre l’ISO et l’ANSItentative de ne faire que clarifierdeux extensions indispensablesensuite, définition d’un nouveau langage

Langages et paradigmes – p.29/311

exemples

Cune grande partie du document sert à préciser cequi n’est pas précisél’important est de ne pas invalider les compilateursdes fabricants de logiciel représentés dans le comitétravail interne à l’ANSI

Langages et paradigmes – p.30/311

Quelques mots sur quelques langages

1.6.2 Quelques mots sur quelques langages

Fortran : « traducteur de formules » plus efficace qu’unbon programmeur (Backus, IBM)

Algol 60 : langage d’expression des algorithmes pour lacommunauté scientifique (universitaires européens etaméricains, Backus, Naur, McCarthy, Bauer,Rutishauser, Woodger, Perlis, Vauquois, etc.)

Cobol : la langue américaine pour dire ce qui doit êtrefait dans les affaires (Codasyl, IBM)

Lisp : λ-calcul, auto-définition, traitement de listes(McCarthy, MIT)

Langages et paradigmes – p.35/311

quelques langages

APL : tout s’exprime par combinaison d’opérateurs etélargissement aux tableaux (Iverson)

PL/I : applications numériques et commerciales dans lemême langage, « tout marche » (IBM)

Algol 68 : groupe WG 2.1 de l’IFIP, principes de basepoussés au paroxysme (van Wijngaarden)

Snobol4 : modèle de Markov, traitement de chaînes decaractères (Griswold, Bell Labs)

Pascal : contre Algol 68, simple, systématique, fait pourenseigner les bases de la programmation (Wirth)

Langages et paradigmes – p.36/311

Commentaires sur le tableau

1.6.1 Commentaires sur le tableau

dates approximatives

filiations schématiques et parfois discutables

choix de langages supposés représentatifs : les plusimportants devraient être présents

certains langages très anciens sont encore très utilisés: Cobol, Lisp

certains langages ne font plus parler d’eux, mais sontutilisés par des communautés fidèles : APL, Simula 67,Snobol4, Algol 68

Langages et paradigmes – p.33/311

généalogie

certains langages sont mentionnés mais n’ont pasd’utilisation importante

parmi les implémentations libres ou gratuites :FSF : C, C++, Fortran 77, Pascal, Ada 95, Prolog,Java, Eiffel (Cobol en cours)autres : Oberon, Scheme, Snobol4, Icon, Perl, APL,etc.

Langages et paradigmes – p.34/311

Moment de prise des décisions

2.1 À quel moment prend-on des décisions ?

à la conception du langage : choix des structuresd’énoncés, des constructeurs de types

à la construction de l’implémentation : choix dudomaine des types de base, de la précision desnombres, des limites variées

à l’écriture du programme : choix des algorithmes, desstructures de données, des noms

à la compilation du programme : correspondance entreles structures de haut niveau et la machine

Langages et paradigmes – p.39/311

moment de prise des décisions

à l’édition de liens : résolution des références entre lesmodules

au chargement : choix des adresses en mémoire, réelleou virtuelle

à l’exécution : valeurs des variables

On appelle en général statiques les choix faitsavant l’exécution, dynamiques ceux qui sont faits àl’exécution.Plus le choix est fait tardivement, plus la souplessed’utilisation est grande, mais moins on peut prédirece qui va se passer. Par conséquent, les choixdynamiques impliquent de moins bonnesperformances.

Langages et paradigmes – p.40/311

quelques langages

C : programmation de bas niveau la plus concisepossible, pas d’avenir prévu (Ritchie, Bell Labs)

Prolog : moteur d’évaluation d’équations logiques, priscomme emblème du projet d’ordinateurs de 5egénération (Colmerauer et Roussel)

Ada : appel d’offres du Ministère de la Défenseaméricain, évaluation internationale (Ichbiah)

Java : projet initial sans avenir, marketing et publicitépour contrer Microsoft (Gosling, Sun)

Langages et paradigmes – p.37/311

Noms

2 Noms

Les langages dits « de haut niveau » tirent leur nomdu niveau d’abstraction qu’ils fournissent. Il s’agitde s’éloigner autant que possible des détails del’ordinateur, mais aussi de faciliter laprogrammation.Un nom sert à désigner autre chose, et enparticulier une abstraction, que ce soit des donnéesou des actions.

Langages et paradigmes – p.38/311

Gestion de l’espace

2.2.1 Gestion de l’espace

allocation statique :les objets ont une adresse fixée pour la durée duprogrammevariables globalesvariables rémanentesconstantes

Langages et paradigmes – p.43/311

gestion de l’espace

allocation en pile :les objets sont détruits en ordre inverse de leurcréationcela se fait en parallèle avec les appels et retours desous-programmesdans un langage sans récursivité, les variableslocales aux sous-programmes peuvent être allouéesstatiquement

allocation en tas :les objets sont créés et détruits à des momentsarbitrairescela implique en général une gestion élaborée del’espace

Langages et paradigmes – p.44/311

Durée de vie

2.2 Durée de vie

Un nom désigne un objet grâce à une liaison. Celaimplique les événements suivants :

création des objetscréation des liaisonsréférences aux objets grâce aux liaisonssuspension et réactivation de certaines liaisonsdestruction des liaisonsdestruction des objets

Langages et paradigmes – p.41/311

durée de vie

L’intervalle entre la création et la destruction de laliaison entre un nom et un objet est sa durée de vie.Même chose pour l’objet lui-même.

Les deux durées de vie ne coïncident pas forcément.

Les durées de vie des objets correspondent à troisgrandes catégories de gestion de l’espace

Langages et paradigmes – p.42/311

Allocation en tas

2.2.3 Allocation en tas

dans le tas les blocs de mémoire sont alloués et libérésde manière arbitraire

après un certain nombre d’allocations et de libérations,le tas est fragmenté et doit être compacté

les techniques de récupération de mémoiredéterminent quels blocs sont encore occupés pour lesregrouper de manière contiguë

Langages et paradigmes – p.47/311

allocation en tas

il existe aussi des techniques qui acceptent unecertaine fragmentation et regroupent les blocs libéréss’ils sont contigus

la récupération de mémoire classique peut bloquertemporairement l’exécution du programme

certains langages imposent la libération explicite desblocs, ce qui évite l’utilisation d’un récupérateur

Langages et paradigmes – p.48/311

Allocation en pile

2.2.2 Allocation en pile

chaque sous-programme est associé à une zoned’activation

les zones d’activation sont toutes placées dans la piled’exécution

à l’intérieur de la zone, les adresses relatives des objetspeuvent être connues à la compilation

un pointeur de zone sert d’adresse de base aux objetslocaux

Langages et paradigmes – p.45/311

allocation en pile

l’adresse de retour et les contenus des registres sontégalement sauvegardés dans la zone d’activation

le prologue et l’épilogue du sous-programme gèrentl’allocation, la gestion et la libération de la zone

Langages et paradigmes – p.46/311

différences entre les langages

C, Java, Icon : pas d’emboîtement dessous-programmes, donc une portée générale statiquepour les noms globaux, et masquage de ces noms parles noms homonymes dans les sous-programmes

Algol, Pascal, PL/I, Ada, etc. : emboîtement dessous-programmes, qui fait gérer la portée statiqueselon un mécanisme de pile

Langages et paradigmes – p.51/311

portée statique

La portée dans les sous-programmes emboîtés estgérée à l’exécution par un lien statique, qui permet desavoir pour chaque zone d’activation quelle est la zonedu sous-programme emboîtant.

Problème : quand commence la portée d’une liaison ?À la déclaration du nom (Ada), ou au début dusous-programme (Pascal) ?

Langages et paradigmes – p.52/311

Règles de portée

2.3 Règles de portée

La portée d’une liaison est la zone textuelle duprogramme où elle est valide.

2.3.1 Portée statique

Dans la plupart des langages, la portée est déterminéede manière statique.

Une liaison est temporairement désactivée si l’on entredans un sous-programme où une autre partie deprogramme qui en crée une portant le même nom. Elleest réactivée à la fin de cette partie.

On parle de portée statique ou lexicale.Langages et paradigmes – p.49/311

Différences entre les langages

Différences entre les langagesCobol, Basic à sa définition : une seule portée statiquepour tout le programme, tous les noms doivent êtredistincts.

Fortran : une portée par sous-programme, tous lessous-programmes sont disjoints, blocs communs pourdéfinir des portées importées de manière sélective parles sous-programmes.

Langages et paradigmes – p.50/311

modularité

En-dehors du module, les liaisons internes au modulesont inactives mais non pas détruites.

L’importation réactive la liaison, éventuellement avecdes restrictions imposées par le module (liaisonopaque, privée, protégée, etc.).

Langages et paradigmes – p.55/311

Portée dynamique

2.4 Portée dynamique

Les liaisons entre noms et objets dépendent dudéroulement de l’exécution et de l’emboîtement desappels de sous-programmes.

Les langages à portée dynamique sont hors del’ordinaire :

APLSnobol4Anciens dialectes de LispPerl (au choix du programmeur)Les shells

Langages et paradigmes – p.56/311

Exemple de sous-programmes emboîtés

�� �� �� �� � �� � � �� �

�� � � � � �� � �

�� � � �� �� � �� � � �� �

�� � � �� �� � � � � � � � �

� � ��� � � � � � � � �

� � �� � ��� � � � � � � � �

�� � � �� �� � �� � � �� �

� � � � � � � � �� � � � � � � �

�� � � � � � � � � �� �

� � ��� � � � � � � � �

� � �� � ��� � � � � � � � �

� � �� � � � � � � � �

Langages et paradigmes – p.53/311

Modularité

2.3.2 Modularité

Un module sert à masquer les détails d’implémentation.

La portée des liaisons ne peut donc pas êtreautomatique.

Il faut donc des déclarations explicites d’importation etexportation.

Variations importantes suivant les langages : Modula-2,Ada, C++ par exemple.

Langages et paradigmes – p.54/311

Liaison des environnements

2.5 Liaison des environnements

2.5.1 Fermeture de sous-programme

Que se passe-t-il quand un sous-programme peutlui-même être manipulé comme un objet, ou quand onpeut avoir des références à des sous-programmes ?

La difficulté est que la structure textuelle du programmen’est plus significative, puisque le sous-programmepeut être appelé à un endroit où il n’est pas directementvisible.

Langages et paradigmes – p.59/311

fermeture de sous-programme

La portée dyamique conduit à une règle de liaison desurface, et la portée statique à une règle de liaison enprofondeur.

L’implémentation construit une fermeture dusous-programme, qui contient un pointeur sur le code etle lien statique.

Langages et paradigmes – p.60/311

portée dynamique

Le mécanisme se comprend facilement par sonimplémentation : les noms sont empilés à l’entrée dansles sous-programmes, et retirés à la sortie ; larecherche d’une liaison se fait à partir du sommet de lapile.

Langages et paradigmes – p.57/311

Exemple de portée dynamique

�� � � � � � � � � �� � � � �

�� �� �� �� � � � �

� � �� � � �� �

� � � �

�� �� �� �� � � � �� �

�� � � � � � � � � �� �

� � ��� � � �

� � � �

� � �� �� �� � �

� � �� � � � � � �� � � �� � � � � ��

� � � � � �

� � � � �

� � � � � � � � � �� �

� � � �

Langages et paradigmes – p.58/311

Quefont les langages ?

2.5.3 Que font les langages ?

les étiquettes sont de troisième classe dans presquetous les langages, mais de deuxième classe en Algol 60

les sous-programmes sont de deuxième classe dans laplupart des langages procéduraux, de troisième classedans la première définition d’Ada

Langages et paradigmes – p.63/311

que font les langages ?

les sous-programmes sont de première classe danstous les langages fonctionnels

avec certaines restrictions, également en Modula-2,Ada 95, C et C++.

seuls quelques langages fonctionnels permettent decréer de nouveaux sous-programmes à l’exécution.

Langages et paradigmes – p.64/311

Exemple

�� � �� � � �� � � � � � �

�� � � �� �� � � � � � � � � �� � �� � � �� �� � � �

�� � � �� �� � � �

� � ��� ��� � � � � � �

� � � �

� � ��� �� � � �� �� � � �

� � � � � � �

� � � � �

� � � �

�� � � �� �� � � �

� � ��� � � � � �

� � �� � � � �

� � � �

Langages et paradigmes – p.61/311

Classe des sous-programmes

2.5.2 Sous-programmes de première ou deuxième classe

Classes des valeurs :Une valeur est de première classe si on peut lapasser comme paramètre, l’affecter à une variableou la fournir comme résultat d’une fonction.Une valeur de deuxième classe peut être passéecomme paramètre, mais c’est tout.Une valeur de troisième classe ne peut pas êtremanipulée.

Langages et paradigmes – p.62/311

surcharge

À ne pas confondre avecconversion automatique : un paramètre d’un typeinattendu est automatiquement converti dans le typedemandé (Fortran, C, Pascal)polymorphisme : plusieurs types distincts sontacceptés pour le même paramètre (langagesfonctionnels, C++, Java)Pascal et Modula-2 fournissent un polymorphismeréduit avec les tableaux conformants

Langages et paradigmes – p.67/311

généricité

généricité : le sous-programme est un modèle quipermet de créér plusieurs sous-programmes concrets,suivant la valeur d’un paramètre de généricité qui peutêtre un type par exemple (Ada)

Langages et paradigmes – p.68/311

Surcharge

2.6 Surcharge

Un nom qui peut se référer à plusieurs objets distinctsdans une portée donnée est surchargé.

Si au contraire plusieurs noms se réfèrent au mêmeobjet, on parle d’alias.

Presque tous les langages surchargent au moins lesopérateurs arithmétiques les plus simples.

Langages et paradigmes – p.65/311

surcharge

Ada permet de surcharger les constantes énumérées.

Ada, C++ et Java permettent de surcharger les nomsde sous-programmes, à condition que le profil dessous-programmes permette de les distinguer.

Algol 68, Ada, C++ et Fortran 90 permettent desurcharger les opérateurs, dans les mêmes conditions.

Langages et paradigmes – p.66/311

difficultés

Autre cas plus compliqué :

��� �� �� �� � � � � �

� � � �� � �

� � �

��� �� �� �� � � � � �

��� �� �� �� � �� ��

� � � �� � � �

� � �

��� �� �� �� � � � � �

Langages et paradigmes – p.71/311

difficultés

Cas des types récursifs :

� � � �� �� � � � �

� � � �� �� �

� � � � � ��� � �

� � �

� � �

Langages et paradigmes – p.72/311

Difficultés avec les portées

2.7 Difficultés avec les portées

Trois exemples pris dans Pascal, qui a pourtant des règlessimples :

Redéfinition du résultat d’une fonction :

� � � � � � � � � � � � � � � � � � ��

� � �� � � � � � � � � � � �

� � � �� � �

� � � � � � � �

Langages et paradigmes – p.69/311

difficultés

Utilisation d’un nom avant sa redéfinition :

� � � � � � � � � � � �

��� �� �� �� � �� ��

� � � � � � � � � � � � � �

� � � � � �

Langages et paradigmes – p.70/311

expressions régulières et lexèmes

Servent à décrire les lexèmes, mais non pas tous lesaspects lexicaux des langages :

majuscules et minuscules (Pascal, Ada)passages à la ligne (anciennes versions de Fortran,point-virgule implicite en Icon)commentaires ordinairescommentaires actifs (pragmas d’Ada, commandesau compilateur)décalages significatifs (Occam, Haskell)

Langages et paradigmes – p.75/311

expressions régulières et lexèmes

Ne fonctionnent bien que si le langage sépareproprement les aspects lexicaux des aspectssyntaxiques :

en Fortran ou PL/I, les mots-clés sont reconnus parleur position et par conséquent non réservésen Algol 60 ou 68, les mots-clés ont une écriturespécifiquedans la plupart des autres langages, les mots-cléssont des identificateurs réservés (y compris enCobol qui en a plus de 400 !)

Langages et paradigmes – p.76/311

Aspects lexico-syntaxiques

3 Aspects lexico-syntaxiques

Beaucoup de ces aspects ont déjà été traités en Licence. Il

faut faire quelques rappels tout de même.

Langages et paradigmes – p.73/311

Expressions régulières et lexèmes

3.1 Expressions régulières et lexèmes

Mécanisme de choix pour décrire des lexèmescompliqués.

Servent aussi de donnée aux générateurs d’analyseurslexicaux.

Pas très faciles à construire, et jamais utilisées dans ladescription des langages, même dans les normes.

Langages et paradigmes – p.74/311

Arbres de dérivation

3.2.2 Arbres de dérivation

Soit la grammaire algébrique :

� � � � � �

� ��

� � �

� � � � �

�� � � �

Langages et paradigmes – p.79/311

arbres de dérivation

La phrase� � � � � admet deux arbres de dérivation, elleest donc ambiguë :

E

i

op

* i + i

op

E op E

i * i +

E

E

E

E

op E

E

i

E

L’une des dérivations possibles est :

� ⇒ � � � � ⇒ � � � � ⇒ � � � ⇒ � � � � � � ⇒ � � �

� � ⇒ � � � � �

Langages et paradigmes – p.80/311

Grammaires algébriques

3.2 Grammaires algébriques

3.2.1 Généralités

Nécessaires pour décrire des structures emboîtées.

Mécanisme de génération assez facile à utiliser pour ladescription.

Toutes les définitions de langages utilisent desvariantes de la Forme Normale de Backus, utiliséeinitialement pour Algol 60.

Langages et paradigmes – p.77/311

généralités

Les extensions simplifient l’écriture des constructionsles plus courantes :

� � � � � pour fragment facultatif

� � � pour fragment répétéen général rien d’autre, ce qui oblige à desrépétitionsparfois on combine grammaires algébriques etexpressions régulières en parties droites

Langages et paradigmes – p.78/311

Analyse lexicale

3.3 Analyse lexicale

3.3.1 Généralités

L’analyseur syntaxique appelle l’analyseur lexical, quilui renvoie un lexème.

À chaque appel, l’analyseur lexical doit reprendre sonalgorithme au début.

Il accepte normalement le lexème le plus long possible.

Le fonctionnement général est celui d’un automated’états finis très simple, dans les cas simples.

Langages et paradigmes – p.83/311

généralités

La programmation peut se faire par un grand énoncécas, ou par un automate général utilisant une matricede transition.

Langages et paradigmes – p.84/311

arbres de dérivation

Une autre est :

� ⇒ � � � � ⇒ � � � � � � � ⇒ � � � � � � � ⇒ � � � � �

� ⇒ � � � � � � ⇒ � � � � � ⇒ � � � � �

Langages et paradigmes – p.81/311

arbres de dérivation

L’ambiguïté peut être levée par des règles de priorité oud’associativité. Également par récriture de la grammaire :

� � � � ��� � � �

� �

� � � � ��� � � �

� �

� � ��

� � �

� ��� � � � � �

� ��� � � � � � �

Langages et paradigmes – p.82/311

aspects pratiques

Les commentaires doivent être ignorés par l’analyseurlexical.

Les « commentaires significatifs » doivent être traitésspécialement :

mettre les vérifications en fonctionmettre certaines améliorations en fonctionproposer de mettre une variable dans un registrecette procédure n’est jamais récursive

Langages et paradigmes – p.87/311

Commentaires

3.3.3 Commentaires

Très différents suivant les langages :

� en colonne 6 en Fortran IV

comment � � � en Algol 60

procedure � � �� � � � �� � � � en Algol 60

end �� �� en Algol 60

com � � � com en Algol 68

� � � ou � � � � � � � en Pascal

� � � � � � � en PL/I et C

� � � � � en Ada ( � � en C++, en Lisp, etc.)

etc.Langages et paradigmes – p.88/311

+ −

espace

non−)

non−*

lettrelettre, chiffre

chiffre

chiffre chiffre

chiffre chiffre chiffre chiffre

)

(* *

*

,

][

.

.

<

=

e E

e E.

Langages et paradigmes – p.85/311

Aspects pratiques

3.3.2 Aspects pratiques

La théorie donne une vision trop simpliste :

Les mots-clés doivent être cherchés dans une table,pour éviter de construire un automate beaucoup tropgrand.

La recherche du lexème le plus long peut conduire àavancer trop loin dans le texte :

� � � � � ou � � � � en Pascal

� � � � � � �� � ou � � � � � � � � � en Fortrancertains opérateurs composites très compliqués enAlgol 68

Langages et paradigmes – p.86/311

Catégories de grammaires

3.4.2 Catégories de grammaires

LR(0) non LL :

� � �

� � � � � �

LALR(1) non SLR :

� � � � � � � �

� � �

Langages et paradigmes – p.91/311

catégories de grammaires

LR(1) non LALR :

� � � � � � � � � � � � �

� � �

� � �non ambiguë mais non LR :

� � � � � � ν

Langages et paradigmes – p.92/311

Analyse syntaxique

3.4 Analyse syntaxique

3.4.1 Généralités

Tous les analyseurs courants procèdent de gauche àdroite de manière déterministe.

L’analyse descendante ou prédictive prédit la prochaineétape d’une dérivation gauche au vu du prochainlexème.

Langages et paradigmes – p.89/311

généralités

L’analyse ascendante ou déductive rassemble tous lescomposants d’une partie droite avant d’effectuer uneréduction, suivant donc de manière rétrograde lesétapes d’une dérivation droite.

L’analyse ascendante n’essaie pas de prédire, ce qui luipermet d’accepter des grammaires plus générales.

Langages et paradigmes – p.90/311

influence sur les langages

En revanche, certaines constructions nécessitent desentorses :

appel de procédure et affectation en Pascaldéclarations de fonctions en Cmodèles des types en Algol 68point-virgule facultatif en Icon

Langages et paradigmes – p.95/311

Énoncés et expressions

4 Énoncés et expressions

4.1 Classification des structures de contrôle

Séquence : les énoncés sont exécutés l’un aprèsl’autre dans l’ordre indiqué.

Sélection : un énoncé est choisi parmi plusieurs,d’après une condition évaluée à l’exécution.

Itération : un groupe d’énoncés est exécuté de manièrerépétitive, soit un certain nombre de fois (répétition),soit jusqu’à ce qu’une certaine condition soit vraie(itération proprement dite).

Langages et paradigmes – p.96/311

catégories de grammaires

LR(0)

LALR(1)

. . .

LALR(2)

LALR

LR(1)

LR(2)

LRLL

LL(1)

LL(2)

. . .

Langages et paradigmes – p.93/311

Influence sur les langages

3.4.3 Influence sur les langages

Certaines définitions de langages sont prévues pour untype particulier d’analyse :

PL/360 (Wirth) est un langage de précédencesimple.Certaines constructions de beaucoup de langagessont prévues pour faciliter l’analyse LL(1), enparticulier le mot-clé en début de chaque typed’énoncé.

Langages et paradigmes – p.94/311

Évaluation des expressions

4.2 Évaluation des expressions

4.2.1 Généralités

Une expression est une suite d’opérateurs etd’opérandes :

appel de fonction : � �� � � � �

opérateurs infixes :� � � �

mélange des deux : ��

��� � � (Algol 68, Ada) ;

� � � � �� � � �� � � � (C++)notation lispienne : � � � � �

Langages et paradigmes – p.99/311

généralités

Parfois extension à des opérateurs conditionnels :Algol 60 :� � � if � � then � else �

Algol 68 :� � � � � � � � � � �

C :� � � � � � � �

très rares opérateurs postfixes :Pascal : �� � � � �� �

C :� � �

Langages et paradigmes – p.100/311

structures de contrôle

Appel de procédure : un groupe d’énoncés estencapsulé de manière à être traité comme un tout, avecparamétrisation.

Récursivité : une expression est partiellement définieen termes d’elle-même.

Parallélisme : plusieurs groupes d’énoncés sontexécutés en même temps, soit grâce à plusieursprocesseurs, soit par partage du temps sur l’uniqueprocesseur.

Langages et paradigmes – p.97/311

structures de contrôle

Non-déterminisme : l’ordre d’exécution de plusieursgroupes d’énoncés peut être choisi de manièrequelconque et imprévisible.

Nous n’étudierons dans ce chapitre que les trois premières

catégories.

Langages et paradigmes – p.98/311

priorités et associativités

Les langages sont extrêmement différents dans cedomaine :

� � � � � � �� �� en PL/I est syntaxiquementcorrect mais de signification stupideif � � � � then en Pascal est normalementsémantiquement incorrect (erreur de type)pour certains langages les opérateurs decomparaison ne sont pas associatifs

� � � � � � � � � � en Icon a la significationattendue mais ne calcule pas un booléen

Langages et paradigmes – p.103/311

Affectation

4.2.3 Affectation

C’est l’énoncé caractéristique des langages impératifs,le moyen de changer l’état de la machine abstraite.Beaucoup de langages impératifs séparent plus oumoins strictement les énoncés des expressions :

Fortran, PL/I, Pascal : séparation totaleAlgol 60, C : expressions conditionnellesAlgol 68, APL, Icon : langages d’expressions

Langages et paradigmes – p.104/311

Priorités et associativités

4.2.2 Priorités et associativités

L’associativité détermine l’ordre d’exécution à prioritéégale :

de gauche à droite en général :� � � �

pas toujours logique :� � � �

parfois de droite à gauche pour l’exponentiation :

� � � � � � en Fortrande droite à gauche pour les fonctions : � � � � � �� � � �

de droite à gauche également en APL : � � � � � � � � ou

� × � � � ÷�

Langages et paradigmes – p.101/311

priorités et associativités

La priorité évite de placer trop de parenthèses dans lesexpressions compliquées :

� � � � � � � � � � �

mais� � � � ��� � � � �

s’il y a trop de niveaux de priorité (voir C ou Icon), leprogrammeur les oublies’il n’y en pas assez, des expressions naturelles sonterronées :if � � and � � then � � � en Pascal

Langages et paradigmes – p.102/311

affectation

Dans ce cas, toute variable est une valeur-G ; quandelle apparaît là où on a besoin d’une valeur-D, on doit ladérepérer (concept introduit par Algol 68).

Java utilise ce mécanisme pour les objets, mais l’autremécanisme pour les types prédéfinis.

Langages et paradigmes – p.107/311

affectation

Orthogonalité de l’affectation :dans un langage d’expression (Algol 68, Icon, APL),tout a une valeur, donc l’affectation aussien Pascal, PL/I ou Ada, l’affectation est un énoncépur

en C, l’affectation a une valeur, qui est celle de sapartie droite ; l’inconvénient est que l’affectation estnotée comme une égalité :

� � �� � �

� � � � � � � � �� � � � � �� � �� �� � � �

� �� � � � � � � � �� � � � �

Langages et paradigmes – p.108/311

affectation

La signification même de l’énoncé d’affectation n’estpas universelle :

en Pascal ou C, les noms sont interprétésdifféremment en partie gauche et en partie droite :

� � �

� � � � �

désigne une valeur en partie droite, unemplacement en partie gauche.en partie gauche on peut mettre une valeur-G, quidénote un emplacement à modifieren partie droite on peut mettre une valeur-D, quidénote une valeur à affecter

Langages et paradigmes – p.105/311

affectation

toute expression ne peut pas être une valeur-G :

� � � � �

� �� � � � � �

�� �� � � � � � � �� �� � � �

dans certains langages, les noms sont des références àdes valeurs, plutôt que les noms d’emplacements :

� � �

� � � � � � � � �� � � � � � � � �� � �� � �� � � � �

� � � � � � � � � � � � � � � � � �� � � � �

� � � �� � � � � � � � � � �

Langages et paradigmes – p.106/311

affectation

Quelques langages proposent l’affectation multiple :

� � � � � � permet d’échanger les valeurs de� et .

Langages et paradigmes – p.111/311

Ordre d’évaluation dans les expressions

4.2.4 Ordre d’évaluation dans les expressions

Associativité et priorité déterminent l’ordre d’évaluationdes opérations, mais pas des opérandes : dans� �

� � �

� � � � on ne sait normalement pas si � � � estévalué avant toute opération, ni si la multiplication estfaite avant la première soustraction.

Même remarque pour les paramètres dessous-programmes (sauf exceptions) : dans � �� � � � � �

� �� � � on ne sait pas dans quel ordre sont évalués lesdeux appels de fonctions.

Langages et paradigmes – p.112/311

affectation

en Java la syntaxe fautive est conservée, mais l’erreurest détectée

Langages et paradigmes – p.109/311

affectation

Opérateurs d’affectation combinés :

� �� � � � � �� � � � nécessite deux références àl’élément du tableauil n’est pas facile en général de programmer uneprocédure qui fait le même travailAlgol 68 introduit les affectations combinées : � � � �

� � � �

C fait la même chose : �� �� � �� � � �

C ajoute les opérateur immédiats sur les variables :

� � � � � ��

� �

Icon combine la totalité des opérateurs infixes :�

� � � � �

Langages et paradigmes – p.110/311

ordre d’évaluation

Si le compilateur réordonne certaines opérations, celapeut :

supprimer ou provoquer des dépassements decapacité : � � � � n’est pas identique à � � � �

si les trois valeurs absolues sont proches de l’entiermaximummodifier de manière significative la précision durésultat : si � �� , alors� � � � n’est pas égal à

� si� est très petit devant et que l’évaluation estfaite strictement de gauche à droite

Langages et paradigmes – p.115/311

Opérateurs booléens à court-circuit

4.2.5 Opérateurs booléens à court-circuit

En algèbre de Boole, (a > b) ` (b > c) appliquel’opérateur d’intersection aux deux comparaisons, quisont donc toutes les deux évaluées.

En programmation, �� � � and � � � � peut ne pasévaluer la deuxième comparaison si la première estfausse.

Langages et paradigmes – p.116/311

ordre d’évaluation

Deux raisons pour que ce soit important :changement de signification si un appel de fonctiona un effet de bord (modification de l’état de lamachine abstraite)possibilité de produire du code efficace si lecompilateur a le droit de choisir l’ordre d’évaluation

Langages et paradigmes – p.113/311

ordre d’évaluation

Les définitions de langages hésitent sur ce qu’il fautfaire :

celles de Pascal ou Ada spécifient que l’ordre n’estpas spécifiécelles d’Algol 60 et de Java imposent l’évaluation degauche à droitecelle d’Algol 68 spécifie que l’évaluation estcollatérale

Langages et paradigmes – p.114/311

contrôle non structuré

L’énoncé de branchement a subsisté en Pascal, Ada ouC, comme moyen de traiter des situationsexceptionnelles :

sortie au milieu d’une boucle : une conditioncouvrant le reste de la boucle la remplace sansproblèmesortie prématurée d’un sous-programme : unénoncé spécialisé est sans doute préférable, àcondition de ne pas en abuser

Langages et paradigmes – p.119/311

contrôle non structuré

traitement d’erreurs : la sortie du sous-programme peutéventuellement sortir de plusieurs sous-programmes encours, d’où effondrement de la pile d’exécution ; untraitement d’exception est sans doute préférable (Ada,C++, Java)

Langages et paradigmes – p.120/311

opérateurs à court-circuit

Les langages diffèrent sur ce point :en Algol 60, tout est évaluéen Pascal, on ne doit pas programmer de manière àcompter sur la non-évaluationen C, les opérateurs booléens font le court-circuiten Ada, les deux types d’opérateurs sont fournis

Le choix du court-circuit facilite la programmation.

Le choix de l’évaluation totale facilite la génération decode et peut produire du code plus efficace.

Langages et paradigmes – p.117/311

Structures d’énoncés

4.3 Structures d’énoncés

4.3.1 Flot de contrôle non structuré

Dans les langages d’assemblage, le flot de contrôle esttraité à l’aide de trois concepts non structurés :

étiquettesbranchement inconditionnelbranchement conditionnel

En Fortran IV, Cobol, Algol 60 ou PL/I, ces mécanismessont les seuls qui permettent de programmer uneitération commandée par une condition logique.

Langages et paradigmes – p.118/311

Sélection

4.3.3 Sélection

En Fortran, seulement branchement conditionnel : � �

� � � � � � � � � � � � �

Algol 60 introduit la forme utilisée par Pascal :

if � � then � � �

else if � � then � � �

� � �

else � � �

Langages et paradigmes – p.123/311

sélection

Pas de symbole de fin, ce qui pose un problèmesyntaxique :

en Algol 60, l’énoncé suivant then ne peut être unénoncé if

en Pascal, règle en langue naturelle pour leverl’ambiguïtéen Algol 68, Fortran 77, etc., on ajoute un symbolede finpour éviter une cascade de endif, on ajoute unsymbole elsif pour remplacer else if

Langages et paradigmes – p.124/311

contrôle non structuré

L’abandon du branchement est le résultat de l’idée deprogrammation structurée des années 70 (Dijkstra, puisHoare et Wirth) : le flot de contrôle du programme doitêtre déterminé par des structures d’énoncés à uneentrée et une sortie.

Introduction des nouvelles structures :conditionnel : Algol 60répétitif : Algol 60choix sélectif : Algol Witératifs : Pascalplusieurs langages ont tenté de proposer desstructures itératives plus complexes, sans grandsuccès

Langages et paradigmes – p.121/311

Séquence

4.3.2 Séquence

Caractéristique des langages impératifs.

Un groupe d’énoncés est parenthésé entre begin et endou entre accolades (C, Icon).

L’énoncé composé peut avoir une valeur (Ada, C, Icon,Lisp), celle de la dernière expression évaluée.

Les énoncés sont exécutés dans l’ordre indiqué, maisles bons compilateurs ne se privent pas de changerl’ordre si c’est possible et souhaitable.

Langages et paradigmes – p.122/311

Choix

4.3.4 Choix

L’énoncé case est introduit par Algol W (Wirth et Hoare) :

case � in

� � � �

� � �

end case

Langages et paradigmes – p.127/311

choix

La forme plus générale est due à Pascal :

case �� � in

� � � �

�� � � �

� � � � � � �

end

Modula-2 ou Ada offrent des variantes syntaxiques.

L’intérêt majeur de l’énoncé est de permettre deproduire du code très efficace, en plus de la clartéexpressive.

Langages et paradigmes – p.128/311

sélection

Si la condition est compliquée, le compilateur peutproduire du code qui court-circuite l’évaluation d’unepartie :

if � � and � � then

� � �

endif

est équivalent à

if � � then if � � then

� � �

endif endif

Langages et paradigmes – p.125/311

sélection

S’il y a une partie else, l’équivalent nécessite desbranchements et étiquettes, ou la duplication d’unepartie du code.

Construction assez différente en Lisp :

�� � � �� �� � � � � � � � �

� � � � � � � � � � �

� � �� � � � � � � � �

Langages et paradigmes – p.126/311

Répétition

4.4.1 Répétition

Énoncé primitif en Fortran :La forme est :

� � � � � � � � � � � �

� � �

� � � �� � �� � �

Ici 10 est une étiquette, et l’énoncé étiqueté ne faitrien.

� est la variable de commande de la boucle, et prendles valeurs de 1 à 19 par pas de 2.

� est une variable simple, locale et entière.Les bornes et le pas sont des constantes ouvariables entières.

Langages et paradigmes – p.131/311

répétition

Les problèmes cachés sont nombreux :rien n’empêche les énoncés dans la boucle dechanger la valeur de � , ce qui change le nombre derépétitionsdes branchements peuvent entrer dans la boucle ouen sortirla valeur de � au sortir de la boucle n’est pas définiepar le langagemême si l’intervalle est vide, le corps de la boucleest exécuté au moins une fois

Langages et paradigmes – p.132/311

choix

Les langages diffèrent suivant le traitement des cas nonprévus :

cas spécial introduit par else ou otherwise

erreur à la compilation si un cas manque (Ada)les cas absents sont ignorés (Fortran 90, C)

C propose une syntaxe très primitive :pas d’intervalles d’étiquettes ni d’étiquettes multiplestraitement de switch comme l’aiguillage d’Algol 60,où chaque cas nécessite une sortie explicite si l’onne veut pas enchaîner avec le suivantmalheureusement, cet énoncé est repris tel quel parC++et Java

Langages et paradigmes – p.129/311

Boucles

4.4 Boucles

C’est un des domaines dans lequel les auteurs de langages

ont le plus laissé libre cours à leur imagination, spéciale-

ment dans les années 70. Initialement les langages ne con-

naissaient que les boucles commandées par la progression

arithmétique d’une variable.

Langages et paradigmes – p.130/311

répétition

suite des réponses :la variable de commande doit être simple, locale etnon modifiée dans la boucle (y compris par un appelde sous-programme)la valeur finale et le pas ne sont évalués qu’uneseule fois, avant l’entrée dans la bouclela condition d’achèvement est vérifiée avant l’entréedans la bouclela valeur de la variable de commande au sortir de laboucle n’est pas définie

Langages et paradigmes – p.135/311

Itération

4.4.2 Itération

L’énoncé while est introduit par Algol W.

Pascal ajoute l’énoncé repeat.

Modula-2 ajoute un énoncé loop, avec sortie au milieupar un énoncé exit.

Certains langages ajoutent des formes symétriques desprécédentes.

Langages et paradigmes – p.136/311

répétition

Questions générales : Soit la forme plus agréable deModula-2 :

� �� � � � � � � � � � �� �� �� �� � � �

� � �

�� �

peut-on modifier� , � � ,� � � � et �� �� � dans le corpsde la boucle ? quel est l’effet ?que se passe-t-il si � � est supérieur à� � �� quand

�� �� � est positif ?quelle est la valeur de� à la fin de la boucle ?

� peut-elle être autre chose qu’une variable simple ?

Langages et paradigmes – p.133/311

répétition

Réponses :Algol 60 définit son énoncé répétitif sous une formesi générale qu’elle permet n’importe quoi :for � �� � � � � to � �� � do � � � � � �

La plupart des langages (mais pas C) imposent desrestrictions :

pour permettre la production de code efficacepour permettre de déterminer le nombre derépétitions dès l’entrée de la boucle

Langages et paradigmes – p.134/311

Autres formes de boucles

4.4.3 Autres formes de boucles

Pascal étendu fait parcourir à la variable de commandeun ensemble de valeurs :

for � in � � � �� � � do � � �

Le langage le plus achevé est SETL, qui manipuledirectement les ensemble et les quantificateurs.

Icon propose le concept de générateur :

� � �� � � � � � � � � � � �� � �� �� � � � � � �

� � �� � �� � � � � � � � � ��� � � � �� � � � � �

� � �� � � � �� � � � � � � �� � � � � � � � �

Langages et paradigmes – p.139/311

autres boucles

On peut construire des mécanismes similaires dansdes langages plus classiques grâce au passage deprocédure en paramètre.

Langages et paradigmes – p.140/311

itération

Plusieurs langages proposent des mécanismes variésde sortie de boucle :

sortie de plusieurs boucles à la fois (nécessited’étiqueter les boucles)saut immédiat à la prochaine itérationl’effet majeur est de rendre moins clair l’effet de laboucle, de rendre difficile la définition d’un invariant

Langages et paradigmes – p.137/311

itération

Quelques langages proposent une combinaison derépétition et d’itération :

Algol 60 :

for � � � � � � to � � � � � while � � � do � � �

PL/I :

� �� � � � � �� � � � � � � �� � � �� � � � � � � � � �� �

C :

� �� �� � � � � � � � � � � � � � �� �� � � � � �

� �� � � � � � � �� � � � �

L’énoncé est compliqué à comprendre, et il est trèsdifficile de produire du code efficace.

Langages et paradigmes – p.138/311

Systèmes de typage

5.2 Systèmes de typage

5.2.1 Introduction

L’idée de typage est la caractéristique majeure deslangages de haut niveau, ce qui les distingue deslangages d’assemblage ou similaires (mentionnés plushaut).

Langages et paradigmes – p.143/311

introduction

Un système de typage est :un mécanisme de définition de typesun mécanisme associant ces définitions à certainesconstructions du langage (quelles constructions ontun type) :

constantesvariableschamps d’articlesparamètressous-programmesexpressions

Langages et paradigmes – p.144/311

Types

5 Types

5.1 Généralités

Même pour les langages dits « non typés » le conceptde type de données est fondamental.

pour ces langages le type n’est pas déterminé pardéclaration mais par les opérations elles-mêmesl’addition entière et l’addition réelle sont distinctesn’importe quelle valeur peut être considérée commede n’importe quel typel’idée est de faire du langage d’assemblage de hautniveau : PL/360, Bliss, BCPL

Langages et paradigmes – p.141/311

généralités

Dans les langages courants, les types fournissent lecontexte des opérations :

opérateurs surchargéstaille d’un objet dynamiqueappel du constructeur de l’objet

Ils limitent l’ensemble d’opérations applicables,fournissant ainsi une validation sémantique partielle.

Points importants :Signification et but des types.

Équivalence et compatibilité des types.Aspects spécifiques des différents types.

Langages et paradigmes – p.142/311

Vérification de type

5.2.2 Vérification de type

La vérification de type sert à assurer que le programmerespecte les règles de compatibilité des types.

Un langage est fortement typé s’il interdit l’applicationd’une opération à un objet qui n’est pas du type prévu(et fait respecter cette interdiction).

Dans un langage faiblement typé, certainesabsences de compatibilité ne sont pas considéréescomme des erreurs.

Langages et paradigmes – p.147/311

vérification de type

Le typage est statique si le langage est fortement typéet que la vérification peut être faite à la compilation.

En fait, même pour les plus statiques des langages,certaines vérifications ne peuvent pas être faites avantl’exécution.

Langages et paradigmes – p.148/311

introduction

Un système de typage est encore :un ensemble de règles :

équivalence de types : quand les types de deuxvaleurs sont-ils identiques ?compatibilité de types : quand une valeur d’uncertain type peut-elle être utilisée dans un certaincontexte ?inférence de types : comment déterminer le typed’une expression à partir des types de sescomposants ou de son contexte ?

Langages et paradigmes – p.145/311

introduction

Dans un langage utilisant le polymorphisme, il fautdistinguer le type d’une expression du type de l’objetqu’elle désigne.

Les sous-programmes doivent avoir un type s’ils sontde première ou deuxième classe : en général c’est leurprofil entier.

Langages et paradigmes – p.146/311

vérification de type

Au contraire, le polymorphisme d’Eiffel ou Oberon estcompatible avec un typage statique : les types dérivésou étendus doivent accepter toutes les opérations dutype de base.

en ML, le compilateur effectue une inférence de typegénérale qui évite la déclaration, mais du coup letypage peut être statique.

Langages et paradigmes – p.151/311

Définition de type

5.2.3 Définition de type

Les langages anciens fournissent un ensemble detypes prédéfinis réduit, et rien d’autre.

Par exemple, Algol 60 fournit les entiers, réels etbooléens, et des tableaux de ces valeurs.

Langages et paradigmes – p.152/311

vérification de type

Exemples :Ada est fortement typé, et le typage est presqueentièrement statique.Pascal a les mêmes propriétés, mais la vérificationdes types articles avec variante sans champsélecteur implique une vérification complexe àl’exécution.C est assez faiblement typé : unions,sous-programmes à nombre variable de paramètres,équivalence entre pointeurs et tableaux, etc. Deplus, les implémentations ne font généralement pasde vérifications à l’exécution.Les langages non typés laissent au programmeurl’entière responsabilité de ses actes.

Langages et paradigmes – p.149/311

vérification de type

Le typage dynamique est une forme de retard desliaisons, présente dans les langages qui ont cettephilosophie : Lisp, Scheme, Smalltalk, Icon.

en Smalltalk ou Icon, chaque opération vérifie àl’exécution le type de ses opérandes, et faitéventuellement les conversions nécessairesen Lisp ou Scheme, la vérification peutéventuellement être court-circuitée, aux risques etpérils du programmeur

La portée dynamique implique en général le typagedynamique : le compilateur ne sait pas quel objet unnom désignera, et ne connaît donc pas son type.

Lisp, Scheme, Smalltalk ou Icon permettent à un nomde désigner n’importe quel objet.

Langages et paradigmes – p.150/311

définition de type

Un type peut être considéré de plusieurs manières :Manière dénotationnelle : un type est un ensemblede valeurs :

l’ensemble de valeurs est un domainetoute construction prend une valeur dans undomaineune mémoire est une application des noms surleurs valeursune fonction est une application d’une mémoiresur une autre mémoiretout s’exprime en termes d’opération sur desensemblesc’est la manière des spécifications sémantiques

Langages et paradigmes – p.155/311

définition de type

Autres manières de considérer un type :Manière constructive : un type est soit prédéfini (ouprimitif) soit composé à partir d’autres types :

les types prédéfinis sont en général simples : entier,réel, booléen, caractèreles constructeurs de types sont l’article, le tableau,l’ensemble, etc.c’est la manière des langages des années 70 : AlgolW, Algol 68, Pascal, Ada

Langages et paradigmes – p.156/311

définition de type

La déclaration n’existe pas toujours :Fortran et Basic ne demandent même pas ladéclaration des variables simples, avec une règledéterminant le type (entier ou réel) d’après lapremière lettre du nom.Bliss et PL/360 n’ont pas de types du tout.ML détermine les types par inférence.Les langages à typage dynamique attendentl’exécution pour déterminer le type.

Tous les autres langages obligent à déclarer le type dechaque objet manipulé.

Langages et paradigmes – p.153/311

définition de type

Une déclaration introduit un nom et en détermine lanature et les caractéristiques.

Une définition de type décrit un type particulier, et peutservir à déclarer un nom de type, ou bien à déclarerdirectement une variable de ce type.

Dans certains cas on peut séparer la déclaration dutype de sa définition :

déclaration anticipée d’un type pointeur ou d’unsous-programmedéclaration d’un type opaque

Langages et paradigmes – p.154/311

types simples

Caractères :dans les langages anciens, pas de manipulationdirecte, à cause de l’architecture de mots desmachinesintroduction à partir d’Algol 68 et Pascal, avec unalphabet plus ou moins appropriéalphabet ASCII (norme américaine, 7 bits) pourénormément de langages, y compris développés enEuropealphabet ISO-8859 (norme internationale, 8 bits) àpartir des langages ayant une norme ISOpassage avec Java à Unicode (pas d’organisme denormalisation, 16 bits)

Langages et paradigmes – p.159/311

types simples

Nombres :certains langages ne connaissent qu’un type pourles réelscertains langages (C, Fortran) proposent deuxlongueurs différentes pour les réels mais neprécisent pas leurs relationsAlgol 68 propose les préfixes long et short pourqualifier les réels, mais encore une fois sansspécifier les propriétésAda permet de spécifier la précision minimum,charge à l’implémentation de la respecter au moinsC et Modula-2 distinguent les entiers des cardinaux(entiers sans signe)

Langages et paradigmes – p.160/311

définition de type

Manière abstraite : un type est une interface forméed’un ensemble d’opérations et de leur sémantique :

on insiste sur la signification du type plus que surson implémentationpremiers langages : Simula–67 et Smalltalkpoint de vue des langages à objets

Langages et paradigmes – p.157/311

Classification des types

5.3 Classification des types

5.3.1 Types simples ou scalaires

Booléens ou logiques :souvent représentés, au moins de manière interne,par 0 et 1PL/I et C n’ont pas de booléensIcon non plus, mais à cause du concept générald’échec ou réussite d’une évaluation

Langages et paradigmes – p.158/311

types simples

Types intervalles :Eux aussi introduits par Wirth pour Pascal.Pris dans les types simples discrets : entiers,caractères, énumérés.En Ada :

� � � � � � � � � � � � � � � � � � �� � � � � � � � �� � est untype dérivé du type� � � � � �� par une contrainte ; ilest incompatible avec son type parent

� � � � � � �� � �� � � � � � �� � � � � � � � � �

� � � � � � � � � � � � �� � est un sous-type contraint dutype � �� � � � � , avec lequel il est compatible

Langages et paradigmes – p.163/311

Types composites

5.3.2 Types composites

Types composites, construits ou structurés, créés parapplication d’un constructeur de type à un ou plusieursautres types.

Articles :

introduits par Cobol (mais pas comme de vrais types)

repris par PL/I et Algol W, puis à peu près tous leslangages

collection hétérogène de champs

produit cartésien des types des champs

Langages et paradigmes – p.164/311

encore des nombres :Fortran et Scheme proposent des nombrescomplexestrès rarement les langages proposent des nombresrationnelsScheme et Icon proposent des entiers de tailleillimitéeCobol et PL/I proposent des nombres décimauxAda propose des nombres en virgule fixenombres décimaux ou virgule fixe sont nécessairespour les calculs financiers et commerciaux

Langages et paradigmes – p.161/311

types simples

Types énumérés :Introduits par Wirth pour Pascal.Valeurs ordonnées.Utilisation dans des boucles, comme indices detableaux.Type distinct des entiers, contrairement à C.En Ada :

on peut spécifier le nombre ordinalle même nom peut servir dans plusieurs typesénumérésle type caractère est un type énuméré

Langages et paradigmes – p.162/311

types composites

Ensemblesintroduits par Pascal sous une forme limitée auxensembles de types discrets

forme complètement générale dans SETL

ensemble de caractères dans Icon

également ensembles généraux en Icon, mais sousforme limitée

Langages et paradigmes – p.167/311

types composites

Pointeursforme spéciale de valeur-G

référence à un objet du type de base

moyen d’implémenter des types récursifs

Langages et paradigmes – p.168/311

types composites

Unions :introduites par Algol 68

restreintes par Pascal aux articles

reprises dans C

remplacées par l’extension de type d’Oberon

Langages et paradigmes – p.165/311

types composites

Tableauxle seul type composite présent partout

application du type des indices sur le type descomposants

cas particulier des tableaux de caractères

Langages et paradigmes – p.166/311

5.3.3 Orthogonalité

Facilite en principe l’apprentissage du langage.

Les langages d’expression sont plus orthogonaux queles autres.

Nécessité d’un type pour les constructions qui nerendent pas de résultat : � �� � en Algol 68 ou C, � � � � enIcon.

Icon procède différemment quand l’évaluation échoue.

Langages et paradigmes – p.171/311

orthogonalité

Le système de types de Pascal est plus orthogonal queceux qui le précèdent, mais :

une seule partie variante par articleune fonction ne peut pas rendre un résultat structuréle type fichier ne permet ni affectation nicomparaison

Puisque les types simples ont leurs constanteslittérales, l’orthogonalité demande la même chose pourles types composites :

Pascal et Modula-2 ne le permettent pasAda le fait de la manière la plus générale, par positioou par nom

Langages et paradigmes – p.172/311

types composites

Listesséquence d’éléments, sans idée d’application d’un typed’indice

longueur variable

accès séquentiel

définition récursive

type fondamental dans les langages fonctionnels

Langages et paradigmes – p.169/311

types composites

Fichiersreprésentation des données extérieures au programme

peuvent être traités comme des tableaux

concept de position courante et accès séquentiel

limitations liées aux contraintes du matériel

Langages et paradigmes – p.170/311

équivalence structurelle

mais pas à :

type �� �� � record

� � �� �

� � � �� �

end

. . . sauf en ML.

Le compilateur doit faire une comparaison récursive dela représentation interne des définitions de types, ce quidonne une vision de plutôt bas niveau de l’équivalence.

Elle peut confondre des types que le programmeurvoudrait voir distincts, s’il arrive par hasard qu’ils sontdécrits de la même manière.

Langages et paradigmes – p.175/311

Équivalence nominale

5.4.3 Équivalence nominale

Deux définitions différentes correspondent à deux typesdifférents, même si leur écriture est identique.

Si l’on définit un alias à un type existant, y a-t-iléquivalence nominale ou non ?

oui en Pascal ou Modula-2 :type

� � � � � record � � � end

� � � � � � � � �

Les types � � � � et � � � � sont équivalents.

Langages et paradigmes – p.176/311

Vérification des types

5.4 Vérification des types

5.4.1 Équivalence de types

Il existe deux manières différentes de définirl’équivalence de types :

l’équivalence structurelle s’appuie sur le contenu desdéfinitions de typesc’est celle d’Algol 68, C ou ML, et celle despremières implémentations de Pascall’équivalence nominale s’appuie sur l’apparition dansle programme des définitions de typesc’est celle de Pascal depuis sa normalisation, desdescendants de Pascal et en particulier Ada, de Java

Langages et paradigmes – p.173/311

Équivalence structurelle

5.4.2 Équivalence structurelle

la forme de la déclaration ne compte pas :type � � � � � record � � � � �� � end

est équivalent à :

type � � � � � record

� � � � �� �

end

et aussi à :

type �� �� � record

� � � �� �

� � �� �

end

Langages et paradigmes – p.174/311

Conversions et forceurs

5.4.4 Conversions et forceurs

Contextes d’attente de types donnés :

Dans une affectation, on attend normalement un typede partie droite identique à celui de l’objet auquel seréfère la partie gauche.

Dans une addition, l’opérateur est surchargé, et ons’attend à deux opérandes entiers pour une additionentière, ou deux opérandes réels pour une additionréelle.

Dans un appel de sous-programme, on attend desparamètres effectifs du même type que les paramètresformels.

Langages et paradigmes – p.179/311

conversions et forceurs

Si dans tous ces cas on veut que les types soientexactement ce qui est attendu, il faut utiliser trèssouvent une conversion explicite, obtenue par unforceur (cast).

Langages et paradigmes – p.180/311

équivalence nominale

mais ce n’est pas toujours souhaitable :

type � � � �� � � � � �� �

�� �� � � � �� � � � �� � var � � � � � �� � �

� � �� �� � � � �� �

� � �� � � �

Langages et paradigmes – p.177/311

équivalence nominale

équivalence stricte : deux noms pour le même type nesont pas des types équivalents (type dérivé d’Ada)

équivalence lâche : les types sont équivalents s’ilsdésignent finalement la même description (Pascal,sous-types d’Ada)

Langages et paradigmes – p.178/311

conversions et forceurs

Changement de type sans conversion :En programmation de bas niveau, cela peut servir àinterpréter la même donnée de plusieurs manièresdifférentes.

C’est indispensable pour programmer un récupérateurde mémoire, par exemple.

En Ada, il faut construire les fonctions correspondantespar instantiation d’une procédure générique.

En C, le nom du type sert aux conversions normales,mais on peut faire des conversions sans vérification enpassant par des pointeurs.

Langages et paradigmes – p.183/311

Conversions automatiques

5.4.5 Compatibilité de types et conversions

automatiques

Pour la plupart des langages, l’équivalence de typen’est pas demandée partout :

ce qui est demandé est la compatibilité du type de lavaleur avec le type demandépour une addition, les deux types doivent êtrecompatibles avec le type entier, ou compatibles avecle type réelpour un appel de sous-programme, les types desparamètres effectifs doivent être compatibles avecles types des paramètres formels

Langages et paradigmes – p.184/311

conversions et forceurs

Modes de conversion :Types structurellement équivalents alors que le langagedemande l’équivalence nominale : aucun code n’estnécessaire pour effectuer la conversion.

Ensembles de valeurs différents, mais mêmereprésentation pour les valeurs communes (typesintervalles) : le code vérifie simplement l’appartenanceau type attendu (ou ne le vérifie pas !).

Types avec des représentations différentes, mais avecune correspondance possible entre les valeurs (entieret réel) : le code effectue réellement la conversion,peut-être à l’aide d’instructions spécialisées duprocesseur.

Langages et paradigmes – p.181/311

conversions et forceurs

Exemple en Ada :

� � � � � � � ��

� � � �� �

� � � � � �

� � � � � �� � �

� � �

� � � � � � � � � � � � � �� � �� � � �� � � � � � � ��� � � � �� � � �

� � � � � � � � �� � � � � � � � � � � � �� �

� � � � �� � � � � � � � � � �� � � �� � � � � � � � � �� �� � �

� � � � � � � � �� �� � � � � � � � �� �� � � � � � �� � �� � � � � � �

� � � � � � � � �� �� � � � � � � � � � �� �

� � � � � � �� � � � � � � � � �� � �� � � � � � �

Langages et paradigmes – p.182/311

Inférence de type

5.4.6 Inférence de type

Une fois connu le type des opérandes, il faut déterminerle type de l’expression.

Cas simples :le résultat d’une opération est en général du typedes opérandes (sauf les comparaisons)le résultat d’une fonction est déclaré dans sonen-têtele résultat d’une affectation (s’il y a lieu) est du typede la partie droite

Langages et paradigmes – p.187/311

inférence de type

Cas des types intervalles :si� est de type � � � � � et de type � � � �� � , quel est letype de� � ?en Pascal, le résultat de l’opération est du type debase des opérandes, ici� � � � � ��

si on affecte une variable d’un type intervalle, il fautfaire une vérificationun compilateur soigné peut éviter une bonne partiede ces vérifications en suivant à travers leprogramme les contraintes respectées par lesvariables

Langages et paradigmes – p.188/311

conversions automatiques

La compatibilité de types est définie de manière trèsdifférente suivant les langages :

très stricte en Ada, où elle ne doit jamais impliquerun changement de représentationun peu moins stricte en Pascal, où la conversionautomatique d’entier en réel est acceptéeassez permissive en Fortran ou C, qui permettentles conversions entre toutes les valeurs numériquesextrêmement permissive en Fortran 90, qui permetdes conversions entre tableauxpermissive et extensible en C++

Langages et paradigmes – p.185/311

conversions automatiques

Si le langage permet à la fois la surcharge et lesconversions automatiques, les choses se compliquentet obligent à établir des priorités (cas des opérationsarithmétiques par exemple).

Si les pointeurs peuvent être considérés comme d’untype universel :

ou bien on perd toute sécurité (programmation d’unrécupérateur de mémoire)ou bien on place dans chaque objet pointél’indication de son typec’est le cas en Java ou Eiffel, mais aussi dans leslangages à typage dynamique

Langages et paradigmes – p.186/311

Syntaxe et opérations

5.5.1 Syntaxe et opérations

La définition ressemble à une suite de déclarations devariables entre deux délimiteurs spécifiques.

Les champs sont nommés, et non pas numérotés engénéral.

En Pascal et ses descendants, la référence à un champse fait en notation pointée :� � �� � � � �� � � � � .

En Cobol, PL/I et Algol 68, l’ordre est inversé :� � � � � of

� � �� � � � .

Langages et paradigmes – p.191/311

syntaxe et opérations

L’emboîtement des définitions est permis :directement en Pascal et ses descendantspar l’intermédiaire d’un nom de type en Fortran 90

Les références s’emboîtent comme les définitions :� � �� � � � � �� � �� � � � � �� �� � � .

En Cobol ou PL/I, on peut omettre les intermédiaires s’iln’y a pas ambiguïté :� �� � � of � � �� � � � � of � � � � � � � �

peut aussi s’écrire� �� � � of � � �� � � � � si cela ne peutêtre interprété que d’une seule manière.

Langages et paradigmes – p.192/311

inférence de type

Cas des types composites :Quel est le type d’une constante structurée ?En Pascal,� � � � � � est du typepacked array � � � � � � of � �� �

Par conséquent, on ne peut pas l’affecter à unevariable d’un type plus long !En revanche, � � � � � � � � est d’un type ensemblenon complètement défini.La solution est de ramener tout ensemble au type debase, ici set of � � � �� � � � , où� � � est défini parl’implémentation.Pour les chaînes, il faut faire des extensions ausystème de compatibilité de type, en complétantautomatiquement à la longueur nécessaire.

Langages et paradigmes – p.189/311

Articles et unions

5.5 Articles et unions

Les articles sont appelés structures en Algol 68, C ouC++, et types en Fortran 90.

En Cobol, un article n’est pas un type, applicable àplusieurs objets, mais un objet spécifique.

Dans les langages à objets, l’article n’existe pas demanière spécifique, c’est un cas particulier de classe.

Langages et paradigmes – p.190/311

Articles avec variante

5.5.3 Articles avec variante

C’est la vision la plus courante du concept d’union, quipermet de conserver un typage assez strict :

type

� � � � � � � � record

� � � � packed array �� � �� � of � � � � �

� � � �� �� � � � � � � � � � � � � � �� � � �� � � � � �

� � � � �� � � � � � � � � � �� � � � � � � � � �

� � �� � � � � � � �� � �

case � � � �� � � � � � � � �� � of

�� � � � � � �� � � � � � � � � � � �

�� � �� � � � � � � � �� � �

�� � � � � � �� � �� � � � �� �

end �

Langages et paradigmes – p.195/311

articles avec variante

le champ �� � � � � � est le sélecteur ou le discriminant

chaque groupe de champs entre parenthèses est unevariante

seule l’une des deux peut exister à tout moment,suivant la valeur du champ sélecteur

les variantes partagent donc le même emplacement demémoire, et d’ailleurs dans le cas présent ne sont pasde même taille

la taille totale de l’article dépend donc de la valeur dusélecteur

Langages et paradigmes – p.196/311

Représentation en mémoire

5.5.2 Représentation en mémoire

Normalement les champs sont rangés en mémoire demanière contiguë.

L’ordre d’énumération est donc important.

Les contraintes d’adressage imposées par la machinepeuvent faire que des zones restent non affectées :

type � � �� � � � � record

� �� � packed array � � � �� � of � � � �

� � � �� �� � �� � � � � � � � � � � �� � � � � � � � � �

� � � � �� � �� � � � � � � �� � � � � � � � � � �

� � �� � � � � � �� �

end

Langages et paradigmes – p.193/311

représentation en mémoire

En Pascal, le préfixe packed demande de ne pas laisserde zone non affectée (ce qui gagne 5 octets dans le casprécédent, au prix d’une grande complication desaccès).

Certains langages permettent de réordonner leschamps pour gagner de la place.

Ada permet de spécifier la position exacte de chaquechamp.

La plupart des langages permettent l’affectationglobale.

Cobol permet l’affectation par nom (articles distinctsmais avec des champs communs).

Ada permet la comparaison pour égalité.

Langages et paradigmes – p.194/311

Tableaux

5.6 Tableaux

C’est le seul type composite qu’on trouve partout.

Normalement homogène, sauf dans les langages àtypage dynamique.

Application du type d’indice sur le type de composant.

Tableaux associatifs dans certains langages (Perl, Icon,C++), pas considérés ici.

Langages et paradigmes – p.199/311

Syntaxe et opérations

5.6.1 Syntaxe et opérations

Référence avec le nom du tableau et une valeurd’indice.

Utilisation de crochets en Pascal, C ou Icon.

Utilisation de parenthèses en Fortran ou Ada :en Fortran, pour limiter le jeu de caractères utiliséen Ada, pour respecter le principe de référenceuniforme, qui masque à l’utilisateur d’un module lamanière d’implémenter les opérations

Langages et paradigmes – p.200/311

articles avec variante

L’idée la plus ancienne est celle de la déclarationd’équivalence de Fortran : � � � � � � � � � � � � � � � � � �

indique que les trois variables mentionnées partagent lemême emplacement.

La contribution de Pascal, réutilisée en Modula-2 etAda, est d’intégrer l’idée dans celle d’article et de fournirles moyens de faire vérifier la validité des références.

Les unions de C nécessitent une notation pluscompliquée.

Langages et paradigmes – p.197/311

articles avec variante

Les problèmes principaux sont la sécurité d’accès :nulle en Fortran ou Ctotale en Algol 68 avec la nécessité de passer par unénoncé case spécifiquebonne en Pascal si le compilateur fait lesvérifications nécessairescependant, la désynchronisation entre leschangements de valeur du sélecteur et l’affectationaux champs n’est pas vérifiablequand le champ sélecteur est omis, la sécuriténécessite que le compilateur en gère un qui estcaché

Langages et paradigmes – p.198/311

syntaxe et opérations

Sections :Une section est une partie rectangulaire d’untableau.On peut toujours se référer à un composant, pourl’examiner ou le modifier.Pascal et ses descendants permettent de se référerà une ligne d’un tableau à deux dimensions, maispas à une colonne.Algol 68 et Fortran 90 permettent de se référer à unsous-tableau quelconque.APL élargit toutes les opérations possibles auxtableaux, quel que soit le nombre de dimensions.

Langages et paradigmes – p.203/311

Dimensions et bornes

5.6.2 Dimensions et bornes

Le point majeur est de savoir quand les valeurs desbornes sont fixées :

durée de vie globale, valeurs des bornes statiques :le compilateur alloue l’espace de manière statique(Fortran)durée de vie locale, valeurs des bornes statiques : lecompilateur alloue l’espace dans la zone d’activationlocale (Pascal)durée de vie locale, valeurs des bornes connues àl’exécution de la déclaration : le compilateur allouel’espace dans la pile, en le faisant pointerindirectement depuis la zone d’activation locale(Algol 60, Ada)

Langages et paradigmes – p.204/311

syntaxe et opérations

Déclaration : méthodes très variées.en C :� �� � � � � � �� � � � �� � �

en Fortran :� �� � � � � �� � � � � � � � � �� � � �

en Pascal :� � � � �� � � � � array �� � � � �� ��

� of

� � � �

en Ada :� � � � �� � � � � � � � � � �� �� � � � � �� � � � � �

� � � � �� ��

� � � � �� � � � � ��

Langages et paradigmes – p.201/311

syntaxe et opérations

Tableaux à plusieurs dimensions :pas toujours considérés de la même manière

� � �� � � � � � � � � � � � � � � � � � � � � � � � � � �� � en Ada

� � �� � � � � array � � � � � � � of array � � � � � � � of � �� �

en Pascal, mais l’abréviation � of array � ⇒ estpermise

� � �� � � � �� � � � � � � � � � � en Cla référence n’utilisant qu’un indice est permise enPascal ou C, elle ne l’est en Ada qu’avec unedéclaration convenable

Langages et paradigmes – p.202/311

dimensions et bornes

Chaînes de caractères :parfois traitées exactement comme des tableaux, sile langage fournit le nécessaire : Icon, Perlmécanisme similaire mais description différente enJavaextensions spécifiques : Pascal, Ada

Langages et paradigmes – p.207/311

Organisation en mémoire

5.6.3 Organisation en mémoire

Le plus souvent, rangement contigu des composants.

Si les composants ont des contraintes d’alignement, ilpeut rester des trous entre eux.

En Pascal on peut spécifier l’attribut packed pour éviterces trous.

Langages et paradigmes – p.208/311

dimensions et bornes

autre manière de fixer les bornes :durée de vie arbitraire, valeurs des bornes connuesà l’exécution de la déclaration : allocation explicitedans le tas (Java)durée de vie arbitraire, valeurs des bornes variables: allocation dans le tas, et création de nouveauxobjets quand les valeurs des bornes changent (APL,Icon, Perl)

Langages et paradigmes – p.205/311

dimensions et bornes

Le cas des paramètres de sous-programme peut êtredifférent :

en Pascal, les paramètres tableaux conformantspermettent une spécification incomplète :function �� �� � � � � � � �� � � �

� � � � array �� � � � � � � � � � � � � � �� � of � �� � � � �� � �

var � � � � � � � �� � � � � � � �� � �

begin

� � � �� � �

for � �� � � � to � � � do � � � �� � � � � � �� � � � �� � �

�� �� � � � � � � �� � � � �� � � �

end �

idée similaire en Ada :� � � � � �� � � � � �� � � � � � � � �

� � � �� �

Langages et paradigmes – p.206/311

organisation en mémoire

Pour un paramètre formel, la représentation nécessiteun descriptif :

borne inférieure dans chaque dimensionnombre d’éléments dans chaque dimensionpointeur sur le tableau dans la pileborne supérieure dans chaque dimension si l’onvérifie la validité des indices

Langages et paradigmes – p.211/311

Pointeurs et types récursifs

5.7 Pointeurs et types récursifs

5.7.1 Généralités

Type récursif : défini à partir de lui-même, ou contenantdes références à lui-même.

Permet de construire des structures dynamiques tellesque listes et arbres.

Dans les langages utilisant un modèle de référencepour les variables (Lisp, Scheme, Icon, Java pour lesobjets), toute variable est une référence, donc un articlede type � � � � contient facilement une référence à unarticle de même type.

Langages et paradigmes – p.212/311

organisation en mémoire

Pour un tableau à deux dimensions, deux manières deranger les éléments :

par ligne : � � � � � � est suivi par � � � � � � (la plupart deslangages)par colonne : � � � � � � est suivi par � �� � � � (Fortran)très significatif pour les performances des parcoursrépétitifs, pour utiliser les possibilités des mémoirescaches

Langages et paradigmes – p.209/311

organisation en mémoire

On peut aussi représenter le tableau à deuxdimensions comme un tableau de pointeurs sur destableaux à une dimension :

place supplémentaire prise par les pointeursaccès plus rapide car sans multiplicationpossibilité de lignes de longueurs variables

Langages et paradigmes – p.210/311

syntaxe et opérations

L’affectation dépend du modèle utilisé :Dans un langage fonctionnel, en général on utiliseun modèle de référence, et l’allocation estautomatique.Dans la plupart des langages impératifs, on utiliseun modèle de valeur (Pascal, C, Modula-2, Ada) :�

� � n’a pour effet de faire désigner par� l’objetdésigné par que si� et sont des pointeurs.Dans les langages utilisant le modèle de référence,on s’arrange cependant pour ne pas utiliser deréférence pour les objets immuables, en particulierles constantes.

Langages et paradigmes – p.215/311

syntaxe et opérations

En Java, les deux modèles coexistent de manièreexplicite :

� � � place la valeur de dans� si les deux variablessont d’un type prédéfini, sinon c’est une affectation depointeur.

Langages et paradigmes – p.216/311

généralités

Dans les langages utilisant un modèle de valeur (PL/I,Algol 68, Pascal, Modula-2, C, Ada), il faut le conceptde pointeur, qui est une valeur servant de référence.

En Pascal ou Modula-2, les pointeurs ne peuventdésigner que des objets dans le tas.

Les autres langages fournissent un opérateur quidonne un pointeur sur un objet ordinaire.

Un pointeur est plus qu’une adresse, c’est un conceptde haut niveau (sauf en C !).

S’il y a allocation dans le tas, il faut soit unedésallocation explicite, soit un récupérateur demémoire.

Langages et paradigmes – p.213/311

Syntaxe et opérations

5.7.2 Syntaxe et opérations

Les opérations sont avant tout l’allocation et ladésallocation des objets pointés, le dérepérage d’unpointeur, et l’affectation d’un pointeur.

Langages et paradigmes – p.214/311

Modèle de valeur

Modèle de valeur :Exemple en Pascal :

type � � � � � � � � � � � � � �

� � � � � � record

� � � � � � � � � �� � � �

�� � � � � � � � �� � � � � � � � � � � �

end

Définitions similaires en Modula-2, Ada ou C.

Langages et paradigmes – p.219/311

Construction

Construction :Pas de constante pour les structures dynamiques, quidoivent être construites explicitement :

var � � � � � � � � � � � �

begin

� � � �� � � � �

with � � � � � dobegin

� � � � � � � � � � � � � � �

� � � � �� � � � � �

� � �� � � � � nil

�� � � � � � �� � � � � � � � � � � � � � �

� � �

end

Langages et paradigmes – p.220/311

Modèle de référence

Modèle de référence :Lisp permet de construire une structure explicitement àpartir de l’opération� � � � , qui construit une pairepointée : couple de pointeurs vers d’autres objets.

En Icon, avec le type d’article� � � �� � � � � � � �� � � � � � � �

�� � � � � � � � �� � � � on peut construire un arbre :

� � � � � � � � � � � � � �� � � � � � � � � � � � � � � �

� � � � � � � �� � � � � � � � � � � � ��

� � � � � � � � � � � � � �

� � � � � � �� � �� � � � � � � � � � �� � � � � � � � � � � � � � � �

Langages et paradigmes – p.217/311

modèle de référence

Dans un langage purement fonctionnel, la structureconstruite est forcément acyclique.

En Icon c’est facile de la rendre cyclique :

� � � � � � � �� � � � � � �� � � � � � � � � � � � �

Langages et paradigmes – p.218/311

Pointeurs et tableaux en C

Pointeurs et tableaux en C :les tableaux de C sont interchangeables avec lespointeurs

après les déclarations suivantes :

� � � �

� � � � �

� � � � � � � �

les affectations suivantes sont possibles :

� � �

� � � �� �

� � � � � � � �

� � � �� �

� � � � � � � �

Langages et paradigmes – p.223/311

pointeurs et tableaux en C

les programmeurs ont pris l’habitude de croire quel’arithmétique sur les pointeurs est plus efficace pourparcourir un tableau

la lecture des définitions de types impliquant pointeurset tableaux est particulièrement difficile : voir ladifférence entre� � � � � � � � et� � � � � � � � � �

deux représentations possibles pour les tableaux àdeux dimensions : tableau de tableaux ou tableau depointeurs sur tableaux

beaucoup d’opérations de très bas niveau pour l’accèsaux tableaux compliqués, et manque total de sécurité

Langages et paradigmes – p.224/311

construction

En C++ ou Java, l’allocation de l’objet appelle de plus(s’il existe) le constructeur de l’objet, qui en initialise lescomposants.

Langages et paradigmes – p.221/311

Dérepérage

Dérepérage :Flèche verticale (représentée par un circonflexe) enPascal ou Modula-2.

Deux notations distinctes en C :

� �� � � � � �� � � � � � � � � � � � � �

� � � � � �� � � � � � � � � � � � � �

Pas d’opérateur explicite en Ada :

� � � � �� � � � � � � � � � � � � � � .

Pas non plus de dérepérage explicite en Lisp ou Icon.

Langages et paradigmes – p.222/311

Autres types

5.8 Autres types

5.8.1 Chaînes de caractères

Dans certains langages, simple tableau de caractères.

La plupart du temps, nécessité d’un peu plus deflexibilité :

nécessité pour la plupart des applicationsseule manière de permettre la concaténationcoût faible à cause de la structure linéaire et sansréférence interne

Langages et paradigmes – p.227/311

chaînes de caractères

Parfois distinction entre la représentation d’uneconstante de type caractère et une chaîne de longueur1 (C).

Conventions variées pour inclure dans la chaîne ledélimiteur ou des caractères non imprimables.

Implémentation par un tableau de caractères avecindication de longueur ou de fin en Pascal, C ou Ada.

Implémentation par un bloc en tas en Lisp, Icon ouJava.

Ensemble d’opérations très élaboré en Snobol4, Iconou Perl.

Langages et paradigmes – p.228/311

Références pendantes

5.7.3 Références pendantes

Il y a trois classes d’allocation pour les objets : statique,en pile ou en tas.

Les objets en pile sont désalloués automatiquement enfin de sous-programme.

Pour les objets en tas :en PL/I, Pascal, Modula-2, C ou C++, il faut uneopération explicite (� � � � � � � , �� � � ,� � � � � � , etc.)en Lisp, Ada, Icon ou Java, un objet n’est désalloué(automatiquement) que quand il n’est plusaccessible

Langages et paradigmes – p.225/311

références pendantes

Une référence pendante est un pointeur qui désigne unobjet qui n’existe plus :

objet en tas désalloué explicitementobjet en pile dont le sous-programme est terminé

En Algol 68, une variable pointeur ne peut désigner unevariable de durée de vie plus courte (mais celanécessite des vérifications dynamiques en cas depasse comme paramètre)

En Ada, la variable pointée ne peut pas avoir une duréede vie plus courte que celle du type pointeur, ce quipeut être vérifié dynamiquement.

On peut faire une assez bonne vérification desréférences en associant une clé aléatoire à tout objetalloué, et en plaçant cette clé dans la représentation dupointeur. Langages et paradigmes – p.226/311

Listes

5.8.3 Listes

Définition récursive comme une paire formée d’un objetet d’une liste, ou le vide.

En Lisp, tout est liste, y compris le programme(propriété d’homoïconicité).

Dans tout langage avec des pointeurs, le programmeurpeut construire des listes.

Sous-programmes ou classes de bibliothèque danscertains langages.

Langages et paradigmes – p.231/311

listes

Icon appelle liste un objet qui est à la fois une liste, unefile, une pile et un tableau :

références indicées, à partir de la gauche ou de ladroitepossibilité de sous-tableaufonctions d’adjonction et de suppression aux deuxextrémités

Langages et paradigmes – p.232/311

Ensembles

5.8.2 Ensembles

Vision la plus courante : celle de Pascal.collection non ordonnée de valeurs d’un type debasepour une représentation efficace, le type de base estdiscret et limitél’implémentation est par la fonction caractéristiquede l’ensemble (un bit par élément possible)opérations d’union, intersection, différence etappartenance

Langages et paradigmes – p.229/311

ensembles

Vision plus élaborée : Icon.les ensembles de caractères permettent de spécifierles opérations d’analyse de chaînesles ensembles sont des collections d’objetsquelconquessur ces derniers, opérations ordinaires etimplémentation par table associative

Langage de manipulation d’ensembles : SETL.

Au total, type peu représenté dans les langages, etc’est dommage.

Langages et paradigmes – p.230/311

Terminologie

Terminologie :L’appelant sous-traite le travail au sous-programme, etattend qu’il soit terminé.

Il lui transmet des paramètres effectifs qui doiventcorrespondre aux paramètres formels dusous-programme.

Un sous-programme qui rend une valeur est unefonction, s’il n’en rend pas c’est une procédure (mais laterminologie n’est pas figée).

Langages et paradigmes – p.235/311

Points importants

Points importants à considérer :séquence d’appel, qui gère la zone d’allocation dusous-programme

représentation des fermetures

modes de transmission des paramètres

autres mécanismes d’abstraction du contrôle

Langages et paradigmes – p.236/311

listes

Notation en Lisp :paire pointée : �� � �

liste : �� � � est équivalent à �� � � � �� �

� � � � � �

correspondante immédiate avec l’implémentation

�� � � � � � � � produit la paire pointée �� � �

� � � fournit le premier élément d’une paire, et� � � ledeuxième

Langages et paradigmes – p.233/311

Sous-programmes

6 Sous-programmes

Abstraction :

L’abstraction permet de nommer un fragment compliquéde programme qui a un rôle spécifique. Elle permet dene plus s’occuper de l’implémentation de ce fragment.

L’abstraction des données sert à représenterl’information.

L’abstraction du contrôle sert à effectuer une opérationprécise.

Le mécanisme d’abstraction de contrôle majeur est lesous-programme.

Langages et paradigmes – p.234/311

zone d’activation

Pour accélérer l’accès aux variables locales dessous-programmes emboîtants, on peut utiliser untableau d’adressage :

l’élément i du tableau pointe sur la zone d’activationdu sous-programme de niveau i

à chaque appel de sous-programme, on doit mettreà jour les dernières entrées dans le tableaus’il est en mémoire, il impose un accès indirectsystématiques’il est en registres, il limite la profondeurd’emboîtement et bloque de nombreux registres

Le fait que C (et ses descendants) n’emboîte pas lessous-programmes signifie-t-il que le concept est inutile?

Langages et paradigmes – p.239/311

Instructions à exécuter

6.1.2 Instructions à exécuter

Trois suites d’instructions sont exécutées à l’occasion desappels de sous-programme :

séquence d’appel dans le sous-programme appelant

prologue en tête du sous-programme appelé

épilogue à la fin du sous-programme appelé

Langages et paradigmes – p.240/311

Appel de sous-programme

6.1 Appel de sous-programme

6.1.1 Zone d’activation

À chaque sous-programme en cours d’exécutioncorrespond une zone d’activation :

Les zones d’activation sont placées dans la piled’exécution.

Le pointeur de pile pointe au sommet de la pile.

Le pointeur de zone courante pointe dans la zoned’activation du sous-programme en cours.

Langages et paradigmes – p.237/311

Les objets locaux de taille statique sont atteints paraddition d’un déplacement à la valeur du pointeur dezone courante.

Les autres objets locaux sont placés en sommet de pileet atteints de manière indirecte.

Si les sous-programmes peuvent être emboîtés(Pascal, Modula-2, Ada), on place dans la zoned’activation un lien statique qui désigne la zoned’activation emboîtante.

Dans tous les cas, l’ancienne valeur du pointeur dezone d’activation est sauvegardée comme liendynamique.

Langages et paradigmes – p.238/311

Transmission des paramètres

6.2 Transmission des paramètres

Dans les premières versions de Basic et de Cobol, pasde paramètres.

Paramètres formels : ceux qui sont utilisés dans lesous-programme.

Paramètres effectifs : les variables et expressionsfournies à l’appel du sous-programme.

Plusieurs modes de transmission, avec des propriétéssémantiques importantes et différentes.

Appel en général sous forme préfixée, sauf pour Lisp etScheme avec leur notation spécifique, et quelqueslangages qui permettent l’appel sous forme d’opérateurinfixe.

Langages et paradigmes – p.243/311

Modes de transmission

6.2.1 Modes de transmission

En Fortran, PL/I, Algol 68, C ou Lisp, il n’y a qu’un seulmode de transmission des paramètres, et c’estfinalement l’appelant qui détermine comment leparamètre est transmis.

En Algol 60, Pascal, Modula-2 ou Ada, on peut choisirparmi plusieurs modes à la déclaration dusous-programme, et l’appelant doit s’y conformer.

Pour les langages à modèle de référence, un seulmode suffit normalement, mais une distinction est faitepar ailleurs.

Les deux modes fondamentaux sont le passage parvaleur et le passage par référence.

Langages et paradigmes – p.244/311

instructions à l’appel

Les actions à effectuer à l’appel sont :passage des paramètressauvegarde de l’adresse de retourbranchement vers le sous-programmeallocation d’espace dans la pile d’exécutionsauvegarde des registres et pointeursmodification du pointeur de zone d’activationinitialisation des objets locaux

Langages et paradigmes – p.241/311

instructions au retour

Les actions à faire au retour sont :passage des paramètres résultatspassage du résultatfinalisation des objets locauxdésallocation de la zone d’activationrestauration des registres et des pointeursretour à l’appelant

La séparation des actions entre les trois suitesd’instructions est assez délicate et dépend despossibilités de la machine.

Langages et paradigmes – p.242/311

passage par valeur et passage par référence

En Icon, le seul mode est le passage de valeur, et unsous-programme ne peut pas modifier un paramètreeffectif.

En Java, les paramètres effectifs de types prédéfinissont passés par valeur, les autres par partage.

Dans les langages fournissant les deux modes :le passage par valeur permet de garantir que leparamètre effectif ne sera pas changéle passage par référence permet de modifier leparamètre effectifil évite de recopier la valeurcertains langages fournissent un mode évitant lacopie mais empêchant la modification

Langages et paradigmes – p.247/311

Modes de passage en Ada

Modes de passage des paramètres en Ada :Trois modes :� � , � � � et� � � � �

Les paramètres� � peuvent être examinés mais nonmodifiés.

Les paramètres � � � n’ont pas de valeur initiale, et sontaffectés au paramètre effectif en fin desous-programme.

Les paramètres� � � � � sont les deux à la fois.

Pour les paramètres simples,� � est un passage parvaleur et � � � un passage par résultat.

� � � � � est un passage par valeur-résultat (Algol W).

Langages et paradigmes – p.248/311

Passage par valeur et passage par référence

Passage par valeur et passage par référence :Le premier mode est par défaut en Pascal, le seul en Cou Icon : le paramètre formel est une variable locale ausous-programme, qui prend comme valeur initiale celledu paramètre effectif.

Mais en C les tableaux ne sont jamais passés parvaleur, ce qui est passé est en fait un pointeur sur letableau.

Pour permettre la modification du paramètre effectif, ilfaut en C passer explicitement un pointeur sur leparamètre véritable.

Langages et paradigmes – p.245/311

passage par valeur et passage par référence

En Fortran, le seul mode est le passage par référence,normalement une valeur-G : le paramètre formel est unalias pour le paramètre effectif.

Si l’on fournit une constante ou une expression commeparamètre effectif, ce qui est passé est un pointeur surla variable temporaire contenant la valeur en question.

En Lisp ou Smalltalk, toute variable est une référence,et le paramètre formel désigne le même objet que leparamètre effectif (passage par partage).

Langages et paradigmes – p.246/311

passage de fermetures en paramètre

En Modula-2, Algol 68 ou Ada 95, lessous-programmes sont des valeurs de première classeet peuvent être passés en paramètre.

�� �� � � � � �� � � �� � � � � �� �� � � �� � � �� �� � � � � �� �� � �

� �� �� � � �� � � �� � � �� � � � � � � �� � � �� � � �

� � � � � � � � � �� �� � �

� � � � � � � � �

�� � � ��� � � �� � �� � � � � � ��

� �� � �� � � �� �

� � �

� � � �

Langages et paradigmes – p.251/311

passage de fermetures en paramètre

C’est évidemment normal et habituel dans les langagesfonctionnels :

� � �� � � � � � �� � � �� �� � � � � � �

� � � � � � � �

� � � � � � � � � � � � �� � � �� � � � � �

La fermeture est représentée par l’adresse du code etle lien statique, sauf s’il n’y a pas d’emboîtement dessous-programmes.

Langages et paradigmes – p.252/311

modes de passage des paramètres en Ad

Pour les paramètres composites, tout peut êtreimplémenté par un passage par référence.

La sémantique dépend donc de la nature desparamètres, et un programme qui en dépend est illégal.

Langages et paradigmes – p.249/311

Passage de fermetures en paramètre

Passage de fermetures en paramètre :C’est le mode de transmission d’un sous-programme :

procedure � � � �� � � �� � function � � � � � � � � � �� � � � � � � � ��

var � � array � � � � � �� � � � of � � � � � �� �

var � � � � � � � ��

beginfor � � � � � to �� � � do

� �� � � � � � � �� � �

end

En C et C++, on peut passer des pointeurs sur dessous-programmes.

Langages et paradigmes – p.250/311

passage par nom

Les utilisations peuvent être assez étonnantes :

real procedure � � � � � �� �� � � � � � � � � � � � �

value �� � � � � � � �

comment �� �� � � � � � � � � � � �� � � � � � � � �

real �� �� �

integer � � � � � � � � � � �

begin

real � � � �

� � � �� � �

for � �� � � � step � until � � � � do

� � � �� � � � � �� �� �

comment �� �� � � �� � � �� �� � � � � � � � � � � � � � � � � �

� � � � � �� � � �

end � � � � � �

Langages et paradigmes – p.255/311

Catégories spéciales de paramètres

6.2.2 Catégories spéciales de paramètres

Tableaux conformants :

La taille des tableaux est fixée :en Pascal et Basic à la compilationen Ada et Fortran 90 à l’élaboration de la déclarationen APL, Icon et Perl à l’exécution

Un paramètre tableau dont la taille n’est fixée qu’àl’appel du sous-programme est dit conformant (Pascal)ou ouvert (Modula-2, Ada).

C permet de passer ce qu’on veut, mais sans lamoindre vérification.

Langages et paradigmes – p.256/311

Passage par nom

Passage par nom :C’est une idée d’Algol 60 reprise par Simula 67.

L’idée initiale était de décrire le mécanisme de passagede paramètre comme une copie de texte (comme dansun mécanisme de macros).

Tout doit se passer comme si le texte du paramètreeffectif venait remplacer le paramètre formel partout oùil apparaît dans le sous-programme.

On suppose en plus que des substitutions sont faitessur les noms pour éviter les conflits.

Langages et paradigmes – p.253/311

passage par nom

Le paramètre effectif doit être réévalué à chaqueutilisation, et dans le contexte de l’appelant.

Le compilateur construit pour chaque paramètre effectifune procédure cachée et sans paramètre, et passe ausous-programme appelé une fermeture correspondantà cette procédure.

Langages et paradigmes – p.254/311

Paramètres nommés

Paramètres nommés :Le mode normal d’énumération des paramètres est parposition.

En Ada ou Fortran 90, on peut nommer les paramètres(on parle de mot-clé).

L’ordre d’énumération des paramètres effectifs ne resteimportant que pour ceux qui ne sont pas nommés.

L’avantage supplémentaire est de fournir unedocumentation sur le rôle des paramètres spécifiés,utile s’il y en a beaucoup.

Langages et paradigmes – p.259/311

Nombre variable de paramètres

Nombre variable de paramètresEn C ou C++, on peut terminer une liste de paramètresformels par « � � � ».

Il faut ensuite utiliser des macros spécifiques pourparcourir la liste des paramètres fournis en dernier.

Le mécanisme ne permet pas de vérifier que les typescorrespondent à ce qui est attendu.

En Icon, un en-tête spécifique permet d’avoir unparamètre qui représente la liste des paramètres.

La vérification des types se fait comme dans le reste dulangage.

Langages et paradigmes – p.260/311

Paramètres facultatifs

Paramètres facultatifs :En Ada on peut proposer des valeurs par défaut pourcertains paramètres :

� � � � � � � � � � � � � � � � �� � � � � � � � �� � � � � �� � �� � � �

� � � � � � � �� � � � � � � � � �� � � � � � � � �� �

�� � � � �� �� � �� � � � � � � � � �� � � � � � �� � � � � �� �

� � � � �� � �� � � � � � � �� � �� � � �

�� � � �� �� � � � � �� � � � � � � � � � � � � � � � � �� �

�� � � � �� � � � � � � � � �� �� � � � �� �� � �� � � �

� � � � � � � � � � �� � �� � � � � �� � �� � � �

Langages et paradigmes – p.257/311

paramètres facultatifs

Les paramètres avec valeur par défaut sont facultatifs.

S’ils apparaissent en dernier, on peut les omettre.

Sinon, le mécanisme de nommage des paramètrespermet de faire ce qu’on veut :

� � � �� � � � � � � � � � � � �

On trouve aussi des paramètres facultatifs en C++ etFortran 90.

En Icon, les paramètres omis prennent la valeur � � � � � .

Langages et paradigmes – p.258/311

Mécanismes supplémentaires

6.3 Mécanismes supplémentaires

6.3.1 Généricité

Si l’on fabrique un type abstrait pour gérer des piles, onvoudrait le paramétrer par le type des composants despiles.

Le polymorphisme inclut dans le mêmesous-programme les traitements des divers types, maisoblige à des vérifications de types complexes oucoûteuses.

Langages et paradigmes – p.263/311

généricité

La généricité permet d’engendrer un ensemble desous-programmes pour chaque instance de type decomposants, quand celui-ci n’est pas important pour lefonctionnement des sous-programmes.

Principalement en Ada, C++ et Eiffel ; exemple en Ada :

Langages et paradigmes – p.264/311

Résultat de fonction

6.2.3 Résultat de fonction

Très souvent des restrictions sur le type du résultat,pour permettre de placer la valeur dans un registre :

en Algol 60 et Fortran, valeur scalaireen Pascal, scalaire ou pointeuren Algol 68, Ada, Modula-2 ou C, types compositespermis égalementen Algol 68, Ada 95 et dans les langagesfonctionnels, résultat de type sous-programme(grâce à une fermeture)

Langages et paradigmes – p.261/311

Affectation du résultat

Différentes manières d’affecter le résultat :dans un langage d’expression, valeur du corps de lafonction

en Algol 60, Fortran et Pascal, affectation au nom de lafonction

dans les langages plus récents, énoncé spécifique, parexemple return expression

la plupart du temps il faut une variable locale pour lerésultat, donc une copie inutile au moment de quitter lafonction

Langages et paradigmes – p.262/311

Traitement d’exceptions

6.3.2 Traitement d’exceptions

Une exception est un événement imprévu ou inhabituelqui apparaît à l’exécution.

Détecté par l’implémentation ou provoqué par leprogramme.

Exemple très courant : erreur d’entrée-sortie (unedonnée n’a pas la forme attendue ou une valeuren-dehors des limites).

Langages et paradigmes – p.267/311

traitement d’exceptions

Traitements possibles :choisir une valeur inventéefournir une valeur indiquant l’état d’erreurfaire traiter l’erreur par un sous-programmespécifique passé en paramètre

Langages et paradigmes – p.268/311

généricité

� � � �� � �� � � � � � � � � �� � � � � �� � �� � � �

� � � � � � � � � � � � � � � � �� �� � � � �

� � � �� � � � � � � � �

�� � � �� �� � � � � � � �� � � � � � � � � � � � � �� � � �

� � � � � � � � � � � � � �� � � � �� � � � � � � �� � � �

�� � �� � �

� � � � � � �� � � � � � � � � � �� � �� � � � � � � � �� � � � � � � � � � �

� � � � � � � �

� � � �� � � � �� � � � � � � �

� � � � � � �� � � � � � � � � � � �� � � � � � � � � �� �� � �� � � � � �

� � � � � � � �

� � �� � � �� � � � � � � � � � �� � � � �� � � � � � � � � � � � �� � � � �� �

� � � �� � � � � � � � � � � �� � � � � � � � � � � � � � � � �� � � � � �

Langages et paradigmes – p.265/311

généricité

Mécanisme purement statique : le compilateur construitles différentes instantiations du type abstrait.

Les parties du code qui ne dépendent pas desparamètres peuvent cependant être partagées.

Langages et paradigmes – p.266/311

Coroutines

6.3.3 Coroutines

Alors que l’appel de sous-programme établit unerelation hiérarchique, l’appel de coroutine correspond àune relation de coopération égalitaire.

Quand on revient d’une coroutine, on reprendl’exécution là où on l’avait suspendue ; quand on yretourne c’est la même chose.

Si deux coroutines coopérent, leurs contextesd’exécution existent ensemble, et le contrôle alterneentre les deux.

Implémentation d’une relationproducteur-consommateur, client-serveur, de tâches.

Langages et paradigmes – p.271/311

coroutines

Les tâches apparaissent en PL/I, Algol 68, Ada, Java.

Les coroutines apparaissent en Simula, Modula-2, Icon.

Opérations nécessaires :créer un environnement d’exécution pour unecoroutineéchanger le contrôle entre la coroutine courante et lacoroutine appeléedétruire l’environnement d’exécution d’une coroutine

Langages et paradigmes – p.272/311

traitement d’exceptions

Première apparition en PL/I :forme :

�� � � � � � �� � �

� � � � � �

l’énoncé est exécuté quand la condition se produit,pas là où il apparaîtil peut abandonner le travail en cours par un énoncéde branchement

Langages et paradigmes – p.269/311

traitement d’exceptions

Formes plus commodes en Ada, C++, Java :le traitement d’exception est lié à un bloc de codeson exécution remplace le bloc inachevési l’exception n’est pas traitée localement, elle estpropagée au sous-programme appelant

Mécanisme offrant en principe une très bonne sécurité,mais voir l’échec de la première mission Ariane V !

Langages et paradigmes – p.270/311

générateurs et itérateurs

Meilleur exemple : Icon.Toute procédure peut devenir un générateur parl’énoncé � � � � � � � .Dans les contextes d’évaluation dirigée par le but, onréveille les générateurs suspendus, en ordre inversede leur suspension, jusqu’à réussite de l’évaluationou épuisement de tous les générateurs.Exemples :

� � �� � �� � � � �� �� �� � �� � � � �� � � � � �

� �� � � � � � � � � � � � � � �

� � � � � � � � � � � � � � � � � � � �� � � � � �

Langages et paradigmes – p.275/311

Modèles de programmation

7 Modèles de programmation

7.1 Introduction

7.1.1 Généralités

Le modèle impératif ou constructif domine largementles langages de programmation, spécialement dans lemonde industriel et commercial.

Les modèles fonctionnel et logique occupent cependantdes niches solides et ont des implémentations dequalité industrielle.

Langages et paradigmes – p.276/311

coroutines

Gestion des zones d’activation :quand on passe d’une coroutine à une autre, on doitchanger de zone d’activation mais sans supprimer lapremièreplusieurs zones d’activation de même niveaudynamique coexistentil faut donc les allouer dans le taschaque contexte d’exécution a sa propre pile, pourles sous-programmes internes

L’opération d’échange est très simple et peu coûteuse.

Langages et paradigmes – p.273/311

Générateurs et itérateurs

6.3.4 Générateurs et itérateurs

Un itérateur énumère des valeurs et permet deconstruire des boucles complexes.

Il s’implémente facilement à l’aide de coroutines, maisn’en nécessite pas forcément.

Un générateur le fait dans un mécanisme plus général,inclus dans les règles de base du langage.

Langages et paradigmes – p.274/311

Historique

7.1.2 Historique

Les modèles impératif et fonctionnel proviennent desmodèles de calcul de mathématiciens dans les années30 :

Alan Turing propose un modèle de calculopérationnel, la machine de Turing, sorte d’automateà pile disposant d’une mémoire linéaire de capacitéillimitée.Alonzo Church propose un modèle de calculfonctionnel, le lambda-calcul, qui s’appuie sur desexpressions paramétrées et la substitution desparamètres.

Langages et paradigmes – p.279/311

historique

deux autres modèles encore :A. A. Markov propose un modèle de calculalgorithmique, les algorithmes de Markov, quis’appuient sur la substitution de caractères dans deschaînes à l’aide de règles extrêmement simples etstrictes.Stephen Kleene et Emil Post proposent des modèlesbeaucoup plus abstraits qui ne conduisent pas à desimplémentations.Il a été démontré que tous ces modèles sontéquivalents.

Langages et paradigmes – p.280/311

généralités

Tout ce qui concerne les noms, portées et visibilité,ainsi que le typage, les expressions, la récursivité, estcommun à la plupart des modèles.

Les frontières entre les différentes catégories sontsouvent floues :

énoncés impératifs dans les langages qui ne le sontpasprogrammation fonctionnelle dans les langagesimpératifsexistence de langages multi-paradigmeslangages hybrides tels que Icon

Langages et paradigmes – p.277/311

généralités

Nous avons déjà vu des concepts importants pour leslangages fonctionnels :

polymorphismeportée dynamiquerécursivité comme mécanisme d’itérationutilisation intensive de listesbeaucoup d’allocation dynamique et nécessité d’unrécupérateur de mémoire

Beaucoup moins de présentation de concepts pour laprogrammation en logique, qui a vingt ans de moinsque la programmation fonctionnelle.

Langages et paradigmes – p.278/311

Exemple

7.1.3 Exemple

On veut calculer le PGCD des valeurs� et .

En programmation impérative :Vérifier si� � . Si oui, imprimer l’un des

deux et terminer. Sinon, remplacer le plus grandpar leur différence et recommencer.

En programmation fonctionnelle :Le PGCD de� et est défini comme étant� si

� � , ou sinon comme étant le PGCD de� et� ,où� est le minimum de� et et� est leurdifférence.

Langages et paradigmes – p.283/311

exemple

En programmation logique :La proposition � � � � �� � � � � est vraie si� , et

� sont tous les trois égaux, ou s’il existe lesnombres� et� tels que� est le minimum de� et

(c’est-à-dire que� � � �� � �� � est vrai) et� est leurdifférence (c’est-à-dire que� � � � �� � �� � est vrai),et que � � � � �� �� � � � est vrai.

On voit que pour les deux derniers modèles, il fautnormalement ajouter une méthode d’évaluation duprogramme, alors que le modèle impératif estauto-évaluable.

Langages et paradigmes – p.284/311

historique

Le but est de formaliser le concept de fonctioncalculable. Cela permet de distinguer formellementdeux mécanismes de démonstration :

démonstration constructive, qui montre commentobtenir l’objet désiré (un programme est unedémonstration constructive de l’existence de ce qu’ilcalcule)démonstration non-constructive, qui montresimplement que l’objet doit exister

Langages et paradigmes – p.281/311

historique

Les langages de programmation actuels proviennent deces modèles :

machine de Turing pour la plupart des langagesimpératifslambda-calcul pour les langages fonctionnelsalgorithmes de Markov pour Snobol et un peu Icon

Le modèle logique est lié à l’idée de démonstrationconstructive, mais de manière plus abstraite :

on écrit un ensemble d’axiomesl’ordinateur découvre une démonstrationconstructive d’un ensemble particulier de valeurs quisatisfont les axiomes pour un ensemble de données

Langages et paradigmes – p.282/311

généralités

Polymorphisme très général :il permet d’utiliser une fonction sur des typesd’arguments très générauxles langages fonctionnels courants sont à typagedynamique

Types et opérateurs pour les listes :les listes ont une définition récursive par essenceleur manipulation récursive (tête, queue) estnaturelle

Langages et paradigmes – p.287/311

généralités

Récursivité :en l’absence d’effets de bord, c’est le seul moyen derépéter une actioncela devient donc le mécanisme fondamentald’évaluation d’un langage fonctionnel

Résultats de fonctions de type quelconque :indispensable pour ne pas limiter le type de calculstout autre mécanisme nécessiterait un effet de bord

Langages et paradigmes – p.288/311

Programmation fonctionnelle

7.2 Programmation fonctionnelle

7.2.1 Généralités

La programmation fonctionnelle au sens propre définitles résultats d’un programme comme une fonctionmathématique des données, sans idée d’état interne nid’effet de bord.

Les langages Miranda, Haskell et Sisal sont purementfonctionnels, ainsi que la proposition de Backus.

Les langages fonctionnels pratiques (Lisp, Scheme etmême ML) contiennent tous des aspects impératifs.

Langages et paradigmes – p.285/311

généralités

Pour que la programmation soit praticable, les langagesfonctionnels comprennent de plus :

Fonctions de première classe et fonctions d’ordresupérieur :

si les fonctions sont des objets de première classe,on doit pouvoir en créer de nouvelles à l’exécution,comme on fait pour tout autre objetune fonction d’ordre supérieur prend une fonctioncomme argument ou produit une fonction commerésultat

Langages et paradigmes – p.286/311

généralités

les fonctions d’ordre supérieur sont une spécificité deslangages fonctionnels

Certaines propriétés de Lisp et Scheme ne sont pasnécessaires aux langages fonctionnels, ni mêmecaractéristiques :

homogénéité des programmes et des données(homoïconicité)auto-définition (l’évaluateur de Lisp se décritsimplement en Lisp)interaction avec l’utilisateur par une boucle delecture, évaluation et affichage

Langages et paradigmes – p.291/311

Difficultés

7.2.2 Difficultés de la programmation fonctionnelle

L’idée de programmation strictement fonctionnelle estséduisante :

l’absence d’effets de bord facilite la lecture desprogrammestoute expression est évaluée indépendamment deson contexteles raisonnements sur les programmes sont facilités

Langages et paradigmes – p.292/311

généralités

Constructeurs pour objets structurés : même remarqueque pour les résultats de fonctions.

Récupération de mémoire :sans effet de bord, il faut à tout moment créer denouveaux objetsla mémoire n’étant pas infinie, il faut donc récupérerceux qui ne servent plus

Comme ces aspects sont quasiment nécessaires à laprogrammation fonctionnelle, les apôtres de ce modèleles considèrent comme indispensables à tout langage.

Langages et paradigmes – p.289/311

généralités

Comme ces aspects ne sont pas indispensables à laprogrammation impérative, les apôtres de ce modèleles considèrent (au moins pour certains) commeinutilement coûteux et de peu d’intérêt :

Fortran jusqu’à la version de 1977 n’a pas derécursivitéPascal ne permet pas qu’une fonction ait un résultatstructurédans la plupart des langages impératifs, lesconstructeurs d’objets structurés manquent ou sontincompletsla récupération de mémoire n’est pas appliquée auxobjets en pile, et n’est pas universellement utilisée

Langages et paradigmes – p.290/311

difficultés

Modification sur place :si les données sont très encombrantes, il faut éviterde les dupliquertri sur place plutôt que tri par copiecalculs scientifiques sur de grandes matrices

Presque tous ces cas se ramènent au problème demodification triviale :

la programmation fonctionnelle pure oblige àconstruire une copie de l’objet structuré pourmodifier un seul de ses composantssi le langage fonctionnel fournit des outils demodification sur place, il introduit donc l’effet de bordet l’affectation

Langages et paradigmes – p.295/311

difficultés

Propositions des apôtres de la programmationfonctionnelle :

un bon compilateur doit découvrir les récursivitésterminales et les remplacer par des itérationsun bon compilateur doit découvrir les modificationstriviales et éviter la copie des structuresla programmation fonctionnelle est moins répandueparce que les étudiants commencent par laprogrammation impérative

Langages et paradigmes – p.296/311

difficultés

De nombreux paradigmes de programmation s’appuient demanière centrale sur l’idée d’affectation ou d’effet de bord :

Utilisation d’entrées-sorties :il faut des mécanismes élaborés pour modéliser lasimple idée de lecture séquentiellec’est encore pire pour l’affichage graphique ou pourles fichiers à accès direct

Langages et paradigmes – p.293/311

difficultés

Initialisation de structures complexes :il est facile dans un langage fonctionnel deconstruire une liste à partir d’une autrec’est beaucoup plus difficile pour un tableau,spécialement à plusieurs dimensions, et surtout sil’ordre d’accès n’est pas purement séquentiel

Construction de statistiques :comptage d’occurences dans une large collection dedonnéesétablissement d’un dictionnaire, d’un lexique, d’unetable associativela méthode naturelle est de mettre à jour desentrées dans une structure de statistique

Langages et paradigmes – p.294/311

généralités

H est vrai si tous les termes Ci sont vrais.

La combinaison de plusieurs clauses permet d’endéduire de nouvelles par résolution :

A et B impliquent C

C implique D

alors A et B impliquent D

Pendant la résolution, les variables libres peuventprendre des valeurs par le processus d’unification :

humide(x)← fleuri(X)humide(Nice)donc fleuri(Nice)

Le seul langage logique réellement utilisé est Prolog,défini par Colmerauer et Roussel à Marseille en 1973.

Langages et paradigmes – p.299/311

Prolog

7.3.2 Prolog

Le programmeur construit une base de données declauses supposées vraies.

Une clause est faite de termes, qui sont desconstantes, des variables ou des structures :

Une constante est un atome (similaire à Lisp ouScheme) ou un nombre.Une variable est un identificateur commençant parune majuscule, elle peut prendre une valeurarbitraire au cours du processus d’unification.Une structure est un prédicat logique ou unestructure de donnée, elle prend la forme d’unfoncteur et d’une liste d’arguments.

Langages et paradigmes – p.300/311

difficultés

Mais :toutes les architectures de machines actuellessuivent le modèle de Von Neumannles tentatives d’architectures spécialisées pour laprogrammation fonctionnelle ont toutes été deséchecset pourtant de grandes universités américaines oufrançaises font aborder la programmation parScheme ou ML

Langages et paradigmes – p.297/311

Programmation logique

7.3 Programmation logique

7.3.1 Généralités

Il s’agit de démontrer des théorèmes à partir d’axiomes.

Le programmeur fournit le théorème, qui est le but àatteindre, et l’implémentation essaie de trouver unecollection d’axiomes et d’étapes de déduction quiconduisent à ce théorème.

Les axiomes sont écrits comme des clauses de Horn :

T ← C1, C2, . . . , Cn

T est la tête et les termes Ci contituent le corps.

Langages et paradigmes – p.298/311

Résolution et unification

Résolution et unification :Principe de résolution (Robinson, 1965) :

Si C1 et C2 sont deux clauses telles que la têtede C1 correspond à l’un des termes de C2, alorson peut remplacer le terme de C2 par le corps deC1.

Langages et paradigmes – p.303/311

résolution et unification

Exemple :

�� � � � � � � � � � � � � � � �

�� � � � � � � � � � � � � � � � � �

�� � � � � �� �� � �� � � � � � �

�� � � � � �� �� � � � � � � � � �

� �� �� � �� � � � � � � � � � � � � � � � � �� � � � �� � � � �

Si� prend la valeur �� �� et � la valeur� � � � � � , on peutremplacer le premier terme de la dernière clause par lecorps (vide) de la quatrième, ce qui donne la nouvelleclause :

� �� �� � � �� �� � � � � � �� � � � �� � � � � � � � � �

donc� est voisin de �� �� s’il habite� � � � � � .

Langages et paradigmes – p.304/311

Prolog

Les clauses peuvent être des faits, des règles ou desbuts, et se terminent par un point :

un fait est une clause de Horn sans partie droite :

� � � � � � � � � � � � �

une règle a une partie droite :

� �� � � �� � � � � � � �� � � � �� � � �� �� � � � � �

un but n’a pas de partie gauche :

� � � �� � � � � � � � � � � �

Langages et paradigmes – p.301/311

Prolog

Un but n’apparaît pas dans un ensemble de clauses,c’est une question posée au moteur de Prolog, quirépond par un ensemble de valeurs de variables quirend vraie la clause donnée comme but.

Langages et paradigmes – p.302/311

extensions

Les notations pour les listes sont inspirées de Lisp :la liste vide est � �

le constructeur de liste est � �� � � � �

la liste � �� � � � � � �� � � � � � � s’abrège sous laforme �� � � � �

on peut expliciter la limite entre tête et queue de laliste avec l’opérateur � , ce qui permet d’écrire lesdeux clauses suivantes :

� �� �� �� � �� � � � � �

� �� �� �� � �� � � � � � � � �� �� � � � � � �

Langages et paradigmes – p.307/311

Ordre d’exécution

Ordre d’exécution :Le mécanisme d’unification sert à trouver une suited’étapes de résolution qui construisent le but à partir dela base de faits, ou à démontrer que cette suite n’existepas.

Deux stratégies sont possibles :partir des clauses existantes et chercher à endériver le but, par chaînage avantpartir du but et procéder à l’envers vers les clausesexistantes, par chaînage arrière.

Langages et paradigmes – p.308/311

résolution et unification

Le mécanisme qui associe une valeur à une variableest l’unification :

une constante s’unifie avec elle-mêmedeux structures s’unifient si elles ont le mêmefoncteur et le même nombre d’arguments, et que lesarguments s’unifient en correspondanceune variable s’unifie avec n’importe quoi

Langages et paradigmes – p.305/311

Extensions

Extensions :Pour rapprocher Prolog d’un langage deprogrammation, on apporte des extensions lexicales ousyntaxiques :

Le but �� � � � � peut s’écrire � � � .

Les expressions arithmétiques s’écrivent comme dansles langages ordinaires, avec en plus le foncteur� � quiunifie son premier argument avec la valeur arithmétiquede son deuxième argument.

Langages et paradigmes – p.306/311

difficulté

Il y a quelques limites théoriques importantes :certains aspects de la logique ne sont pas couvertsles clauses sont déclaratives, mais l’ordred’exploration du moteur de Prolog est déterminantle programmeur doit souvent en tenir compte pourque le programme soit efficace, ou simplement setermineil n’y a pas de moyen propre et clair d’exprimer lanégation

Langages et paradigmes – p.311/311

ordre d’exécution

C’est la deuxième stratégie qu’utilise Prolog : l’arbredes recherches possibles est exploré en profondeur etde gauche à droite.

Les clauses étant ordonnées et l’algorithme derecherche connu, le résultat est déterministe.

En revanche, l’ordre des clauses est très important, enparticulier pour éviter une descente infinie.

Pour donner au programmeur un certain contrôle sur ledéroulement de la recherche, on introduit une coupure,notée � , qui fige toutes les unifications faites jusqu’aupoint où on la rencontre.

Langages et paradigmes – p.309/311

Difficultés

7.3.3 Difficultés de la programmation logique

Le « Programme d’ordinateurs de cinquième génération» du Ministère de l’industrie japonais (mi-70) devaitutiliser Prolog comme langage machine.

En fait, l’idée même a été abandonnée.

On peut considérer les clauses de Horn comme un bonformalisme de spécification du problème à résoudre.

Prolog est un mécanisme d’implémentation de cettespécification, avec les difficultés mentionnées.

Langages et paradigmes – p.310/311