techniques de r éécriture et transformations pierre-etienne . moreau @loria.fr
DESCRIPTION
Techniques de R éécriture et Transformations Pierre-Etienne . Moreau @loria.fr. 26 F évrier 2007. Informatique. Science du traitement de l’information Repr ésentation des données Transformation de ces données R éécriture Abstraction o ù les données sont des termes - PowerPoint PPT PresentationTRANSCRIPT
2
Informatique
Science du traitement de l’information• Représentation des données
• Transformation de ces données
Réécriture• Abstraction où les données sont des termes
• C’est un moyen d’étudier les relations qui existent entre les termes
• C’est une façon de décrire des transformations de termes
3
Dans la suite
Je vais présenter un langage fondé sur ces principes• Qui permet de représenter facilement des données arborescentes
• Qui permet de les inspecter ou les transformer
Intérêt par rapport à un langage classique• Plus haut niveau d’abstraction
• On fait moins d’erreurs
• On programme plus vite
4
Un exemple
+33* France
+333* Est
+33383* D.54
+0800* Gratuit
+33383593019 France, Est, D.54
5
Impératifs techniques
• Bonne interaction avec C, Java, …
• Faciliter la communication avec l’extérieur (I/O, Corba, …)
• S’adapter aux structures de données de l’utilisateur
Java JavaJava + îles formelles
6
Mise en pratique des îlots formels
Un langage qui permet de :
• Construire des structures arborescentes
• Reconnaître des motifs dans une structure de donnée
Lorsqu’un motif est reconnu
• On dit que le motif « filtre » vers la structure
• On peut exécuter une action, écrite en C ou Java
…
7
Présentation de Tom
8
Système de réécriture
%rule {
one() -> suc(zero())
}
System.out.println(« one = » + one());
> one = suc(zero)
Une fonction Java est associée à chaque symbole défini
9
Système de réécriture
%rule {
one() -> suc(zero())
}
%rule {
two() -> suc(one())
}
System.out.println(« two = » + two());
> two = suc(suc(zero))
Les règles doivent commencer par le même symbole de tête
On peut définir plusieurs systèmes de réécriture
10
Questions
Quels sont les statuts de « zero » et « suc »?
Peut-on écrire « zero(suc) »?
Il y a une notion de signature :• définition du nom et des profils des opérateurs
11
Signature
%gom {
module Peano
abstract syntax
Nat = zero
| suc(Nat)
| fib(Nat)
| plus(Nat, Nat)
}
12
Système de réécriture
%rule {
plus(x, zero()) -> x
plus(x, suc(y)) -> suc(plus(x,y))
}
System.out.println(« res = » + plus(one(),two()));
> res = suc(suc(suc(zero)))
Un membre droit peut utiliser :• des constructeurs, • des symboles définis et • des variables introduites dans le membre gauche
13
Quelques remarques
%rule {
fib(zero()) -> one()
fib(suc(zero())) -> one()
fib(suc(suc(x))) -> plus(fib(x),fib(suc(x)))
}
Le type des variables n’est pas déclaré, mais est inféré
Applique une stratégie leftmost-innermost
14
Question
Peut-on écrire le programme suivant ?
%rule {
fib(zero()) -> one()
fib(one()) -> one()
fib(suc(suc(x))) -> plus(fib(x),fib(suc(x)))
}
Oui
Pourquoi cette question ?
15
Exercice
Evaluer le terme fib(plus(one(),two()))
Ecrire la trace d’exécutionone()
-> suc(zero())
two()
-> suc(suc(zero()))
plus(suc(zero()),suc(suc(zero())))
-> suc(plus(suc(zero()),suc(zero())))
-> suc(suc(plus(suc(zero()),zero())))
-> suc(suc(suc(zero())))
fib(suc(suc(suc(zero()))))
-> plus(fib(suc(zero())),fib(suc(suc(zero()))))
fib(suc(zero()))
-> ?
-> fib(suc(zero()))
16
Question
Que donne l’évaluation du programme suivant ?
System.out.println(« res = » + fib(plus(one(),two())));
> res = suc(suc(suc(zero)))
Que donne l’évaluation du programme suivant ?
System.out.println(« res = » + suc(fib(plus(one(),two()))));
ne compile pas : suc n’est pas une fonction Java
17
Mécanisme de base
`suc(suc(zero))
permet de construire un terme
suc
suc
zero
Le terme doit être bien formé et bien typé
18
Utilisation de `
System.out.println(« res = » + `suc(fib(plus(one(),two()))));
> res = suc(suc(suc(suc(zero))))
Un ` peut contenir des constructeurs, des symboles définis
À partir de la signature %gom, on peut représenter et afficher des termes
19
Utilisation en Java
Nat one = `suc(zero());
Nat two = `suc(suc(zero()));
System.out.println(« one = » + one);
System.out.println(« two = » + two);
> one = suc(zero)
> two = suc(suc(zero))
20
Question
Peut-on écrire :
Nat one = `suc(zero());
Nat two = `suc(one);
Oui
Un ` peut contenir des constructeurs, des symboles définis et des variables Java
21
Résumé
%gom permet de définir une signature
%rule permet de définir un système de réécriture contenant :• des constructeurs et des variables dans le lhs
• des constructeurs, des variables et des symboles définis dans le rhs
` permet de construire un terme à partir de constructeurs, symboles définis, variables et fonctions Java
22
Question
Comment Java sait qu’il doit afficher « suc(suc(zero)) » ?
A chaque signature correspond une implantation en Java
23
Bibliothèque ATerm
Aterm• AFun
• ATermAppl
• ATermList
• ATermInt
• ATermReal
• ATermPlaceholder
• ATermBlob
ATermFactory
24
ATerms
25
Bibliothèque ATerm
Aterm• AFun
• ATermAppl
• ATermList
• ATermInt
• ATermReal
• ATermPlaceholder
• ATermBlob
ATermFactory
getAnnotationsetAnnotationtoStringetc.
26
Bibliothèque ATerm
Aterm• AFun
• ATermAppl
• ATermList
• ATermInt
• ATermReal
• ATermPlaceholder
• ATermBlob
ATermFactory
getNamegetArity
27
Bibliothèque ATerm
Aterm• AFun
• ATermAppl
• ATermList
• ATermInt
• ATermReal
• ATermPlaceholder
• ATermBlob
ATermFactory
getAFungetArgumentsetArgumentetc.
28
Bibliothèque ATerm
Aterm• AFun
• ATermAppl
• ATermList
• ATermInt
• ATermReal
• ATermPlaceholder
• ATermBlob
ATermFactory
getFirstgetNextelementAtinsertappendconcatetc.
29
Bibliothèque ATerm
Aterm• AFun
• ATermAppl
• ATermList
• ATermInt
• ATermReal
• ATermPlaceholder
• ATermBlob
ATermFactory
makeAFunmakeAppl…parsereadFromFile
etc.
30
Utilisation des ATerms
Aterm t1 = factory.parse("a")
Aterm t2 = factory.parse("f(a,b)")
t2.getArgument(1) == t1 ?
> true
Aterm t3 = t2.setArgument(t1,2)
> t3 = f(a,a)
Aterm t4 = factory.parse("f(a,f(b))")
> ‘f’ n’a pas de signature particulière
Les ATerms permettent de construire des termes, mais il n’y a pas de sécurité (signature, types)
31
Gom
A partir d’une signature multi-sortées
Génère des classes, reposant sur les ATerms, permettant de représenter les termes
• partage maximal
• typage fort des termes
• tout terme typé est un ATerm
32
Exemple
%gom {
module Expression
imports int
abstract syntax
Expr = Cst(value:int)
| Plus(e1:Expr, e2:Expr)
| Mult(e1:Expr, e2:Expr)
Bool = True()
| False()
| Equal(b1:Bool,b2:Bool)
}
33
Exercice
Écrire un évaluateur d’expressions capable d’évaluer :
Plus(Cst(1),Cst(2))
Plus(Mult(Cst(3),Cst(4)),Cst(1))
34
Tom, la suite…
35
Pattern non-linéaire
Une variable peut apparaître plusieurs fois dans le membre gauche%rule {
equal(x,x) -> True()
equal(x,y) -> False()
}
Réduire :
equal(suc(zero()), zero())
-> False()
equal(fib(plus(one,two)), suc(suc(suc(zero()))))
-> equal(fib(suc(suc(suc(zero())))), suc(suc(suc(zero()))))
-> equal(suc(suc(suc(zero()))), suc(suc(suc(zero()))))
-> True()
Les règles s’évaluent du haut vers le bas
36
Règles conditionnelles
%rule {
fib(zero()) -> suc(zero())
fib(suc(x)) -> suc(x) if x == zero()
fib(suc(suc(x))) -> plus(y,fib(suc(x))) where y := fib(x)
}
calcul de la substitution
instanciation et évaluation des conditions/wheres
instanciation du membre droit et réduction
37
Codage de la non-linéarité
%rule {equal(x,x) -> True()
equal(x,y) -> False()
}
peut également s’écrire
%rule {equal(x,y) -> True() if x == y
equal(x,y) -> False() if x != y
}
il faut disposer de l’égalité sur les termes
38
Remarques
la construction %rule peut contenir des variables et des fonctions Java (dans le membre droit)
sinon, pour utiliser %rule il faudrait que tout soit défini avec des %rule
39
Exercice
Définir une fonction
plusInt(Nat, Nat) -> int
Qui retourne l’addition de deux Nat sous forme d’entier
System.out.println(« res = » + `plusInt(one,two));
> res = 3
40
Solution
%gom {
…
imports int
…
plusInt(Nat, Nat) -> int
…
}
%rule {
plusInt(zero(),zero()) -> 0
plusInt(suc(x),y) -> increment(plusInt(x,y))
plusInt(x,suc(y)) -> increment(plusInt(x,y))
}
public static int increment(int a) { return a+1; }
41
Pour combiner filtrage et Java
public Nat plus(Nat n1, Nat n2) {
%match(n1, n2) {
x, zero() -> { return `x; }
x, suc(y) -> { return `suc(plus(x,y)); }
}
}
plus n’est plus un symbole défini, mais une fonction Java
x et y sont des variables instanciées par filtrage
elles deviennent des variables Java locales à chaque règle
42
On aurait pu écrire
public Nat plus(Nat n1, Nat n2) {
%match(n2) {
zero() -> { return n1; }
suc(y) -> { return `suc(plus(n1,y)); }
}
}
43
Exercice
Ecrire le programme qui affiche le résultat sous forme d’entier
System.out.println(« res = » + `entier(suc(plus(one,two))));
> res = 4
44
Solution
public int entier(Nat n) {
%match(n) {
zero() -> { return 0; }
suc(x) -> { return 1 + entier(`x); }
}
}
Le membre droit peut mélanger Tom et Java
•
45
Sémantique du %match
Sélectionne le premier pattern qui filtre
Evalue l’action associée
L’exécution reprend• après l’action (i.e. sélectionne le pattern suivant) s’il n’y a pas eu de
break ou de return
• en fonction du flot de contrôle
46
Question
Peut-on encoder un système de réécriture conditionnelle avec le %match ?
47
Réponse
Oui, il suffit de mettre une condition dans la partie action
public int entier(Nat n) {%match(n) {
zero() -> { return 0; }suc(x) -> {
if(`x != `zero() ) { return 1 + `entier(x); } }
suc(zero()) -> { return 1; }}
}
•
48
Pattern non-linéaire
%rule {
f(x,x) -> rhs
}
peut aussi s’écrire
%rule {
f(x,y) -> rhs if x == y
}
%match(…) {
f(x,y) -> { if( x == y ) { return `rhs; } }
}
49
Exercice
Ré-écrire l’évaluateur d’expressions en utilisant %match
50
Exemple : Polynôme
51
Problème
On veut pouvoir calculer des dérivées de polynômes
Comment représenter un polynôme ?
Comment calculer un polynôme dérivé ?
52
1er essai de signature
%gom {
module expression
abstract syntax
Expression =
| diff(e:Expression,v:Expression)
| X()
| a()
| zero()
| one()
| mult(arg1:Expression,arg2:Expression)
| plus(arg1:Expression,arg2:Expression)
}
53
Signature plus générique
%gom {
module expression
abstract syntax
Expression =
| zero()
| one()
| mult(arg1:Expression,arg2:Expression)
| plus(arg1:Expression,arg2:Expression)
| exp(arg1:Expression)
| variable(string:String)
| constant(string:String)
| number(integer:Int)
| diff(e:Expression,v:Expression)
}
54
Dérivation de polynomes
%rule {
diff(variable(v1),variable(v1)) -> one()
diff(plus(a1,a2),vx) -> plus(diff(a1,vx), diff(a2,vx))
diff(mult(a1,a2),vx) -> plus(mult(a1,diffa2,vx)), mult(a2,diff(a1,vx)))
diff(exp(a1),vx) -> mult(diff (a1,vx),exp(a1))
diff(variable(_),_) -> zero()
diff(constant(_),_) -> zero()
diff(number(_),_) -> zero()
diff(zero(),_) -> zero()
}
diff(one(),_) -> zero()
55
Dérivation de polynomes
%rule {
diff(variable(v1),variable(v1)) -> one()
diff(plus(a1,a2),vx) -> plus(diff(a1,vx), diff(a2,vx))
diff(mult(a1,a2),vx) -> plus(mult(a1,diffa2,vx)), mult(a2,diff(a1,vx)))
diff(e@exp(a1),vx) -> mult(diff (a1,vx),e)
diff(variable(_),_) -> zero()
diff(constant(_),_) -> zero()
diff(number(_),_) -> zero()
diff(zero(),_) -> zero()
}
diff(one(),_) -> zero()
56
Dérivation de polynomes
%rule {
diff(variable(v1),variable(v1)) -> one()
diff(plus(a1,a2),vx) -> plus(diff(a1,vx), diff(a2,vx))
diff(mult(a1,a2),vx) -> plus(mult(a1,diffa2,vx)), mult(a2,diff(a1,vx)))
diff(e@exp(a1),vx) -> mult(diff (a1,vx),e)
diff[e=variable(_)] -> zero()
diff(constant(_),_) -> zero()
diff(number(_),_) -> zero()
diff(zero(),_) -> zero()
}
diff(one(),_) -> zero()
57
Dérivation de polynomes
%rule {
diff(variable(v1),variable(v1)) -> one()
diff(plus(a1,a2),vx) -> plus(diff(a1,vx), diff(a2,vx))
diff(mult(a1,a2),vx) -> plus(mult(a1,diffa2,vx)), mult(a2,diff(a1,vx)))
diff(e@exp(a1),vx) -> mult(diff (a1,vx),e)
diff(variable[],_) -> zero()
diff(constant[],_) -> zero()
diff(number[],_) -> zero()
diff(zero(),_) -> zero()
}
diff(one(),_) -> zero()
58
Dérivation de polynomes
%rule {
diff(variable(v1),variable(v1)) -> one()
diff(plus(a1,a2),vx) -> plus(diff(a1,vx), diff(a2,vx))
diff(mult(a1,a2),vx) -> plus(mult(a1,diffa2,vx)), mult(a2,diff(a1,vx)))
diff(e@exp(a1),vx) -> mult(diff (a1,vx),e)
diff(variable[],_) -> zero()
diff(constant[],_) -> zero()
diff(number[],_) -> zero()
diff(zero[],_) -> zero()
}
diff(one[],_) -> zero()
59
Dérivation de polynomes
%rule {
diff(variable(v1),variable(v1)) -> one()
diff(plus(a1,a2),vx) -> plus(diff(a1,vx), diff(a2,vx))
diff(mult(a1,a2),vx) -> plus(mult(a1,diffa2,vx)), mult(a2,diff(a1,vx)))
diff(e@exp(a1),vx) -> mult(diff (a1,vx),e)
diff( (variable|constant|number|zero|one)[],_) -> zero()
}
60
Exécution
diff(mult(variable("X"),plus(variable("X"),constant("a"))), variable("X"))
> plus(
mult(variable("X"),plus(zero,zero)),
mult(plus(variable("X"),constant("a")),zero))
Exercice : on voudrait simplifier le résultat, pour obtenir :
> zero
61
Filtrage syntaxique
62
Utilisations de Tom
Bien adapté pour
manipuler des formules symboliques
modéliser des règles d’inférence
programmer des prouveurs
implanter des systèmes de contraintes symboliques
…
décrire des algorithmes de filtrage
63
Règles
Decompose: (f P1…Pn) << (f A1…An) i=1…n Pi<<Ai
SymbolClash: (f P1…Pn) << (g A1…An) False
Delete: P << P True
PropagageClash: S False False
PropagateSuccess: S True S
f(x,g(y)) << f(a,g(b))
x<<a g(y)<<g(b)
x<<a y<<b
f(b,g(y)) << f(a,g(b))
b<<a g(y)<<g(b)
False y<<b
False
64
Implantation en Tom
Quelle signature choisir ?Variable(name:String) -> Term
Appl(name:String, args:TermList) -> Term
cons(head:Term,tail:TermList ) -> TermList
nil -> TermList
True -> Term
False -> Term
Match(pattern:Term, subject:Term) -> Term
And(a1:Term, a2:Term) -> Term
65
Codage des règles
%rule {
// Delete
// SymbolClash
Match(Appl(name1,a1),Appl(name2,a2)) -> False()
}
Match(Appl(name,a1),Appl(name,a2)) -> decomposeList(a1,a2)
// Decompose
Match(P,P) -> True()
66
Décomposition - Simplification
%rule {
decomposeList(nil(),nil()) -> True()
decomposeList(cons(h1,t1),cons(h2,t2)) -> And(Match(h1,h2),decomposeList(t1,t2))
}
%rule {
// PropagateClash
And(_,False()) -> False()
// PropagateSuccess
And(True(),x) -> x
And(x,True()) -> x
And(x,x) -> x
}
And(False(),_) -> False()
67
Démo
68
Ancrage formel
69
Problématique
Comment faciliter l’utilisation du filtrage dans les programmes existants ?
• en permettant un mélange des syntaxes
• en permettant de filtrer vers des structures du langage hôte
Nous avons donc besoin de filtrer « modulo des vues »
70
Solution adoptée
Tom permet de « voir » les objets en mémoire comme des termes algébrique
Il faut pour cela définir un « ancrage formel » permettant• de savoir si un terme commence par un symbole donné
• d’accéder à un sous terme donné
71
Plus formellement
On considère les ensembles :• [N], la représentation des entiers naturels
• [B], la représentation des booléens
• [F], la représentation des symboles
• [T(F)], la représentation des termes clos
• [X], la représentation des variables
72
Contraintes à respecter
t1,t2T(F),
eq([t1],[t2]) = [t1=t2]
fF, tT(F), is_fsym(t,f) = [Symb(t)=f]
fF, i[1..ar(f)], tT(F) subtermf(t,i) = [t|i]
73
Structure de données
struct term {int symb;
struct term **subterm;
}
On représente les symboles par des entiers (zero,3), (suc,5), (plus,7), …
74
Mapping de Nat vers une structure C
%typeterm Nat {
implement
equals(t1,t2)
}
%op Nat zero {
is_fsym(t)
}
%op Nat suc(p:Nat) {
is_fsym(t)
get_slot(p,t)
}
{ struct term* }{ term_equals(t1,t2) }
{ t!=null && t->symb==3 }
{ t!=null && t->symb==5 }{ t->subterm[0] }
75
Mapping
Permet de voir une structure arborescente comme un terme
Plus généralement, permet de voir n’importe quelle structure de donnée comme un terme
Permet de filtrer vers des objets en mémoire
76
Exercice
Peut-on voir les entiers machine comme des entiers de Peano ?%typeterm Nat {
implement { int }
}
%op Nat zero {
is_fsym(t) { t==0 }
}
%op Nat suc(p:Nat) {
is_fsym(t) { t>0 }
get_slot(p,t) { t-1 }
}
77
Peut-on filtrer vers des objets ?class A { int a; }
class B extends A { int b; }
%typeterm A {
implement { A }
equals(t1,t2) {t1.equals(t2)}
}
%typeterm B {
implement { B }
equals(t1,t2) {t1.equals(t2)}
}
78
Mapping objet
%op A A(a:int) {
is_fsym(t) { t instanceof A }
get_slot(a,t) { t.a }
}
%op A B(a:int,b:int) {
is_fsym(t) { t instanceof B }
get_slot(a,t) { t.a }
get_slot(b,t) { t.b }
}
A[a=x] << new A(3)
B[b=x] << new B(2,3)
A[a=x] << new B(2,3)