◦ ◦◦◦ TECHNISCHE UNIVERSITAT¨ MUNCHEN¨ ◦◦◦◦ ◦ ◦ ◦◦◦ ◦◦◦◦ ¨ ¨ ◦ ◦◦ FAKULTAT FUR INFORMATIK
Linearization in Multiple Inheritance
Seminar “Example Talk”
Dr. Michael Petter Winter term 2016 Outline Basics of Linearization
1 Linearization vs. Ambiguous Dispatching 2 Resources for Establishing Order
DFS Linearizations
1 DFS (w. or w/o. Duplicate Cancellation) 2 Reverse Rightmost DFS 3 Refined DFSs
C3 Linearization
1 Basic algorithm 2 Practical example
Discussion
1 Linearization vs. Explicit Qualification 2 Language examples Multiple inheritance class diagram
A B int f(int) int f(int) int a int b
C
int c Ambiguities
classA{ void f(int); }; classB{ void f(int); }; classC: publicA, public B {};
C* pc; pc->f(42);
! Which method is called? Solution I: Explicit qualification Solution II: Automagical resolution Idea: The Compiler introduces a pc->A::f(42); linear order on the nodes of the pc->B::f(42); inheritance graph Linearization
Principle 1: Inheritance Relation Principle 2: Multiplicity Relation Defined by parent-child. Example: Defined by the succession of C(A, B) =⇒ C −BA ∧ C −BB multiple parents. Example: C(A, B) =⇒ A → B
In General: 1 Inheritance is a uniform mechanism, and its searches (→ total order) apply identically for all object fields or methods 2 In the literature, we also find the set of constraints to create a linearization as Method Resolution Order 3 Linearization is a best-effort approach at best L[A] = ABCW XPrinciple 1 inheritance is fixed
L[A] = ABCW V
! Principle 2 multiplicity not fulfillable ! However B → C =⇒ W → V ??
L[A] = ABW C
! Principle 1 inheritance is violated Python: classical python objects (≤ 2.1) use LPDFS! LPDFS with Duplicate Cancellation
Python: new python objects (2.2) use LPDFS(DC)! LPDFS with Duplicate Cancellation
MRO via DFS W Leftmost Preorder Depth-First Search
B C
A A(B,C) B(W ) C(W ) L[A] = ABCW V
! Principle 2 multiplicity not fulfillable ! However B → C =⇒ W → V ??
L[A] = ABCW XPrinciple 1 inheritance is fixed
Python: new python objects (2.2) use LPDFS(DC)! LPDFS with Duplicate Cancellation
MRO via DFS W Leftmost Preorder Depth-First Search
L[A] = ABW C B C ! Principle 1 inheritance is violated Python: classical python objects (≤ 2.1) use LPDFS! LPDFS with Duplicate Cancellation A A(B,C) B(W ) C(W ) L[A] = ABCW V
! Principle 2 multiplicity not fulfillable ! However B → C =⇒ W → V ??
MRO via DFS W Leftmost Preorder Depth-First Search
L[A] = ABW C B C ! Principle 1 inheritance is violated Python: classical python objects (≤ 2.1) use LPDFS! LPDFS with Duplicate Cancellation A A(B,C) B(W ) C(W ) L[A] = ABCW XPrinciple 1 inheritance is fixed V W Python: new python objects (2.2) use LPDFS(DC)! LPDFS with Duplicate Cancellation B C
A A(B,C)B(V,W )C(W, V ) MRO via DFS W Leftmost Preorder Depth-First Search
L[A] = ABW C B C ! Principle 1 inheritance is violated Python: classical python objects (≤ 2.1) use LPDFS! LPDFS with Duplicate Cancellation A A(B,C) B(W ) C(W ) L[A] = ABCW XPrinciple 1 inheritance is fixed V W Python: new python objects (2.2) use LPDFS(DC)! LPDFS with Duplicate Cancellation B C L[A] = ABCW V ! Principle 2 multiplicity not fulfillable A ! However B → C =⇒ W → V ?? A(B,C)B(V,W )C(W, V ) L[A] = ABCDGEF
! But principle 2 multiplicity is violated!
L[A] = ABCDEF G XRefine graph with conflict edge & rerun RPRDFS!
L[A] = ABF DCEGHW XLinear extension of inheritance relation
RPRDFS
FG CLOS: uses Refined RPDFS [3] B D E Refined RPRDFS C A A(B,C) B(F,G) C(D,E) D(G) E(F )
MRO via Refined Postorder DFS W Reverse Postorder Rightmost DFS G D EF H B C A A(B,C) B(F,D) C(E,H) D(G) E(G) F (W ) G(W ) H(W ) L[A] = ABCDEF G XRefine graph with conflict edge & rerun RPRDFS!
L[A] = ABCDGEF
! But principle 2 multiplicity is violated! CLOS: uses Refined RPDFS [3]
Refined RPRDFS
FG B D E C A A(B,C) B(F,G) C(D,E) D(G) E(F )
MRO via Refined Postorder DFS W Reverse Postorder Rightmost DFS G L[A] = ABF DCEGHW D EF H XLinear extension of inheritance relation B C A RPRDFS A(B,C) B(F,D) C(E,H) D(G) E(G) F (W ) G(W ) H(W )
FG B D E C A A(B,C) B(F,G) C(D,E)
D(G) E(F ) L[A] = ABCDEF G XRefine graph with conflict edge & rerun RPRDFS!
CLOS: uses Refined RPDFS [3]
Refined RPRDFS
FG B D E C A A(B,C) B(F,G) C(D,E) D(G) E(F )
MRO via Refined Postorder DFS W Reverse Postorder Rightmost DFS G L[A] = ABF DCEGHW D EF H XLinear extension of inheritance relation B C A RPRDFS A(B,C) B(F,D) C(E,H) D(G) E(G) F (W ) G(W ) H(W ) L[A] = ABCDGEF ! But principle 2 multiplicity is violated! FG B D E C A A(B,C) B(F,G) C(D,E)
D(G) E(F ) CLOS: uses Refined RPDFS [3]
L[A] = ABCDEF G XRefine graph with conflict edge & rerun RPRDFS! FG B D E C A A(B,C) B(F,G) C(D,E) D(G) E(F )
MRO via Refined Postorder DFS W Reverse Postorder Rightmost DFS G L[A] = ABF DCEGHW D EF H XLinear extension of inheritance relation B C A RPRDFS A(B,C) B(F,D) C(E,H) D(G) E(G) F (W ) G(W ) H(W ) L[A] = ABCDGEF ! But principle 2 multiplicity is violated! FG B D E Refined RPRDFS C A A(B,C) B(F,G) C(D,E)
D(G) E(F ) MRO via Refined Postorder DFS W Reverse Postorder Rightmost DFS G L[A] = ABF DCEGHW D EF H XLinear extension of inheritance relation B C A RPRDFS A(B,C) B(F,D) C(E,H) D(G) E(G) F (W ) G(W ) H(W ) L[A] = ABCDGEF ! But principle 2 multiplicity is violated! FG CLOS: uses Refined RPDFS [3] B D E Refined RPRDFS L[A] = ABCDEF G C A XRefine graph with conflict edge & rerun RPRDFS! A(B,C) B(F,G) C(D,E) D(G) E(F ) Refined RPRDFS ! Monotonicity is not guaranteed!
MRO via Refined Postorder DFS
FG B D E Extension Principle: Monotonicity C If C1 → C2 in C’s linearization, then C1 → C2 for every linearization of C’s children. A A(B,C) B(F,G) C(D,E) D(G) E(F ) MRO via Refined Postorder DFS
Refined RPRDFS ! Monotonicity is not guaranteed! FG B D E Extension Principle: Monotonicity C If C1 → C2 in C’s linearization, then C1 → C2 for every linearization of C’s children. A A(B,C) B(F,G) C(D,E) D(G) E(F ) MRO via Refined Postorder DFS
Refined RPRDFS ! Monotonicity is not guaranteed! FG B D E Extension Principle: Monotonicity C If C1 → C2 in C’s linearization, then C1 → C2 for every linearization of C’s children. A A(B,C) B(F,G) C(D,E) D(G) E(F ) L[A] = ABCDEFG =⇒ F → G
L[C] = DGEF =⇒ G → F MRO via C3 Linearization
A linearization L is an attribute L[C] of a class C. Classes B1,...,Bn are superclasses to child class C, defined in the local precedence order C(B1 ...Bn). Then G L[C] = C · (L[B1],...,L[Bn],B1 · ... · Bn) | C(B1,...,Bn) L[Object] = Object
with
( F G c · ( i(Li \ c)) if ∃min k∀j c = head(Lk) ∈/ tail(Lj) (Li) = ! i fail else E · F D · G
C3 detects and reports a violation of monotonicity with the addition of A(B,C) to the class set. C3 linearization [1]: is used in OpenDylan, Python, and Perl 6
MRO via C3 Linearization
FG B D E L[G] G L[F ] F C L[E] A L[D] A(B,C) B(F,G) C(D,E) L[B] D(G) E(F ) L[C] L[A] C3 detects and reports a violation of monotonicity with the addition of A(B,C) to the class set. C3 linearization [1]: is used in OpenDylan, Python, and Perl 6
MRO via C3 Linearization
FG B D E L[G] G L[F ] F C L[E] E · F A L[D] D · G A(B,C) B(F,G) C(D,E) L[B] D(G) E(F ) L[C] L[A] C3 detects and reports a violation of monotonicity with the addition of A(B,C) to the class set. C3 linearization [1]: is used in OpenDylan, Python, and Perl 6
MRO via C3 Linearization
FG B D E L[G] G L[F ] F C L[E] E · F A L[D] D · G A(B,C) B(F,G) C(D,E) L[B] B · (L[F ] t L[G] t (F · G)) D(G) E(F ) L[C] L[A] C3 detects and reports a violation of monotonicity with the addition of A(B,C) to the class set. C3 linearization [1]: is used in OpenDylan, Python, and Perl 6
MRO via C3 Linearization
FG B D E L[G] G L[F ] F C L[E] E · F A L[D] D · G A(B,C) B(F,G) C(D,E) L[B] B · (F t G t (F · G)) D(G) E(F ) L[C] L[A] C3 detects and reports a violation of monotonicity with the addition of A(B,C) to the class set. C3 linearization [1]: is used in OpenDylan, Python, and Perl 6
MRO via C3 Linearization
FG B D E L[G] G L[F ] F C L[E] E · F A L[D] D · G A(B,C) B(F,G) C(D,E) L[B] B · F · G D(G) E(F ) L[C] L[A] C3 detects and reports a violation of monotonicity with the addition of A(B,C) to the class set. C3 linearization [1]: is used in OpenDylan, Python, and Perl 6
MRO via C3 Linearization
FG B D E L[G] G L[F ] F C L[E] E · F A L[D] D · G A(B,C) B(F,G) C(D,E) L[B] B · F · G D(G) E(F ) L[C] C · (L[D] t L[E] t (D · E)) L[A] C3 detects and reports a violation of monotonicity with the addition of A(B,C) to the class set. C3 linearization [1]: is used in OpenDylan, Python, and Perl 6
MRO via C3 Linearization
FG B D E L[G] G C L[F ] F A L[E] E · F A(B,C) B(F,G) C(D,E) L[D] D · G D(G) E(F ) L[B] B · F · G L[C] C · ((D · G) t (E · F ) t (D · E)) L[A] C3 detects and reports a violation of monotonicity with the addition of A(B,C) to the class set. C3 linearization [1]: is used in OpenDylan, Python, and Perl 6
MRO via C3 Linearization
FG B D E L[G] G L[F ] F C L[E] E · F A L[D] D · G A(B,C) B(F,G) C(D,E) L[B] B · F · G D(G) E(F ) L[C] C · D · (G t (E · F ) t E) L[A] C3 detects and reports a violation of monotonicity with the addition of A(B,C) to the class set. C3 linearization [1]: is used in OpenDylan, Python, and Perl 6
MRO via C3 Linearization
FG B D E L[G] G L[F ] F C L[E] E · F A L[D] D · G A(B,C) B(F,G) C(D,E) L[B] B · F · G D(G) E(F ) L[C] C · D · G · E · F L[A] C3 detects and reports a violation of monotonicity with the addition of A(B,C) to the class set. C3 linearization [1]: is used in OpenDylan, Python, and Perl 6
MRO via C3 Linearization
FG B D E L[G] G C L[F ] F A L[E] E · F A(B,C) B(F,G) C(D,E) L[D] D · G D(G) E(F ) L[B] B · F · G L[C] C · D · G · E · F L[A] A · ((B · F · G) t (C · D · G · E · F ) t (B · C)) C3 detects and reports a violation of monotonicity with the addition of A(B,C) to the class set. C3 linearization [1]: is used in OpenDylan, Python, and Perl 6
MRO via C3 Linearization
FG B D E L[G] G C L[F ] F A L[E] E · F A(B,C) B(F,G) C(D,E) L[D] D · G D(G) E(F ) L[B] B · F · G L[C] C · D · G · E · F L[A] A · B · C · D · ((F · G) t (G · E · F )) C3 detects and reports a violation of monotonicity with the addition of A(B,C) to the class set. C3 linearization [1]: is used in OpenDylan, Python, and Perl 6
MRO via C3 Linearization
FG B D E L[G] G L[F ] F C L[E] E · F A L[D] D · G A(B,C) B(F,G) C(D,E) L[B] B · F · G D(G) E(F ) L[C] C · D · G · E · F L[A] ! fail MRO via C3 Linearization
FG B D E L[G] G L[F ] F C L[E] E · F A L[D] D · G A(B,C) B(F,G) C(D,E) L[B] B · F · G D(G) E(F ) L[C] C · D · G · E · F L[A] ! fail
C3 detects and reports a violation of monotonicity with the addition of A(B,C) to the class set. C3 linearization [1]: is used in OpenDylan, Python, and Perl 6 Linearization vs. explicit qualification
Linearization Qualification No switch/duplexer code More flexible, fine-grained necessary Linearization choices may be No explicit naming of qualifiers awkward or unexpected Unique super reference Reduces number of multi-dispatching conflicts
Languages with automatic linearization exist CLOS Common Lisp Object System Dylan, Python and Perl 6 with C3 Prerequisite for → Mixins Further reading...
K. Barrett, B. Cassels, P. Haahr, D. Moon, K. Playford, and T. Withington. A monotonic superclass linearization for dylan. In Object Oriented Programming Systems, Languages, and Applications, 1996.
CodeSourcery, Compaq, EDG, HP, IBM, Intel, R. Hat, and SGI. Itanium C++ ABI. URL: http://www.codesourcery.com/public/cxx-abi.
R. Ducournau and M. Habib. On some algorithms for multiple inheritance in object-oriented programming. In Proceedings of the European Conference on Object-Oriented Programming (ECOOP), 1987.
R. Kleckner. Bringing clang and llvm to visual c++ users. URL: http://llvm.org/devmtg/2013-11/#talk11.
B. Liskov. Keynote address – data abstraction and hierarchy. In Addendum to the proceedings on Object-oriented programming systems, languages and applications, OOPSLA ’87, pages 17–34, 1987.
L. L. R. Manual. Llvm project. URL: http://llvm.org/docs/LangRef.html.
R. C. Martin. The liskov substitution principle. In C++ Report, 1996.
P. Sabanal and M. Yason. Reversing c++. In Black Hat DC, 2007. URL: https://www.blackhat.com/presentations/bh-dc-07/Sabanal_Yason/Paper/bh-dc-07-Sabanal_Yason-WP.pdf.
B. Stroustrup. Multiple inheritance for C++. In Computing Systems, 1999.