r éé criture pour la programmation et la preuve claude kirchner pierre-etienne moreau
TRANSCRIPT
Réécriture pour la programmation et la
preuveClaude Kirchner
Pierre-Etienne Moreau
Application à XML
Document XML
XML permet de décrire des documents structurés
<?xml version="1.0" encoding="UTF-8"?>
<Persons>
<Person Age="30"> <FirstName> Paul </FirstName> </Person>
<Person Age="42"> <FirstName> Mark </FirstName> </Person>
<Person Age="21"> <FirstName> Jurgen </FirstName> </Person>
<Person Age="21"> <FirstName> Julien </FirstName> </Person>
<Person Age="24"> <FirstName> Pierre </FirstName> </Person>
</Persons>
On peut voir un document XML comme un arbre
Transformation de documents XML
On a envie de pouvoir manipuler ces données pour y rechercher de l’information pour générer de nouveaux documents (HTML, LaTeX, PDF, XML, etc.)
Quels sont les outils permettant de le faire XSLT / XPath Xquery Xduce / Cduce DOM …
Peu permettent de manipuler un document XML en Java Les manipulations se font souvent en utilisant DOM directement
Exemple
On veut savoir s’il existe un noeud de la forme <Person><FirstName> Julien </FirstName></Person>
<?xml version="1.0" encoding="UTF-8"?>
<Persons>
<Person Age="30"> <FirstName> Paul </FirstName> </Person>
<Person Age="42"> <FirstName> Mark </FirstName> </Person>
<Person Age="21"> <FirstName> Jurgen </FirstName> </Person>
<Person Age="21"> <FirstName> Julien </FirstName> </Person>
<Person Age="24"> <FirstName> Pierre </FirstName> </Person>
</Persons>
Filtrage
Il faut savoir si un pattern XML filtre vers un noeud de document XML
On aimerait pouvoir écrire%match(t) {
<Person><FirstName> Julien </FirstName></Person> -> {
// Noeud trouvé
}
}
Ou plus généralement :<Person><FirstName> X </FirstName></Person> -> { … }
Modèle de donnée (simplifié)
ElementNode(name:str, attrList:TNodeList,
childList:TNodeList) -> TNode
AttributeNode(name:str, value:str) -> TNode
TextNode(data:str) -> TNode
conc(TNode*) -> TNodeList
XML vs. Term
Un document XML peut se voir comme un arbre<A a="at1"><B/></A>
est représenté par :
ElementNode("A",
conc(AttributeNode("a", "at1")),
conc(ElementNode("B",conc(),conc()))
)
Pattern XML
On veut pouvoir écrire un pattern de la forme<A a="at1">X</A>
qui sera encodé par :
ElementNode("A",
conc(AttributeNode("a", "at1")),
conc(X)
)
Questions
A-t-on : <A a="at1">X</A> << <A a="at1"><B/></A> ? <A a="at1">X</A> << <A a="at1"><B/><C/></A> ?
Quel est le type de X ? TNode ? TNodeList ? On voudrait pouvoir écrire
<A a="at1">X*</A> << <A a="at1"><B/><C/></A>
Quelles sont les solutions ?
Questions
En fonction du parseur, <A a="at1"><B/></A> peut être reconnu comme <A a="at1"><B/></A>
A-t-on : <A a="at1">X</A> << <A a="at1"><B/></A> ? <A a="at1">X*</A> << <A a="at1"><B/></A> ?
Comment est encodé <A a="at1"><B/></A> ?ElementNode("A",
conc(AttributeNode("a", "at1")),conc(
TextNode(""),ElementNode("B",conc(),conc()),TextNode(""))
) Est-ce que cela filtre ?
Notation explicite
<A a="at1">(_*,X,_*)</A>
qui correspond à :
<A a="at1">conc(_*,X,_*)</A>
A-t-on <A a="at1">(_*,X,_*)</A> << <A a="at1"><B/></A> ?
Oui, il y a 3 solutions
Notation implicite
<A a="at1">(_*,X,_*)</A>
qui correspond à :
<A a="at1">[X]</A>
qui correspond également à
<A a="at1">X</A>
A-t-on <A a="at1">X</A> << <A a="at1"><B/></A> ?
Oui, il y a 3 solutions
Attributs
Les attributs sont représentés par une liste de couples (nom,valeur)
Il existe également des notations implicites et explicites
Ainsi : <A a="at1"> correspond à <A [a="at1"]> qui correspond à <A (_*,a="at1",_*)>
Questions
A-t-on : <A a="at1"></A> << <A a="at1"></A> ? <A a="at1"></A> << <A a="at1" b="at2"></A> ?
Pourquoi ? car <A (_*,a="at1",_*)></A> << <A (a="at1" b="at2 »)></A> ?
A-t-on : <A a="at1" b="at2"></A> << <A a="at1" b="at2"></A> ? <A a="at1" b="at2"></A> << <A b="at2" a="at1"></A> ?
Non, car : (_*, a="at1", _*, b="at2", _*) !<< (b="at2", a="at1") Il faudrait du filtrage AC avec élément neutre!
Attributs dans Tom
On considère un ordre sur les noms d’attributs et les formes canoniques où les attributs sont triés Ainsi, <A b="at2" a="at1"></A> est représenté par
ElementNode("A",
conc( AttributeNode("a", "at1"),
AttributeNode("b", "at2")),
conc()) De même, pour les motifs
Utilisation dans Tom
Node sort(Node subject) { %match(subject) { <Persons>(X1*,p1,X2*,p2,X3*)</Persons> -> { if(`compare(p1,p2) > 0) { return sort(`xml(<Persons>
X1* p2 X2* p1 X3*</Persons>));
} } } return subject; }
Comparaison d’attributs
int compare(Node t1, Node t2) { %match(t1, t2) { <Person Age=a1><FirstName> n1 </FirstName></Person>, <Person Age=a2><FirstName> n2 </FirstName></Person> -> { return `a1.compareTo(`a2); } } return 0; }
Ancrage formel
Mapping
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 »
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é
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
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]
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), …
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] }
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
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 }}
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)}
}
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)
Demo
Questions
Doit-on écrire des mappings ?Que fait %vas au juste ?
Outils autour de Tom
Aterm, SDF, ApiGen, Vas
Bibliothèque ATerm
Aterm AFun ATermAppl ATermList ATermInt ATermReal ATermPlaceholder ATermBlob
ATermFactory
ATerms
Bibliothèque ATerm
Aterm AFun ATermAppl ATermList ATermInt ATermReal ATermPlaceholder ATermBlob
ATermFactory
getAnnotationsetAnnotationtoStringetc.
Bibliothèque ATerm
Aterm AFun ATermAppl ATermList ATermInt ATermReal ATermPlaceholder ATermBlob
ATermFactory
getNamegetArity
Bibliothèque ATerm
Aterm AFun ATermAppl ATermList ATermInt ATermReal ATermPlaceholder ATermBlob
ATermFactory
getAFungetArgumentsetArgumentetc.
Bibliothèque ATerm
Aterm AFun ATermAppl ATermList ATermInt ATermReal ATermPlaceholder ATermBlob
ATermFactory
getFirstgetNextelementAt insertappendconcatetc.
Bibliothèque ATerm
Aterm AFun ATermAppl ATermList ATermInt ATermReal ATermPlaceholder ATermBlob
ATermFactory
makeAFunmakeAppl…parsereadFromFile
etc.
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)
ApiGen / Vas
A partir d’une signature multi-sortéeGé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
Exemple
Module Expressions
true -> Bool
false -> Bool
eq(lhs:Expr, rhs:Expr) -> Bool
id(value:str) -> Expr
nat(value:int) -> Expr
add(lhs:Expr, rhs:Expr) -> Expr
mul(lhs:Expr, rhs:Expr) -> Expr
Classes générées
Classes générées
Stratégies
Programmation par réécriture
Avantages le filtrage est un mécanisme expressif les règles expriment des transformations
élémentairesLimitations
les systèmes de règles sont souvent non-terminant et/ou non confluent
en général, on ne veut pas appliquer toutes les règles en même temps
Exemple de système non terminant
And(Or(x,y),z) Or(And(x,z),And(y,z))
And(z,Or(x,y)) Or(And(z,x),And(z,y))
Or(And(x,y),z) And(Or(x,z),Or(y,z))
Or(z,And(x,y)) And(Or(z,x),Or(z,y))
Not(Not(x)) x
Not(And(x,y)) Or(Not(x),Not(y))
Not(Or(x,y)) And(Not(x),Not(y))
Codage du contrôle dans les règles
Solution classique introduire un nouvel opérateur f pour
restreindre l’ensemble de règles permettant de normaliser
l r devient f(l) r’ on normalise un terme f(t) l’opérateur f permet de contrôler les règles
à appliquer
Encodage du contrôle
f(And(x,y)) and(x,y)f(Not(x)) not(x)f(Or(x,y)) Or(f(x),f(y)) and(Or(x,y),z) Or(and(x,z),and(y,z))and(z,Or(x,y)) Or(and(z,x),and(z,y))and(x,y) And(x,y) not(Not(x)) x not(And(x,y)) Or(not(x),not(y)) not(Or(x,y)) and(not(x),not(y))not(x) Not(x)
Conséquences
Il faut définir la congruence explicitement, pour chaque règle et chaque constructeur
Il n’y a plus de séparation entre transformation et contrôle cela rend la compréhension plus difficile les règles sont moins réutilisables
Ce qu’on voudrait
pouvoir contrôle l’application des règlespouvoir spécifier simplement le
« traversée » d’une terme (I.e. appliquer une règles dans les sous-termes)
tout en séparant règle et contrôle
Solution
Utiliser des stratégiesCombiner des transformations élémentairesExemples
disjunctive normal formdnf = innermost(DAOL <+ DAOR <+ DN <+…)DAOL : And(Or(x,y),z) Or(And(x,z),And(y,z))DAOR : And(z,Or(x,y)) Or(And(z,x),And(z,y)) DN : Not(Not(x)) x conjunctive normal form cnf = innermost(DOAL <+ DOAR <+ DN <+…)
Autres stratégies de traverse
simplify = bottomup(repeat(R1 <+ …))simplify = topdown(repeat(R1 <+ …))
… Slide 14
Stratégies en Tom
Constructeurs élémentaires
Identity Fail Not Sequence Choice All One Some IfThenElse Omega mu
Définition de stratégies%op VisitableVisitor Try(s1:VisitableVisitor) {
make(v) { `Choice(v,Identity) }}%op VisitableVisitor Repeat(s1:VisitableVisitor) {
make(v) { `mu(MuVar("x"),Choice(Sequence(v,MuVar("x")),Identity())) }}%op VisitableVisitor TopDown(s1:VisitableVisitor) { make(v) { `mu(MuVar("x"),Sequence(v,All(MuVar("x")))) }
%op VisitableVisitor OnceBottomUp(s1:VisitableVisitor) {make(v) { `mu(MuVar("x"),Choice(One(MuVar("x")),v)) }
}%op VisitableVisitor Innermost(s1:VisitableVisitor) { make(v) { `mu(MuVar("x"), Sequence(All(MuVar("x")),
Try(Sequence(v,MuVar("x"))))) }}
}
Stratégie élémentaire en Tom
class RewriteSystem extends strategy.term.termVisitableFwd {public RewriteSystem() {
}public Term visit_Term(Term arg) throws VisitFailure {
%match(Term arg) { a() -> { return `b(); }
b() -> { return `c(); } g(c(),c()) -> { return `c(); } }
}}
throw new VisitFailure();
super(`Fail());
Utilisations
VisitableVisitor rule = new RewriteSystem();
Term subject = `f(g(g(a,b),g(a,a)));
`OnceBottomUp(rule).visit(subject);
`Innermost(rule).visit(subject);
`Repeat(OnceBottomUp(rule)).visit(subject);
(mode paranoïaque)VisitableVisitor rule = new RewriteSystem();Term subject = `f(g(g(a,b),g(a,a)));VisitableVisitor onceBottomUp =
`mu(MuVar("x"),Choice(One(MuVar("x")),rule));onceBottomUp.visit(subject));
VisitableVisitor innermostSlow = `mu(MuVar("y"),Choice(Sequence(onceBottomUp,MuVar("y")),Identity()));innermostSlow.visit(subject));
VisitableVisitor innermost = `mu(MuVar("x"),Sequence(All(MuVar("x")),Choice(Sequence(rule,MuVar("x")),Identity)));
innermost.visit(subject));
Questions
Comment calculer des ensembles de résultats
Exemples f(g(g(a,b),g(a,b))) trouver les x tels que g(x,b) filtre un sous
terme
Solution
considerer s(col) : g(x,b) col.add(x)
appliquer Try(BottomUp(s(col)))
énumérer col
Codage class RewriteSystem extends strategy.term.termVisitableFwd {
Collection collection; public RewriteSystem(Collection c) { super(`Fail()); this.collection = c; } public Term visit_Term(Term arg) throws VisitFailure { g(x,b()) -> { collection.add(`x); } }
return arg;}
}
%match(Term arg) {
Codage
Collection collection = new HashSet();
VisitableVisitor rule = new RewriteSystem(collection);
Term subject = `f(g(g(a,b),g(c,b)));
`Try(BottomUp(rule)).visit(subject);
System.out.println("collect : " + collection);
Stratégie Oméga
OmégaPosition
Replace et Subterm
Etant donnée une position pgetReplace(t’) retourne une stratégie qui,
appliquée sur un terme donné, remplace le sous-terme à la position p donnée par le terme t’
getSubterm() retourne une stratégie qui retourne le sous-terme à la position p
ces stratégies encodent les l’accès à un sous-terme et l’opération de remplacement
cela permet d’encoder de l’exploration traversée + non-déterministe
Exemple complexe
Xmas
Principales applications