Packages et Types De la Spécification Formelle A l'implémentation Ada.

Slides:



Advertisements
Présentations similaires
La programmation orientée objet avec Java L3-MIAGE Plan
Advertisements

PL/SQL : Le Langage PL/SQL est une extension du SQL, qui offre
Cours n° 7 Standard Template Library II.
Partie publique Corps Partie privée p1 Un paquetage est constitué dune partie publique dune partie privée et dun corps.
Algorithmes et structures de données 9ème cours Patrick Reuter maître de conférences
C++ 6ème cours Patrick Reuter maître de conférences
Spécification et qualité du logiciel
SI3 MAM3 Hydro Nathan Cohen Igor Litovsky Christophe Papazian
Au programme du jour …. Un peu plus de structures de données
C.
1 Révisions. 2 Tableaux non contraints Déclaration du type : type Tvecteur = tableau ( intervalle dentiers) de entiers type Tvecteur is array (integer.
PHP5 poo.
Oracle: OO.
Quoi ? Un tampon.
PHP Interface base de données
Chapitre IV. Structures linéaires (piles, files, listes chaînées)
Tests Programmation par contrats
Structures de données et algorithmes – TP2
JavaBeans Réalise par: EL KHADRAOUY TARIK AOUTIL SAFOWAN.
IFT313 Introduction aux langages formels
Les Classes les structures en C (struct) regroupent des variables : structuration de l'analyse mais problèmes de cohérence problèmes de sécurité d'accès.
Gestion des erreurs Packages ©Alain Villeneuve, 1999
Structures de données IFT-2000
Structures de données IFT Abder Alikacem Gestion des exceptions Département dinformatique et de génie logiciel Édition Septembre 2009.
66 Utilisation des classes et des objets. 6-2 Objectifs A la fin de ce cours, vous serez capables de : Créer de nouvelles classes à laide de Eclipse Utiliser.
Contrôle de types Les types en programmation Expressions de types Un contrôleur de types Equivalence de types Conversions de types Généricité.
Chapitre 9 Les sous-programmes.
Types de données abstrait et mécanismes d'encapsulation
Partie II Sémantique.
COURS DE PROGRAMMATION ORIENTEE OBJET :

Structures de données IFT-2000
Modélisation des opérations Spécifier les transformations détat que lon attend des services de la machine Létat dune machine entièrement déterminée par.
Procédures Stockées Schedule: Timing Topic 60 minutes Lecture
Structures de données IFT-2000 Abder Alikacem Retour sur les listes ordonnées Département dinformatique et de génie logiciel Édition Septembre 2009.
Structures de données IFT-2000
Animateur : Med HAIJOUBI
27/02/2006L3 MIAGE - GLO ADA1 Les Paquetages Permettent d’encapsuler un groupe d’entités logiquement reliées. Comme toute unité de programme, le paquetage.
Modélisation VHDL d’un chemin des données
Objectifs À la fin de ce cours, vous serez capables de :
Implémentation Ada Gestion de la mémoire. Put 20 L'affectation de Comptes (σ-modèle) La sémantique intuitive des comptes ne laisse guère de place à l'affectation.
Vers un nouvel empirisme: l’ancien et le nouvel empirisme John Goldsmith Université de Chicago CNRS MoDyCo.
O-notation 1. Introduction 2. O-notation 3. Opérations 3.1 Somme 3.2 Produit 4. Règles générales 5. Exemple 6.Analyse des algorithmes récursifs 6.1 Dilatation.
Cours 61 6 La sécurité, Portée, Visibilité Programmer avec sécurité.
Le Langage de BLOC PL/SQL
Cours 9 Exceptions (fin) Généricité. POO-L3 H. Fauconnier2 Chaînage d'exceptions  Une exception peut être causée par une autre.  il peut être utile.
Types Abstraits.
Du « comment c’est fait ? » Au « à quoi ça sert ? »
Programmation objet La base.
Chapitre 6.2 Les curseurs Cours SGBD 3A Mme hkimi Jihène
Variables et accès en Java. Déclaration des variables final transient static private Printer hp; transient => ne doivent pas être sérialisées volatile.
Créer des packages.
Les modules. Modules Un module est un ensemble de définitions de constantes, de variables et de fonctions réutilisables de projet en projet. Le langage.
Concepts intermédiaires de VHDL
Master 1 SIGLIS Java Lecteur Stéphane Tallard Les erreurs communes en Java.
Tutorat en bio-informatique
5ième Classe (Mercredi, 19 octobre) Prog CSI2572.
Structures de données avancées : Arbres ‘Left Leaning Red-Black’
Les classes et les objets Les données finales class A { … private final int n = 20 ; // la valeur de n est définie dans sa déclaration … } class A { public.
CSI 3525, Implémentation des sous-programmes, page 1 Implémentation des sous-programmes L’environnement dans les langages structurés en bloc La structure.
Liste Une liste est une séquence d’éléments. Concept important: Chaque élément possède une position dans la liste. Notation: De quelles opérations a-t-on.
Introduction  Langage propre à Oracle basé sur ADA  Offre une extension procédurale à SQL  PL/SQL permet d’utiliser un sous-ensemble du langage SQL.
Héritage Conception par Objet et programmation Java
Note: Les nombres écrits en gras renvoie à des leçons entières. Symbole %FOUND 6-13 %ISOPEN 6-13 %NOTFOUND 6-13 %ROWCOUNT 6-13 %ROWTYPE 5, 6-17 %TYPE 1-20.
Nicolas Ribot Introduction aux triggers Nicolas Ribot - Licence GNU FDL - Version 1.1.
Conception de Programmes - IUT de Paris - 1ère année Les classes Introduction Déclaration d’une classe Utilisation d’une classe Définition des.
Les exceptions Une exception est un identificateur PL/SQL détecté pendant la phase d’exécution. Comment est-elle déclenchée ? À la suite d’une erreur.
French 1 Chapter 2 Grammar 2
Analyse et programmation langage ADA
Transcription de la présentation:

Packages et Types De la Spécification Formelle A l'implémentation Ada

Les Comptes (sans historique) Le seul constructeur est Open. Chaque terme de la syntaxe tel que Put (Get (Put (Open (m), n), p), q) peut donc se réduire à un terme équivalent Open (m+n-p+q) Dès lors qu'il est sémantiquement correct : p <= m + n

Les Comptes (σ-algèbre des termes) Un compte peut donc être représenté par le terme réduit formé - de l'identifiant du constructeur qui l'a produit, - des arguments fournis à ce constructeur.

Les Comptes (constructeurs) Les constructeurs d'un type sont toujours en nombre fini. Leurs identifiants peuvent donc être représentés par une énumération : Type Builder is (Open);

Les Comptes (type) Le terme peut avoir des arguments différents selon le constructeur sur lequel il repose. On peut donc le représenter par un enregistrement avec variante. Type Account (selon : Builder) is record case … end case ; end record;

Les Comptes (type) Le terme peut avoir des arguments différents selon le constructeur sur lequel il repose. On peut donc le représenter par un enregistrement avec variante. Type Account (selon : Builder) is record case … end case ; end record;

Chaque variante comportera des champs correspondant à ses arguments. Les Comptes (type) Type Account (selon : Builder) is record case selon is when Open => balance : natural ; end case ; end record; La taille de l'enregistrement n'est pas déterminée tant que le constructeur ne l'est pas (il est non contraint)

Cette représentation interne du compte par son terme représentatif ne concerne pas l'utilisateur : elle est en zone private Les Comptes (terme) private type Builder is (Open); type Account (selon : Builder) is record case selon is when Open => balance : natural ; end case; end record;

L'utilisateur doit avoir accès (public) : - au type (non contraint), - aux opérations sur ce type. Les Comptes (opérations) type account (<>) is private ; function Open (m : natural) return account; function Put (a : account ; m : natural) return account; function Get (a : account ; m : natural) return account; function Balance (a : account ) return natural; Le type privé est muni d'une égalité implicite qui n'a pas été axiomatisée...

Les types et les profils des opérations de la sorte forment la spécification d'un package, avec deux parties : publique et privée. Les Comptes (spécification) package Accounts is type account (<>) is private; function Open (m : natural) return account; function Put (a : account ; m : natural) return account; function Get (a : account ; m : natural) return account; function Balance (a : account) return natural; private type builder is (Open); type account (selon : builder) is record case selon is when Open => balance:natural; end case; end record ; end accounts;

Le corps du package : - alloue les termes construits, - définit observateurs et extenseurs (conformément aux axiomes), - assure la vérification des préconditions (par des assertions) Les Comptes (corps) package body Accounts is... end Accounts;

L'allocation du constructeur. Les Comptes (constructeur) package body Accounts is function Open (m : natural) return account is begin return (selon => Open, balance => m) ; end Open ;... end Accounts;

Observateurs et extenseurs sont définis selon les axiomes Les Comptes (extenseurs/observateurs) package body Accounts is... function Balance (a : account) return natural is begin return a.balance ; end Balance; function Put (a : account ; m : natural) return account is begin return Open (a.balance + m) ; end Put;... end Accounts;

les préconditions (traduites par des assertions) Les Comptes (assertions) package body Accounts is... function Get (a : account ; m : natural) return account pragma assert (m <= balance (a)); is begin return Open (a.balance - m) ; end Get ; end Accounts; L'assertion n'est effective que si le package est compilé avec l'option ad'hoc (-gnata).

Dans cette mouture, - outre le solde - l'objectif est d'accéder à l'historique des opérations. il y a plusieurs constructeurs : - l'un initialise le compte (Open) - les deux autres (Get et Put) utilisent un terme construit (c). Les Comptes avec Historique -- Constructeurs open (m) => ACCOUNT; put (c, n) => ACCOUNT; get (c, n) => ACCOUNT :: n <=balance(c) ; :: n <=balance(c) ; -- Observateurs balance (c) => NATURAL is balance (open (m)) → m | balance (put (c, n)) → balance (c)+n | balance (get (c, n)) → balance (c)-n; operations (c) => NATURAL is operations (open (m)) → 0 | operations (put (c, n)) → operations (c)+1 | operations (get (c, n)) → operations (c)+1; history (c, i) => NATURAL :: i NATURAL :: i <=operations (c) is history (open (m), i) → m | history (put (c, n), i) → if operations (c) + 1 <= i then history (c, i-1)+n else history (c, i) else history (c, i) | history (get (c, n), i) → if operations (c) + 1 <= i then history (c, i-1)-n else history (c, i); else history (c, i); end accounts; sort accounts is -- Types Déclarés ACCOUNT ; -- Variables c : ACCOUNT ; i, m, n: NATURAL; end Accounts; La représentation du terme sera donc récursive.

Le compte représenté par un pointeur : - devient un type contraint, - est limité pour éviter une sémantique douteuse de l'égalité, le partage de pointeurs. Les Comptes (spécification) type account is limited private; function Open (m : natural) return account; function Put (a : account ; m : natural) return account; function Get (a : account ; m : natural) return account; function Balance (a : account ) return natural; function Operation (a : account) return natural; function history (a : account ; n : natural) return natural;

Les Comptes (spécification) package Accounts is type account is limited private ; function Open (m : natural) return account; function Put (a : account ; m : natural) return account; function Get (a : account ; m : natural) return account; function Balance (a : account) return natural; function Operations (a : account) return natural; function history (a : account ; n : natural) return natural; private type builder is (Open, Put, Get); type term (selon : builder) is record case selon is when Open => initial : natural ; when Put | Get => changed : account ; change : natural ; end case; end record ; type account is access term; end Accounts;

Un constructeur alloue dans le « tas » un terme dont l'adresse représente un compte. Les Comptes (constructeurs) function Open (m : natural) return account is begin return new Term'(Selon => Open, Initial => m); end ; function Put (a : account; m : natural) return account is begin return new Term'(Selon => Put,Changed => a, Change => m); end Put ; function Get (a : account; m : natural) return account is pragma Assert (m <= balance (A)); begin return new Term'(Selon=>Get, Changed=>a, Change=>m); end Get;

Un observateur rend compte cas par cas des axiomes rédigés pour chaque constructeur. a.all.changed n'est rien d'autre que l'état du compte tel qu'il était avant qu'on lui applique le dernier Get|Put. La récursivité se construit sur la trame fixée par les variantes du type term. Les Comptes (observateurs) function Operations (a : account) return natural is begin case a.all.Selon is when Open => return 0; when Get | Put => return Operations (a.all.changed) + 1; end case; end Operations;

Des opérations de même profil (Get|Put) peuvent engendrer, dans le respect des axiomes, des traitements différents au sein d'un même observateur. Les Comptes (observateurs) function Balance (A : Account) return Natural is begin case A.all.Selon is when Open=>return A.all.Initial; when Put=>return Balance (A.all.Changed) + A.all.Change; when Get=>return Balance (A.all.Changed) - A.all.Change; end case; end Balance ;

History se définit récursivement. Chaque appel utilise Operations, récursive. quadratique La complexité est quadratique... Les Comptes (observateurs) function history (A : Account; N : Natural) return Natural is pragma Assert (N <= Operations (A)); begin case A.all.Selon is when Open => return A.all.Initial; when Put => if Operations (A) <= N then return history (A.all.Changed, N - 1) + A.all.Change; else return history (A.all.Changed, N); end if; when Get => if Operations (A) <= N then return history (A.all.Changed, N - 1) - A.all.Change; else return history (A.all.Changed, N); end if; end case; end history ;

Pour retrouver les « facilités » de l'affectation, on renonce à l'attribut limited. Il faut alors définir une égalité sémantique sur les comptes (même historique) En utilisant : L'égalité des entiers = L'égalité récursive = Les Comptes (avec égalité) x, y : account ; m, n : natural ; _=_ (x,y)=>boolean is Open (m)= Open(n) → m=n Open (m)= Open(n) → m=n | Open (m)= Get(y,n) → false | Open (m)= Put(y,n) → false | Get(x,m) = Open(n) → false | Get(x,m) = Get(y,n) → x=y and m=n | Get(x,m) = Put(y,n) → false | Put(x,m) = Open(n) → false | Put(x,m) = Get(y,n) → false | Put(x,m) = Put(y,n) → x=y and m=n; ᄇ

Elle se tratuit immédiatement par l'observateur Les Comptes (avec égalité) function "=" (X, Y : Account) return Boolean is begin case X.all.Selon is when Open => case Y.all.Selon is when Open => return X.all.Initial = Y.all.Initial; when Put | Get => return false ; end case ; when Put => case Y.all.Selon is when Open | Get => return false ; when Put => return x.all.changed = y.all.changed and then x.all.change = y.all.change ; end case ; when Get => case Y.all.Selon is when Open | Put => return false ; when Get => return x.all.changed = y.all.changed and then x.all.change = y.all.change ; end case; end case; end "=";

L'implémentation standard par les sigma termes - engendre des observateurs de complexité au moins linéaire - nécessite une utilisation des pointeurs pour traduire la structure récursive, - demande une définition explicite de l'égalité. On cherche une implémentation dans laquelle - les opérations se font en temps constant, - les pointeurs brillent par leur absence, - l'égalité est native. Les Comptes (σ-termes)

En utilisant un tableau - on a tout gagné (y compris l'égalité par défaut) - mais le type est non contraint, Les Comptes (tableau) package Accounts is type account (<>) is private ; function Open (m : natural) return account; function Put (a : account ; m : natural) return account; function Get (a : account ; m : natural) return account; function Balance (a : account) return natural; function Operations (a : account) return natural; function History (a : account ; n : natural) return natural; private type naturals is array (natural range <>) of natural ; type account (Operations : natural) is record history : naturals (0.. Operations) ; end record; end Accounts;

Les Comptes (tableau : constructeurs) package body Accounts is – les constructeurs function Open (m : natural) return account is begin return (operations => 0, history => (0 => m)) ; end; function Put (a : account ; m : natural) return account is begin return (operations => a.operations+1, history => a.history & (a.history(a.operations) +m)) ; end Put; function Get (a : account ; m : natural) return account is pragma assert (m <= Balance (a)); begin return (operations => a.operations+1, history => a.history & (a.history(a.operations) -m)) ; end Get;... end Accounts;

Les observateurs sont - soit un accès direct à un champ d'enregistrement, - soit l'accès (direct) à un élément de tableau, - soit une combinaison des deux. Les Comptes (tableau : observateurs) package body Accounts is... – les observateurs function Balance (a : account) return natural is begin return a.history (a.operations); end ; function Operations (a : account) return natural is begin return a.operations; end Operations; function History(a : account ; n : natural) return natural is pragma assert (n <= Operations (a)) ; begin return a.history(n); end history; end Accounts;

- la spécification algébrique peut se traduire mot à mot en ADA en utilisant un terme constitué de constructeurs comme représentation des objets. - cette traduction implique des pointeurs dès lors que la structure de donnée est récursive. - elle n'interdit pas d'autres implémentations plus efficaces qui partageront la partie publique de sa spécification ADA, ainsi que les préconditions et dont il faudra prouver qu'elles respectent les axiomes. De la Spécification Formelle A l’Implémentation Ada

Les types abstraits d'Ada vont permettre de déclarer dans un package représentant la sorte - les types de cette sorte sans les implémenter, - les profils des opérations sans les définir. Implémentation Ada types abstraits

L'attribut abstract du type account permet de déclarer les opérations dans les définir. Pour pouvoir créer des fils concrets du type abstrait, il faut un type extensible (tagged). Ces fils concrets seront dans l'obligation de définir les opérations surchargeant les abstraites. L'égalité doit permettre de comparer un compte à un autre, même si ce dernier n'a pas le même type concret ; donc un seul argument est abstrait, les autres sont pris dans la classe du type abstrait (account'class ). La définition du type est privée (private) et vide (null record). Les Comptes (abstraction) package Accounts is type Account is abstract tagged private; function Open (M : Natural) return account is abstract; function Put (A : account ; M : Natural) return account is abstract; function Get (A : account ; M : Natural) return account is abstract; function Balance (A : account) return Natural is abstract; function Operations (A : account) return Natural is abstract; function History (A : account ; N : Natural) return Natural is abstract; function"="(X : account; Y : account'class) return Boolean is abstract; private type Account is abstract tagged null record; end Accounts; ²

les développements - de l'application sur la classe : procedure manage (x : in out accounts.account'class); - des implémentations de la classe type account is new accounts.account with private; sont indépendants, s'appuient sur le type abstrait. Implémentation Ada classes

les développements - de l'application sur la classe : procedure manage (x : in out accounts.account'class); - des implémentations de la classe type account is new accounts.account with private; sont indépendants, s'appuient sur le type abstrait. Implémentation Ada classes

Les Comptes (application) Cette application sera utilisable sur toute implémentation du pourvu qu'elle appartienne à accounts.account'class. with accounts, ada.text_io; use accounts, ada.text_io; procedure manage (a : in out accounts.account'class) is c : character; begin put ("initial?"); a:=open(natural'value(get_line)); loop begin put ("balance=" & Natural'Image (Balance (A))); put (" [P]ut |[G]et |[A]mount |[Q]uit?"); Get (C); case c is when 'p' => a:= put(a, natural'value(get_line)); when 'g' => a:= get(a, natural'value(get_line)); when 'a' => put(natural'image (history(a,natural'value(get_line)))); when 'q' => skip_line; exit; when others => skip_line; end case; exception when others => Put ("erreur"); Skip_Line; end; end loop; end manage ;

Les Comptes (σ-implémentation) Le type accounts.sigma.account (concret) hérite de accounts.account (abstrait) Le premier doit donc définir les opérations abstraites du second. Le type concret devient un modèle. package accounts.sigma is type account is new accounts.account with private; function open (initial : natural) return account; function put (a : account; m : natural) return account; function get (a : account; m : natural) return account; function balance (a : account) return natural; function operations (a : account) return natural; function history (a : account;m : natural) return natural; function "="(x : account; y : accounts.account'class) return boolean; private type term (<>) ; type model is access term; type builder is (Open, Put, Get); type term (selon : builder) is record case selon is when Open => initial : natural ; when Put|Get=>changed:model; change:natural ; end case; end record ; type account is new accounts.account with record some : model; end record ; end accounts.sigma;

Les Comptes (implémentation optimale) Ce package ne se distingue du package accounts.optimal que par le modèle. Ce modèle doit être un type contraint : pour cela on utilise un pointeur sur la structure non contrainte. package accounts.optimal is type account is new accounts.account with private; function open (initial : natural) return account; function put (a : account; m : natural) return account; function get (a : account; m : natural) return account; function balance (a : account) return natural; function operations (a : account) return natural; function history (a : account;m : natural) return natural; function "="(x : account; y : accounts.account'class) return boolean; private type naturals is array (natural range <>) of Natural; type unconstrained (operations : Natural) is record history : naturals (0.. operations); end record; type model is access unconstrained; type account is new accounts.account with record some : model; end record ; end accounts.optimal;

Les Comptes (implémentation générique) Dans la spécification du package générique - la partie publique est celle de toutes les implémentations, - l'égalité est définie y compris entre implémentations différentes, - la définition du modèle n'a plus sa place en partie privée, il est générique. generic type model is private;... package accounts.implementation is type account is new accounts.account with private; function open (initial : natural) return account; function put (a : account; m : natural) return account; function get (a : account; m : natural) return account; function balance (a : account) return natural; function operations (a : account) return natural; function history (a : account;m : natural) return natural; function "="(x : account; y : accounts.account'class) return boolean; private type account is new accounts.account with record some : model; end record ; end accounts.implementation;

Les Comptes (implémentation générique) Dans le corps du package générique, seules restent les fonctions - traduisant le morphisme entre modèle et implémentation, - en exprimant les préconditions.... package body Accounts.Implementation is function Open (M : Natural) return Account is begin return (Accounts.Account with some => Open (M)); end; function Put (A : Account; M : Natural) return Account is begin return (Accounts.Account with some => Put (A.some, M)); end; function Get (A : Account; M : Natural) return Account is pragma Assert (M <= Balance (A)); begin return (Accounts.Account with some => Get (A.some,M)); end; function Operations (A : Account) return Natural is begin return Operations (A.some); end Operations; function History (A : Account; N : Natural) return Natural is pragma Assert (N <= Operations (A)); begin return History (A.some, N); end History;... end Accounts.Implementation ;

Les Comptes (implémentation générique) Les opérations pour lesquelles existe une opération de classe sont facultatives pour le modèle (pointeur null) ; on utilise alors par défaut la version de classe. Les opérations qui impliquent éventuellement des implémentations différentes nécessitent l'opération de classe. with Accounts.Class.Balance, with Accounts.Class.Equal; package body Accounts.Implementation is... function Balance (A : Account) return Natural is begin if Access_Balance /= null then return Access_Balance.all (A.some); else return Class.Balance (A); end if; end Balance; function "=" (X : Account; Y : Accounts.Account'Class) return Boolean is begin if not (Y in Account) then return Class.Equal(X, Y); elsif Access_Equal /= null then return Access_Equal.all (X.some, Account (Y).some); else return Class.Equal (X, Y); end if; end "="; end Accounts.Implementation ;

Les Comptes (implémentation générique) Les opérations sur les modèles sont des paramètres de généricité qui prennent deux formes : Si existe une fonction de classe, le paramètre générique prend la forme d'un pointeur (éventuellement null) sur le profil de l'opérateur. Sinon, il prend la forme d'un profil ; l'association à un opérateur effectif de même profil est automatique par la présence de <> ; generic type Model is private; with function Open (M : Natural) return Model is <>; with function Put (A : Model ; M : Natural) return Model is <>; with function Get (A : Model ; M : Natural) return Model is <>; with function Operations (A : Model) return Natural is <>; with function History (A : Model ; N : Natural) return Natural is <>; Access_Balance : access function (X : Model) return Natural := null; Access_Equal : access function (X, Y : Model) return Boolean := null; package Accounts.Implementation is … end Accounts.Implementation;

Les Comptes (classe) Les opérations de classe sont filles d'un package class qui permet de les préfixer. package Accounts.Class is end Accounts.Class; function Accounts.Class.Balance (X : Account'Class) return Natural; function Accounts.Class.Equal (X, Y : Account'Class) return Boolean;

Les Comptes (fonctions de classe) La première est une simple composition de fonctions. La seconde utilise une fonction récursive auxiliaire. function Accounts.Class.Balance (X : Account'Class) return Natural is begin return History (X, operations (X)); end Accounts.Class.Balance; function Accounts.Class.Equal (X, Y : Account'Class) return Boolean is function Same (N : Natural) return Boolean is begin if N = 0 then return History (X, 0) = History (Y, 0); else return History (X, N) = History (Y, N) and then Same (N - 1); end if; end Same; begin return Operations (X) = Operations (Y) and then Same (Operations (X)); end Accounts.Class.Equal;