Techniques de R éécriture et Transformations Pierre-Etienne . Moreau @loria.fr

Preview:

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 Presentation

Citation preview

1

Techniques de Réécriture et Transformations

Pierre-Etienne.Moreau@loria.fr

26 Février 2007

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)

Recommended