Successfully reported this slideshow.

Strategies for Rule-Based Program Transformation

1,002 views

Published on

Slides for invited talk at Seminar on Transformation Techniques in Software Engineering held in Dagstuhl in April 2005.

Published in: Technology
  • Be the first to comment

  • Be the first to like this

Strategies for Rule-Based Program Transformation

  1. 1. Strategies for Rule-Based Program Transformation Software Engineering Techniques for Program Transformation Eelco Visser Center for Software Technology Department of Information & Computing Sciences Faculty of Science Utrecht University The Netherlands April 18, 2005 Dagstuhl Seminar Transformation Techniques in Software Engineering
  2. 2. Sources A Survey of Strategies in Rule-Based Program Transformation Systems E. Visser (JSC 2005) Program Transformation with Stratego/XT E. Visser (DSPG’03) Program Transformation with Scoped Dynamic Rewrite Rules M. Bravenboer, A. van Dam, K. Olmos, and E. Visser (FI) Composing Source-to-Source Data-Flow Transformations with Rewriting Strategies and Dependent Dynamic Rewrite Rules K. Olmos and E. Visser. (CC’05)
  3. 3. Sources A Survey of Strategies in Rule-Based Program Transformation Systems E. Visser (JSC 2005) Program Transformation with Stratego/XT E. Visser (DSPG’03) Program Transformation with Scoped Dynamic Rewrite Rules M. Bravenboer, A. van Dam, K. Olmos, and E. Visser (FI) Composing Source-to-Source Data-Flow Transformations with Rewriting Strategies and Dependent Dynamic Rewrite Rules K. Olmos and E. Visser. (CC’05)
  4. 4. Sources A Survey of Strategies in Rule-Based Program Transformation Systems E. Visser (JSC 2005) Program Transformation with Stratego/XT E. Visser (DSPG’03) Program Transformation with Scoped Dynamic Rewrite Rules M. Bravenboer, A. van Dam, K. Olmos, and E. Visser (FI) Composing Source-to-Source Data-Flow Transformations with Rewriting Strategies and Dependent Dynamic Rewrite Rules K. Olmos and E. Visser. (CC’05)
  5. 5. Outline 1 Program Transformation 2 Transformation Rules 3 Transformation Strategies 4 Dynamic Rules
  6. 6. Part IProgram Transformation
  7. 7. Computing with Programs Program transformation is the domain of computing where programs are the data
  8. 8. Improving Programs Program transformation is the mechanical manipulation of a program in order to improve it relative to some cost function C such that C (tr (P)) < C (P) [Pettorossi 1996]
  9. 9. Improving Programs Program transformation is the mechanical manipulation of a program in order to improve it relative to some cost function C such that C (tr (P)) < C (P) [Pettorossi 1996] Dimensions of improvement Performance Maintainability Memory usage Portability Understandability Correctness Flexibility Satisfaction of requirements
  10. 10. Application: Software Development Software development is concerned with transformation from requirements to specification to implementation
  11. 11. Application: Software Development Software development is concerned with transformation from requirements to specification to implementation Supporting abstraction
  12. 12. Application: Software Development Software development is concerned with transformation from requirements to specification to implementation Supporting abstraction Approaches have varying degrees of automation
  13. 13. Application: Software Development Transformational programming [Partsch 1986, Feather 1987] Formal development of implementations from specifications Properties Mechanizable and traceable ‘Correct by construction’ Fold/Unfold [Burstall & Darlington 1977] Calculating efficient programs from general ones Application-specific Program refinement [Green, Paige, Smith, ...] Kids: Specialization of solution theories to domain theories Pragmas [Peyton Jones et al. 2001] Programmer directives to compiler Draco, Popart, CIP, ...
  14. 14. Application: Software Development Compilation [ASU 1986, ...] Fully automatic transformation from high-level language to low-level language Instruction selection [Fraser et al. 1992] cost-driven translation from IR to machine instructions Compilation by transformation [Peyton Jones & Santos 1998] compilation as sequence of small transformation steps Program optimization [Appel 1998, Muchnik 1997, ...] improve run-time, memory usage, power consumption inlining, constant propagation, dead code elimination, ... Application generation [Smaragdakis & Batory 2000] Compilation for domain-specific languages
  15. 15. Application: Software Evolution Software evolution is concerned with the understanding and maintenance of existing legacy programs
  16. 16. Application: Software Evolution Software evolution is concerned with the understanding and maintenance of existing legacy programs Recovering abstractions
  17. 17. Application: Software Evolution Software evolution is concerned with the understanding and maintenance of existing legacy programs Recovering abstractions Reverse Engineering [Chikofski & Cross 1990, V.d. Brand et al. 1997] Extract from a low-level program a high-level program or specification Decompilation Architecture extraction Documentation generation Software Visualization
  18. 18. Application: Software Evolution Software Renovation Change the extensional behaviour of a program Error repair (Y2K) Changing requirements (Euro) Refactoring [Fowler 1999] improving the design of existing programs Obfuscation [Collberg et al. 1998] make a program harder to understand Migration Transformation to another language at the same level of abstraction Dialect upgrading Porting (Pascal to C, Java to C#)
  19. 19. Realizing Program Transformations Transformations are useful in software engineering if they are Correct Reproducable Automatic Scalable
  20. 20. Realizing Program Transformations Transformations are useful in software engineering if they are Correct Reproducable Automatic Scalable How to compose transformation systems that have these properties?
  21. 21. Realizing Program Transformations Transformations are useful in software engineering if they are Correct Reproducable Automatic Scalable How to compose transformation systems that have these properties? What are the right abstractions for building transformation systems?
  22. 22. Realizing Program Transformations Transformations are useful in software engineering if they are Correct Reproducable Automatic Scalable How to compose transformation systems that have these properties? What are the right abstractions for building transformation systems? Goal A component-based approach to program transformation in which basic transformation components can be reused in many different compositions.
  23. 23. Program Transformation Mechanics Basic Components Transformation rule: one step transformation of part of a program
  24. 24. Program Transformation Mechanics Basic Components Transformation rule: one step transformation of part of a program Perspective A high-level, language parametric, rule-based program transformation system, which supports a wide range of transformations, admitting efficient implementations that scale to large programs
  25. 25. Program Transformation Mechanics Basic Components Transformation rule: one step transformation of part of a program Perspective A high-level, language parametric, rule-based program transformation system, which supports a wide range of transformations, admitting efficient implementations that scale to large programs Practice Many different systems with different trade-offs expressivity of rule specification strategies for control efficiency of implementation object languages supported range of transformations
  26. 26. Architecture of Transformation Systems program program parse pretty-print transform transform tree tree tree
  27. 27. Part II Transformation Rules1 Program Transformation2 Transformation Rules3 Transformation Strategies4 Dynamic Rules
  28. 28. Example: Desugaring for i := 1 to n do for j := 1 to n do c[i,j] := sum k = 1 to n (a[i,k] * b[k,j])
  29. 29. Example: Desugaring for i := 1 to n do for j := 1 to n do c[i,j] := sum k = 1 to n (a[i,k] * b[k,j]) for i := 1 to n do for j := 1 to n do c[i,j] := let var d := 0 in for k := 1 to n do d := d + a[i,k] * b[k,j]; d end
  30. 30. Example: Desugaring for i := 1 to n do for j := 1 to n do c[i,j] := sum k = 1 to n (a[i,k] * b[k,j]) for i := 1 to n do for j := 1 to n do c[i,j] := let var d := 0 in for k := 1 to n do d := d + a[i,k] * b[k,j]; d end let var d in for i := 1 to n do for j := 1 to n do (d := 0; for k := 1 to n do d := d + a[i,k] * b[k,j]; c[i,j] := d) end
  31. 31. Programs as Terms Abstract Syntax Programs can be represented as terms sum k = 1 to n (a[i,k] * b[k,j]) ⇓ Sum([Index("k",Int("1"),Var("n"))], Times(Subscript(Var("a"),[Var("i"),Var("k")]), Subscript(Var("b"),[Var("k"),Var("j")])))
  32. 32. Patterns Term patterns can be used to analyze and compose programs Sum([idx | idx*], e) matches Sum([Index("k",Int("1"),Var("n"))], Times(Subscript(Var("a"),[Var("i"),Var("k")]), Subscript(Var("b"),[Var("k"),Var("j")])))
  33. 33. Rewrite Rules SumSplit : Sum([idx | idx*], e) -> Sum([idx], Sum(idx*, e)) where <not([])> idx* DefSum : Sum([Index(x, e1, e2)], e3) -> Let([VarDec(y, NoTp(), Int("0"))], [For(Var(x), e1, e2, Assign(Var(y), Plus(Var(y), e3))), Var(y)]) where new => y LetFromAssign : Assign(lv, Let(d*, e*)) -> Let(d*, [Assign(lv, Seq([e*]))])
  34. 34. Term Rewriting Term rewriting = normalization with respect to a set of rules normalization = exhaustive application normal form : no sub-term can be rewritten
  35. 35. Patterns in Concrete Syntax Problem: terms are hard to read, especially larger terms Observation: one-to-one correspondence between abstract syntax and concrete syntax Solution: use concrete syntax for patterns SumSplit : |[ sum idx; idx* (e) ]| -> |[ sum idx(sum idx*(e)) ]| where <not([])> idx* DefSum : |[ sum x = e1 to e2 ( e3 ) ]| -> |[ let var y := 0 in for x := e1 to e2 do y := y + e3 ; y end ]| where new => y
  36. 36. Systems that support Term Rewriting OBJ ASF+SDF Elan Maude TXL DMS ...
  37. 37. Extensions of Term Rewriting Matching modulo equations Associative, commutative, identity, ... List matching Combinations: A, AC, ACI, AI Object variable bindings De Bruijn indices Higher-order abstract syntax FreshML
  38. 38. Part IIITransformation Strategies 1 Program Transformation 2 Transformation Rules 3 Transformation Strategies 4 Dynamic Rules
  39. 39. Example: Compilation by Transformation sum k = 1 to n a_0 := 0; (a[i,k] * b[k,j]) for k := 1 to n do (t_1 := a[i,k]; a_0 := 0; t_2 := b[k,j]; k := 1; t_0 := t_1 * t_2; d_0 := n; a_0 := a_0 + t_0) t_3 := k <= d_0; label f_0; a_0 := 0; i_0 := not(t_3); k := 1; if i_0 goto g_0; d_0 := n; t_1 := a[i,k]; t_3 := k <= d_0; t_2 := b[k,j]; while t_3 do t_0 := t_1 * t_2; (t_1 := a[i,k]; a_0 := a_0 + t_0; t_2 := b[k,j]; k := k + 1; t_0 := t_1 * t_2; t_3 := k <= d_0; a_0 := a_0 + t_0; goto f_0; k := k + 1; label g_0 t_3 := k <= d_0)
  40. 40. Controlling Application of Rules Limitations of Term Rewriting Non-Termination Exhaustive application may not terminate Non-Confluence There may be diverging paths in rewrite relation Non-Selection All rules are applied everywhere Program transformation requires control over application of rules
  41. 41. Controlling Application of Rules Common Solution: Functional Rewriting Use extra constructors (called ‘functions’) to define control-point Traversal overhead: one rule for each constructor Tangling of rules and strategy: rules not reusable Compile(e) -> CollectDecls(SimpleExpressions(ForToWhile(Desugar(e)))) Desugar(|[ sum idx; idx+ (e) ]|) -> Desugar(|[ sum idx(sum idx+ (e)) ]|) Desugar(|[ sum x = e1 to e2 ( e3 ) ]|) -> Desugar(|[ ... ]| Desugar(|[ let d1* in e1* ]|) -> |[ let d2* in e2* ]| where Desugar(d1*) => d2*; Desugar(e1*) => e2*
  42. 42. Controlling Application of Rules Strategic Control Application of rules controlled by strategies Select rules and strategy Separation of rules and strategies reuse of rules in multiple transformations instantiate strategies with different rules TAMPR [Boyle et al. 1997] Transformation Assisted Multiple Program Realization Normalization with selection of rules Sequence of normal forms: divide transformation in stages Similar to layered graph grammars?
  43. 43. Staged Transformation compile = for-with-while ; return-value ; mark-procedure-calls ; simple-expressions ; control-flow-to-goto Compilation by sequence of ; collect-declarations transformations ; use-return-register ; vars-on-stack ; add-stack-machine ; flatten-sequences ; unmark-procedure-calls for-with-while = topdown(try(ForToWhile)) simple-expressions = innermost(Simplify <+ LiftNonAtomicArgument <+ Desugar <+ LetSplit)
  44. 44. Controlling Application of Rules Strategic Rewriting [Luttik & Visser 1997] Application of rules controlled by strategies Select rules and strategy Separation of rules and strategies reuse of rules in multiple transformations instantiate strategies with different rules Strategies are composed using strategy combinators Generic traversal reduces traversal overhead
  45. 45. Controlling Application of Rules Strategic Rewriting [Luttik & Visser 1997] Application of rules controlled by strategies Select rules and strategy Separation of rules and strategies reuse of rules in multiple transformations instantiate strategies with different rules Strategies are composed using strategy combinators Generic traversal reduces traversal overhead Strategic Programming [Laemmel, Visser & Visser 2003] Language independent paradigm for programming with strategies, in particular, generic traversals. Instantiated for rewriting, logic programming, functional programing, object-oriented programming
  46. 46. Sequential Composition Sequential Composition Syntax: s1 ; s2 Apply s1 , then s2 Fails if either s1 or s2 fails Variable bindings are propagated Plus(Var("a"),Int("3")) stratego> ?Plus(e1, e2); !Plus(e2, e1) Plus(Int("3"),Var("a"))
  47. 47. Deterministic Choice Deterministic Choice (Left Choice) Syntax: s1 < 2 +s First apply s1 , if that fails apply s2 Note: local backtracking PlusAssoc : Plus(Plus(e1, e2), e3) -> Plus(e1, Plus(e2, e3)) EvalPlus : Plus(Int(i),Int(j)) -> Int(k) where <addS>(i,j) => k Plus(Int("14"),Int("3")) stratego> PlusAssoc command failed stratego> PlusAssoc <+ EvalPlus Int("17")
  48. 48. Identity and Failure Identity Failure Syntax: id Syntax: fail Always succeed Always fail Some laws Some laws id ; s ≡ s fail <+ s ≡ s s ; id ≡ s s <+ fail ≡ s id <+ s ≡ id fail ; s ≡ fail s <+ id ≡ s s ; fail ≡ fail Defined Combinators try(s) = s <+ id repeat(s) = try(s; repeat(s)) while(c, s) = if c then s; while(c,s) end do-while(s, c) = s; if c then do-while(s, c) end
  49. 49. Traversal Traversal Styles Full traversal Folds: functional programming Visitors: object-oriented programming Strategic programming One-level traversal combinator descend to direct subterms Combine into multiple full traversal strategies Flavours Congruence operator: specific for signature Generic: independent of signature
  50. 50. Traversal Strategies Visiting All Subterms Syntax: all(s) Apply strategy s to all direct sub-terms Plus(Int("14"),Int("3")) stratego> all(!Var("a")) Plus(Var("a"),Var("a"))
  51. 51. Traversal Strategies Visiting All Subterms Syntax: all(s) Apply strategy s to all direct sub-terms Plus(Int("14"),Int("3")) stratego> all(!Var("a")) Plus(Var("a"),Var("a")) bottomup(s) = all(bottomup(s)); s topdown(s) = s; all(topdown(s)) downup(s) = s; all(downup(s)); s alltd(s) = s <+ all(alltd(s)) innermost(s) = bottomup(try(s; innermost(s)))
  52. 52. Traversal Strategies Visiting All Subterms Syntax: all(s) Apply strategy s to all direct sub-terms Plus(Int("14"),Int("3")) stratego> all(!Var("a")) Plus(Var("a"),Var("a")) bottomup(s) = all(bottomup(s)); s topdown(s) = s; all(topdown(s)) downup(s) = s; all(downup(s)); s alltd(s) = s <+ all(alltd(s)) innermost(s) = bottomup(try(s; innermost(s))) for-with-while = topdown(try(ForToWhile)) simple-expressions = innermost(Simplify <+ LiftNonAtomicArgument <+ Desugar <+ LetSplit)
  53. 53. Traversal Strategies Congruence Operator: Data-type Specific Traversal Syntax: c(s1 ,...,sn ) for each n-ary constructor c Apply strategies to direct sub-terms of a c term Plus(Int("14"),Int("3")) stratego> Plus(!Var("a"), id) Plus(Var("a"),Int("3")) mark-procedure-calls = rec mark( alltd( Assign(id, id) <+ While(id, mark) <+ For(id, id, id, mark) <+ If(id, mark, mark) <+ VarDec(id, id, id) <+ !Proc(<Call(id,id)>)))
  54. 54. History of Strategies A Slice of History LCF etc: tactics in theorem provers ASF+SDF language processing environment: rewriting (later added traversal functions) Rewriting logic ELAN specification system: rewriting & strategy expressions Stratego: generic traversal & dynamic rules Strafunski: generic traversal in Haskell JJTraveler: visitor combinators in Java Other Slices TXL: generic traversal function DMS ...
  55. 55. Part IV Dynamic Rules1 Program Transformation2 Transformation Rules3 Transformation Strategies4 Dynamic Rules
  56. 56. Context-Sensitive Transformations Problem: Rewrite Rules are Context-free Rewrite rules can only access information in term that is matched
  57. 57. Context-Sensitive Transformations Problem: Rewrite Rules are Context-free Rewrite rules can only access information in term that is matched Many Transformations are Context-Sensitive Constant propagation Copy propagation Common-subexpression elimination Partial evaluation Function inlining Dead code elimination
  58. 58. Context-Sensitive Transformations Problem: Rewrite Rules are Context-free Rewrite rules can only access information in term that is matched Many Transformations are Context-Sensitive Constant propagation Copy propagation Common-subexpression elimination Partial evaluation Function inlining Dead code elimination Solution: Dynamic Rewrite Rules Define rewrite rules during transformation
  59. 59. Constant Folding Constant folding y := x * (3 + 4) ⇒ y := x * 7 Constant folding rules EvalAdd : | i + j ] -> | k ] where <add>(i, j) => k [ | [ | EvalMul : | i * j ] -> | k ] where <mul>(i, j) => k [ | [ | AddZero : | 0 + e ] -> | e ] [ | [ |
  60. 60. Constant Folding Constant folding y := x * (3 + 4) ⇒ y := x * 7 Constant folding rules EvalAdd : | i + j ] -> | k ] where <add>(i, j) => k [ | [ | EvalMul : | i * j ] -> | k ] where <mul>(i, j) => k [ | [ | AddZero : | 0 + e ] -> | e ] [ | [ | Constant folding strategy (bottom-up) EvalBinOp = EvalAdd < AddZero < EvalMul < EvalOther + + + try(s) = s < id + constfold = all(constfold); try(EvalBinOp)
  61. 61. Defining and Undefining Rules Dynamically Constant Propagation and Folding in Straight-Line Code b := 1; c := b + 3; b := foo(); a := b + c prop-const = PropConst < prop-const-assign + < (all(prop-const); try(EvalBinOp)) + prop-const-assign = | x := <prop-const => e> ] [ | ; if <is-value> e then rules( PropConst : | x ] -> | e ] ) [ | [ | else rules( PropConst :- | x ] ) [ | end
  62. 62. Defining and Undefining Rules Dynamically Constant Propagation and Folding in Straight-Line Code b := 1; c := b + 3; b := foo(); a := b + c prop-const = PropConst < prop-const-assign + < (all(prop-const); try(EvalBinOp)) + prop-const-assign = | x := <prop-const => e> ] [ | ; if <is-value> e then rules( PropConst : | x ] -> | e ] ) [ | [ | else rules( PropConst :- | x ] ) [ | end
  63. 63. Defining and Undefining Rules Dynamically Constant Propagation and Folding in Straight-Line Code b := 1; c := b + 3; b := foo(); a := b + c prop-const = PropConst < prop-const-assign + < (all(prop-const); try(EvalBinOp)) + prop-const-assign = | x := <prop-const => e> ] [ | ; if <is-value> e then rules( PropConst : | x ] -> | e ] ) [ | [ | else rules( PropConst :- | x ] ) [ | end
  64. 64. Defining and Undefining Rules Dynamically Constant Propagation and Folding in Straight-Line Code b := 1; b -> 1 c := b + 3; b := foo(); a := b + c prop-const = PropConst < prop-const-assign + < (all(prop-const); try(EvalBinOp)) + prop-const-assign = | x := <prop-const => e> ] [ | ; if <is-value> e then rules( PropConst : | x ] -> | e ] ) [ | [ | else rules( PropConst :- | x ] ) [ | end
  65. 65. Defining and Undefining Rules Dynamically Constant Propagation and Folding in Straight-Line Code b := 1; b -> 1 c := b + 3; b := foo(); a := b + c prop-const = PropConst < prop-const-assign + < (all(prop-const); try(EvalBinOp)) + prop-const-assign = | x := <prop-const => e> ] [ | ; if <is-value> e then rules( PropConst : | x ] -> | e ] ) [ | [ | else rules( PropConst :- | x ] ) [ | end
  66. 66. Defining and Undefining Rules Dynamically Constant Propagation and Folding in Straight-Line Code b := 1; b -> 1 c := b + 3; b := foo(); a := b + c prop-const = PropConst < prop-const-assign + < (all(prop-const); try(EvalBinOp)) + prop-const-assign = | x := <prop-const => e> ] [ | ; if <is-value> e then rules( PropConst : | x ] -> | e ] ) [ | [ | else rules( PropConst :- | x ] ) [ | end
  67. 67. Defining and Undefining Rules Dynamically Constant Propagation and Folding in Straight-Line Code b := 1; b -> 1 c := 1 + 3; b := foo(); a := b + c prop-const = PropConst < prop-const-assign + < (all(prop-const); try(EvalBinOp)) + prop-const-assign = | x := <prop-const => e> ] [ | ; if <is-value> e then rules( PropConst : | x ] -> | e ] ) [ | [ | else rules( PropConst :- | x ] ) [ | end
  68. 68. Defining and Undefining Rules Dynamically Constant Propagation and Folding in Straight-Line Code b := 1; b -> 1 c := 1 + 3; b := foo(); a := b + c prop-const = PropConst < prop-const-assign + < (all(prop-const); try(EvalBinOp)) + prop-const-assign = | x := <prop-const => e> ] [ | ; if <is-value> e then rules( PropConst : | x ] -> | e ] ) [ | [ | else rules( PropConst :- | x ] ) [ | end
  69. 69. Defining and Undefining Rules Dynamically Constant Propagation and Folding in Straight-Line Code b := 1; b -> 1 c := 4; b := foo(); a := b + c prop-const = PropConst < prop-const-assign + < (all(prop-const); try(EvalBinOp)) + prop-const-assign = | x := <prop-const => e> ] [ | ; if <is-value> e then rules( PropConst : | x ] -> | e ] ) [ | [ | else rules( PropConst :- | x ] ) [ | end
  70. 70. Defining and Undefining Rules Dynamically Constant Propagation and Folding in Straight-Line Code b := 1; b -> 1 c := 4; b := foo(); a := b + c prop-const = PropConst < prop-const-assign + < (all(prop-const); try(EvalBinOp)) + prop-const-assign = | x := <prop-const => e> ] [ | ; if <is-value> e then rules( PropConst : | x ] -> | e ] ) [ | [ | else rules( PropConst :- | x ] ) [ | end
  71. 71. Defining and Undefining Rules Dynamically Constant Propagation and Folding in Straight-Line Code b := 1; c := 4; b -> 1 & c -> 4 b := foo(); a := b + c prop-const = PropConst < prop-const-assign + < (all(prop-const); try(EvalBinOp)) + prop-const-assign = | x := <prop-const => e> ] [ | ; if <is-value> e then rules( PropConst : | x ] -> | e ] ) [ | [ | else rules( PropConst :- | x ] ) [ | end
  72. 72. Defining and Undefining Rules Dynamically Constant Propagation and Folding in Straight-Line Code b := 1; c := 4; b -> 1 & c -> 4 b := foo(); a := b + c prop-const = PropConst < prop-const-assign + < (all(prop-const); try(EvalBinOp)) + prop-const-assign = | x := <prop-const => e> ] [ | ; if <is-value> e then rules( PropConst : | x ] -> | e ] ) [ | [ | else rules( PropConst :- | x ] ) [ | end
  73. 73. Defining and Undefining Rules Dynamically Constant Propagation and Folding in Straight-Line Code b := 1; c := 4; b := foo(); b - & c -> 4 a := b + c prop-const = PropConst < prop-const-assign + < (all(prop-const); try(EvalBinOp)) + prop-const-assign = | x := <prop-const => e> ] [ | ; if <is-value> e then rules( PropConst : | x ] -> | e ] ) [ | [ | else rules( PropConst :- | x ] ) [ | end
  74. 74. Defining and Undefining Rules Dynamically Constant Propagation and Folding in Straight-Line Code b := 1; c := 4; b := foo(); b - & c -> 4 a := b + c prop-const = PropConst < prop-const-assign + < (all(prop-const); try(EvalBinOp)) + prop-const-assign = | x := <prop-const => e> ] [ | ; if <is-value> e then rules( PropConst : | x ] -> | e ] ) [ | [ | else rules( PropConst :- | x ] ) [ | end
  75. 75. Defining and Undefining Rules Dynamically Constant Propagation and Folding in Straight-Line Code b := 1; c := 4; b := foo(); b - & c -> 4 a := b + 4 prop-const = PropConst < prop-const-assign + < (all(prop-const); try(EvalBinOp)) + prop-const-assign = | x := <prop-const => e> ] [ | ; if <is-value> e then rules( PropConst : | x ] -> | e ] ) [ | [ | else rules( PropConst :- | x ] ) [ | end
  76. 76. Defining and Undefining Rules Dynamically Constant Propagation and Folding in Straight-Line Code b := 1; c := 4; b := foo(); a := b + 4 b - & c -> 4 & a - prop-const = PropConst < prop-const-assign + < (all(prop-const); try(EvalBinOp)) + prop-const-assign = | x := <prop-const => e> ] [ | ; if <is-value> e then rules( PropConst : | x ] -> | e ] ) [ | [ | else rules( PropConst :- | x ] ) [ | end
  77. 77. Properties of Dynamic Rules Rules are defined dynamically Carry context information Multiple rules with same name can be defined Rules can be undefined Rules with same left-hand side override old rules
  78. 78. Properties of Dynamic Rules Rules are defined dynamically Carry context information Multiple rules with same name can be defined Rules can be undefined Rules with same left-hand side override old rules b := 3; b -> 3 ... b -> 3 b := 4; b -> 4
  79. 79. Flow-Sensitive Transformations Flow-Sensitive Constant Propagation (x := 3; (x := 3; y := x + 1; y := 4; if foo(x) then if foo(3) then (y := 2 * x; (y := 6; x := y - 2) x := 4) else else (x := y; (x := 4; y := 23); y := 23); z := x + y) z := 4 + y)
  80. 80. Flow-Sensitive Transformations x := 3 x := 3 x -> 3 Flow-Sensitive Constant Propagation y := x + 1 y := 4 x -> 3 y -> 4 (x := 3; (x := 3; if foo(x) y := x + 1; y := 4; if foo(3) if foo(x) then if foo(3) then x -> 3 x -> 3 y -> 4 y -> 4 (y := 2 * x; (y := 6; y := 2 * x x := y x := y - 2) x := 4) y := 6 x := 4 else else x -> 3 x -> 4 (x := y; (x := 4; y -> 6 y -> 4 y := 23); y := 23); x := y - 2 y := 23 x := 4 y := 23 z := x + y) z := 4 + y) x -> 4 x -> 4 y -> 6 y -> 23 fork rule sets and combine at merge point x -> 4 y - z := x + y z := 4 + y
  81. 81. Constant propagation in abstract syntax tree ; x -> 3 x := 3 ; x := 3 x -> 3 x -> 3 y -> 4 y := x + 1 ; y := 4 x -> 3 x -> 4 y -> 4 y - if foo(x) z := x + y if foo(3) z := 4 + y x -> 3 x -> 3 y -> 4 y -> 4 ; ; x -> 3 x -> 3 x -> 3 x -> 4 y -> 4 y -> 6 y -> 4 y -> 4 y := 2 * x x := y - 2 x := y y := 23 y := 6 x := 4 x := 4 y := 23
  82. 82. Forking and Intersecting Dynamic Rulesets Flow-sensitive Constant Propagation prop-const-if = | if <prop-const> then <id> else <id> ] [ | ; (| [if <id> then <prop-const> else <id>]| /PropConst | [if <id> then <id> else <prop-const>] |) s1 /R s2 : fork and intersect
  83. 83. Propagation through Loops (a := 1; (a := 1; i := 0; i := 0; while i < m do ( while i < m do ( j := a; j := 1; a := f(); ⇒ a := f(); a := j; a := 1; i := i + 1 i := i + 1 ); ); print(a, i, j)) print(1, i, j))
  84. 84. Fixpoint Iteration Flow-sensitive Constant Propagation prop-const-while = ?| while e1 do e2 ] [ | ; (/PropConst* |[while <prop-const> do <prop-const>] |) /R* s ≡ ((id /R s) /R s) /R ...) until fixedpoint of ruleset is reached
  85. 85. Fixpoint Iteration Flow-sensitive Constant Propagation prop-const-while = ?| while e1 do e2 ] [ | ; (/PropConst* |[while <prop-const> do <prop-const>] |) /R* s ≡ ((id /R s) /R s) /R ...) until fixedpoint of ruleset is reached prop-const-while terminates: fewer rules defined each iteration
  86. 86. Combining Analysis and Transformation Unreachable code elimination i := 1; j := 2; i := 1; if j = 2 ⇒ j := 2; then i := 3; i := 3; else z := foo() print(3) print(i)
  87. 87. Combining Analysis and Transformation Unreachable code elimination i := 1; j := 2; i := 1; if j = 2 ⇒ j := 2; then i := 3; i := 3; else z := foo() print(3) print(i) EvalIf : | if 0 then e1 else e2 ] -> | e2 ] [ | [ | EvalIf : | if i then e1 else e2 ] -> | e1 ] [ | [ | where <not(eq)>(i,| |) [0]
  88. 88. Combining Analysis and Transformation Unreachable code elimination i := 1; j := 2; i := 1; if j = 2 ⇒ j := 2; then i := 3; i := 3; else z := foo() print(3) print(i) EvalIf : | if 0 then e1 else e2 ] -> | e2 ] [ | [ | EvalIf : | if i then e1 else e2 ] -> | e1 ] [ | [ | where <not(eq)>(i,| |) [0] prop-const-if = | if <prop-const> then <id> else <id> ] [ |; (EvalIf; prop-const < (| + [if <id> then <prop-const> else <id>] /PropConst | | [if <id> then <id> else <prop-const>] |))
  89. 89. Combining Analysis and Transformation Unreachable code elimination (x := 10; while A do (x := 10; if x = 10 then dosomething() ⇒ while A do dosomething(); else (dosomethingelse(); y := 10) x := x + 1); y := x) Conditional Constant Propagation [Wegman & Zadeck 1991] Graph analysis + transformation in Vortex [Lerner et al. 2002]
  90. 90. Dependent Dynamic Rules Dependent Dynamic Rules Record all dependencies of dynamic rules in order to undefine all rules depending on a dependency Use to define generic data-flow strategies Common-subexpression elimination cse = forward-prop(fail, id, cse-after | ["CSE"], [], []) cse-assign = ?| x := e ] [ | ; where( <pure-and-not-trivial(|x)> | e ] ) [ | ; where( get-var-dependencies => xs ) ; rules( CSE : | e ] -> | x ] depends on xs ) [ | [ | cse-after = try(cse-assign < CSE) +
  91. 91. Combining Transformations super-opt = forward-prop( prop-const-transform , bvr-before , bvr-after; copy-prop-after ; prop-const-after; cse-after | ["PropConst", "CopyProp", "CSE"] , [] , ["RenameVar"] ) Apply multiple data-flow transformations simultaneously
  92. 92. Experience with Dynamic Rules Tiger compiler: sandbox for transformation techniques bound variable renaming, inlining, constant propagation, copy propagation, common-subexpression elimination, dead assignment elimination, partial redundancy elimination, online and offline partial evaluation, loop normalization, loop vectorization, ... Octave compiler type specialization, partial evaluation, other data-flow transformations, combined transformations, loop vectorization Stratego compiler inlining, specialization, bound-unbound variables analysis, aspect weaving, ... LVM optimizer (functional) substitutions, inlining, (deforestation, warm fusion) Java Compiler name disambiguation, type propagation, assimilation of embedded domain-specific languages
  93. 93. Other Approaches to Context-Sensitive Transformation Environments explicit threading dynamic rules abstract over environments, symbol tables, etc. Attribute grammars implicit scheduling of attribute evaluation (declarative) incremental evaluation: interaction between analysis and transformation Graph transformations Regular path queries [De Moor et al 2004] Side conditions are regular expressions over execution paths reaching this node
  94. 94. Conclusion Programmable rewriting strategies and dynamic rules Small set of abstractions Supports a wide range of transformations For a wide range of languages
  95. 95. Challenges Integration equational matching object variable bindings regular path queries (De Moor) combining rewriting and attribute grammars (JastAdd; Hedin) Extensibility of transformation systems domain-/application-specific optimization plugins language extensions and embeddings Higher level abstractions for transformation make transformations available to programmers capture class of transformations for specific language compile to strategies example: aspects
  96. 96. Expectations I’m always looking for new transformation problems to apply transformation strategies to and interested in subsuming cool transformation mechanisms
  97. 97. The End

×