Université de Provence M1 Informatique- Logique, Déduction, Programmation 2008 – 2009 TD 5 Solange Coupet-Grimal Sémantique opérationnelle et points fixes On se donne, à partir de l’environnement initial Caml E0 , les définitions suivantes: let a =3;; let rec liste = fun n -> if n = 0 then [] else a::(liste (n-1));; let a = 1;; 1. Donner l’état de l’environnement courant après chaque définition. 2. Décrire avec précision chaque étape de l’évaluation de liste (a+a) dans le dernier environnement obtenu à la question précédente. 3. Quelle est la réponse affichée par Caml après: let resultat() = liste (a+a);; puis après : resultat;; puis enfin après : resultat();; 4. Définir une fonctionnelle F dont liste est point fixe. 5. Reprogrammer liste comme point fixe de F. 6. Décrire les étapes de l’évaluation de liste (a+a) avec cette nouvelle définition. Aspects Impératifs Question 1 Ecrire une fonction qui imprime à l’écran une liste d’entiers, séparés par une virgule suivie d’un caractère blanc. Plus précisément on devra obtenir: #print_list [12; 187; 0];; 12, 187, 0 - : unit = () Question 2 Ecrire une fonction qui imprime à l’écran une matrice d’entiers, représentée sous forme de listes de listes. On écrira deux fonctions, produisant les effets suivants: print_matrice [[1;23;251]; [12;4; 975]; [4321; 11; 0]; [0;0;0]];; 1 23 251 12 4 975 4321 11 0 0 0 0 - : unit = () print_matrice’ [[1;23;251]; [12;4; 975]; [4321; 11; 0]; [0;0;0]];; 1 23 251 12 4 975 4321 11 0 0 0 0 - : unit = () Termes Formels On considère dans cet exercice le type tree des arbres quelconques défini par: type ’a tree = Tr of ’a* ’a tree list;; On s’intéresse, dans un premier temps, à des expressions définies par un type récursif simple, dont les constructeurs s’appliquent sur un certain nombre d’arguments du même type. Le type ty suivant en est un exemple: type ty = A | B of ty | C of ty*ty;; Question 1 Ecrire la fonction tree of ty qui calcule l’arbre syntaxique d’une expression de type ty. Par exemple, on devra obtenir l’évaluation suivante: #tree_of_ty (C(B(C(A, A)), B(A)));; - : string tree = Tr ("C", [Tr ("B", [Tr ("C", [Tr ("A", []); Tr ("A", [])])]); Tr ("B", [Tr ("A", [])])]) Réciproquement, on se propose de déterminer si un arbre donné est, ou n’est pas, l’arbre syntaxique d’une expression d’un certain type récursif simple. Il faut en particulier vérifier si le nombre de fils d’un noeud correspond bien à l’arité de l’étiquette. Pour cela on se donne une liste de signatures, qui indique le nombre d’arguments de chaque constructeur. Avec l’exemple du type ty, la liste des signatures est la suivante: #let sig1=[("A",0);("B",1);("C",2)];; sig1 : (string * int) list = ["A", 0; "B", 1; "C", 2] De façon générale, une signature pour un type récursif simple sera du type ’a*int list. Question 2 Ecrire une fonction arity qui étant donné un constructeur et une liste de signatures, permet de rechercher l’arité d’un constructeur. Si le constructeur ne figure pas dans la liste, on devra lever une exception Sig error que l’on aura définie au préalable. Question 3 Ecrire une fonction correct qui étant donnée une liste de signatures et un arbre, renvoie un booléen indiquant s’il s’agit de l’arbre syntaxique d’une expression correcte. On considère maintenant le cas des types mutuellement récursifs, comme par exemple les types: #type ty1 = A|B of ty1*ty2 and ty2 = C|D of ty2*ty1;; Type ty1 defined. Type ty2 defined. Question 4 Ecrire des fonctions tree of ty1 et tree of ty2 analogues à la fonction tree of ty de la question 1. On devra obtenir par exemple l’exécution suivante: #tree_of_ty1 (B(A,D(C,A)));; - : string tree = Tr ("B", [Tr ("A", []); Tr ("D", [Tr ("C", []); Tr ("A", [])])]) De tels types sont caractérisés par une liste de signatures, associant à chaque constructeur son type, et la liste des types des arguments. L’arité est inutile, ce n’est autre que la longueur de la liste des types des arguments. Pour ty1 et ty2 on obtient: #let sig2 = [("A",([],"ty1"));("B",(["ty1";"ty2"],"ty1"));("C",([],"ty2")); ("D",(["ty2";"ty1"],"ty2"))];; sig2 : (string * (string list * string)) list = ... Question 5 Ecrire une fonction get type qui étant donnée une liste de signatures et un constructeur renvoie la signature de ce constructeur en renvoyant éventuellement l’exception Sig error si ce constructeur ne figure pas dans la liste. Question 5 Ecrire une fonction typing qui étant donnée une liste de signatures et un arbre renvoie le type de l’expression représentée par l’arbre s’il est correct et une exception sinon. On devra par exemple obtenir les évaluations suivantes: #typing sig2 (Tr ("B", [Tr ("A", []); Tr ("D", [Tr ("C", []); Tr ("A", [])])]));; - : string = "ty1" #typing sig2 (Tr ("A", [Tr ("A", []); Tr ("D", [Tr ("C", []); Tr ("A", [])])]));; Uncaught exception: Sig_error Ici, le typage de ”A” n’est pas bon. #typing sig2 (Tr ("E", [Tr ("A", []); Tr ("D", [Tr ("C", []); Tr ("A", [])])]));; Uncaught exception: Sig_error Ici, ”E” n’existe pas. Question 6 Ecrire une fonction qui étant donnée une liste de signatures et une liste l d’arbres, renvoie true si tous les arbres de la liste sont bien typés et f alse sinon.