Context-Sensitive Transformation
                         Lecture 8



                                               Cour...
Syntax
                                        Definition




                                                            P...
Coming up
Lecture 8: Context-sensitive transformation
   ★ design 2
   ★ transformation with dynamic rewrite rules

Lectur...
Outline


Design 2
   ★ designing a domain-specific language

Context-sensitive transformation
   ★ global-to-local, local-...
Design 2
Build your own DSL
Design 2: Purpose


Design a domain-specific language
Domain analysis
   ★ find abstractions in an existing programming doma...
Design 2: Ingredients


Syntax definition
   ★ elegant and efficient notation for a domain

Model transformation
   ★ reduce...
Design 2: Considerations

Type system
   ★ do you catch errors at compile-time (in the IDE)?

Customization
   ★ can appli...
Design 2: Inductive (bottom-up) design



Finding abstractions
Identify coding patterns
   ★ are there standard patterns i...
Design 2: Examples

Improve existing language
-   Software building DSL generating ANT

-   XML transformation DSL generat...
JavaSwul
import javax.swing.*;
import java.awt.*;

public class Test3 {
  public static void main(String[] ps) {
         ...
private String[] initAddressList() {
             contactList.setContainerDataSource(addressBookData);


Vaadin
          ...
Design 2: Advice

Choosing a domain
-   choose a domain that you know or are interested to learn

Agile software developme...
Model Transformation
Compilation by Normalization
Types of Model Transformation

Reduction to sub-language
   ★ Normalization
   ★ Desugaring
   ★ Optimization
   ★ Aspect ...
Term Rewriting
Term Rewriting



Term rewrite rules
   ★ transform term to term
   ★ pattern matching
   ★ variable binding
   ★ substitu...
Term Rewrite Rule


                         left-hand side pattern
label/name



      desugar :
        Property(x, t) -...
Rewrite Strategy


                                  generic strategy
strategy definition



     desugar-all = innermost(d...
Constant Folding
y := a + (3 * 5 - 17);


        Assign(
          Var("y")
        , Plus(
            Var("a")
        ...
Constant Folding Rules

strategies

 eval-all = innermost(desugar + eval)

rules

 eval :
   BinOp(IntLit(x), "+", IntLit(...
Conditional Rewrite Rules

                                    bound in condition

            eval :
              BinOp(...
Context-sensitive
 Transformation
define page blog(b : Blog) {
       Template Inlining                   header{output(b.name)}
                           ...
Context-sensitive Transformation



Local-to-local
   ★ replace term by another term

Local-to-global
   ★ local term influ...
define page blog(b : Blog) {
                                           header{output(b.name)}
                           ...
Inlining as Rewrite Problem




outputPost(p) -> navigate post(p) { output(p.name) }
where define outputPost(pst : Post) {...
Rewrite Rules are Context-free




desugar :
  Property(x, t) -> Property(x, t, [])
Simplification: Parameterless Templates


                                define page blog(b : Blog) {
                    ...
Rewrite in Context



Inline :
  [def@TemplateDef(f,[],elem1*) | def1*] -> [def | def2*]
  where def2* := <alltd((Call(f) ...
Intermezzo:
Rewriting Strategies
transformation
                              is
partial* function from terms to terms


          * transformation may fai...
Defining Transformations: Rules & Strategies


Rewrite rules are basic transformations
   ★ transform term matching lhs to ...
Strategy Combinators


id
     ★ Identity

fail
     ★ failure

s1 ; s2
     ★ sequential composition

s1 <+ s2
     ★ cho...
Variables
{x, y : s}
     ★ term variable scope

?t
     ★ match term pattern t

!t
     ★ build term pattern t

t1 := t2
...
Rewrite Rules




l : t1 -> t2 where s
  ★ named, scoped rewrite rule
  ★ all variables in t1, t2, s are in scope of the r...
Rewrite in Context



Inline :
  [def@TemplateDef(f,[],elem1*) | def1*] -> [def | def2*]
  where def2* := <alltd((Call(f) ...
Inline :
  [def@TemplateDef(f,[],elem*) | def1*] -> [def | def2*]
  where def2* := <alltd((Call(f) -> Call("container", el...
Strategy Definitions

f(x,y|a,b) = s
  ★ x, y are strategy parameters
  ★ a, b are term parameters
  ★ s uses all parameter...
Rules with Parameters

Transform all elements of a list
 map(s) : [] -> []

 map(s) : [x|xs] -> [<s>x | <map(s)> xs]


Inv...
Traversal Combinators



all(s)
  ★ apply s to all direct sub-terms (children)

one(s)
  ★ apply s to exactly one sub-term...
Traversal Strategies


topdown(s) = s; all(topdown(s))
  ★ apply s to all sub-terms in top-down order

bottomup(s) = all(b...
Rewrite in Context: Local Traversal



Inline :
  [def@TemplateDef(f,[],elem1*) | def1*] -> [def | def2*]
  where def2* :=...
Dynamic Rewrite Rules
Rewrite in Context: Not Optimal
Inline :
  [def@TemplateDef(f,[],elem1*) | def1*] -> [def | def2*]
  where def2* := <alltd...
Dynamic Rewrite Rules
Inline :
  [def@TemplateDef(f,[],elem1*) | def1*] -> [def | def2*]
  where def2* := <alltd((Call(f) ...
Inlining as Rewrite Problem (Revisited)


  outputPost(p) -> navigate post(p) { output(p.name) }
  where define outputPost...
define page blog(b : Blog) {
       Template Parameter                  header{output(b.name)}
                           ...
Inlining Templates with Parameters
declare-inline :
  def@TemplateDef(mod*,f,param*,elem1*) -> def
  where rules(
    Inli...
Element Parameters

              define list() { <ul> elements </ul> }




declare-inline :
  def@TemplateDef(mod*,f,para...
Removing Intermediate Structures



rules // remove containers

 desugar-container :
   [Call("container",[], elem1*) | el...
Inlining Strategy


module template-inlining

imports libstratego-lib
imports include/nwl
imports desugar

strategies

  i...
module template-inlining

                    imports libstratego-lib
                    imports include/nwl
            ...
Free Variable Capture
Free Variable Capture in Template Inlining
define page blogfront(b : Blog) {
  header{output(b.name)}
  list{
    for(p : ...
Free Variable Capture in Template Inlining
define page blogfront(b : Blog) {
  header{output(b.name)}
  list{
    for(p : ...
Free Variable Capture in Template Inlining


define page blogfront(b : Blog) {
  for(p : Post in b.posts) {
    postInline...
Avoiding Free Variable Capture

substitute-args :
  (param*, e*, elem1*) -> elem2*
  where {| Subst
         : <zip(bind-a...
Free Variable Capture in Template Inlining


define page blogfront(b : Blog) {
  for(p : Post in b.posts) {
    postInline...
Aspect Weaving
Aspect Weaving



Aspect definition
   ★ modular definition of cross cutting concerns

Aspect weaving
   ★ apply aspects to ...
Access Control Rules
define page post(p : Post) {
  header{output(p.title)}
  output(p.text)
  par{ "Posted by " outputUse...
Access Control Weaving
define page post(p : Post) {
  header{output(p.title)}
  output(p.text)
  par{ "Posted by " outputU...
Access Control Weaving: Protect Page
define page post(p : Post) {
  header{output(p.title)}
  output(p.text)
  par{ "Poste...
Access Control Weaving: Protect Link
define page post(p : Post) {
  header{output(p.title)}
  output(p.text)
  par{ "Poste...
Access Control Weaving: Strategy




weave-ac-rules =
	 alltd(declare-ac-rule);
	 bottomup(try(ProtectPage <+ ProtectNavig...
Access Control Weaving: Protect Navigate




declare-ac-rule :
	 r@Rule([Page()], f, param1*, e) -> r
	 where rules(
	    ...
Access Control Weaving: Protect Page


declare-ac-rule :
	 r@Rule([Page()], f, param1*, e) -> r
	 where rules(
     Protec...
Access Control Weaving: Complete*
    weave-ac-rules =
    	   alltd(declare-ac-rule);
    	   bottomup(try(ProtectPage <+...
Extend Entity

module blog

entity Post {
  url    : String (id)
  title : String (name)
  text   : WikiText
  blog   : Bl...
Extend Entity                           module woven

                                            entity Post {
          ...
Other Model
Transformations
Other Applications of Model Transformation

Refactoring
   ★ behaviour preserving transformation to improve design
   ★ e....
Schedule
Case 3
  ★ Syntax definition & term rewriting
  ★ Deadline:

Design 2
  ★ Make a proposal (can be submitted separa...
Upcoming SlideShare
Loading in …5
×

Model-Driven Software Development - Context-Sensitive Transformation

2,683 views
2,564 views

Published on

A lecture in the course on Model-Driven Software Development. Topic is context-sensitive transformation.

0 Comments
1 Like
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
2,683
On SlideShare
0
From Embeds
0
Number of Embeds
737
Actions
Shares
0
Downloads
45
Comments
0
Likes
1
Embeds 0
No embeds

No notes for slide

Model-Driven Software Development - Context-Sensitive Transformation

  1. 1. Context-Sensitive Transformation Lecture 8 Course IN4308 Eelco Visser Master Computer Science http://eelcovisser.org Delft University of Technology
  2. 2. Syntax Definition Pretty-Print Parse Table Signature Table Parse Transform Pretty-Print @Entity entity User { class User { name :: String String _user; pw :: Secret public User } getUser() { def output(u : syntax definition is basis of language definition return _user; User) { }
  3. 3. Coming up Lecture 8: Context-sensitive transformation ★ design 2 ★ transformation with dynamic rewrite rules Lecture 9: Static analysis & error checking ★ name resolution, reference resolution ★ type analysis Lecture 10: Code generation ★ string templates, code generation by model transformation ★ concrete object syntax Lecture 11: Code generation strategies ★ customization of generated code
  4. 4. Outline Design 2 ★ designing a domain-specific language Context-sensitive transformation ★ global-to-local, local-to-global Rewriting strategies ★ controlling the application of rules Dynamic rewrite rules ★ context-sensitive transformation with rewrite rules
  5. 5. Design 2 Build your own DSL
  6. 6. Design 2: Purpose Design a domain-specific language Domain analysis ★ find abstractions in an existing programming domain Language design ★ define a notation and translational semantics Language implementation ★ build IDE and code generator Understand tradeoffs in language design
  7. 7. Design 2: Ingredients Syntax definition ★ elegant and efficient notation for a domain Model transformation ★ reduce rich surface syntax to core language Static analysis ★ find errors during editing Code generation ★ generate complete implementation from models
  8. 8. Design 2: Considerations Type system ★ do you catch errors at compile-time (in the IDE)? Customization ★ can application developers work around lack of coverage? Native interface ★ how are models integrated with environment? Modularity ★ can models be broken down into smaller components? Incremental language processing
  9. 9. Design 2: Inductive (bottom-up) design Finding abstractions Identify coding patterns ★ are there standard patterns in programs in this domain Identify commonality ★ code generation templates Identify variability ★ language constructs
  10. 10. Design 2: Examples Improve existing language - Software building DSL generating ANT - XML transformation DSL generating XSLT Abstract from existing framework/library - DSL for Vaadin (http://vaadin.com) - Javascript widget DSL generating JQuery or Dojo - Game DSL generating Ogre C++ AndroidDSL - Generate Java for Android applications - Android & Nexus One phones available for experiments
  11. 11. JavaSwul import javax.swing.*; import java.awt.*; public class Test3 { public static void main(String[] ps) { import javax.swing.*; JFrame frame = frame { import java.awt.*; title = "Welcome!" public class Test3 content = panel of border layout { { public static void main(String[] ps) center = label { text = "Hello World" } { JButton jButton_1; south = panel of grid layout { JButton jButton_0; JPanel jPanel_1; row = { JLabel jLabel_0; button { text = "cancel" } JPanel jPanel_0; JFrame jFrame_0; button { text = "ok"} jFrame_0 = new JFrame(); jFrame_0.setTitle("Welcome!"); } jPanel_0 = new JPanel(); } BorderLayout borderLayout_0 = new BorderLayout(); jPanel_0.setLayout(borderLayout_0); } jFrame_0.setContentPane(jPanel_0); JFrame frame = jFrame_0; }; jLabel_0 = new JLabel(); jLabel_0.setText("Hello World"); frame.pack(); jPanel_0.add(jLabel_0, BorderLayout.CENTER); frame.setVisible(true); jPanel_1 = new JPanel(); GridLayout gridLayout_0 = new GridLayout(1, 2); } jButton_0 = new JButton(); jButton_0.setText("cancel"); } jButton_1 = new JButton(); jButton_1.setText("ok"); jPanel_1.setLayout(gridLayout_0); jPanel_1.add(jButton_0); jPanel_1.add(jButton_1); jPanel_0.add(jPanel_1, BorderLayout.SOUTH); frame.pack(); frame.setVisible(true); } }
  12. 12. private String[] initAddressList() { contactList.setContainerDataSource(addressBookData); Vaadin contactList.setVisibleColumns(visibleCols); contactList.setSelectable(true); contactList.setImmediate(true); contactList.addListener(new Property.ValueChangeListener() { public void valueChange(ValueChangeEvent event) { Object id = contactList.getValue(); contactEditor.setItemDataSource(id == null ? null : contactList .getItem(id)); contactRemovalButton.setVisible(id != null); } }); return visibleCols; } private void initFilteringControls() { for (final String pn : visibleCols) { final TextField sf = new TextField(); bottomLeftCorner.addComponent(sf); sf.setWidth("100%"); sf.setInputPrompt(pn); sf.setImmediate(true); bottomLeftCorner.setExpandRatio(sf, 1); sf.addListener(new Property.ValueChangeListener() { public void valueChange(ValueChangeEvent event) { addressBookData.removeContainerFilters(pn); if (sf.toString().length() > 0 && !pn.equals(sf.toString())) { addressBookData.addContainerFilter(pn, sf.toString(), true, false); } getMainWindow().showNotification( "" + addressBookData.size() + " matches found"); } }); } } private static IndexedContainer createDummyData() { String[] fnames = { "Peter", "Alice", "Joshua", "Mike", "Olivia", "Nina", "Alex", "Rita", "Dan", "Umberto", "Henrik", "Rene", "Lisa", "Marge" }; String[] lnames = { "Smith", "Gordon", "Simpson", "Brown", "Clavel", "Simons", "Verne", "Scott", "Allison", "Gates", "Rowling", "Barks", "Ross", "Schneider", "Tate" };
  13. 13. Design 2: Advice Choosing a domain - choose a domain that you know or are interested to learn Agile software development - identify iterations - minimize risks - create working version in first week and evolve Proposal - don’t get stuck on it - choose a domain and go
  14. 14. Model Transformation
  15. 15. Compilation by Normalization
  16. 16. Types of Model Transformation Reduction to sub-language ★ Normalization ★ Desugaring ★ Optimization ★ Aspect weaving ★ Instrumentation ★ Refactoring Translation to another language ★ Conversion ★ Migration ★ Compilation
  17. 17. Term Rewriting
  18. 18. Term Rewriting Term rewrite rules ★ transform term to term ★ pattern matching ★ variable binding ★ substitution Rewriting strategy ★ algorithm for applying rewrite rules
  19. 19. Term Rewrite Rule left-hand side pattern label/name desugar : Property(x, t) -> Property(x, t, []) variable right-hand side pattern
  20. 20. Rewrite Strategy generic strategy strategy definition desugar-all = innermost(desugar) strategy instantiation apply transformation s exhaustively to all sub- innermost(s) terms of subject term in bottom-up order
  21. 21. Constant Folding y := a + (3 * 5 - 17); Assign( Var("y") , Plus( Var("a") , Minus(Times(IntLit("3"), IntLit("5")), IntLit("17")) parse ) ) Assign( Var("y") , BinOp(Var("a"), "+", IntLit("25")) desugar + eval ) y := (a + 25); pretty-print
  22. 22. Constant Folding Rules strategies eval-all = innermost(desugar + eval) rules eval : BinOp(IntLit(x), "+", IntLit(y)) -> IntLit(<addS>(x, y)) eval : BinOp(IntLit(x), "-", IntLit(y)) -> IntLit(<subtS>(x, y)) eval : BinOp(IntLit(x), "*", IntLit(y)) -> IntLit(<mulS>(x, y)) eval : BinOp(IntLit(x), "/", IntLit(y)) -> IntLit(<divS>(x, y))
  23. 23. Conditional Rewrite Rules bound in condition eval : BinOp(IntLit(x), "+", IntLit(y)) -> IntLit(z) condition where z := <addS>(x, y) match apply transformation eval : BinOp(IntLit(x), "+", IntLit(y)) -> IntLit(<addS>(x, y))
  24. 24. Context-sensitive Transformation
  25. 25. define page blog(b : Blog) { Template Inlining header{output(b.name)} list{ for(p : Post in b.posts) { listitem{ outputPost(p) } } } } define outputPost(pst : Post) { navigate post(pst) { output(pst.name) } } define list() { <ul> elements </ul> } define listitem() { <li> elements </li> } define header() { <h1> elements </h1> } define page blog ( b : Blog ) { <h1> output(b.name) </h1> <ul> for ( p : Post in b.posts ) { <li> navigate post(p) { output(p.name) } </li> } </ul> }
  26. 26. Context-sensitive Transformation Local-to-local ★ replace term by another term Local-to-global ★ local term influence terms in other parts of model Global-to-local ★ global information influences transformation of local terms
  27. 27. define page blog(b : Blog) { header{output(b.name)} list{ for(p : Post in b.posts) { listitem{ outputPost(p) } } } Inlining is Global-to-Local } define outputPost(pst : Post) { navigate post(pst) { output(pst.name) } } define list() { <ul> elements </ul> } define listitem() { <li> elements </li> } define header() { <h1> elements </h1> } define page blog ( b : Blog ) { <h1> output(b.name) </h1> <ul> for ( p : Post in b.posts ) { <li> navigate post(p) { output(p.name) } </li> } </ul> }
  28. 28. Inlining as Rewrite Problem outputPost(p) -> navigate post(p) { output(p.name) } where define outputPost(pst : Post) { navigate post(pst) { output(pst.name) } } (this is not a valid Stratego rewrite rule)
  29. 29. Rewrite Rules are Context-free desugar : Property(x, t) -> Property(x, t, [])
  30. 30. Simplification: Parameterless Templates define page blog(b : Blog) { ... footer() } define footer() { navigate url(http://webdsl.org) { “WebDSL” } } define page blog ( b : Blog ) { ... container() { navigate url(http://webdsl.org) { “WebDSL” } } }
  31. 31. Rewrite in Context Inline : [def@TemplateDef(f,[],elem1*) | def1*] -> [def | def2*] where def2* := <alltd((Call(f) -> Call("container", elem1*)))> def1* local traversal bound in context container needed to replace single call with multiple elements
  32. 32. Intermezzo: Rewriting Strategies
  33. 33. transformation is partial* function from terms to terms * transformation may fail to apply to a term
  34. 34. Defining Transformations: Rules & Strategies Rewrite rules are basic transformations ★ transform term matching lhs to instantiation of rhs ★ evaluate condition (where clause) Strategies combine rules into complex transformations ★ select rules to apply ★ select algorithm to apply rules Strategy combinators ★ composition of custom transformations
  35. 35. Strategy Combinators id ★ Identity fail ★ failure s1 ; s2 ★ sequential composition s1 <+ s2 ★ choice
  36. 36. Variables {x, y : s} ★ term variable scope ?t ★ match term pattern t !t ★ build term pattern t t1 := t2 ★ match term t2 to term (pattern) t1 <s> t ★ apply strategy s to term t
  37. 37. Rewrite Rules l : t1 -> t2 where s ★ named, scoped rewrite rule ★ all variables in t1, t2, s are in scope of the rule (t1 -> t2 where s) ★ unscoped rewrite rule ★ variables are in scope of enclosing scope
  38. 38. Rewrite in Context Inline : [def@TemplateDef(f,[],elem1*) | def1*] -> [def | def2*] where def2* := <alltd((Call(f) -> Call("container", elem1*)))> def1* bound in context
  39. 39. Inline : [def@TemplateDef(f,[],elem*) | def1*] -> [def | def2*] where def2* := <alltd((Call(f) -> Call("container", elem*)))> def1* f elem* [ TemplateDef( "footer" , [] , [Navigate(PageRef("webdsl", []), [String("WebDSL")])] ) , TemplateDef( "blog" , [Param("b", SimpleType("Blog"))] , [Call("footer")] ) ] Call(f) def1*
  40. 40. Strategy Definitions f(x,y|a,b) = s ★ x, y are strategy parameters ★ a, b are term parameters ★ s uses all parameters f(x) = s f = s ★ term parameters are optional ★ all parameters are optional Examples ★ try(s) = s <+ id ★ repeat(s) = try(s; repeat(s))
  41. 41. Rules with Parameters Transform all elements of a list map(s) : [] -> [] map(s) : [x|xs] -> [<s>x | <map(s)> xs] Invert order of elements of a list inverse(|ys) : [] -> ys inverse(|ys) : [x|xs] -> <inverse(|[x|ys])> xs Pair elements of two lists zip(s) : ([],[]) -> [] zip(s) : ([x|xs],[y|ys]) -> [<s>(x,y) | <zip(s)>(xs,ys)]
  42. 42. Traversal Combinators all(s) ★ apply s to all direct sub-terms (children) one(s) ★ apply s to exactly one sub-term some(s) ★ apply s to at least one sub-term
  43. 43. Traversal Strategies topdown(s) = s; all(topdown(s)) ★ apply s to all sub-terms in top-down order bottomup(s) = all(bottomup(s)); s ★ apply s to all sub-terms in bottom-up order oncetd(s) = s <+ one(oncetd(s)) ★ apply s to one sub-term alltd(s) = s <+ all(alltd(s)) ★ apply s to frontier
  44. 44. Rewrite in Context: Local Traversal Inline : [def@TemplateDef(f,[],elem1*) | def1*] -> [def | def2*] where def2* := <alltd((Call(f) -> Call("container", elem1*)))> def1* local traversal
  45. 45. Dynamic Rewrite Rules
  46. 46. Rewrite in Context: Not Optimal Inline : [def@TemplateDef(f,[],elem1*) | def1*] -> [def | def2*] where def2* := <alltd((Call(f) -> Call("container", elem1*)))> def1* requires def before use local traversal for each declaration
  47. 47. Dynamic Rewrite Rules Inline : [def@TemplateDef(f,[],elem1*) | def1*] -> [def | def2*] where def2* := <alltd((Call(f) -> Call("container", elem1*)))> def1* declare-inline : TemplateDef(f,[],elem1*) -> TemplateDef(f,[],elem1*) where rules( InlineTemplate : Call(f) -> Call("container", elem1*) ) inline = alltd(declare-inline); topdown(try(InlineTemplate)) separate traversal from rule definition (binding closures)
  48. 48. Inlining as Rewrite Problem (Revisited) outputPost(p) -> navigate post(p) { output(p.name) } where define outputPost(pst : Post) { navigate post(pst) { output(pst.name) } } (informal) declare-inline : TemplateDef(f,[],elem1*) -> TemplateDef(f,[],elem1*) where rules( InlineTemplate : Call(f) -> Call("container", elem1*) ) (formal; but not yet complete)
  49. 49. define page blog(b : Blog) { Template Parameter header{output(b.name)} list{ for(p : Post in b.posts) { listitem{ outputPost(p) } } } } define outputPost(pst : Post) { navigate post(pst) { output(pst.name) } } define list() { <ul> elements </ul> } define listitem() { <li> elements </li> } define header() { <h1> elements </h1> } define page blog ( b : Blog ) { <h1> output(b.name) </h1> <ul> for ( p : Post in b.posts ) { <li> navigate post(p) { output(p.name) } </li> } </ul> }
  50. 50. Inlining Templates with Parameters declare-inline : def@TemplateDef(mod*,f,param*,elem1*) -> def where rules( InlineTemplate : Call(f, e*, []) -> Call("container", [], elem3*) where elem3* := <substitute> (param*, e*, elem1*) ) substitute : (param*, e*, elem1*) -> elem2* where {| Subst : <zip(bind-arg)> (param*, e*) ; elem2* := <alltd(Subst)> elem1* |} bind-arg : (Param(x, t), e) -> (Param(x, t), e) where rules( Subst : Var(x) -> e )
  51. 51. Element Parameters define list() { <ul> elements </ul> } declare-inline : def@TemplateDef(mod*,f,param*,elem1*) -> def where rules( InlineTemplate : Call(f, e*, elem2*) -> Call("container", [], elem3*) where {| Subst : rules( Subst : Elements() -> Call("container",[],elem2*) ) ; elem3* := <substitute> (param*, e*, elem1*) |} )
  52. 52. Removing Intermediate Structures rules // remove containers desugar-container : [Call("container",[], elem1*) | elem2*] -> [elem1*, elem2*] desugar : elem1* -> elem2* where elem2* := <at-suffix(desugar-container)> elem1* container needed to replace single call with multiple elements
  53. 53. Inlining Strategy module template-inlining imports libstratego-lib imports include/nwl imports desugar strategies inline-all = desugar-all; alltd(declare-inline); innermost(desugar <+ InlineTemplate) rules declare-inline : ...
  54. 54. module template-inlining imports libstratego-lib imports include/nwl imports desugar strategies inline-all = desugar-all; alltd(declare-inline); innermost(desugar <+ InlineTemplate) rules declare-inline : TemplateDef(mod*,f,param*,elem1*) -> TemplateDef(mod*,f,param*,elem1*) where rules( InlineTemplate : Call(f, e*, elem2*) -> Call("container", [], elem3*) Template Inlining where {| Subst : rules( Subst : Elements() -> Call("container", [], elem2*) ) ; elem3* := <substitute> (param*, e*, elem1*) Transformation ) |} substitute : (param*, e*, elem1*) -> elem2* where {| Subst : <zip(bind-arg)> (param*, e*) ; elem2* := <alltd(Subst)> elem1* |} bind-arg : (Param(x, t), e) -> (Param(x, t), e) where rules( Subst : Var(x) -> e ) rules // remove containers desugar-container : [Call("container",[], elem1*) | elem2*] -> [elem1*, elem2*] desugar : elem1* -> elem2* where elem2* := <at-suffix(desugar-container)> elem1*
  55. 55. Free Variable Capture
  56. 56. Free Variable Capture in Template Inlining define page blogfront(b : Blog) { header{output(b.name)} list{ for(p : Post in b.posts) { listitem{ postInline(p) { par{ "Posted by " outputUser(p.author) } } } } } } define postInline(pst : Post) { header{output(pst.title)} output(pst.text) for(p : Tag in pst.tags) { elements } }
  57. 57. Free Variable Capture in Template Inlining define page blogfront(b : Blog) { header{output(b.name)} list{ for(p : Post in b.posts) { listitem{ postInline(p) { par{ "Posted by " outputUser(p.author) } } define page blogfront(b : Blog) { } <h1> output(b.name) </h1> } <ul> } for(p : Post in b.posts) { } <li> define postInline(pst : Post) { <h1>output(p.title)</h1> header{output(pst.title)} output(p.text) output(pst.text) for ( p : Tag in p.tags ) { for(p : Tag in pst.tags) { <p> elements "Posted by " } navigate user(p.author) { output(p.author.name) } } </p> } </li> } </ul> }
  58. 58. Free Variable Capture in Template Inlining define page blogfront(b : Blog) { for(p : Post in b.posts) { postInline(p) { "Posted by " outputUser(p.author) } } } define postInline(pst : Post) { for(p : Tag in pst.tags) { output(p.name) elements } } define page blogfront(b : Blog) { for(p : Post in b.posts) { for(p : Tag in p.tags) { output(p.name) "Posted by " navigate user(p.author) { output(p.author.name) } } } }
  59. 59. Avoiding Free Variable Capture substitute-args : (param*, e*, elem1*) -> elem2* where {| Subst : <zip(bind-arg)> (param*, e*) ; elem2* := <substitute> elem1* |} substitute = alltd(Subst <+ rename-bound) rename-bound : ForElem(x, t, e1, elem1*) -> ForElem(y, t, e2, elem2*) where {| Subst : y := <newname> x ; e2 := <substitute> e1 ; rules( Subst : Var(x) -> Var(y) ) ; elem2* := <substitute> elem1* |} rename bound variables
  60. 60. Free Variable Capture in Template Inlining define page blogfront(b : Blog) { for(p : Post in b.posts) { postInline(p) { "Posted by " outputUser(p.author) } } } define postInline(pst : Post) { for(p : Tag in pst.tags) { output(p.name) elements } } define page blogfront(b : Blog) { for(p : Post in b.posts) { for(p3 : Tag in p.tags) { output(p3.name) "Posted by " navigate user(p.author) { output(p.author.name) } } } }
  61. 61. Aspect Weaving
  62. 62. Aspect Weaving Aspect definition ★ modular definition of cross cutting concerns Aspect weaving ★ apply aspects to base program Applications ★ instrumentation for logging, tracing, debugging, profiling ★ access control, data validation, entity extension
  63. 63. Access Control Rules define page post(p : Post) { header{output(p.title)} output(p.text) par{ "Posted by " outputUser(p.author) } navigate editpost(p) { "Edit" } } rule page editpost(pst : Post) { principal == pst.blog.author } define page editpost(p : Post) { action save() { return post(p); } header{output(p.title)} form{ input(p.url) input(p.title) input(p.text) submit save() { "Save" } } }
  64. 64. Access Control Weaving define page post(p : Post) { header{output(p.title)} output(p.text) par{ "Posted by " outputUser(p.author) } navigate editpost(p) { "Edit" } } rule page editpost(pst : Post) { principal == pst.blog.author } define page editpost(p : Post) { action save() { return post(p); } header{output(p.title)} form{ input(p.url) input(p.title) input(p.text) submit save() { "Save" } } }
  65. 65. Access Control Weaving: Protect Page define page post(p : Post) { header{output(p.title)} output(p.text) par{ "Posted by " outputUser(p.author) } navigate editpost(p) { "Edit" } } define page editpost(p : Post) { init { rule page editpost(pst : Post) { if(!(principal == pst.blog.author)) { principal == pst.blog.author return accessdenied() ; } } } define page editpost(p : Post) { action save() { return post(p) ; } action save() { header{output(p.title)} return post(p); form{ } input(p.url) header{output(p.title)} input(p.title) form{ input(p.text) input(p.url) submit save ( ) { "Save" } input(p.title) } input(p.text) } submit save() { "Save" } } }
  66. 66. Access Control Weaving: Protect Link define page post(p : Post) { header{output(p.title)} output(p.text) par{ "Posted by " outputUser(p.author) } navigate editpost(p) { "Edit" } } define page editpost(p : Post) { init { rule page editpost(pst : Post) { if(!(principal == pst.blog.author)) { principal == pst.blog.author return accessdenied() ; } } } define page editpost(p : Post) { action save() { return post(p) ; } action save() { header{output(p.title)} return post(p); define page post ( p : Post ) { form{ } header{output(p.title)} input(p.url) header{output(p.title)} output(p.text) input(p.title) form{ par{"Posted by "outputUser(p.author)} input(p.text) input(p.url) if(principal == ( ) { "Save" } { submit save p.blog.author) input(p.title) }navigate editpost(p) { "Edit" } input(p.text) }} submit save() { "Save" } } } }
  67. 67. Access Control Weaving: Strategy weave-ac-rules = alltd(declare-ac-rule); bottomup(try(ProtectPage <+ ProtectNavigate))
  68. 68. Access Control Weaving: Protect Navigate declare-ac-rule : r@Rule([Page()], f, param1*, e) -> r where rules( ProtectNavigate : elem@Navigate(PageRef(f, e*), elem*) -> If(e2,Block([elem]),Block([])) where e2 := <substitute-args> (param1*, e*, e) )
  69. 69. Access Control Weaving: Protect Page declare-ac-rule : r@Rule([Page()], f, param1*, e) -> r where rules( ProtectNavigate : ... ProtectPage : TemplateDef([Page()], f, param2*, elem*) -> TemplateDef([Page()], f, param2*, [Init([ If(Not(e), Block([ReturnPage(PageRef("accessdenied", []))]), Block([]))]), elem*]) where e2 := <substitute-args> (param1*, <map(param-to-exp)> param2*, e) ) param-to-exp : Param(x, t) -> Var(x)
  70. 70. Access Control Weaving: Complete* weave-ac-rules = alltd(declare-ac-rule); bottomup(try(ProtectPage <+ ProtectNavigate)) declare-ac-rule : r@Rule([Page()], f, param1*, e) -> r where rules( ProtectPage : TemplateDef([Page()], f, param2*, elem1*) -> TemplateDef([Page()], f, param2*, [Init([ If(Not(e), Block([ReturnPage(PageRef("accessdenied", []))]), Block([]))]), elem1*]) where e2 := <substitute-args> (param1*, <map(param-to-exp)> param2*, e) ProtectNavigate : elem@Navigate(PageRef(f, e*), elem*) -> If(e2,Block([elem]),Block([])) where e2 := <substitute-args> (param1*, e*, e) ) param-to-exp : Param(x, t) -> Var(x) * complete specification for this limited example; WebDSL AC is more complex
  71. 71. Extend Entity module blog entity Post { url : String (id) title : String (name) text : WikiText blog : Blog (inverse:posts) author : User module tags blog : Blog } entity Tag { key : String (id) title : String (name) text : WikiText posts : Set<Post> } extend entity Post { tags : Set<Tag> (inverse:posts) } modular extensibility => more cohesion (?)
  72. 72. Extend Entity module woven entity Post { url : String (id) title : String (name) module blog text : WikiText blog : Blog (inverse:posts) entity Post { author : User url : String (id) blog : Blog title : String (name) tags : Set<Tag> (inverse:posts) text : WikiText } blog : Blog (inverse:posts) author : User entity Tag { module tags blog : Blog key : String (id) } title : String (name) entity Tag { text : WikiText key : String (id) posts : Set<Post> title : String (name) } text : WikiText posts : Set<Post> } extend entity Post { tags : Set<Tag> (inverse:posts) } modular extensibility => more cohesion (?)
  73. 73. Other Model Transformations
  74. 74. Other Applications of Model Transformation Refactoring ★ behaviour preserving transformation to improve design ★ e.g. extract/inline function/template/entity Difference detection ★ detect differences between two models Migration ★ update model to conform to new meta-model Optimization ★ derive more efficient version ★ e.g. query prefetching
  75. 75. Schedule Case 3 ★ Syntax definition & term rewriting ★ Deadline: Design 2 ★ Make a proposal (can be submitted separately) ★ Deadline: Lab this week ★ Install Spoofax ★ Make Case 3 Next ★ Lecture 9: static analysis

×