Backstage Java - Making a Difference in Metaprogrammingzpalmer/publications/bsj... · 2016. 1....
Transcript of Backstage Java - Making a Difference in Metaprogrammingzpalmer/publications/bsj... · 2016. 1....
Backstage JavaMaking a Difference in Metaprogramming
Zachary Palmer and Scott F. Smith
The Johns Hopkins University
October 27, 2011
Difference-Based Metaprogramming
• Introduction to Metaprogramming
• Compile-Time Metaprogramming in Java
• Traditional Metaprogramming Model
• Difference-Based Metaprogramming Model
Difference-Based Metaprogramming
• Introduction to Metaprogramming
• Compile-Time Metaprogramming in Java
• Traditional Metaprogramming Model
• Difference-Based Metaprogramming Model
Difference-Based Metaprogramming
• Introduction to Metaprogramming
• Compile-Time Metaprogramming in Java
• Traditional Metaprogramming Model
• Difference-Based Metaprogramming Model
Difference-Based Metaprogramming
• Introduction to Metaprogramming
• Compile-Time Metaprogramming in Java
• Traditional Metaprogramming Model
• Difference-Based Metaprogramming Model
What is metaprogramming?
Metaprogramming• Programs input data and output data.
Input ρ Output
• Metaprograms input programs (or programfragments) and output the same.
ρ φ ρ′
Metaprogramming• Programs input data and output data.
Input ρ Output
• Metaprograms input programs (or programfragments) and output the same.
ρ φ ρ′
Examples of Metaprogramming
• C Macros
• C++ Templates
• LISP Macros
• Template Haskell
• MetaOCaml
• Stratego
• Groovy
• etc. etc.
Classifying Metaprogramming
• When is it run?• Compile-time (static)• Runtime (dynamic)
• How are programs represented?• Textually (strings)• Lexically (tokens)• Structurally (ASTs)• Semantically (various structures)
• Which language is used to metaprogram?• Same language (homogenous)• Different language (heterogeneous)
from Accomplishments and Research Challenges in Metaprogramming (Tim Sheard)
Classifying Metaprogramming
• When is it run?• Compile-time (static)• Runtime (dynamic)
• How are programs represented?• Textually (strings)• Lexically (tokens)• Structurally (ASTs)• Semantically (various structures)
• Which language is used to metaprogram?• Same language (homogenous)• Different language (heterogeneous)
from Accomplishments and Research Challenges in Metaprogramming (Tim Sheard)
Template Haskell Example
$(
let mkExp n v =
if n == 0
then [| 1 |]
else [| $(v) * $(mkExp (n-1) v) |]
in
let f n =
let funNm = mkName ("exp" ++ (show n)) in
let params = [varP (mkName "x")] in
funD funNm $ [clause params
(normalB $ mkExp n (varE $ mkName "x")) []]
in
mapM f [2..50]
)
Template Haskell Example
exp2 x = x * x
exp3 x = x * x * x
exp4 x = x * x * x * x
exp5 x = x * x * x * x * x
exp6 x = x * x * x * x * x * x...
......
exp50 x =
50︷ ︸︸ ︷x * x * . . . * x * x
Template Haskell
• Programmatic code generation
• Literal syntax for AST construction
• Functional programming style
• Very limited ability to inspect environment
Template Haskell
• Programmatic code generation
• Literal syntax for AST construction
• Functional programming style
• Very limited ability to inspect environment
Template Haskell
• Programmatic code generation
• Literal syntax for AST construction
• Functional programming style
• Very limited ability to inspect environment
Template Haskell
• Programmatic code generation
• Literal syntax for AST construction
• Functional programming style
• Very limited ability to inspect environment
Why not Template Java?
Template Java?public class Location {
private int x;
public int getX() { return this.x; }
public void setX(int x) { this.x = x; }
private int y;
public int getY() { return this.y; }
public void setY(int y) { this.y = y; }
public Location(int x, int y) {
this.x = x;
this.y = y;
}
public String toString() {
return "("+this.x+","+this.y+")";
}
}
Template Java?public class Location {
private int x;
public int getX() { return this.x; }
public void setX(int x) { this.x = x; }
private int y;
public int getY() { return this.y; }
public void setY(int y) { this.y = y; }
public Location(int x, int y) {
this.x = x;
this.y = y;
}
public String toString() {
return "("+this.x+","+this.y+")";
}
}
Template Java?public class Location {
$( property( [|private int x|] )
private int y;
public int getY() { return this.y; }
public void setY(int y) { this.y = y; }
public Location(int x, int y) {
this.x = x;
this.y = y;
}
public String toString() {
return "("+this.x+","+this.y+")";
}
}
Template Java?public class Location {
$( property( [|private int x|] )
private int y;
public int getY() { return this.y; }
public void setY(int y) { this.y = y; }
public Location(int x, int y) {
this.x = x;
this.y = y;
}
public String toString() {
return "("+this.x+","+this.y+")";
}
}
Template Java?public class Location {
$( property( [|private int x|] )
$( property( [|private int y|] )
public Location(int x, int y) {
this.x = x;
this.y = y;
}
public String toString() {
return "("+this.x+","+this.y+")";
}
}
Template Java?public class Location {
$( property( [|private int x|] )
$( property( [|private int y|] )
public Location(int x, int y) {
this.x = x;
this.y = y;
}
public String toString() {
return "("+this.x+","+this.y+")";
}
}
Template Java?public class Location {
$( property( [|private int x|] )
$( property( [|private int y|] )
$( makePropertyConstructor(
[|int x|], [|int y|]) )
public String toString() {
return "("+this.x+","+this.y+")";
}
}
Template Java?public class Location {
$( property( [|private int x|] )
$( property( [|private int y|] )
$( makePropertyConstructor(
[|int x|], [|int y|]) )
public String toString() {
return "("+this.x+","+this.y+")";
}
}
• Metaprograms can’t react to surrounding code• Metaprogrammers compensate by duplicating
information• Functional metaprogramming in a declarative
object-oriented language
Template Java?public class Location {
$( property( [|private int x|] )
$( property( [|private int y|] )
$( makePropertyConstructor(
[|int x|], [|int y|]) )
public String toString() {
return "("+this.x+","+this.y+")";
}
}
• Metaprograms can’t react to surrounding code
• Metaprogrammers compensate by duplicatinginformation
• Functional metaprogramming in a declarativeobject-oriented language
Template Java?public class Location {
$( property( [|private int x|] )
$( property( [|private int y|] )
$( makePropertyConstructor(
[|int x|], [|int y|]) )
public String toString() {
return "("+this.x+","+this.y+")";
}
}
• Metaprograms can’t react to surrounding code• Metaprogrammers compensate by duplicating
information
• Functional metaprogramming in a declarativeobject-oriented language
Template Java?public class Location {
$( property( [|private int x|] )
$( property( [|private int y|] )
$( makePropertyConstructor(
[|int x|], [|int y|]) )
public String toString() {
return "("+this.x+","+this.y+")";
}
}
• Metaprograms can’t react to surrounding code• Metaprogrammers compensate by duplicating
information• Functional metaprogramming in a declarative
object-oriented language
What Do We Want?
• Object-oriented, declarative metaprogrammingstyle
• Awareness of surrounding code
• Modular, independent metaprograms
What Do We Want?
• Object-oriented, declarative metaprogrammingstyle
• Awareness of surrounding code
• Modular, independent metaprograms
What Do We Want?
• Object-oriented, declarative metaprogrammingstyle
• Awareness of surrounding code
• Modular, independent metaprograms
Backstage Java
How about some of this?
@@GenerateConstructorFromProperties
public class Location {
@@Property private int x;
@@Property private int y;
public String toString() {
return "("+this.x+","+this.y+")";
}
}
Harder than it looks...
Backstage Java
How about some of this?
@@GenerateConstructorFromProperties
public class Location {
@@Property private int x;
@@Property private int y;
public String toString() {
return "("+this.x+","+this.y+")";
}
}
Harder than it looks...
Traditional Metaprogramming
Traditional Metaprogramming
• Metaprograms are a series of programtransformations
• Each available transformation occurs exactlyonce
• True even for embedded syntax
Traditional Metaprogramming
• Metaprograms are a series of programtransformations
• Each available transformation occurs exactlyonce
• True even for embedded syntax
Traditional Metaprogramming
• Metaprograms are a series of programtransformations
• Each available transformation occurs exactlyonce
• True even for embedded syntax
Embedded Metaprogram Semantics
φ1 φ2
How do we pick?
Embedded Metaprogram Semantics
φ1 φ2
How do we pick?
Embedded Metaprogram Semantics
φ1 φ2
How do we pick?
Embedded Metaprogram Semantics
φ1
(φ2
( ))
φ1 φ2
How do we pick?
Embedded Metaprogram Semantics
φ2
(φ1
( ))
φ1 φ2
How do we pick?
Embedded Metaprogram Semantics
φ2
(φ1
( ))
φ1 φ2
How do we pick?
Ambiguity in Metaprogramming
Assuming three transformations φ1, φ2, φ3...
ρ
? ? ? ? ? ?
OpenJava, Groovy
Ambiguity in Metaprogramming
Assuming three transformations φ1, φ2, φ3...
ρ
? ? ? ? ? ?
OpenJava, Groovy
Total Ordering Solution
Declaring φ2 before φ1, which is before φ3.
ρ
ρ′
ROSE
Total Ordering Solution
Declaring φ2 before φ1, which is before φ3.
ρ
ρ′
ROSE
Necessary Commutation Solution
Requiring that φi ◦ φj = φj ◦ φi for all i and j
ρ
ρ′
Template Haskell, MetaOCaml, LISP, ...
Necessary Commutation Solution
Requiring that φi ◦ φj = φj ◦ φi for all i and j
ρ
ρ′
Template Haskell, MetaOCaml, LISP, ...
Hybrid Solution
Suppose that φ1 and φ2 commute.Suppose that φ3 must occur after them.
ρ
Backstage Java*
Hybrid Solution
Suppose that φ1 and φ2 commute.
Suppose that φ3 must occur after them.
ρ
Backstage Java*
Hybrid Solution
Suppose that φ1 and φ2 commute.
Suppose that φ3 must occur after them.
ρ
◦
◦
Backstage Java*
Hybrid Solution
Suppose that φ1 and φ2 commute.Suppose that φ3 must occur after them.
ρ
◦
◦
Backstage Java*
Hybrid Solution
Suppose that φ1 and φ2 commute.Suppose that φ3 must occur after them.
ρ
◦
◦
Backstage Java*
Hybrid Solution
Suppose that φ1 and φ2 commute.Suppose that φ3 must occur after them.
ρ
◦
◦
Backstage Java*
Hybrid Solution
Suppose that φ1 and φ2 commute.Suppose that φ3 must occur after them.
ρ
◦
◦
Backstage Java*
Hybrid Solution
Suppose that φ1 and φ2 commute.Suppose that φ3 must occur after them.
ρ
◦
◦
Backstage Java*
Commuting Transformations
How do we tell if φ1 and φ2 commute?
◦?
Determining whether or not two arbitrarytransformations commute is undecidable!
Commuting Transformations
How do we tell if φ1 and φ2 commute?
◦?
Determining whether or not two arbitrarytransformations commute is undecidable!
Commuting Transformations
How do we tell if φ1 and φ2 commute?
◦?
Determining whether or not two arbitrarytransformations commute is undecidable!
Difference-Based Metaprogramming
Difference-Based MetaprogrammingTreat metaprograms as transformation generators:
φ(ρ) = δ̄
Jδ̄K(ρ) = ρ′
Difference-Based MetaprogrammingTreat metaprograms as transformation generators:
φ(ρ) = δ̄
Jδ̄K(ρ) = ρ′
Difference-Based MetaprogrammingTreat metaprograms as transformation generators:
φ(ρ) = δ̄
Jδ̄K(ρ) = ρ′
Difference-Based MetaprogrammingTreat metaprograms as transformation generators:
φ(ρ) = δ̄
Jδ̄K(ρ) = ρ′
• Language of δ̄ is not Turing-complete
• Each δ̄ is generated on a case-by-case basis
• No practically significant loss of expressiveness
Difference-Based MetaprogrammingTreat metaprograms as transformation generators:
φ(ρ) = δ̄
Jδ̄K(ρ) = ρ′
• Language of δ̄ is not Turing-complete
• Each δ̄ is generated on a case-by-case basis
• No practically significant loss of expressiveness
Difference-Based MetaprogrammingTreat metaprograms as transformation generators:
φ(ρ) = δ̄
Jδ̄K(ρ) = ρ′
• Language of δ̄ is not Turing-complete
• Each δ̄ is generated on a case-by-case basis
• No practically significant loss of expressiveness
Difference-Based MetaprogrammingTreat metaprograms as transformation generators:
φ(ρ) = δ̄
Jδ̄K(ρ) = ρ′
δ̄ can express:
• Creation of a node
• Assignment to a node property
• Additions before or after an element in a list
• Removal of an element from a list
Difference-Based MetaprogrammingTreat metaprograms as transformation generators:
φ(ρ) = δ̄
Jδ̄K(ρ) = ρ′
δ̄ can express:
• Creation of a node
• Assignment to a node property
• Additions before or after an element in a list
• Removal of an element from a list
Difference-Based MetaprogrammingTreat metaprograms as transformation generators:
φ(ρ) = δ̄
Jδ̄K(ρ) = ρ′
δ̄ can express:
• Creation of a node
• Assignment to a node property
• Additions before or after an element in a list
• Removal of an element from a list
Difference-Based MetaprogrammingTreat metaprograms as transformation generators:
φ(ρ) = δ̄
Jδ̄K(ρ) = ρ′
δ̄ can express:
• Creation of a node
• Assignment to a node property
• Additions before or after an element in a list
• Removal of an element from a list
Difference-Based MetaprogrammingTreat metaprograms as transformation generators:
φ(ρ) = δ̄
Jδ̄K(ρ) = ρ′
Now, prove commutation over pairs of Jδ̄K.
◦
Jδ̄1K Jδ̄2K
Jδ̄2K Jδ̄1K
Difference-Based MetaprogrammingTreat metaprograms as transformation generators:
φ(ρ) = δ̄
Jδ̄K(ρ) = ρ′
Now, prove commutation over pairs of Jδ̄K.
◦
Jδ̄1K Jδ̄2K
Jδ̄2K Jδ̄1K
A Simple BSJ Examplepublic class Example {
public static void main(String[] arg) {
[:
BlockStatementListNode list = context.getAnchor().
getNearestAncestorOfType(
BlockStatementListNode.class);
list.addFirst(
<:System.out.println("Hello, world!");:>);
:]
[:
BlockStatementListNode list = context.getAnchor().
getNearestAncestorOfType(
BlockStatementListNode.class);
list.addLast(
<:System.out.println("How are you?");:>);
:]
}
}
A Simple Examplepublic class Example {
public static void main(String[] arg) {
System.out.println("Hello, world!");
M1
M2
System.out.println("How are you?");
}
}
• Replace metaprograms with anchors
• Run each metaprogram to collect its changes
• φ1(ρ) = δ̄1 (“Hello, world!” first)• φ2(ρ) = δ̄2 (“How are you?” last)
• Prove that δ̄1 and δ̄2 commute.
• Execute δ̄1 and δ̄2 in some order.
A Simple Examplepublic class Example {
public static void main(String[] arg) {
System.out.println("Hello, world!");
M1
M2
System.out.println("How are you?");
}
}
• Replace metaprograms with anchors• Run each metaprogram to collect its changes
• φ1(ρ) = δ̄1 (“Hello, world!” first)• φ2(ρ) = δ̄2 (“How are you?” last)
• Prove that δ̄1 and δ̄2 commute.
• Execute δ̄1 and δ̄2 in some order.
A Simple Examplepublic class Example {
public static void main(String[] arg) {
System.out.println("Hello, world!");
M1
M2
System.out.println("How are you?");
}
}
• Replace metaprograms with anchors• Run each metaprogram to collect its changes
• φ1(ρ) = δ̄1 (“Hello, world!” first)
• φ2(ρ) = δ̄2 (“How are you?” last)
• Prove that δ̄1 and δ̄2 commute.
• Execute δ̄1 and δ̄2 in some order.
A Simple Examplepublic class Example {
public static void main(String[] arg) {
System.out.println("Hello, world!");
M1
M2
System.out.println("How are you?");
}
}
• Replace metaprograms with anchors• Run each metaprogram to collect its changes
• φ1(ρ) = δ̄1 (“Hello, world!” first)• φ2(ρ) = δ̄2 (“How are you?” last)
• Prove that δ̄1 and δ̄2 commute.
• Execute δ̄1 and δ̄2 in some order.
A Simple Examplepublic class Example {
public static void main(String[] arg) {
System.out.println("Hello, world!");
M1
M2
System.out.println("How are you?");
}
}
• Replace metaprograms with anchors• Run each metaprogram to collect its changes
• φ1(ρ) = δ̄1 (“Hello, world!” first)• φ2(ρ) = δ̄2 (“How are you?” last)
• Prove that δ̄1 and δ̄2 commute.
• Execute δ̄1 and δ̄2 in some order.
A Simple Examplepublic class Example {
public static void main(String[] arg) {
System.out.println("Hello, world!");
M1
M2
System.out.println("How are you?");
}
}
• Replace metaprograms with anchors• Run each metaprogram to collect its changes
• φ1(ρ) = δ̄1 (“Hello, world!” first)• φ2(ρ) = δ̄2 (“How are you?” last)
• Prove that δ̄1 and δ̄2 commute.
• Execute δ̄1 and δ̄2 in some order.
A Simple Examplepublic class Example {
public static void main(String[] arg) {
System.out.println("Hello, world!");
M1
M2
System.out.println("How are you?");
}
}
• Replace metaprograms with anchors• Run each metaprogram to collect its changes
• φ1(ρ) = δ̄1 (“Hello, world!” first)• φ2(ρ) = δ̄2 (“How are you?” last)
• Prove that δ̄1 and δ̄2 commute.
• Execute δ̄1 and δ̄2 in some order.
A Simple Examplepublic class Example {
public static void main(String[] arg) {
System.out.println("Hello, world!");
M1
M2
System.out.println("How are you?");
}
}
• Replace metaprograms with anchors• Run each metaprogram to collect its changes
• φ1(ρ) = δ̄1 (“Hello, world!” first)• φ2(ρ) = δ̄2 (“How are you?” last)
• Prove that δ̄1 and δ̄2 commute.
• Execute δ̄1 and δ̄2 in some order.
A Simple Examplepublic class Example {
public static void main(String[] arg) {
System.out.println("Hello, world!");
M1
M2
System.out.println("How are you?");
}
}
• Replace metaprograms with anchors• Run each metaprogram to collect its changes
• φ1(ρ) = δ̄1 (“Hello, world!” first)• φ2(ρ) = δ̄2 (“How are you?” last)
• Prove that δ̄1 and δ̄2 commute.
• Execute δ̄1 and δ̄2 in some order.
A Simple Examplepublic class Example {
public static void main(String[] arg) {
System.out.println("Hello, world!");
M1
M2
System.out.println("How are you?");
}
}
• Replace metaprograms with anchors• Run each metaprogram to collect its changes
• φ1(ρ) = δ̄1 (“Hello, world!” first)• φ2(ρ) = δ̄2 (“How are you?” last)
• Prove that δ̄1 and δ̄2 commute.
• Execute δ̄1 and δ̄2 in some order.
A Simple Examplepublic class Example {
public static void main(String[] arg) {
System.out.println("Hello, world!");
M1
M2
System.out.println("How are you?");
}
}
• Replace metaprograms with anchors• Run each metaprogram to collect its changes
• φ1(ρ) = δ̄1 (“Hello, world!” first)• φ2(ρ) = δ̄2 (“How are you?” last)
• Prove that δ̄1 and δ̄2 commute.
• Execute δ̄1 and δ̄2 in some order.
A Simple Examplepublic class Example {
public static void main(String[] arg) {
System.out.println("Hello, world!");
;
;
System.out.println("How are you?");
}
}
• Replace metaprograms with anchors• Run each metaprogram to collect its changes
• φ1(ρ) = δ̄1 (“Hello, world!” first)• φ2(ρ) = δ̄2 (“How are you?” last)
• Prove that δ̄1 and δ̄2 commute.
• Execute δ̄1 and δ̄2 in some order.
An Example of Conflictpublic class Example {
public static void main(String[] arg) {
[:
BlockStatementListNode list = context.getAnchor().
getNearestAncestorOfType(
BlockStatementListNode.class);
list.addFirst(
<:System.out.println("Hello, world!");:>);
:]
[:
BlockStatementListNode list = context.getAnchor().
getNearestAncestorOfType(
BlockStatementListNode.class);
list. addFirst (
<:System.out.println("How are you?");:>);
:]
}
}
An Example of Conflictpublic class Example {
public static void main(String[] arg) {
System.out.println("Hello, world!");
System.out.println("Hello, world!");
M1
M2
}
}
• Replace metaprograms with anchors• Run each metaprogram to collect its changes
• φ1(ρ) = δ̄1 (“Hello, world!” first)• φ2(ρ) = δ̄2 (“How are you?” first)
• Now, δ̄1 and δ̄2 do not commute!
• But we can detect this!
An Example of Conflictpublic class Example {
public static void main(String[] arg) {
System.out.println("Hello, world!");
System.out.println("Hello, world!");
M1
M2
}
}
• Replace metaprograms with anchors• Run each metaprogram to collect its changes
• φ1(ρ) = δ̄1 (“Hello, world!” first)• φ2(ρ) = δ̄2 (“How are you?” first)
• Now, δ̄1 and δ̄2 do not commute!
• But we can detect this!
An Example of Conflictpublic class Example {
public static void main(String[] arg) {
System.out.println("Hello, world!");
System.out.println("How are you?");
M1
M2
}
}
• Replace metaprograms with anchors• Run each metaprogram to collect its changes
• φ1(ρ) = δ̄1 (“Hello, world!” first)• φ2(ρ) = δ̄2 (“How are you?” first)
• Now, δ̄1 and δ̄2 do not commute!
• But we can detect this!
An Example of Conflictpublic class Example {
public static void main(String[] arg) {
System.out.println("Hello, world!");
System.out.println("How are you?");
M1
M2
}
}
• Replace metaprograms with anchors• Run each metaprogram to collect its changes
• φ1(ρ) = δ̄1 (“Hello, world!” first)• φ2(ρ) = δ̄2 (“How are you?” first)
• Now, δ̄1 and δ̄2 do not commute!
• But we can detect this!
An Example of Conflictpublic class Example {
public static void main(String[] arg) {
System.out.println("Hello, world!");
System.out.println("Hello, world!");
M1
M2
}
}
• Replace metaprograms with anchors• Run each metaprogram to collect its changes
• φ1(ρ) = δ̄1 (“Hello, world!” first)• φ2(ρ) = δ̄2 (“How are you?” first)
• Now, δ̄1 and δ̄2 do not commute!
• But we can detect this!
An Example of Conflictpublic class Example {
public static void main(String[] arg) {
System.out.println("Hello, world!");
System.out.println("Hello, world!");
M1
M2
}
}
• Replace metaprograms with anchors• Run each metaprogram to collect its changes
• φ1(ρ) = δ̄1 (“Hello, world!” first)• φ2(ρ) = δ̄2 (“How are you?” first)
• Now, δ̄1 and δ̄2 do not commute!
• But we can detect this!
An Example of Conflictpublic class Example {
public static void main(String[] arg) {
System.out.println("How are you?");
System.out.println("Hello, world!");
M1
M2
}
}
• Replace metaprograms with anchors• Run each metaprogram to collect its changes
• φ1(ρ) = δ̄1 (“Hello, world!” first)• φ2(ρ) = δ̄2 (“How are you?” first)
• Now, δ̄1 and δ̄2 do not commute!
• But we can detect this!
An Example of Conflictpublic class Example {
public static void main(String[] arg) {
System.out.println("How are you?");
System.out.println("Hello, world!");
;
;
}
}
• Replace metaprograms with anchors• Run each metaprogram to collect its changes
• φ1(ρ) = δ̄1 (“Hello, world!” first)• φ2(ρ) = δ̄2 (“How are you?” first)
• Now, δ̄1 and δ̄2 do not commute!
• But we can detect this!
An Example of Conflictpublic class Example {
public static void main(String[] arg) {
System.out.println("How are you?");
System.out.println("Hello, world!");
;
;
}
}
• Replace metaprograms with anchors• Run each metaprogram to collect its changes
• φ1(ρ) = δ̄1 (“Hello, world!” first)• φ2(ρ) = δ̄2 (“How are you?” first)
• Now, δ̄1 and δ̄2 do not commute!
• But we can detect this!
Conflict DetectionRecord Node Creation Ruleη 7→ v̂ /∈ ρ ρJη 7→ {l 7→ v̂}K⇒ ρ
′
(+R η(l = v̂)) ρ⇒ ρ′
List Node Creation Ruleη 7→ v̂ /∈ ρ
ρJη 7→ [(.,M, ∅), (/,M, ∅)]K⇒ ρ′
(M � +Lη) ρ⇒ ρ′
Record Assignment Ruleη 7→ R ∈ ρ ρJη 7→ RJl 7→ v̂KK⇒ ρ
′
(η.l ← v̂) ρ⇒ ρ′
List Add Before RuleMη3 6= . η1 7→ L ∈ ρ
◦η3 = Σ(Mη3,M,L) L = [◦η′, ◦η3,
◦η′′]
L′ = [◦η′, (η2,M, ∅), ◦η3,◦η′′]
ρJη1 7→ L′K⇒ ρ
′
(M � η1 : η2 " Mη3) ρ⇒ ρ
′
List Add After RuleMη3 6= / η1 7→ L ∈ ρ
◦η3 = Σ(Mη3,M,L) L = [◦η′, ◦η3,
◦η′′]
L′ = [◦η′, ◦η3, (η2,M, ∅), ◦η′′]
ρJη1 7→ L′K⇒ ρ
′
(M � η1 :Mη3 # η2) ρ⇒ ρ
′
List Remove Ruleη1 7→ L ∈ ρ◦η2 = (η2,M
′,S) = Σ(η2,M,L)
L = [◦η′, ◦η2,◦η′′]
L′ = [◦η′, (η2,M′,S ∪ {M}), ◦η′′]
ρJη1 7→ L′K⇒ ρ
′
(M � η1 : ↓ η2) ρ⇒ ρ′
Recursive Application Ruleδ′ e ⇒ ρ δ ρ⇒ ρ
′
δ (δ′ e)⇒ ρ′
Value Rule
v̂ ⇒ v̂
Record Assignment Conflict Rulev̂ 6= v̂′
η.l ← v̂ = η.l ← v̂′
Add Before Conflict Ruleω(η2) ω(η′2)
η1 : η2 " Mη3 = η1 : η′2 " M
η3
Add After Conflict Ruleω(η2) ω(η′2)
η1 :Mη3 # η2 = η1 :
Mη3 # η
′2
Unordered Creation Conflict Ruleδ = +R η(l 7→ v̂) ∨ δ = +Lη η ∈ δ′
δ = δ′
Conflict DetectionRecord Node Creation Ruleη 7→ v̂ /∈ ρ ρJη 7→ {l 7→ v̂}K⇒ ρ
′
(+R η(l = v̂)) ρ⇒ ρ′
List Node Creation Ruleη 7→ v̂ /∈ ρ
ρJη 7→ [(.,M, ∅), (/,M, ∅)]K⇒ ρ′
(M � +Lη) ρ⇒ ρ′
Record Assignment Ruleη 7→ R ∈ ρ ρJη 7→ RJl 7→ v̂KK⇒ ρ
′
(η.l ← v̂) ρ⇒ ρ′
List Add Before RuleMη3 6= . η1 7→ L ∈ ρ
◦η3 = Σ(Mη3,M,L) L = [◦η′, ◦η3,
◦η′′]
L′ = [◦η′, (η2,M, ∅), ◦η3,◦η′′]
ρJη1 7→ L′K⇒ ρ
′
(M � η1 : η2 " Mη3) ρ⇒ ρ
′
List Add After RuleMη3 6= / η1 7→ L ∈ ρ
◦η3 = Σ(Mη3,M,L) L = [◦η′, ◦η3,
◦η′′]
L′ = [◦η′, ◦η3, (η2,M, ∅), ◦η′′]
ρJη1 7→ L′K⇒ ρ
′
(M � η1 :Mη3 # η2) ρ⇒ ρ
′
List Remove Ruleη1 7→ L ∈ ρ◦η2 = (η2,M
′,S) = Σ(η2,M,L)
L = [◦η′, ◦η2,◦η′′]
L′ = [◦η′, (η2,M′,S ∪ {M}), ◦η′′]
ρJη1 7→ L′K⇒ ρ
′
(M � η1 : ↓ η2) ρ⇒ ρ′
Recursive Application Ruleδ′ e ⇒ ρ δ ρ⇒ ρ
′
δ (δ′ e)⇒ ρ′
Value Rule
v̂ ⇒ v̂
Record Assignment Conflict Rulev̂ 6= v̂′
η.l ← v̂ = η.l ← v̂′
Add Before Conflict Ruleω(η2) ω(η′2)
η1 : η2 " Mη3 = η1 : η′2 " M
η3
Add After Conflict Ruleω(η2) ω(η′2)
η1 :Mη3 # η2 = η1 :
Mη3 # η
′2
Unordered Creation Conflict Ruleδ = +R η(l 7→ v̂) ∨ δ = +Lη η ∈ δ′
δ = δ′
Huzzah!
• Metaprogram conflicts are detected at compiletime
• Metaprograms are still aware of theirsurroundings
,
Huzzah!
• Metaprogram conflicts are detected at compiletime
• Metaprograms are still aware of theirsurroundings
,
Huzzah!
• Metaprogram conflicts are detected at compiletime
• Metaprograms are still aware of theirsurroundings
,
Dependencies
So how do we resolve the conflict?
Dependenciespublic static void main(String[] arg) {
[:
#depends foo; ← Declare target dependency
BlockStatementListNode list = context.getAnchor().
getNearestAncestorOfType(
BlockStatementListNode.class);
list.addFirst(
<:System.out.println("Hello, world!");:>);
:]
[:
#target foo; ← Declare target membership
BlockStatementListNode list = context.getAnchor().
getNearestAncestorOfType(
BlockStatementListNode.class);
list.addFirst(
<:System.out.println("How are you?");:>);
:]
}
Dependenciespublic static void main(String[] arg) {
[:
#depends foo; ← Declare target dependency
BlockStatementListNode list = context.getAnchor().
getNearestAncestorOfType(
BlockStatementListNode.class);
list.addFirst(
<:System.out.println("Hello, world!");:>);
:]
[:
#target foo; ← Declare target membershipBlockStatementListNode list = context.getAnchor().
getNearestAncestorOfType(
BlockStatementListNode.class);
list.addFirst(
<:System.out.println("How are you?");:>);
:]
}
Dependenciespublic static void main(String[] arg) {
[:
#depends foo; ← Declare target dependencyBlockStatementListNode list = context.getAnchor().
getNearestAncestorOfType(
BlockStatementListNode.class);
list.addFirst(
<:System.out.println("Hello, world!");:>);
:]
[:
#target foo;
← Declare target membership
BlockStatementListNode list = context.getAnchor().
getNearestAncestorOfType(
BlockStatementListNode.class);
list.addFirst(
<:System.out.println("How are you?");:>);
:]
}
Dependenciespublic static void main(String[] arg) {
[:
#depends foo;
← Declare target dependency
BlockStatementListNode list = context.getAnchor().
getNearestAncestorOfType(
BlockStatementListNode.class);
list.addFirst(
<:System.out.println("Hello, world!");:>);
:]
[:
#target foo;
← Declare target membership
BlockStatementListNode list = context.getAnchor().
getNearestAncestorOfType(
BlockStatementListNode.class);
list.addFirst(
<:System.out.println("How are you?");:>);
:]
}
Dependency Graph
M1 M2
foo
• One node per metaprogram
• M2 is a member of target “foo”
• M1 depends on the target “foo”
• Therefore, M1 depends on M2 (M1 M2)
• No more requirement for them to commute!
Dependency Graph
M1 M2
foo
• One node per metaprogram
• M2 is a member of target “foo”
• M1 depends on the target “foo”
• Therefore, M1 depends on M2 (M1 M2)
• No more requirement for them to commute!
Dependency Graph
M1 M2
foo
• One node per metaprogram
• M2 is a member of target “foo”
• M1 depends on the target “foo”
• Therefore, M1 depends on M2 (M1 M2)
• No more requirement for them to commute!
Dependency Graph
M1 M2foo
• One node per metaprogram
• M2 is a member of target “foo”
• M1 depends on the target “foo”
• Therefore, M1 depends on M2 (M1 M2)
• No more requirement for them to commute!
Dependency Graph
M1 M2foo
• One node per metaprogram
• M2 is a member of target “foo”
• M1 depends on the target “foo”
• Therefore, M1 depends on M2 (M1 M2)
• No more requirement for them to commute!
Dependency Graph
M1 M2foo
• One node per metaprogram
• M2 is a member of target “foo”
• M1 depends on the target “foo”
• Therefore, M1 depends on M2 (M1 M2)
• No more requirement for them to commute!
Dependency Graph
M1 M2foo
• One node per metaprogram
• M2 is a member of target “foo”
• M1 depends on the target “foo”
• Therefore, M1 depends on M2 (M1 M2)
• No more requirement for them to commute!
Dependency Graph
M1 M2foo
• One node per metaprogram
• M2 is a member of target “foo”
• M1 depends on the target “foo”
• Therefore, M1 depends on M2 (M1 M2)
• No more requirement for them to commute!
Dependency Graph
M1 M2foo
• One node per metaprogram
• M2 is a member of target “foo”
• M1 depends on the target “foo”
• Therefore, M1 depends on M2 (M1 M2)
• No more requirement for them to commute!
Dependency Graph
M1 a M4 c M6
M2 M3 b M5 M7
/* M1 */ [: #target a; :]
/* M2 */ [: #target a; :]
/* M3 */ [: #target a, b; :]
/* M4 */ [: #target c; #depends a; :]
/* M5 */ [: #target c; #depends b; :]
/* M6 */ [: #depends c; :]
/* M7 */ [: :]
Dependency Graph
M1 a M4 c M6
M2 M3 b M5 M7
• M6 depends on M2 - no obligation to commute
• No path between M5 and M4 - must commute
• No path to M7 - must always commute
• More paths means less obligation to provecommutativity
Dependency Graph
M1 a M4 c M6
M2 M3 b M5 M7
• M6 depends on M2 - no obligation to commute
• No path between M5 and M4 - must commute
• No path to M7 - must always commute
• More paths means less obligation to provecommutativity
Dependency Graph
M1 a M4 c M6
M2 M3 b M5 M7
• M6 depends on M2 - no obligation to commute
• No path between M5 and M4 - must commute
• No path to M7 - must always commute
• More paths means less obligation to provecommutativity
Dependency Graph
M1 a M4 c M6
M2 M3 b M5 M7
• M6 depends on M2 - no obligation to commute
• No path between M5 and M4 - must commute
• No path to M7 - must always commute
• More paths means less obligation to provecommutativity
A more practical example...
...but first, a new feature
A more practical example...
...but first, a new feature
Meta-Annotations
@@Property private int x;
• Declarative metaprogramming abstraction
• Specifies metaprogram code and dependencies
• Can annotate any declaration or blockstatement
• Allows easy reuse of metaprogrammingconstructs
• Here defined by user class named Property
Meta-Annotations
@@Property private int x;
• Declarative metaprogramming abstraction
• Specifies metaprogram code and dependencies
• Can annotate any declaration or blockstatement
• Allows easy reuse of metaprogrammingconstructs
• Here defined by user class named Property
Meta-Annotations
@@Property private int x;
• Declarative metaprogramming abstraction
• Specifies metaprogram code and dependencies
• Can annotate any declaration or blockstatement
• Allows easy reuse of metaprogrammingconstructs
• Here defined by user class named Property
Meta-Annotations
@@Property private int x;
• Declarative metaprogramming abstraction
• Specifies metaprogram code and dependencies
• Can annotate any declaration or blockstatement
• Allows easy reuse of metaprogrammingconstructs
• Here defined by user class named Property
Meta-Annotations
@@Property private int x;
• Declarative metaprogramming abstraction
• Specifies metaprogram code and dependencies
• Can annotate any declaration or blockstatement
• Allows easy reuse of metaprogrammingconstructs
• Here defined by user class named Property
Meta-Annotation Dependencies@@GenerateConstructorFromProperties
public class Location {
@@Property private int x;
@@Property private int y;
public String toString() {
return "("+this.x+","+this.y+")";
}
}
• Meta-annotation defns. include dependencies• @@Property is a member of target “property”• @@GenerateConstructorFromProperties
depends on “property”
Meta-Annotation Dependencies@@GenerateConstructorFromProperties
public class Location {
@@Property private int x;
@@Property private int y;
public String toString() {
return "("+this.x+","+this.y+")";
}
}
• Meta-annotation defns. include dependencies
• @@Property is a member of target “property”• @@GenerateConstructorFromProperties
depends on “property”
Meta-Annotation Dependencies@@GenerateConstructorFromProperties
public class Location {
@@Property private int x;
@@Property private int y;
public String toString() {
return "("+this.x+","+this.y+")";
}
}
• Meta-annotation defns. include dependencies• @@Property is a member of target “property”
• @@GenerateConstructorFromProperties
depends on “property”
Meta-Annotation Dependencies@@GenerateConstructorFromProperties
public class Location {
@@Property private int x;
@@Property private int y;
public String toString() {
return "("+this.x+","+this.y+")";
}
}
• Meta-annotation defns. include dependencies• @@Property is a member of target “property”• @@GenerateConstructorFromProperties
depends on “property”
BSJ Dependency Graph
@@Property @@Property
@@GenerateConstructorFromProperties
φ1
φ3
φ2
property
• One node per metaprogram
• @@Property participates in “property” target
• @@GenerateConstructorFromProperties
depends on “property”
BSJ Dependency Graph
@@Property @@Property
@@GenerateConstructorFromProperties
φ1
φ3
φ2
property
• One node per metaprogram
• @@Property participates in “property” target
• @@GenerateConstructorFromProperties
depends on “property”
BSJ Dependency Graph
@@Property @@Property
@@GenerateConstructorFromProperties
φ1
φ3
φ2
property
• One node per metaprogram
• @@Property participates in “property” target
• @@GenerateConstructorFromProperties
depends on “property”
BSJ Dependency Graph
@@Property @@Property
@@GenerateConstructorFromProperties
φ1
φ3
φ2
property
• One node per metaprogram
• @@Property participates in “property” target
• @@GenerateConstructorFromProperties
depends on “property”
BSJ Dependency Graph
@@Property @@Property
@@GenerateConstructorFromProperties
φ1
φ3
φ2
property
• One node per metaprogram
• @@Property participates in “property” target
• @@GenerateConstructorFromProperties
depends on “property”
BSJ Dependency Graph
@@Property @@Property
@@GenerateConstructorFromProperties
φ1
φ3
φ2
property
• One node per metaprogram
• @@Property participates in “property” target
• @@GenerateConstructorFromProperties
depends on “property”
BSJ Dependency Graph
@@Property @@Property
@@GenerateConstructorFromProperties
φ1
φ3
φ2
property
• One node per metaprogram
• @@Property participates in “property” target
• @@GenerateConstructorFromProperties
depends on “property”
BSJ Dependency Graph
@@Property @@Property
@@GenerateConstructorFromProperties
φ1
φ3
φ2
property
• φ3 depends on φ1
• φ3 depends on φ2
ρ
◦
◦
BSJ Dependency Graph
@@Property @@Property
@@GenerateConstructorFromProperties
φ1
φ3
φ2
property
• φ3 depends on φ1
• φ3 depends on φ2
ρ
◦
◦
BSJ Dependency Graph
@@Property @@Property
@@GenerateConstructorFromProperties
φ1
φ3
φ2
property
• φ3 depends on φ1
• φ3 depends on φ2
ρ
◦
◦
BSJ Dependency Graph
@@Property @@Property
@@GenerateConstructorFromProperties
φ1
φ3
φ2
property
• φ3 depends on φ1
• φ3 depends on φ2
ρ
◦
◦
Execution Example
ρ
δ̄1
φ1
δ̄2
φ2
+getX
+setX
+getY
+setY
+getY
+setY
+getX
+setX
∼=
Jδ̄1K Jδ̄2K
Jδ̄2K Jδ̄1K
◦
δ̄3
φ3
ρ′
Jδ̄3K
• Execute φ1 obtaining δ̄1.
• Execute φ2 obtaining δ̄2.
• Prove Jδ̄1K and Jδ̄2K commute.
Execution Example
ρ
δ̄1
φ1
δ̄2
φ2
+getX
+setX
+getY
+setY
+getY
+setY
+getX
+setX
∼=
Jδ̄1K Jδ̄2K
Jδ̄2K Jδ̄1K
◦
δ̄3
φ3
ρ′
Jδ̄3K
• Execute φ1 obtaining δ̄1.
• Execute φ2 obtaining δ̄2.
• Prove Jδ̄1K and Jδ̄2K commute.
Execution Example
ρ
δ̄1
φ1
+getX
+setX
δ̄2
φ2
+getX
+setX
+getY
+setY
+getY
+setY
+getX
+setX
∼=
Jδ̄1K Jδ̄2K
Jδ̄2K Jδ̄1K
◦
δ̄3
φ3
ρ′
Jδ̄3K
• Execute φ1 obtaining δ̄1.
• Execute φ2 obtaining δ̄2.
• Prove Jδ̄1K and Jδ̄2K commute.
Execution Example
ρ
δ̄1
φ1
δ̄2
φ2
+getX
+setX
+getY
+setY
+getY
+setY
+getX
+setX
∼=
Jδ̄1K Jδ̄2K
Jδ̄2K Jδ̄1K
◦
δ̄3
φ3
ρ′
Jδ̄3K
• Execute φ1 obtaining δ̄1.
• Execute φ2 obtaining δ̄2.
• Prove Jδ̄1K and Jδ̄2K commute.
Execution Example
ρ
δ̄1
φ1
δ̄2
φ2 +getY
+setY
+getX
+setX
+getY
+setY
+getY
+setY
+getX
+setX
∼=
Jδ̄1K Jδ̄2K
Jδ̄2K Jδ̄1K
◦
δ̄3
φ3
ρ′
Jδ̄3K
• Execute φ1 obtaining δ̄1.
• Execute φ2 obtaining δ̄2.
• Prove Jδ̄1K and Jδ̄2K commute.
Execution Example
ρ
δ̄1
φ1
δ̄2
φ2
+getX
+setX
+getY
+setY
+getY
+setY
+getX
+setX
∼=
Jδ̄1K Jδ̄2K
Jδ̄2K Jδ̄1K
◦
δ̄3
φ3
ρ′
Jδ̄3K
• Execute φ1 obtaining δ̄1.
• Execute φ2 obtaining δ̄2.
• Prove Jδ̄1K and Jδ̄2K commute.
Execution Example
ρ
δ̄1
φ1
δ̄2
φ2
+getX
+setX
+getY
+setY
+getY
+setY
+getX
+setX
∼=
Jδ̄1K Jδ̄2K
Jδ̄2K Jδ̄1K
◦
δ̄3
φ3
ρ′
Jδ̄3K
• Execute φ1 obtaining δ̄1.
• Execute φ2 obtaining δ̄2.
• Prove Jδ̄1K and Jδ̄2K commute.
Execution Example
ρ
δ̄1
φ1
δ̄2
φ2
+getX
+setX
+getY
+setY
+getY
+setY
+getX
+setX
∼=
Jδ̄1K Jδ̄2K
Jδ̄2K Jδ̄1K
◦
δ̄3
φ3
ρ′
Jδ̄3K
• Execute φ1 obtaining δ̄1.
• Execute φ2 obtaining δ̄2.
• Prove Jδ̄1K and Jδ̄2K commute.
Execution Example
ρ
δ̄1
φ1
δ̄2
φ2
+getX
+setX
+getY
+setY
+getY
+setY
+getX
+setX
∼=
Jδ̄1K Jδ̄2K
Jδ̄2K Jδ̄1K
◦
δ̄3
φ3
ρ′
Jδ̄3K
• Execute φ1 obtaining δ̄1.
• Execute φ2 obtaining δ̄2.
• Prove Jδ̄1K and Jδ̄2K commute.
Execution Example
ρ
δ̄1
φ1
δ̄2
φ2
+getX
+setX
+getY
+setY
+getY
+setY
+getX
+setX
∼=
Jδ̄1K Jδ̄2K
Jδ̄2K Jδ̄1K
◦
δ̄3
φ3
ρ′
Jδ̄3K
• Apply Jδ̄1K and Jδ̄2K to ρ.
• Execute φ3 on the result to get δ̄3.
• Apply Jδ̄3K to get the final object program.
Execution Example
ρ
δ̄1
φ1
δ̄2
φ2
+getX
+setX
+getY
+setY
+getY
+setY
+getX
+setX
∼=
Jδ̄1K Jδ̄2K
Jδ̄2K Jδ̄1K
◦
δ̄3
φ3
ρ′
Jδ̄3K
• Apply Jδ̄1K and Jδ̄2K to ρ.
• Execute φ3 on the result to get δ̄3.
• Apply Jδ̄3K to get the final object program.
Execution Example
ρ
δ̄1
φ1
δ̄2
φ2
+getX
+setX
+getY
+setY
+getY
+setY
+getX
+setX
∼=
Jδ̄1K Jδ̄2K
Jδ̄2K Jδ̄1K
◦
δ̄3
φ3
ρ′
Jδ̄3K
• Apply Jδ̄1K and Jδ̄2K to ρ.
• Execute φ3 on the result to get δ̄3.
• Apply Jδ̄3K to get the final object program.
Execution Example
ρ
δ̄1
φ1
δ̄2
φ2
+getX
+setX
+getY
+setY
+getY
+setY
+getX
+setX
∼=
Jδ̄1K Jδ̄2K
Jδ̄2K Jδ̄1K
◦
δ̄3
φ3
ρ′
Jδ̄3K
• Apply Jδ̄1K and Jδ̄2K to ρ.
• Execute φ3 on the result to get δ̄3.
• Apply Jδ̄3K to get the final object program.
Execution Example
ρ
δ̄1
φ1
δ̄2
φ2
+getX
+setX
+getY
+setY
+getY
+setY
+getX
+setX
∼=
Jδ̄1K Jδ̄2K
Jδ̄2K Jδ̄1K
◦
δ̄3
φ3
ρ′
Jδ̄3K
• Apply Jδ̄1K and Jδ̄2K to ρ.
• Execute φ3 on the result to get δ̄3.
• Apply Jδ̄3K to get the final object program.
Execution Example
ρ
δ̄1
φ1
δ̄2
φ2
+getX
+setX
+getY
+setY
+getY
+setY
+getX
+setX
∼=
Jδ̄1K Jδ̄2K
Jδ̄2K Jδ̄1K
◦
δ̄3
φ3
ρ′
Jδ̄3K
• Apply Jδ̄1K and Jδ̄2K to ρ.
• Execute φ3 on the result to get δ̄3.
• Apply Jδ̄3K to get the final object program.
Execution Example
ρ
δ̄1
φ1
δ̄2
φ2
+getX
+setX
+getY
+setY
+getY
+setY
+getX
+setX
∼=
Jδ̄1K Jδ̄2K
Jδ̄2K Jδ̄1K
◦
δ̄3
φ3
ρ′
Jδ̄3K
• Apply Jδ̄1K and Jδ̄2K to ρ.
• Execute φ3 on the result to get δ̄3.
• Apply Jδ̄3K to get the final object program.
Execution Example
ρ
δ̄1
φ1
δ̄2
φ2
+getX
+setX
+getY
+setY
+getY
+setY
+getX
+setX
∼=
Jδ̄1K Jδ̄2K
Jδ̄2K Jδ̄1K
◦
δ̄3
φ3
ρ′
Jδ̄3K
• Apply Jδ̄1K and Jδ̄2K to ρ.
• Execute φ3 on the result to get δ̄3.
• Apply Jδ̄3K to get the final object program.
Execution Example
ρ
δ̄1
φ1
δ̄2
φ2
+getX
+setX
+getY
+setY
+getY
+setY
+getX
+setX
∼=
Jδ̄1K Jδ̄2K
Jδ̄2K Jδ̄1K
◦
δ̄3
φ3
ρ′
Jδ̄3K
• Apply Jδ̄1K and Jδ̄2K to ρ.
• Execute φ3 on the result to get δ̄3.
• Apply Jδ̄3K to get the final object program.
Difference-Based MetaprogrammingSummary
• Ambiguities detected at compile-time
• Metaprograms can inspect their environments
• Modular, declarative metaprogramming style
• Suitable for OO languages like Java
Difference-Based MetaprogrammingSummary
• Ambiguities detected at compile-time
• Metaprograms can inspect their environments
• Modular, declarative metaprogramming style
• Suitable for OO languages like Java
Difference-Based MetaprogrammingSummary
• Ambiguities detected at compile-time
• Metaprograms can inspect their environments
• Modular, declarative metaprogramming style
• Suitable for OO languages like Java
Difference-Based MetaprogrammingSummary
• Ambiguities detected at compile-time
• Metaprograms can inspect their environments
• Modular, declarative metaprogramming style
• Suitable for OO languages like Java
Backstage Java Implementation
• Working reference implementation available
• Includes source (∼50k SLOC)
• Full superset of Java 1.6
Backstage Java Implementation
• Working reference implementation available
• Includes source (∼50k SLOC)
• Full superset of Java 1.6
Backstage Java Implementation
• Working reference implementation available
• Includes source (∼50k SLOC)
• Full superset of Java 1.6
BSJ Standard Library – @@Memoized
@@Memoized
• Class for generating images
• Each image is generated from pair of Colors
• Memoizing image generation routine forperformance
• Store cached images in a private Map keyed byinput to generation method
BSJ Standard Library – @@Memoized
@@Memoized
• Class for generating images
• Each image is generated from pair of Colors
• Memoizing image generation routine forperformance
• Store cached images in a private Map keyed byinput to generation method
BSJ Standard Library – @@Memoized
@@Memoized
• Class for generating images
• Each image is generated from pair of Colors
• Memoizing image generation routine forperformance
• Store cached images in a private Map keyed byinput to generation method
BSJ Standard Library – @@Memoized
@@Memoized
• Class for generating images
• Each image is generated from pair of Colors
• Memoizing image generation routine forperformance
• Store cached images in a private Map keyed byinput to generation method
BSJ Standard Library – @@Memoized
@@Memoized
• Class for generating images
• Each image is generated from pair of Colors
• Memoizing image generation routine forperformance
• Store cached images in a private Map keyed byinput to generation method
BSJ Standard Library – @@Memoized
public class ImageGenerator {
@@Memoized
public Image gen(Color a, Color b) {· · · }}
BSJ Standard Library – @@Memoized
public class ImageGenerator {
@@Memoized
public Image gen(Color a, Color b) {· · · }}
BSJ Standard Library – @@Memoized
public class ImageGenerator {
private static class Key {
private Color a;
private Color b;
· · ·}
public Image gen(Color a, Color b) {· · · }
public Image gen(Color a, Color b) {
/* return cache value, igen as needed */
}
}
BSJ Standard Library – @@Memoized
public class ImageGenerator {
private static class Key {
private Color a;
private Color b;
· · ·}
private Map<???,Image> cache = new · · ·public Image gen(Color a, Color b) {· · · }
public Image gen(Color a, Color b) {
/* return cache value, igen as needed */
}
}
BSJ Standard Library – @@Memoized
public class ImageGenerator {
private static class Key {
private Color a;
private Color b;
· · ·}
private Map<???,Image> cache = new · · ·public Image gen(Color a, Color b) {· · · }
public Image gen(Color a, Color b) {
/* return cache value, igen as needed */
}
}
BSJ Standard Library – @@Memoized
public class ImageGenerator {
private static class Key {
private Color a;
private Color b;
· · ·}
private Map<Key,Image> cache = new · · ·public Image gen(Color a, Color b) {· · · }
public Image gen(Color a, Color b) {
/* return cache value, igen as needed */
}
}
BSJ Standard Library – @@Memoized
public class ImageGenerator {
private static class Key {
private Color a;
private Color b;
· · ·}
private Map<Key,Image> cache = new · · ·private Image igen(Color a, Color b) {· · · }
public Image gen(Color a, Color b) {
/* return cache value, igen as needed */
}
}
BSJ Standard Library – @@Memoized
public class ImageGenerator {
private static class Key {
private Color a;
private Color b;
· · ·}
private Map<Key,Image> cache = new · · ·private Image igen(Color a, Color b) {· · · }public Image gen(Color a, Color b) {
/* return cache value, igen as needed */
}
}
BSJ Standard Library – @@Memoized
public class ImageGenerator {
@@Memoized
public Image gen(Color a, Color b) {· · · }}
Difference-Based Metaprogramming
Questions?
Difference-Based MetaprogrammingQuestions?
Expressiveness
Difference-based metaprogramming separatesanalysis from modification.
public class Example {
private int x = 0;
private int y = 0;
@@LogAndCount
public void foo() { · · · }
@@LogAndCount
public void bar() { · · · }
}
Injection Conflicts
M1 M2 M3
M4
t
Injection Conflicts
M1 M2 M3
M4 t