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. 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. 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. 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. 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. 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);
}
}
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
18. Term Rewriting
Term rewrite rules
★ transform term to term
★ pattern matching
★ variable binding
★ substitution
Rewriting strategy
★ algorithm for applying rewrite rules
19. Term Rewrite Rule
left-hand side pattern
label/name
desugar :
Property(x, t) -> Property(x, t, [])
variable
right-hand side pattern
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. 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
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. 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. 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. 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)
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
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. 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. Rewrite in Context
Inline :
[def@TemplateDef(f,[],elem1*) | def1*] -> [def | def2*]
where def2* := <alltd((Call(f) -> Call("container", elem1*)))> def1*
bound in context
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. 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. 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. 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. Rewrite in Context: Local Traversal
Inline :
[def@TemplateDef(f,[],elem1*) | def1*] -> [def | def2*]
where def2* := <alltd((Call(f) -> Call("container", elem1*)))> def1*
local traversal
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
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. 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. 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 (?)
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. 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