• Share
  • Email
  • Embed
  • Like
  • Save
  • Private Content
Model-Driven Software Development - Context-Sensitive Transformation
 

Model-Driven Software Development - Context-Sensitive Transformation

on

  • 2,781 views

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

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

Statistics

Views

Total Views
2,781
Views on SlideShare
2,046
Embed Views
735

Actions

Likes
1
Downloads
38
Comments
0

3 Embeds 735

https://blackboard.tudelft.nl 701
http://blackboard.tudelft.nl 21
http://www.slideshare.net 13

Accessibility

Categories

Upload Details

Uploaded via as Adobe PDF

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

    Model-Driven Software Development - Context-Sensitive Transformation Model-Driven Software Development - Context-Sensitive Transformation Presentation Transcript

    • Context-Sensitive Transformation Lecture 8 Course IN4308 Eelco Visser Master Computer Science http://eelcovisser.org Delft University of Technology
    • 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) { }
    • 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
    • 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
    • Design 2 Build your own DSL
    • 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
    • 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
    • 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
    • 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
    • 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
    • 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); } }
    • 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" };
    • 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
    • Model Transformation
    • Compilation by Normalization
    • Types of Model Transformation Reduction to sub-language ★ Normalization ★ Desugaring ★ Optimization ★ Aspect weaving ★ Instrumentation ★ Refactoring Translation to another language ★ Conversion ★ Migration ★ Compilation
    • Term Rewriting
    • Term Rewriting Term rewrite rules ★ transform term to term ★ pattern matching ★ variable binding ★ substitution Rewriting strategy ★ algorithm for applying rewrite rules
    • Term Rewrite Rule left-hand side pattern label/name desugar : Property(x, t) -> Property(x, t, []) variable right-hand side pattern
    • 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
    • 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
    • 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))
    • 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))
    • Context-sensitive Transformation
    • 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> }
    • 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
    • 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> }
    • 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)
    • Rewrite Rules are Context-free desugar : Property(x, t) -> Property(x, t, [])
    • 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” } } }
    • 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
    • Intermezzo: Rewriting Strategies
    • transformation is partial* function from terms to terms * transformation may fail to apply to a term
    • 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
    • Strategy Combinators id ★ Identity fail ★ failure s1 ; s2 ★ sequential composition s1 <+ s2 ★ choice
    • 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
    • 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
    • Rewrite in Context Inline : [def@TemplateDef(f,[],elem1*) | def1*] -> [def | def2*] where def2* := <alltd((Call(f) -> Call("container", elem1*)))> def1* bound in context
    • 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*
    • 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))
    • 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)]
    • 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
    • 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
    • Rewrite in Context: Local Traversal Inline : [def@TemplateDef(f,[],elem1*) | def1*] -> [def | def2*] where def2* := <alltd((Call(f) -> Call("container", elem1*)))> def1* local traversal
    • Dynamic Rewrite Rules
    • 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
    • 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)
    • 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)
    • 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> }
    • 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 )
    • 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*) |} )
    • 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
    • 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 : ...
    • 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*
    • Free Variable Capture
    • 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 } }
    • 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> }
    • 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) } } } }
    • 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
    • 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) } } } }
    • Aspect Weaving
    • 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
    • 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" } } }
    • 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" } } }
    • 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" } } }
    • 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" } } } }
    • Access Control Weaving: Strategy weave-ac-rules = alltd(declare-ac-rule); bottomup(try(ProtectPage <+ ProtectNavigate))
    • 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) )
    • 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)
    • 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
    • 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 (?)
    • 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 (?)
    • Other Model Transformations
    • 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
    • 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