700 likes | 798 Views
R éé criture pour la programmation et la preuve. Claude 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>
E N D
Réécriture pour la programmation et la preuve Claude Kirchner Pierre-Etienne Moreau
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 structureC %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)
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
Bibliothèque ATerm • Aterm • AFun • ATermAppl • ATermList • ATermInt • ATermReal • ATermPlaceholder • ATermBlob • ATermFactory • getAnnotation • setAnnotation • toString • etc.
Bibliothèque ATerm • Aterm • AFun • ATermAppl • ATermList • ATermInt • ATermReal • ATermPlaceholder • ATermBlob • ATermFactory • getName • getArity
Bibliothèque ATerm • Aterm • AFun • ATermAppl • ATermList • ATermInt • ATermReal • ATermPlaceholder • ATermBlob • ATermFactory • getAFun • getArgument • setArgument • etc.
Bibliothèque ATerm • Aterm • AFun • ATermAppl • ATermList • ATermInt • ATermReal • ATermPlaceholder • ATermBlob • ATermFactory • getFirst • getNext • elementAt • insert • append • concat • etc.
Bibliothèque ATerm • Aterm • AFun • ATermAppl • ATermList • ATermInt • ATermReal • ATermPlaceholder • ATermBlob • ATermFactory • makeAFun • makeAppl • … • parse • readFromFile • 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ée • 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
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
Programmation par réécriture • Avantages • le filtrage est un mécanisme expressif • les règles expriment des transformations élémentaires • Limitations • 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