Post on 01-Apr-2015
1
http://tom.loria.fr 1
Strategic Programming in Java
Pierre-Etienne MoreauAntoine Reilles
Stratego User Day, December, 1st, 2006
2
http://tom.loria.fr 2
Context
• Protheo group, Nancy (C. Kirchner)
• 4 permanent researchers
• 12 PhD students
• Application domain: improve the quality of software• semantics of (rule and graph based) languages: Rho calculus
• theorem provers: deduction modulo, termination
• rule based programming: Elan, …, Tom
– 4 PhD students involved
– program analysis
– compilation
– certification
– language design (constraint, business rule)
3
http://tom.loria.fr 3
Motivations
After 20 years of research in rewriting
We are convinced that:• specifying by rewriting is a nice idea
But, we now want to:• make rewriting usable in practice
• integrate rewriting into existing programming environments
4
http://tom.loria.fr 4
Motivations
• Our approach:• take the best of ASF+SDF, ELAN, Maude, and Stratego
• design and develop a set of Java tools that offer similar constructs:
– algebraic data-type (Gom)
– equational pattern matching (Tom)
– strategic programming (Java Library + Gom)
– simplification rules (Tom + Gom)
5
http://tom.loria.fr 5
Short presentation of Tom
• A Java program is a Tom program
import pil.term.types.*;
import java.util.*;
public class Pil {
…
public final static void main(String[] args) {
Expr p1 = …;
System.out.println("p1 = " + p1);
…
}
}
6
http://tom.loria.fr 6
Tom adds algebraic data-types to Java
• Gom supports many-sorted first order signature
import pil.term.types.*;
import java.util.*;
public class Pil {
…
public final static void main(String[] args) {
Expr p1 = …;
System.out.println("p1 = " + p1);
…
}
}
%gom { module Term imports int String abstract syntax Bool = | True() | False() | Eq(e1:Expr, e2:Expr) Expr = | Var(name:String) | Let(var:Expr, e:Expr, body:Expr) | Seq(i1:Expr, i2:Expr) | If(cond:Bool, e1:Expr, e2:Expr) | a() | b()}
7
http://tom.loria.fr 7
An algebraic term is a Java object
• Back-quote (`) to build a term
import pil.term.types.*;
import java.util.*;
public class Pil {
…
public final static void main(String[] args) {
Expr p1 =
System.out.println("p1 = " + p1);
…
}
}
%gom { module Term imports int String abstract syntax Bool = | True() | False() | Eq(e1:Expr, e2:Expr) Expr = | Var(name:String) | Let(var:Expr, e:Expr, body:Expr) | Seq(i1:Expr, i2:Expr) | If(cond:Bool, e1:Expr, e2:Expr) | a() | b()}
`Let(Var("x"),a(), Let(Var("y"),b(),Var("x")));
8
http://tom.loria.fr 8
Tom adds pattern matching to Java
• %match supports syntactic and associative pattern matching
import pil.term.types.*;
import java.util.*;
public class Pil {
…
public final static void main(String[] args) {
Expr p1 = …;
System.out.println("p1 = " + p1);
…(pretty(p1));
}
…
}
public static String pretty(Object o) { %match(o) { Var(name) -> { return `name; }
Let(var,expr,body) -> { return "let " + pretty(`var) + " <- " + pretty(`expr) + " in " + pretty(`body); }
…
} return o.toString(); }
9
http://tom.loria.fr 9
Summary
• Tom offers 3 new constructs:• %gom : generate a typed data structure
• ` : build a term
• %match : syntactic matching and list-matching
Gom
Tom
JavaTom+Java
Data structure
Pattern matching
10
10
Demo
11
http://tom.loria.fr 11
Strategies in Tom
• Tom is powerful, but clearly not enough
• There is no separation between Transformation and Control
• Question:• starting from the JJTraveler library (J. Visser, OOPSLA 2001)• studying ASF+SDF, ELAN and Stratego• can we design a powerful strategy language, usable in Java ?
• The answer is Yes
12
http://tom.loria.fr 12
First inspiration: Stratego [E. Visser]• Elementaty strategies
• Id• Fail• Transformation rule
• Basic strategies• Sequence• Choice• All• One• Not
• Parameterized and recursive strategies• Try(s) = Choice(s,Identity)• Repeat(s) = Try(Sequence(s,Repeat(s)))• Repeat(s) = mu x . Try(Sequence(s,x))• BottomUp(s) = mu x . Sequence(All(x),s)
13
http://tom.loria.fr 13
Second inspiration: JJTraveler [J. Visser]public interface Visitor { /** Pay a visit to any visitable object. */ public Visitable visit(Visitable any) throws VisitFailure;}
public interface Visitable {
/** Returns the number of children of any visitable. */
public abstract int getChildCount();
/** Returns the ith child of any visitable. */
public abstract Visitable getChildAt(int i);
/** Replaces the ith child of any visitable, and returns this visitable. */
public abstract Visitable setChildAt(int i, Visitable child);
}
14
http://tom.loria.fr 14
Visitor combination and traversal control module term T1 = a() | b() | f(arg:T1) T2 = …
class T1 extends termAbstractType { termAbstractType accept(termVisitor v) { v.visit_T1(this); } }
interface termVisitor { T1 visit_T1(T1 arg); T2 visit_T2(T2 arg); }
abstract class termAbstractType { termAbstractType accept(termVisitor v); }
class termForward { Visitable visit(Visitable v) { return ((termAbstractType)v).accept(this); } T1 visit_T1(T1 arg) { return default.visit(arg); } T2 visit_T2(T2 arg) { return default.visit(arg); }}
class Rule extends termForward { public Rule() { super(new Fail()); } T1 visit_T1(T1 arg) { // code that implements lhs -> rhs // … return new Fail().visit(arg); } }
This is a Strategy!
15
http://tom.loria.fr 15
public class TopDown extends Sequence { public TopDown(Visitor s) { super(s,new All(this));
} }
TopDown(Rule)
TopDown(s) = mu x . Sequence(s,All(x))
T1 t = `f(a,f(a,b)); Visitor v = new TopDown(new Rule()); v.visit(t);
public class TopDown extends Sequence { public TopDown(Visitor s) { super(s,null); then = new All(this); } }
public class Sequence implements Visitor { public Visitor first; public Visitor then; … public Visitable visit(Visitable any) throws VisitFailure { return then.visit(first.visit(any)); } }
Sequence
s All
16
http://tom.loria.fr 16
Comparison with Stratego
• Each elementary strategy is an object
• Execution is done via interpretation (method call)
• Failure is implemented via Java exception
17
http://tom.loria.fr 17
Elementary strategies in Tom
• A Rule is an elementary strategy
• Identity and Fail are also elementary strategies
• a strategy is built using `• “x” and “z” are parameters of sort String• the rule is applied once, at root position
%strategy RenameVar(n1:String,n2:String) extends Identity() { visit Expr { Var(n) -> { if(`n==n1) return `Var(n2); } } }
Expr p1 = `Let(Var("x"),a(), Let(Var("y"),b(),Var("x")));
Expr p2 = `RenameVar("x","z").visit(p1);
> Let(Var("x"),a(), Let(Var("y"),b(),Var("x")))
18
http://tom.loria.fr 18
Basic strategies
• Big difference wrt. JJTraveler:• BottomUp is user defined using the mu operator
Expr p1 = `Let(Var("x"),a(), Let(Var("y"),b(),Var("x")));
Expr p2 = `BottomUp(RenameVar("x","z”)).visit(p1);
> Let(Var(”z"),a(), Let(Var("y"),b(),Var(”z")))
public Strategy BottomUp(Strategy s) { return `mu(MuVar("x"),Sequence(All(MuVar("x")),s));}
19
http://tom.loria.fr 19
Key ingredients
• A strategy is a term• can be built• matched• traversed
• Mu-expansion is done by applying a BottomUp
Sequence
Mu
x
Rule All
x
Sequence
Mu
x
Rule All
20
http://tom.loria.fr 20
How does it work?%typeterm Strategy {
implement
equals(t1,t2)
}
%op Strategy Fail() {
is_fsym(t)
make()
}
%op Strategy Choice(s1, s2) {
is_fsym(t)
get_slot(s1,t)
get_slot(s2,t)
make(first,then)
}
{ VisitableVisitor }
{ t1.equals(t2) }
{ t instanceof Fail }
{ new Fail() }
{ t instanceof Choice}
{ t.getChildAt(FIRST) }
{ t.getChildAt(THEN) }
{ new Choice(first,then) }
• `Choice(Rule(),Fail());• is equivalent to: • new Choice(new Rule(), new Fail())
• We have Choice(x,y) << s
• `BottomUp(Expand()).apply(s) returns a new Strategy
21
21
Current library:basic.tomcomposed.tom
22
http://tom.loria.fr 22
Parameterized strategies
• a strategy can be parameterized by values:
• a strategy can do side effects:
%strategy RenameVar(n1:String,n2:String) extends Identity() { … }
%strategy CollectVar(c:Collection) extends Identity() { visit Expr { v@Var(_) -> { c.add(v) } } } Collection set = new HashSet(); `BottomUp(CollectVar(set)).apply(p1);
23
http://tom.loria.fr 23
• sometimes we need to recursively call the current calling strategy
• this breaks separation between rules and control
• solution: give the calling context as argument
Strategies parameterized by a strategy
`mu(MuVar(“s”),BottomUp(Rule(MuVar(“s”)).visit()
%strategy Rule(s:Strategy) extends Identity() { visit Expr { Let(v,e,body) -> { … `s.apply(body); } } }
`BottomUp(Rule()).visit() %strategy Rule() extends Identity() { visit Expr { Let(v,e,body) -> { … `BottomUp(Rule()).visit(body); … } } } %strategy Rule(s:Strategy) extends Identity() {
visit Expr { Let(v,e,body) -> { %match(s) { Mu(x, Choice(…)) -> { Strategy ds = `debugWeaver().visit(s); … `ds.visit(body); } } } } }
Sequence
Mu
x
AllSequence
Debug Rule
24
24
Demo
25
http://tom.loria.fr 25
From ASF+SDF, ELAN, Maude and Stratego
• From ASF+SDF• list-matching (associative matching with neutral element)
• From Stratego• traversal strategies (All, One)• naming and semantics of operators
• From ELAN• statically typed rules and strategies• non-determinism experience• no AC, no backtracking• strategy as a term
• New in Tom• identity based strategies• strategy can be applied on a strategy• notion of position
26
http://tom.loria.fr 26
Identity based strategies
%strategy Rule() extends Fail() { // a -> b // default: failure }
Innermost(s) = mu x . All(x) ; ((s ; x) <+ Id)
`Innermost(Rule()).visit(t);
%strategy RuleId() extends Identity() { // a -> b // default: x -> x }
InnermostId(s) = mu x . All(x) ; SequenceId(s,x)
`InnermostId(RuleId()).visit(t);
27
http://tom.loria.fr 27
Other nice features
• A strategy knows where it is applied (global information)• useful to implement non-deterministic search (prover, model checker)
• Gom provides a hook mechanism• useful to maintain terms in canonical form (sorted list)
• Anti-pattern matching• car(white,!ecological)
• XML pattern matching• <A>(_*, x, _*, x, _*)</A> -> { … }
• Strategy library for graphs• useful for bytecode analysis
28
http://tom.loria.fr 28
Conclusion
• There are many similarities with Stratego
• Integration of rules and strategies in a Java environment
• Pure Java implementation
• Main advantages:• Tom and Java data-structures are compliant• makes debugging easier• any Java program is a Tom program• no deployment problem
• Room for improvements:• better integration into Java• connection to SDF• support for concrete syntax