A couple of basic applications of dynamic rewrite rules in Stratego: constant propagation, variable renaming, function inlining, common-subexpression elimination
Why Teams call analytics are critical to your entire business
Scoped dynamic rewrite rules
1. Scoped Dynamic Rewrite Rules
Program Transformation 2004–2005
Eelco Visser
Institute of Information & Computing Sciences
Utrecht University,
The Netherlands
February 29, 2005
2. Limitations of Rewriting
Lack of control over application of rules
Non-termination
Non-confluence
Common solution: encode with extra rules
Stratego: programmable rewriting strategies
Context-free nature of rewrite rules
Inlining
Bound variable renaming
Dead code elimination
Common solution: encode with extra rules
Stratego: scoped dynamic rewrite rules
http://www.strategoxt.org
Scoped Dynamic Rewrite Rules
3. Limitations of Rewriting
Lack of control over application of rules
Non-termination
Non-confluence
Common solution: encode with extra rules
Stratego: programmable rewriting strategies
Context-free nature of rewrite rules
Inlining
Bound variable renaming
Dead code elimination
Common solution: encode with extra rules
Stratego: scoped dynamic rewrite rules
For details see paper:
Program Transformation with Scoped Dynamic Rewrite Rules
http://www.strategoxt.org
Scoped Dynamic Rewrite Rules
4. Contextual Rules
UnfoldCall :
| let function f(x) = e1 in e2[f(e3)] end ] ->
[
|
| let function f(x) = e1
[
in e2[let var x := e3 in e1 end] end ]
|
http://www.strategoxt.org
Scoped Dynamic Rewrite Rules
5. Contextual Rules
UnfoldCall :
| let function f(x) = e1 in e2[f(e3)] end ] ->
[
|
| let function f(x) = e1
[
in e2[let var x := e3 in e1 end] end ]
|
Implementation
UnfoldCall :
| let function f(x) = e1 in e2 end ] ->
[
|
| let function f(x) = e1 in e2’ end ]
[
|
where <oncetd({e3 :
(|
[f(e3)] -> |
|
[let var x := e3 in e1 end]
|)
})> e2 => e2’
http://www.strategoxt.org
Scoped Dynamic Rewrite Rules
6. Contextual Rules
UnfoldCall :
| let function f(x) = e1 in e2[f(e3)] end ] ->
[
|
| let function f(x) = e1
[
in e2[let var x := e3 in e1 end] end ]
|
Implementation
UnfoldCall :
| let function f(x) = e1 in e2 end ] ->
[
|
| let function f(x) = e1 in e2’ end ]
[
|
where <oncetd({e3 :
(|
[f(e3)] -> |
|
[let var x := e3 in e1 end]
|)
})> e2 => e2’
Problems
Local traversal
One rule at a time
http://www.strategoxt.org
Scoped Dynamic Rewrite Rules
7. Idea
Contextual Rule
UnfoldCall :
| let function f(x) = e1 in e2 end ] ->
[
|
| let function f(x) = e1 in e2’ end ]
[
|
where <oncetd({e3 :
(|
[f(e3)] -> |
|
[let var x := e3 in e1 end]
|)
})> e2 => e2’
http://www.strategoxt.org
Scoped Dynamic Rewrite Rules
8. Idea
Contextual Rule
UnfoldCall :
| let function f(x) = e1 in e2 end ] ->
[
|
| let function f(x) = e1 in e2’ end ]
[
|
where <oncetd({e3 :
(|
[f(e3)] -> |
|
[let var x := e3 in e1 end]
|)
})> e2 => e2’
Observation: Local rule inherits variable bindings from context
http://www.strategoxt.org
Scoped Dynamic Rewrite Rules
9. Idea
Contextual Rule
UnfoldCall :
| let function f(x) = e1 in e2 end ] ->
[
|
| let function f(x) = e1 in e2’ end ]
[
|
where <oncetd({e3 :
(|
[f(e3)] -> |
|
[let var x := e3 in e1 end]
|)
})> e2 => e2’
Observation: Local rule inherits variable bindings from context
Dynamic Rule
define-unfold =
?| let function f(x) = e1 in e2 end ]
[
|
; rules(
UnfoldCall : |
[f(e3)] -> |
|
[let var x := e3 in e1 end]
|
)
http://www.strategoxt.org
Scoped Dynamic Rewrite Rules
10. Dynamic Rewrite Rules
Properties
Defined at run-time
Multiple rules with the same name can be defined
Rules can be redefined
Rules can be undefined
The scope in which a rule is applicable can be limited
Scope labels provide fine grained control over the scope in
which a rule is defined
Rules can be extended to rewrite to multiple right-hand sides
Rule sets can be forked and later joined again with
intersection or union operations
http://www.strategoxt.org
Scoped Dynamic Rewrite Rules
12. Example: Constant Propagation
(b
c
b
b
a
:=
:=
:=
:=
:=
1;
b +
b +
z +
b +
3;
1;
b;
c)
⇒
b -> 1
b -> 1,
b -> 2,
b-,
b-,
c
c
c
c
->
->
->
->
4
4
4
4, a-
⇒
(b
c
b
b
a
:=
:=
:=
:=
:=
prop-const =
PropConst
<+ prop-const-assign
<+ (all(prop-const); try(EvalBinOp <+ EvalRelOp))
prop-const-assign =
|[ x := <prop-const => e> ]|
; if <is-value> e then
rules( PropConst : |[ x ]| -> |[ e ]| )
else
rules( PropConst :- |[ x ]| ) end
http://www.strategoxt.org
Scoped Dynamic Rewrite Rules
1;
4;
2;
z + 2;
b + 4)
13. Bound Variable Renaming
let var a : int :=
function foo(a
let var a :=
var z :=
in for a :=
z := z
in foo(a) end
x
:
a
0
a
+
int) : int =
+ 3
to a + 100 do
a end
⇓
let var a : int := x
function foo(b : int) : int =
let var c := b + 3
var z := 0
in for d := c to c + 100 do
z := z + d end
in foo(a) end
http://www.strategoxt.org
Scoped Dynamic Rewrite Rules
14. Bound Variable Renaming
exprename = rec rn(
RenameVar
<+ RenameVarDec
<+ |[ let <*id> in <*id> end ]|
; {| RenameVar : all(rn) |}
<+ |[ for <id> := <rn> to <rn> do <id> ]|
; {| RenameVar: RenameFor
; |[ for <id> := <id> to <id> do <rn> ]| |}
<+ |[ function <id>(<*id>) <id> = <id> ]|
; {| RenameVar :
RenameArgs
; |[ function <id>(<*id>) <id> = <rn> ]| |}
<+ all(rn))
http://www.strategoxt.org
Scoped Dynamic Rewrite Rules
15. Bound Variable Renaming
RenameVarDec :
|[ var x ta := e ]| -> |[ var y ta := e ]|
where <NewVar> x => y
RenameFor :
|[ for x := e1 to e2 do e3 ]| ->
|[ for y := e1 to e2 do e3 ]|
where <NewVar> x => y
RenameArgs :
|[ function f(x1*) ta = e ]| ->
|[ function f(x2*) ta = e ]|
where <map(FArg|[ <NewVar> : <id> ]|)> x1* => x2*
NewVar :
x -> y where new => y
; rules( RenameVar : |[ x ]| -> |[ y ]| )
http://www.strategoxt.org
Scoped Dynamic Rewrite Rules
16. Function Inlining
let function fact(n : int) : int =
let function f(n : int, acc : int) : int =
(while n > 0 do
(acc := acc * n; n := n - 1)
; acc)
in f(n, 1) end
in fact(10) end
⇓
let var n : int := 10
var b : int := n
var acc : int := 1
in while b > 0 do
(acc := acc * b;
b := b - 1);
acc end
http://www.strategoxt.org
Scoped Dynamic Rewrite Rules
17. Function Inlining
inline = inline-call <+ inline-let <+ inline-fundecs
<+ all(inline)
inline-call = UnfoldCall; exprename; inline
inline-let = |[ let <*id> in <*id> end ]|
; {| UnfoldCall : all(inline) |}
inline-fundecs =
|[ <fd*: map(if is-inlineable
then define-unfold
else undefine-unfold end)
; map(inline)
; filter(if is-inlineable
then define-fold; fail
else undefine-unfold end)> ]|
http://www.strategoxt.org
Scoped Dynamic Rewrite Rules
18. Function Inlining
define-unfold =
?|[ function f(x*) ta = e ]|
; rules(
UnfoldCall :
|[ f(a*) ]| -> |[ let d* in e end ]|
where <zip(bind-arg)> (x*, a*) => d* )
bind-arg :
(FArg|[ x ta ]|, e) -> |[ var x ta := e ]|
undefine-unfold =
?|[ function f(x*) ta = e ]|
; rules( UnfoldCall :- |[ f(a*) ]|)
http://www.strategoxt.org
Scoped Dynamic Rewrite Rules
19. Scope Labels – Constant Propagation with Local Variables
let var a := 1 var b := 2 var c := 3
in a := b + c;
let var c := a + 1
in b := b + c;
a := a + b;
b := z + b end;
a := c + b + a end
⇓
let var a := 1 var b := 2 var c := 3
in a := 5;
let var c := 6
in b := 8;
a := 13;
b := z + 8 end;
a := 3 + b + 13 end
http://www.strategoxt.org
Scoped Dynamic Rewrite Rules
20. Constant Propagation with Local Variables
prop-const = PropConst <+ prop-const-assign
<+ prop-const-let <+ prop-const-vardec
<+ all(prop-const); try(EvalBinOp <+ EvalRelOp)
prop-const-let =
|[ let <*id> in <*id> end ]|
; {| PropConst : all(prop-const) |}
prop-const-vardec =
|[ var x ta := <prop-const => e> ]|
; if <is-value> e
then rules( PropConst+x : |[ x ]| -> |[ e ]| )
else rules( PropConst+x :- |[ x ]| ) end
prop-const-assign =
|[ x := <prop-const => e> ]|
; if <is-value> e
then rules( PropConst.x : |[ x ]| -> |[ e ]| )
else rules( PropConst.x :- |[ x ]| ) end
http://www.strategoxt.org
Scoped Dynamic Rewrite Rules