Upload
others
View
0
Download
0
Embed Size (px)
Citation preview
From Object Algebrasto Attribute Grammars
Tillmann Rendel · Jonathan Brachthäuser · Klaus OstermannUniversity of Marburg · University of Tübingen
http://www.informatik.uni-marburg.de/~rendel/oa2ag
Presentation by Tillmann Rendel at the International Conferenceon Object-Oriented Programming, Systems, Languages, and ApplicationsPortland, Oregon, October 23, 2014
Tree Traversals
1/15
Tree Traversals
1/15
Tree Traversals
How to structurea programthat containsmultiple traversalsof complex trees?
1/15
Visitor Patternin object-oriented programming
Folds & Traversal Schemesin functional programming
Church Encodingin theoretical work
Attribute Grammarsfor compiler construction
2/15
Visitor Patternin object-oriented programming
Folds & Traversal Schemesin functional programming
Church Encodingin theoretical work
Attribute Grammarsfor compiler construction
Hinze (2006)
Chirica & Martin (1979) Johnsson (1987)
Gibbons (2006)
Buchlovsky & Thielecke (2006) Oliveira et al. (2008)Oliveira et al. (2013)
Middelkoop et al. (2011)
2/15
Visitor Patternin object-oriented programming
Folds & Traversal Schemesin functional programming
Church Encodingin theoretical work
Attribute Grammarsfor compiler construction
Hinze (2006)
Chirica & Martin (1979) Johnsson (1987)
Gibbons (2006)
Buchlovsky & Thielecke (2006) Oliveira et al. (2008)Oliveira et al. (2013)
this paper
Middelkoop et al. (2011)
2/15
Visitor Patternin object-oriented programming
Folds & Traversal Schemesin functional programming
Church Encodingin theoretical work
Object Algebrasin Scala
Attribute Grammarsfor compiler construction
Hinze (2006)
Chirica & Martin (1979) Johnsson (1987)
Gibbons (2006)
Buchlovsky & Thielecke (2006) Oliveira et al. (2008)Oliveira et al. (2013)
this paper
Middelkoop et al. (2011)
2/15
Bottom-Up Data Flow
3/15
Synthesized Attributes
Grammare0 → n { Lit }e1 → e2 "+" e3 { Add }
Signaturetrait Sig[E] { def Lit: Int ⇒ E def Add: (E, E) ⇒ E}
Equationse0.value = ne1 .value = e2.value + e3.value
Algebraval Alg = new Sig[Int] { def Lit = n ⇒ n def Add = (e2, e3) ⇒ e2 + e3}
4/15
Synthesized Attributes
Grammare0 → n { Lit }e1 → e2 "+" e3 { Add }
Signaturetrait Sig[E] { def Lit: Int ⇒ E def Add: (E, E) ⇒ E}
Equationse0.value = ne1 .value = e2.value + e3.value
Algebraval Alg = new Sig[Int] { def Lit = n ⇒ n def Add = (e2, e3) ⇒ e2 + e3}
4/15
Synthesized Attributes
Grammare0 → n { Lit }e1 → e2 "+" e3 { Add }
Signaturetrait Sig[E] { def Lit: Int ⇒ E def Add: (E, E) ⇒ E}
Equationse0.value = ne1 .value = e2.value + e3.value
Algebraval Alg = new Sig[Int] { def Lit = n ⇒ n def Add = (e2, e3) ⇒ e2 + e3}
4/15
Synthesized Attributes
Grammare0 → n { Lit }e1 → e2 "+" e3 { Add }
Signaturetrait Sig[E] { def Lit: Int ⇒ E def Add: (E, E) ⇒ E}
Equationse0.value = ne1 .value = e2.value + e3.value
Algebraval Alg = new Sig[Int] { def Lit = n ⇒ n def Add = (e2, e3) ⇒ e2 + e3}
4/15
Synthesized Attributes
Grammare0 → n { Lit }e1 → e2 "+" e3 { Add }
Signaturetrait Sig[E] { def Lit: Int ⇒ E def Add: (E, E) ⇒ E}
Equationse0.value = ne1 .value = e2.value + e3.value
Algebraval Alg = new Sig[Int] { def Lit = n ⇒ n def Add = (e2, e3) ⇒ e2 + e3}
4/15
Synthesized Attributes
Grammare0 → n { Lit }e1 → e2 "+" e3 { Add }
Signaturetrait Sig[E] { def Lit: Int ⇒ E def Add: (E, E) ⇒ E}
Equationse0.value = ne1 .value = e2.value + e3.value
Algebraval Alg = new Sig[Int] { def Lit = n ⇒ n def Add = (e2, e3) ⇒ e2 + e3}
4/15
Synthesized Attributes
Grammare0 → n { Lit }e1 → e2 "+" e3 { Add }
Signaturetrait Sig[E] { def Lit: Int ⇒ E def Add: (E, E) ⇒ E}
Equationse0.value = ne1 .value = e2.value + e3.value
Algebraval Alg = new Sig[Int] { def Lit = n ⇒ n def Add = (e2, e3) ⇒ e2 + e3}
4/15
Synthesized Attributes
Grammare0 → n { Lit }e1 → e2 "+" e3 { Add }
Signaturetrait Sig[E] { def Lit: Int ⇒ E def Add: (E, E) ⇒ E}
Equationse0.value = ne1 .value = e2.value + e3.value
Algebraval Alg = new Sig[Int] { def Lit = n ⇒ n def Add = (e2, e3) ⇒ e2 + e3}
4/15
Synthesized Attributes
Grammare0 → n { Lit }e1 → e2 "+" e3 { Add }
Signaturetrait Sig[E] { def Lit: Int ⇒ E def Add: (E, E) ⇒ E}
Equationse0.value = ne1 .value = e2.value + e3.value
Algebraval Alg = new Sig[Int] { def Lit = n ⇒ n def Add = (e2, e3) ⇒ e2 + e3}
4/15
Synthesized Attributes
Grammare0 → n { Lit }e1 → e2 "+" e3 { Add }
Signaturetrait Sig[E] { def Lit: Int ⇒ E def Add: (E, E) ⇒ E}
Equationse0.value = ne1 .value = e2.value + e3.value
Algebraval Alg = new Sig[Int] { def Lit = n ⇒ n def Add = (e2, e3) ⇒ e2 + e3}
4/15
Top-Down Data Flow
5/15
Inherited Attributes
Grammare0 → n { Lit }e1 → e2 "+" e3 { Add }
Signaturetrait Sig[E] { def Add1: E ⇒ E def Add2: (E, E) ⇒ E}
Equationse2 .left = truee3 .left = false
Algebraval Alg = new Sig[Bool] { def Add1 = e ⇒ true def Add2 = (e1, e2) ⇒ false}
6/15
Inherited Attributes
Grammare0 → n { Lit }e1 → e2 "+" e3 { Add }
Signaturetrait Sig[E] { def Add1: E ⇒ E def Add2: (E, E) ⇒ E}
Equationse2 .left = truee3 .left = false
Algebraval Alg = new Sig[Bool] { def Add1 = e ⇒ true def Add2 = (e1, e2) ⇒ false}
6/15
Inherited Attributes
Grammare0 → n { Lit }e1 → e2 "+" e3 { Add }
Signaturetrait Sig[E] { def Add1: E ⇒ E def Add2: (E, E) ⇒ E}
Equationse2 .left = truee3 .left = false
Algebraval Alg = new Sig[Bool] { def Add1 = e ⇒ true def Add2 = (e1, e2) ⇒ false}
6/15
Inherited Attributes
Grammare0 → n { Lit }e1 → e2 "+" e3 { Add }
Signaturetrait Sig[E] { def Add1: E ⇒ E def Add2: (E, E) ⇒ E}
Equationse2 .left = truee3 .left = false
Algebraval Alg = new Sig[Bool] { def Add1 = e ⇒ true def Add2 = (e1, e2) ⇒ false}
6/15
Inherited Attributes
Grammare0 → n { Lit }e1 → e2 "+" e3 { Add }
Signaturetrait Sig[E] { def Add1: E ⇒ E def Add2: (E, E) ⇒ E}
Equationse2 .left = truee3 .left = false
Algebraval Alg = new Sig[Bool] { def Add1 = e ⇒ true def Add2 = (e1, e2) ⇒ false}
6/15
Inherited Attributes
Grammare0 → n { Lit }e1 → e2 "+" e3 { Add }
Signaturetrait Sig[E] { def Add1: E ⇒ E def Add2: (E, E) ⇒ E}
Equationse2 .left = truee3 .left = false
Algebraval Alg = new Sig[Bool] { def Add1 = e ⇒ true def Add2 = (e1, e2) ⇒ false}
6/15
Composition
7/15
Composition
compose
7/15
Composition
compose
7/15
Composition
assemble
7/15
compose( , ) =
Extensible Recordstrait HasValue { def value: Int }trait HasLeft { def left: Bool }def mix[A, B]: (A, B) ⇒ A with B
Dependency Trackingtrait Sig[-E, -C, +O] { def Lit: Int ⇒ C ⇒ O def Add: (E, E) ⇒ C ⇒ O}
8/15
compose( , ) =
Extensible Recordstrait HasValue { def value: Int }trait HasLeft { def left: Bool }def mix[A, B]: (A, B) ⇒ A with B
Dependency Trackingtrait Sig[-E, -C, +O] { def Lit: Int ⇒ C ⇒ O def Add: (E, E) ⇒ C ⇒ O}
8/15
compose( , ) =
Extensible Recordstrait HasValue { def value: Int }trait HasLeft { def left: Bool }def mix[A, B]: (A, B) ⇒ A with B
Dependency Trackingtrait Sig[-E, -C, +O] { def Lit: Int ⇒ C ⇒ O def Add: (E, E) ⇒ C ⇒ O}
8/15
compose( , ) =
Extensible Recordstrait HasValue { def value: Int }trait HasLeft { def left: Bool }def mix[A, B]: (A, B) ⇒ A with B
Dependency Trackingtrait Sig[-E, -C, +O] { def Lit: Int ⇒ C ⇒ O def Add: (E, E) ⇒ C ⇒ O}
8/15
compose( , ) =
Extensible Recordstrait HasValue { def value: Int }trait HasLeft { def left: Bool }def mix[A, B]: (A, B) ⇒ A with B
Dependency Trackingtrait Sig[-E, -C, +O] { def Lit: Int ⇒ C ⇒ O def Add: (E, E) ⇒ C ⇒ O}
8/15
compose( , ) =
Extensible Recordstrait HasValue { def value: Int }trait HasLeft { def left: Bool }def mix[A, B]: (A, B) ⇒ A with B
Dependency Trackingtrait Sig[-E, -C, +O] { def Lit: Int ⇒ C ⇒ O def Add: (E, E) ⇒ C ⇒ O}
8/15
compose( , ) =
Extensible Recordstrait HasValue { def value: Int }trait HasLeft { def left: Bool }def mix[A, B]: (A, B) ⇒ A with B
Dependency Trackingtrait Sig[-E, -C, +O] { def Lit: Int ⇒ C ⇒ O def Add: (E, E) ⇒ C ⇒ O}
8/15
compose( , ) =
Extensible Recordstrait HasValue { def value: Int }trait HasLeft { def left: Bool }def mix[A, B]: (A, B) ⇒ A with B
Dependency Trackingtrait Sig[-E, -C, +O] { def Lit: Int ⇒ C ⇒ O def Add: (E, E) ⇒ C ⇒ O}
8/15
current node
compose( , ) =
Extensible Recordstrait HasValue { def value: Int }trait HasLeft { def left: Bool }def mix[A, B]: (A, B) ⇒ A with B
Dependency Trackingtrait Sig[-E, -C, +O] { def Lit: Int ⇒ C ⇒ O def Add: (E, E) ⇒ C ⇒ O}
8/15
current node
children
compose( , ) =
Extensible Recordstrait HasValue { def value: Int }trait HasLeft { def left: Bool }def mix[A, B]: (A, B) ⇒ A with B
Dependency Trackingtrait Sig[-E, -C, +O] { def Lit: Int ⇒ C ⇒ O def Add: (E, E) ⇒ C ⇒ O}
8/15
current node
context fromparent
compose( , ) =
Extensible Recordstrait HasValue { def value: Int }trait HasLeft { def left: Bool }def mix[A, B]: (A, B) ⇒ A with B
Dependency Trackingtrait Sig[-E, -C, +O] { def Lit: Int ⇒ C ⇒ O def Add: (E, E) ⇒ C ⇒ O}
8/15
current node
compose( , ) =
Extensible Recordstrait HasValue { def value: Int }trait HasLeft { def left: Bool }def mix[A, B]: (A, B) ⇒ A with B
Dependency Trackingtrait Sig[-E, -C, +O] { def Lit: Int ⇒ C ⇒ O def Add: (E, E) ⇒ C ⇒ O}
8/15
compose( , ) =
Extensible Recordstrait HasValue { def value: Int }trait HasLeft { def left: Bool }def mix[A, B]: (A, B) ⇒ A with B
Dependency Trackingtrait Sig[-E, -C, +O] { def Lit: Int ⇒ C ⇒ O def Add: (E, E) ⇒ C ⇒ O}
8/15
compose( , ) =
Extensible Recordstrait HasValue { def value: Int }trait HasLeft { def left: Bool }def mix[A, B]: (A, B) ⇒ A with B
Dependency Trackingtrait Sig[-E, -C, +O] { def Lit: Int ⇒ C ⇒ O def Add: (E, E) ⇒ C ⇒ O}
8/15
compose( , ) =
Composing two algebrasdef compose [E1, C1, O1, E2, C2 >: C1 with O1, O2] (alg1: Sig[E1, C1, O1], alg2: Sig[E2, C2, O2]): Sig[E1 with E2, C1, O1 with O2]
9/15
compose( , ) =
Composing two algebrasdef compose [E1, C1, O1, E2, C2 >: C1 with O1, O2] (alg1: Sig[E1, C1, O1], alg2: Sig[E2, C2, O2]): Sig[E1 with E2, C1, O1 with O2]
9/15
compose( , ) =
Composing two algebrasdef compose [E1, C1, O1, E2, C2 >: C1 with O1, O2] (alg1: Sig[E1, C1, O1], alg2: Sig[E2, C2, O2]): Sig[E1 with E2, C1, O1 with O2]
9/15
compose( , ) =
Composing two algebrasdef compose [E1, C1, O1, E2, C2 >: C1 with O1, O2] (alg1: Sig[E1, C1, O1], alg2: Sig[E2, C2, O2]): Sig[E1 with E2, C1, O1 with O2]
9/15
compose( , ) =
Composing two algebrasdef compose [E1, C1, O1, E2, C2 >: C1 with O1, O2] (alg1: Sig[E1, C1, O1], alg2: Sig[E2, C2, O2]): Sig[E1 with E2, C1, O1 with O2]
9/15
compose( , ) =
Composing two algebrasdef compose [E1, C1, O1, E2, C2 >: C1 with O1, O2] (alg1: Sig[E1, C1, O1], alg2: Sig[E2, C2, O2]): Sig[E1 with E2, C1, O1 with O2]
9/15
compose( , ) =
Composing two algebrasdef compose [E1, C1, O1, E2, C2 >: C1 with O1, O2] (alg1: Sig[E1, C1, O1], alg2: Sig[E2, C2, O2]): Sig[E1 with E2, C1, O1 with O2]
9/15
compose( , ) =
Composing two algebrasdef compose [E1, C1, O1, E2, C2 >: C1 with O1, O2] (alg1: Sig[E1, C1, O1], alg2: Sig[E2, C2, O2]): Sig[E1 with E2, C1, O1 with O2]
9/15
Assembling a one-pass traversaldef assemble [C, O] (alg1: Sig1[C with O, C, O], alg2: Sig2[C with O, C, C]): Sig[C ⇒ C with O]
assemble( , ) =
10/15
Assembling a one-pass traversaldef assemble [C, O] (alg1: Sig1[C with O, C, O], alg2: Sig2[C with O, C, C]): Sig[C ⇒ C with O]
assemble( , ) =
10/15
Assembling a one-pass traversaldef assemble [C, O] (alg1: Sig1[C with O, C, O], alg2: Sig2[C with O, C, C]): Sig[C ⇒ C with O]
assemble( , ) =
10/15
Assembling a one-pass traversaldef assemble [C, O] (alg1: Sig1[C with O, C, O], alg2: Sig2[C with O, C, C]): Sig[C ⇒ C with O]
assemble( , ) =
10/15
Assembling a one-pass traversaldef assemble [C, O] (alg1: Sig1[C with O, C, O], alg2: Sig2[C with O, C, C]): Sig[C ⇒ C with O]
assemble( , ) =
10/15
Results
Object algebras correspondto synthesized attributes(bottom-up data-flow)
We extend object algebrasto support inherited attributes(top-down data flow)
We assemble multiple algebrasto support L-attributed grammars(arbitrary one-pass compiler)
11/15
Results
Object algebras correspondto synthesized attributes(bottom-up data-flow)
We extend object algebrasto support inherited attributes(top-down data flow)
We assemble multiple algebrasto support L-attributed grammars(arbitrary one-pass compiler)
11/15
Results
Object algebras correspondto synthesized attributes(bottom-up data-flow)
We extend object algebrasto support inherited attributes(top-down data flow)
We assemble multiple algebrasto support L-attributed grammars(arbitrary one-pass compiler)
11/15
11/15
Results
Object algebras correspondto synthesized attributes(bottom-up data-flow)
We extend object algebrasto support inherited attributes(top-down data flow)
We assemble multiple algebrasto support L-attributed grammars(arbitrary one-pass compiler)
Modularizing a One-Pass Compiler
● existing one-pass compiler for a subset of C● 9 nonterminals● written for teaching at Aarhus university
(not by the authors of the present paper)
12/15
Monolithic compiler1 file807 lines of Java codeentangled
Modularized compilerca. 25 files1620 lines of Scala codemodular
13/15
Properties of the Encoding
ModularAttributes are defined and type-checked separately
ScalableScala code size is linear in AG specification size.
CompositionalEach AG artifact is represented as a Scala value.
14/15
Properties of the Encoding
ModularAttributes are defined and type-checked separately
ScalableScala code size is linear in AG specification size.
CompositionalEach AG artifact is represented as a Scala value.
14/15
Properties of the Encoding
ModularAttributes are defined and type-checked separately
ScalableScala code size is linear in AG specification size.
CompositionalEach AG artifact is represented as a Scala value.
14/15
Properties of the Encoding
ModularAttributes are defined and type-checked separately
ScalableScala code size is linear in AG specification size
CompositionalEach AG artifact is represented as a Scala value.
14/15
Conclusions
Object Algebrasin Scala
Attribute Grammarsfor compiler construction
Rendel et al. (2014)
15/15
Conclusions
Object Algebrasin Scala
Benefits for OA
● Support forinherited attributes
● Access toextensive AG research
● Future work:encode more AG features
Attribute Grammarsfor compiler construction
Rendel et al. (2014)
15/15
Conclusions
Object Algebrasin Scala
Benefits for OA
● Support forinherited attributes
● Access toextensive AG research
● Future work:encode more AG features
Attribute Grammarsfor compiler construction
Benefits for AG
● Modular, scalable, and compositional encoding
● Embedding enablesabstraction via meta language
● Future work:AG compiler to object algebras
Rendel et al. (2014)
15/15
Conclusions
Object Algebrasin Scala
Benefits for OA
● Support forinherited attributes
● Access toextensive AG research
● Future work:encode more AG features
Attribute Grammarsfor compiler construction
Benefits for AG
● Modular, scalable, and compositional encoding
● Embedding enablesabstraction via meta language
● Future work:AG compiler to object algebras
Rendel et al. (2014)
Thank You!