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 Paul Mark Jurgen Julien Pierre 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 Julien Paul Mark Jurgen Julien Pierre
Filtrage Il faut savoir si un pattern XML filtre vers un noeud de document XML On aimerait pouvoir é crire %match(t) { Julien -> { // Noeud trouv é } Ou plus g é n é ralement : X -> { … }
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 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 X qui sera encod é par : ElementNode("A", conc(AttributeNode("a", "at1")), conc(X) )
Questions A-t-on : X ? Quel est le type de X ? TNode ? TNodeList ? On voudrait pouvoir é crire X* Quelles sont les solutions ?
Questions En fonction du parseur, peut être reconnu comme A-t-on : X ? X* ? Comment est encod é ? ElementNode("A", conc(AttributeNode("a", "at1")), conc( TextNode(" "), ElementNode("B",conc(),conc()), TextNode(" ")) ) Est-ce que cela filtre ?
Notation explicite (_*,X,_*) qui correspond à : conc(_*,X,_*) A-t-on (_*,X,_*) ? Oui, il y a 3 solutions
Notation implicite (_*,X,_*) qui correspond à : [X] qui correspond é galement à X A-t-on X ? 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 : correspond à qui correspond à
Questions A-t-on : ? Pourquoi ? car ? A-t-on : ? 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, 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) { (X1*,p1,X2*,p2,X3*) -> { if(`compare(p1,p2) > 0) { return sort(`xml( X1* p2 X2* p1 X3* )); } return subject; }
Comparaison d attributs int compare(Node t1, Node t2) { %match(t1, t2) { n1, n2 -> { 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 t 1,t 2 T(F), eq([t 1 ],[t 2 ]) = [t 1 =t 2 ] f F, t T(F), is_fsym(t,f) = [Symb(t)=f] f F, i [1..ar(f)], t T(F) subterm f (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 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
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 é 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
Ce qu on voudrait pouvoir contrôle l application des r è gles pouvoir 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 é gies Combiner des transformations é l é mentaires Exemples disjunctive normal form dnf = 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() { super(`Fail()); } 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(); }
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 { %match(Term arg) { g(x,b()) -> { collection.add(`x); } } return 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 é ga Position
Replace et Subterm Etant donn é e une position p getReplace(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