Chapitre 1 Introduction Buts du chapitre : Motivation pour l étude des types abstraits de données ; Syntaxe de base pour l écriture de spécifications. 1.1 Introduction 1.1.1 Bibliothèques 1. L3, déjà une certaine expérience de la programmation en C, Java, OCaml 2. Principe commun à tous ces langaes : les bibliothèques 3. Rôle des bibliothèques : Implémenter toutes les fonctions relevant d un certain domain (sockets, OpenSSL, libgs,... ) Implémenter des structures de données (GLib, List.ml,... ) génériques note : focus sur les modules OCaml 1.1.2 Programmation de Haute Qualité 1. Systèmes informatiques complexes : $ ls /usr/lib/lib*.so wc -l 496 pour une installation de base de Linux. Plus de 12000 packages sur docjar.org. Pour qu une bibliothèque soit utilisable, il faut : Principe 1 (modularité) : chaque bibliothèque doit avoir une utilisation simple et facilement compréhensible 2. Utilisation industrielle demande distribution du travail, donc communication entre équipes pour la définition de l architecture globale et le partage du travail. Pour cela il faut : Principe 2 (spécification) : il faut pouvoir décrire chaque bibliothèque de manière complète et non ambigue Principe 3 (correction) : chaque morceau de code écrit doit implémenter de manière exacte une spécification discutée en commun 3. Système informatiques critiques : (a) bugs, cas général : on passe énormément de temps à débugger une application, ça coûte de l argent. Les bugs sont douloureux. (b) bugs, systèmes critiques : la voiture ne freine pas, le train déraille, l avion s écrase, et la fusée explose. Les bugs sont intolérables. 7
8 4. Le premier principe relève du bon sens et des méthodes de génie logiciel 5. On s intéresse dans ce cours aux principes 2 et 3 6. Des dizaines de méthodes applicables sont utilisées, on n en verra que 2 : spécification équationnelle d une bibliothèque (maintenant) ; spécification avec le langage B d un programme (2ème partie du cours). 1.2 Syntaxe des Types abstraits de données Pour définir une bibliothèque on a besoin de connaître : les types de données qu elle défini. Sortes les fonctions qu elle rend publiques les rapports de ces fonctions entre elles 1.2.1 Déclaration de sortes Type vide Type RIEN La déclaration de base spécifie un type qui correspond à un fichier vide Déclaration de base d une sorte, sans opérations. Type ATOM Sortes A on vient de définir une bibliothèque qui possède juste une sorte, A, et qui ne fait rien. Mais on n est pas assuré que cette sorte contient ne serait-ce qu un élément! Pour cela, il faut introduire des constantes. 1.2.2 Déclaration d opérateurs Déclaration d une sorte avec une constante. Type UN Sortes U u : U On vient de déclarer une constante de la sorte U. C est un cas particulier de fonction qui n a pas d arguments. Déclaration d une sorte avec une fonction. Type BINAIRE Sortes B paire : B, B B Si on a plusieurs arguments, la syntaxe est de type : nom : Sorte Arg1,..., Sorte Argn Sorte Res La signification est que si l argument x 1 est de la sorte S 1,..., et si l argument x n est de la sorte S n, et si f est de la sorte : S 1,..., S n S
9 alors f(x 1,..., x n ) est de la sorte S. I Exercice : Écriture de spécifications simples (a) Écrire une spécification qui déclare deux constantes, 0 et 1, de la sorte Bool (b) Écrire une spécification qui déclare une fonction unaire f qui prend un argument de la sorte A et rend un argument de la sorte B (c) Proposer des sortes et opérations pour spécifier un éditeur de SMS, sachant que l utilisateur doit pouvoir : créer un SMS vide insérer un caractère en appuyant sur une touche modifier le dernier caractère (par rotation des caractères associés à la touche) supprimer le dernier caractère entré Type SMS Sortes T exte, T ouche, Caractere creer : T exte appuyer : T ouche, T exte T exte modif ier : T exte T exte supprimer : T exte T exte (d) Proposer des sortes et opérations pour spécifier un distrubuteur de boissons sachant que l utilisateur doit pouvoir : insérer une pièce de 0.1, 0.2, 0.5 ou 1 euro demander le remboursement choisir une boisson (thé ou café) : rien ne se passe si la somme est inférieure à 0.8 euros observer le montant rendu et prendre la somme prendre la boisson (si possible) Type DISTRIBUTEUR Sortes Dist, P iece, Bouton, Euro P 10 : P iece P 20 : P iece P 50 : P iece P 100 : P iece creer : Dist inserer : P iece, Dist Dist rembourser : Dist Dist rendu : Dist Euro boisson? : Dist Dist 1.2.3 Spécification des opérateurs Pour l instant, on n a rien fait d autre que de traduire des contenus de fichiers.h ou.mli dans un nouveau langage : on vient de définir des fonctions et des constantes (même pas des variables globales!) en utilisant un nouveau langage, rien de plus. Mais si on regarde une déclaration de module caml normale, on voit aussi des choses supplémentaires :
10 val hd : a list -> a Return the first element of the given list. Raise Failure "hd" if the list is empty. val rev : a list -> a list List reversal. Normalement, quand on écrit un programme, il y a toujours des commentaires qui expliquent à quoi sert une fonction qu on vient de déclarer! Ces commentaires ne sont pas forcément très explicites (ex : List reversal). Et surtout, comme ils sont écris en langage naturel (français, anglais,... ) ils ne sont pas faits pour être utilisés par des programmes. Pour spécifier réellement une bibliothèque, il faut utiliser un langage utilisable par d autres programmes. Le but est de pouvoir comprendre automatique une spécification avant de pouvoir la traiter (par exemple, avant de la valider). Avant de voir complètement ce langage, voyons quelques exemples. Type PEANO Sortes N 0 : N s : N N Pour l instant, on vient juste de définir une sorte N qui contient une constante et une fonction de N dans lui-même. Par exemple, les constructions qu on peut faire avec ce type sont : 0, s(0), s(s(0)),..., s n (0),... avec la notation : s n (0) = { s(s n 1 (0)) si n > 0 0 si n = 0 On appelle ces constructions les entiers de Peano. On peut ajouter la spécification de l addition en spécifiant ses propriétés : Type SANO Sortes N 0 : N s : N N + : N, N N Variables n 1, n 2, n 3 : N Variables utilisés dans les axiomes ((+ com )) n 1 + n 2 = n 2 + n 1 (Addition commutative) ((+ Base )) 0 + n 2 = n 2 (Cas de base) ((+ Rec )) s(n 1 ) + n 2 = s(n 1 + n 2 ) (Récurrence) II Exercice : (a) Ajouter des axiomes à l éditeur de SMS sachant que : la suppression n a aucun effet sur un message vide, la suppression annule le dernier caractère inséré. Type SMS Sortes T exte, T ouche, Caractere
11 creer : T exte appuyer : T ouche, T exte T exte modif ier : T exte T exte supprimer : T exte T exte Variables m : T exte, t : T ouche ((sup vide)) supprimer(creer) = creer suppression sur message vide ((sup app)) supprimer(appuyer(t, m)) = m suppression après insersion ((sup mod)) supprimer(modif ier(m)) = m suppression après modification (b) Ajouter des axiomes au distributeur de boissons sachant que : Le retour de monnaie et le crédit sont vides au départ, L appui sur le remboursement retourne tout le crédit qui est alors annulé, L insertion d une pièce ajoute sa valeur au crédit. De nouveaux opérateurs seront nécessaires. Type DISTRIBUTEUR Sortes Dist, P iece, Bouton, Euro P 10 : P iece P 20 : P iece P 50 : P iece P 100 : P iece creer : Dist inserer : P iece, Dist Dist rembourser : Dist Dist rendu : Dist Euro boisson? : Dist Dist Nouveaux opérateurs valeur : P iece Euro credit : Dist Euro + : Euro, Euro Euro 0 : Euro Variables d : Dist, p : P iece ((r vide)) rendu(creer) = 0 rendu initial ((c vide)) credit(creer) = 0 crédit initial ((r rmb)) rendu(rembourser(d)) = credit(d) rendu après remboursement ((c rmb)) credit(rembourser(d)) = 0 crédit après remboursement ((c ins)) credit(inserer(p, d)) = credit(d) + valeur(p) crédit après insersion Quelques questions posées par ce type de spécification : On réutilise des constantes, des fonctions unaires et binaires. Comment réutiliser les spécifications déjà définies? Est-ce que l ensemble des axiomes est minimal? Dit autrement, est-ce que certains axiomes sont des conséquences des autres? être conséquence de est une notion logique. Que veut-elle précisément dire? On verra les problèmes logiques plus tard, pour l instant, on se concentre sur la syntaxe.
12 1.2.4 Syntaxe des extensions Pour l instant, extensions simples : on enrichit la spécification d un type avec les spécifications d autres types ; Typiquement, pas de nouvelles sortes. Type MONOIDE Sortes T étend BINAIRE, avec paire renommé +, avec B renommé T UN, avec u renommé 0, avec U renommé T Variables x 1, x 2, x 3 : T Variables utilisés dans les axiomes ((+ assoc )) x 1 + (x 2 + x 3 ) = (x 1 + x 2 ) + x 3 (Op. associative) ((+ assoc )) x 1 + 0 = x 1 (Élt neutre d.) ((+ assoc )) x 1 = 0 + x 1 (Élt neutre g.) III Exercice : Extension et renommage (a) Définir un type spécifiant qu une opération binaire est commutative (b) Redéfinir le type PEANO de la manière la plus modulaire possible (c) Définir un module BOOL0 contenant deux constantes. (d) Reprendre la spécification du distributeur en exploitant le mécanisme d extension. 1.2.5 Equations conditionnelles Un axiome peut-être une équation conditionnée par un ensemble d équations (clause de Horn). La syntaxe d un axiome devient alors : t 1 = u 1,..., t n = u n t = u Exemple Type ORDRE étend Sortes T BOOL0 : T, T B min : T, T T Variables x, y : T ((min l )) x y = true min(x, y) = x (min à gauche) ((min r )) y x = true min(x, y) = y (min à droite)
13 1.2.6 Appartenance à une sorte, sous-sortes On introduit une relation d ordre partiel sur les sortes pour définir par exemple la sous-sorte des listes non vides, des entiers non nuls. Cette sous-sorte sera par exemple le domaine source de l opérateur prédecesseur, ou du 2ème argument de l opérateur de division : Type SNAT Sortes Nat, NzNat < Nat 0 : N at s : Nat NzNat pred : NzNat Nat / : Nat, NzNat Nat La propriété importante d une sous-sorte est la propriété de coercion implicite : un terme appartenant à une soussorte appartient aussi à la sorte de base : n : NzNat n : Nat. A toute déclaration de sous-sorte est associé un tel axiome. Extension des clauses de Horn Les clauses de Horn jusque-là limitées à des prédicats équationnels sont maintenant étendues à des prédicats d appartenance à des sortes. On écrira par exemple : Type SNAT1 étend SNAT Variables x : Nat ((sp)) x : NzNat s(pred(x)) = x (succ-pred) Remarque de Horn : Calendrier La déclaration de sous-sorte s 1 < s 2 est donc équivalente à l ajout d un axiome représenté par une clause x : s 1 x : s 2