DynBindModel: Difference between revisions

From EiffelStudio: an EiffelSoftware project
Jump to navigation Jump to search
Konradm (talk | contribs)
Manus (talk | contribs)
mNo edit summary
 
(126 intermediate revisions by 2 users not shown)
Line 1: Line 1:
[[Category:ECMA]]
[[Category:ECMA]]
{{Warning|'''Warning''': Article under development}}
{{UnderConstruction}}
Author: Matthias Konrad
Author: Matthias Konrad


Related articles:  
Related articles:  
*Example for the model shown: [[DynBindModelExamples]]
*Haskel module that implements the model: [[DynBindModelHaskell]]
*Haskel module that implements the model: [[DynBindModelHaskell]]


===Motivation:===
===Motivation:===


Eiffels dynamic binding is somewhat more complex than that of other languages. Its structure is still very simple and is described by the function:
Eiffel's dynamic binding is somewhat more complex than that of other languages. Its structure is still very simple and is described by the function:


<math>\gamma : \left(\mbox{TYPE} \times \mbox{NAME}\right) \rightarrow \left(\mbox{TYPE} \rightarrow \mbox{FEATURE}\right) </math>
<math>\gamma : \left(\mbox{TYPE} \times \mbox{NAME}\right) \rightarrow \left(\mbox{TYPE} \rightarrow \mbox{FEATURE}\right) </math>
Line 16: Line 14:
Function <math>\gamma\,</math> contains both the static and dynamic binding part of the language. In the following feature:
Function <math>\gamma\,</math> contains both the static and dynamic binding part of the language. In the following feature:


<code>[N,Eiffel]
{|border="0" cellpadding="2" cellspacing="0" align="center"
|-valign="top" -halign="center"
|
<eiffel>
f (a: ANY)
f (a: ANY)
   do
   do
       print (a.out)
       print (a.out)
   end
   end
</code>
</eiffel>
|}


The static binding part of call ''a.out'' can be decribed as:
The static binding part of call ''a.out'' can be described as:


<math>\gamma \left( \mbox{ANY} \mapsto \mbox{out}\right)</math>
<math>\gamma \left( \mbox{ANY} \mapsto \mbox{out}\right)</math>
Line 81: Line 83:
<math>E \mapsto F \in p \ll q</math>
<math>E \mapsto F \in p \ll q</math>
is equivalent to:
is equivalent to:
<math>E \mapsto F \in q \,\lor\, \left( E \mapsto F \in p \,\land\, E \not\in \mbox{dom}\left( p \right) \right)</math>
<math>E \mapsto F \in q \,\lor\, \left( E \mapsto F \in p \,\land\, E \not\in \mbox{dom}\left( q \right) \right)</math>


Example:
Example:
Line 90: Line 92:
\left\{ 1 \mapsto 4, 2 \mapsto 3, 3 \mapsto 6 \right\}
\left\{ 1 \mapsto 4, 2 \mapsto 3, 3 \mapsto 6 \right\}
</math>
</math>
====Operator: union====
====Operator: union====
<math>E \in \mbox{UNION} \ x \cdot \left(x \in S \ |\ T \right)</math>
<math>E \in \mbox{UNION} \ x \cdot \left(x \in S \ |\ T \right)</math>
Line 131: Line 134:
<math>\tau =  
<math>\tau =  
\left\{
\left\{
   A \mapsto \left\{ f1 \mapsto \underline{A.f1}, g1 \mapsto \underline{A.g1} \right\},  
   A \mapsto \left\{ f_1 \mapsto \underline{A.f_1}, g_1 \mapsto \underline{A.g_1} \right\},  
   B \mapsto \left\{ f2 \mapsto \underline{B.f2}, g2 \mapsto \underline{B.g2} \right\},
   B \mapsto \left\{ f_2 \mapsto \underline{B.f_2}, g_2 \mapsto \underline{B.g_2} \right\},
   D \mapsto \left\{ f1 \mapsto \underline{D.f1}, g1 \mapsto \underline{D.g1} \right\}
   D \mapsto \left\{ f_1 \mapsto \underline{D.f_1}, g_1 \mapsto \underline{D.g_1} \right\}
\right\}
\right\}
</math>
</math>
Line 139: Line 142:
====The direct inheritance function====
====The direct inheritance function====
Eiffel classes can inherit from each other. This is described by the function <math>\alpha\,</math>:
Eiffel classes can inherit from each other. This is described by the function <math>\alpha\,</math>:
<math>\alpha : \mbox{TYPE} \rightarrow \mathbb{P} \left( \mbox{TYPE} \right)</math>
<math>\alpha : \mbox{TYPE} \rightarrow \mathbb{P} \left( \mbox{TYPE} \right)</math>
For the example system:
For the example system:
Line 158: Line 162:
<math>\eta : \mbox{TYPE} \rightarrow \left( \mbox{TYPE} \rightarrow \left( \mbox{NAME} \leftrightarrow \mbox{NAME} \right) \right)</math>
<math>\eta : \mbox{TYPE} \rightarrow \left( \mbox{TYPE} \rightarrow \left( \mbox{NAME} \leftrightarrow \mbox{NAME} \right) \right)</math>


For the example system it:
For the example system it is:


<math>\eta =  
<math>\eta =  
Line 172: Line 176:
</math>
</math>


So <math>\eta \left( D \right) \left( B \right) </math> gives the renamings in class D for the inherited class B.
So <math>\eta \left( D \right) \left( B \right) </math> gives the renaming in class D for the inherited class B.


Again, the fact that the final result is not a function but just a relation is surprising. Take it as a property of CoreEiffel, that for a given base class a feature can be renamed to many different names. This is also possible in Eiffel, since it allows several parent parts reference the same class.  
Again, the fact that the final result is not a function but just a relation is surprising. Take it as a property of CoreEiffel, that for a given base class a feature can be renamed to many different names. This is also possible in Eiffel, since it allows several parent parts to refer to the same class.


====The select function====
====The select function====
Line 190: Line 194:
\right\}
\right\}
</math>
</math>
====No undefine or redefine====
Undefine and redefine are not represented in this model. The latter is generally not relevant for the semantics.
This article assumes that there is an unfolded form for undefines which is needed for the join semantics of precondition.


====The order====
====The order====
Line 202: Line 211:
<math> \forall x, y\ \cdot \left( x > y \Rightarrow \lnot \left( C \left(x\right) < C \left(y\right) \right) \right) </math>
<math> \forall x, y\ \cdot \left( x > y \Rightarrow \lnot \left( C \left(x\right) < C \left(y\right) \right) \right) </math>


Without loss of generality it is stated, that any Eiffel system <math>S\,</math> is a set of classes
For the example system there is only one such order:
<math>\left\{ C_1, C_2 \ldots C_n \right\}</math> such that <math>C_q \not< C_p </math> if  <math>q < p\,</math>. In practice class <math>C_1\,</math> will allways be class <eiffel>ANY</eiffel> but this is not of importance here.
 
<math>
  C = \left\{ 1 \mapsto A, 2 \mapsto B, 3 \mapsto D \right\}
</math>
 
In practice class <math>C\left(1\right)</math> is always class <eiffel>ANY</eiffel>. For simplification, in this article classes are not implicitly inherited by <eiffel>ANY</eiffel>, this simplifies the examples.


Furthermore we give the following shortcuts:
====Some shortcuts====
To simplify the discussion, some shortcuts are introduced:
*<math>C_{n}\,</math> for <math>C\left( n \right)</math>
*<math>\tau_{n}\,</math> for <math>\tau\left( C_n \right) </math>
*<math>\tau_{n}\,</math> for <math>\tau\left( C_n \right) </math>
*<math>\eta_{n, b}\,</math> for <math>\eta \left( C_n \right) \left( b \right) </math>
*<math>\eta_{n, b}\,</math> for <math>\eta \left( C_n \right) \left( b \right) </math>
*<math>\alpha_{n}\,</math> for <math>\alpha \left( C_n \right) </math>
*<math>\alpha_{n}\,</math> for <math>\alpha \left( C_n \right) </math>
*<math>\sigma_{n, b}\,</math> for <math>\sigma \left( C_n \right) \left( b \right) </math>
*<math>\sigma_{n, b}\,</math> for <math>\sigma \left( C_n \right) \left( b \right) </math>
*<math>S_m\,</math> for <math>\left\{ C_1 \ldots C_m \right\}</math>


====An example====
====The full example====
For the following System:
The full model of the example is thus:
{|border="0" cellpadding="2" cellspacing="0" align="center"
 
|-valign="top" -halign="center"
<math>S=\left\{ A, B, D\right\}</math>
|<code>[eiffel, N]
class
  B
feature
  f do ... end
end
</code>
|
<code>[eiffel, N]
class
  C
inherit
  B
      rename f as f1 redefine f1 end
feature
  f1 do ... end
end
</code>
|
<code>[eiffel, N]
class
  D
inherit
  C
  B
      rename f as f2 redefine f2 select f2 end
  B
      rename f as f3 redefine f3 end
feature
  f2 do ... end
  f3 do ... end
end
</code>
|}


We get:
<math>\tau =  
*<math>S = \left\{ B, C, D \right\} </math>
*<math>\tau =  
\left\{
\left\{
   B \mapsto \left\{ f \mapsto \underline{B.f} \right\},  
   A \mapsto \left\{ f1 \mapsto \underline{A.f1}, g1 \mapsto \underline{A.g1} \right\},  
   C \mapsto \left\{ f1 \mapsto \underline{C.f1} \right\},
   B \mapsto \left\{ f2 \mapsto \underline{B.f2}, g2 \mapsto \underline{B.g2} \right\},
   D \mapsto \left\{ f2 \mapsto \underline{D.f2}, f3 \mapsto \underline{D.f3} \right\}
   D \mapsto \left\{ f1 \mapsto \underline{D.f1}, g1 \mapsto \underline{D.g1} \right\}
\right\}
</math>
 
<math>\alpha = \left\{
  A \mapsto \emptyset,
  B \mapsto \left\{ A \right\},
  D \mapsto \left\{ A, B \right\}
\right\}
\right\}
</math>
</math>
*<math>\eta =  
 
<math>\eta =  
\left\{
\left\{
   C \mapsto \left\{  
   A \mapsto \emptyset,
       B \mapsto \left\{ f \mapsto f1 \right\}  
  B \mapsto \left\{  
   \right\},  
       A \mapsto \left\{ f_1 \mapsto f_2, g_1 \mapsto g_2 \right\}  
   \right\},
   D \mapsto \left\{  
   D \mapsto \left\{  
       B \mapsto \left\{ f \mapsto f2, f \mapsto f3 \right\}
       A \mapsto \emptyset, B \mapsto \emptyset
   \right\}
   \right\}
\right\}
\right\}
</math>
</math>
*<math>\alpha = \left\{
 
   C \mapsto \left\{ B \right\},
<math>\sigma = \left\{
   D \mapsto \left\{ B, C \right\}
   A \mapsto \emptyset,
  B \mapsto \left\{ A \mapsto \emptyset \right\},  
   D \mapsto \left\{ A \mapsto \left\{ g_1 \right\},
                    B \mapsto \left\{ f_2 \right\} \right\}
\right\}
\right\}
</math>
</math>
*<math>\sigma = \left\{
 
  D \mapsto \left\{ B \mapsto \left\{ f2 \right\} \right\}
<math>
\right\}
  C = \left\{ 1 \mapsto A, 2 \mapsto B, 3 \mapsto D \right\}
</math>
</math>


Line 285: Line 278:
<math>\beta_S: \left( \mbox{TYPE} \times \mbox{TYPE} \right) \rightarrow\left( \mbox{NAME} \rightarrow\mbox{NAME} \right)</math>
<math>\beta_S: \left( \mbox{TYPE} \times \mbox{TYPE} \right) \rightarrow\left( \mbox{NAME} \rightarrow\mbox{NAME} \right)</math>


In the previous example class ''C'' renames feature ''f'' to ''f1''. <math>\beta_{\left\{ B, C, D \right\}} \left( B \mapsto C \right) \left( f \right)</math> thus evaluates to ''f1''. <math>\beta_{\left\{ B, C, D \right\}} \left( B \mapsto D \right) \left( f \right)</math> evaluates to ''f2'', the selected feature in class ''D''. The range of <math>\beta_S\,</math> is a function, this means that every name is mapped to just one name.  
When one looks at a feature with name n in a class X and is interested in the name of the selected version of this feature in descendant class Y the naming function tells the answer:
 
<math>\beta\left(X\right)\left(Y\right)\left(n\right)</math>
 
This function simplifies the construction of the dynamic binding function.


As an example the complete function <math>\beta_{\left\{ B, C, D \right\}}</math> is shown:
For the example system:


{|border="0" cellpadding="2" cellspacing="0" align="center"
{|border="0" cellpadding="2" cellspacing="0" align="center"
|-valign="top" -halign="center"
|-valign="top" -halign="center"
|
|
<math>\beta_{\left\{ B, C, D \right\}} = \{</math>
<math>\beta_{\left\{ A, B, D \right\}} = \{</math>
|
<math>
  \left( A \mapsto A \right) \mapsto \left\{f_1 \mapsto f_1, g_1 \mapsto g_1 \right\},
</math>
|-
||
|
|
<math>
<math>
   \left( B \mapsto B \right) \mapsto \left\{f \mapsto f \right\},
   \left( A \mapsto B \right) \mapsto \left\{ f_1 \mapsto f_2, g_1 \mapsto g_2 \right\},
  \left( B \mapsto C \right) \mapsto \left\{ f \mapsto f1 \right\},
  \left( B \mapsto D \right) \mapsto \left\{ f \mapsto f2 \right\},
</math>
</math>
|-
|-
Line 303: Line 304:
|
|
<math>
<math>
   \left( C \mapsto C \right) \mapsto \left\{ f1 \mapsto f1 \right\},
   \left( A \mapsto D \right) \mapsto \left\{ f_1 \mapsto f_2, g_1 \mapsto g_1 \right\},
  \left( C \mapsto D \right) \mapsto \left\{ f1 \mapsto f1 \right\},
</math>
</math>
|-
|-
Line 310: Line 310:
|
|
<math>
<math>
   \left( D \mapsto D \right) \mapsto \left\{ f1 \mapsto f1, f2 \mapsto f2, f3 \mapsto f3 \right\} \}
  \left( B \mapsto B \right) \mapsto \left\{ f_2 \mapsto f_2, g_2 \mapsto g_2 \right\},
</math>
|-
||
|
<math>
  \left( B \mapsto D \right) \mapsto \left\{ f_2 \mapsto f_2, g_2 \mapsto g_2 \right\},
</math>
|-
||
|
<math>
   \left( D \mapsto D \right) \mapsto \left\{ f_1 \mapsto f_1, f_2 \mapsto f_2, g_1 \mapsto g_1, g_2 \mapsto g_2 \right\} \}
</math>
</math>


|}
|}
====Definition of the naming function====
The naming function <math>\beta_S\,</math> is defined recursively. Meaning, that <math>\beta_{S_m }</math> is defined based on <math>\beta_{ S_{m-1}}</math>.
This is sound since:
<math>\beta_{ \left\{ C_1 \right\} } \subseteq \beta_{ \left\{ C_1, C_2 \right\} } \subseteq \ldots  \subseteq \beta_S</math>


====Definition of the naming function====
The details of the functions are covered in the succeeding sections, its definition is shown here:
The shortcut <math>S_m\,</math> denotes the system <math>\left\{ C_1 \ldots C_m \right\}</math>.


A recursive definition of <math>\beta_S\,</math> follows. <math>\beta_{S_m }</math> is defined based on <math>\beta_{ S_{m-1}}</math>.
<math>  
\beta_{ S_m } \left( C_q \mapsto C_p \right) =


This is sound since:
\begin{cases}
<math>\beta_{ \left\{ C_1 \right\} } \subseteq \beta_{ \left\{ C_1, C_2 \right\} } \subseteq \ldots  \beta_S</math>


The trivial function <math>S_0\,</math> is the empty set.  <math>S_m\,</math> for <math>m>0\,</math> is defined by by showing what <math>\beta_{ S_m } \left( C_q \mapsto C_p \right)</math> evaluates to for <math>q\leq m\,</math> and <math>p\leq m\,</math>. There are two trivial cases. When <math>q > p \,</math> it evaluates to the empty set and when both <math>p\,</math> and <math>q\,</math> are smaller than <math>m\,</math>, it is defined by  <math>\beta_{ S_{m-1} } \left( C_q \mapsto C_p \right)</math>.
\emptyset           
&
\mbox{if } q > p \\


<math>\beta_{ S_m } \left( C_m \mapsto C_m \right)</math> is an identity function over the set of feature names of <math>C_m\,</math>. The set of feature names consists of the names of
\beta_{ S_{m-1} } \left( C_q \mapsto C_p \right)          
* the inherited features (after renaming).
&
* the features declared in <math>C_m\,</math>.
\mbox{if } q <= p < m \\
The features declared in <math>C_m\,</math> are given by the domain of <math>\tau_m\,</math>. Every base class <math>b \in \alpha_m</math> contributes the set: <math>\mbox{ran}\left( \beta_{ S_{m-1} } \left( b \mapsto b \right) \ll \eta_{m, b} \right)</math> to the set of inherited feature names. We can now define:


<math>
\beta_{ S_m } \left( C_m \mapsto C_m \right)
  =
\mbox{id} \left(  
\mbox{id} \left(  
   \mbox{dom} \left( \tau_m \right)
   \mbox{dom} \left( \tau_m \right)
   \, \cup \,
   \, \cup \,
\mbox {UNION} \ b \, \cdot \, \left(
\mbox {UNION} \ b \cdot \left(
     b \in \alpha_m
     b \in \alpha_m
       \ |\ \mbox{ran}\left( \beta_{ S_{m-1} } \left( b \mapsto b \right) \ll \eta_{m, b} \right)
       \ |\ \mbox{ran}\left( \beta_{ S_{m-1} } \left( b \mapsto b \right) \ll \eta_{m, b} \right)
     \right)
     \right)
     \right)
     \right)
</math>
&
\mbox{if } q = p = m \\


The definition of <math>\beta_{ S_m } \left( C_q \mapsto C_m \right)</math> for <math>q<m\,</math> depends on two helper functions. Function <math>\beta^\prime_S</math> ignores whether a features is selected or not, apart from that it is similar to the naming function <math>\beta_S\,</math>. Its structure is:
\mathcal{A} \ll \mathcal{B}


<math>\beta^\prime_S: \left( \mbox{TYPE} \times \mbox{TYPE} \right) \rightarrow\left( \mbox{NAME} \leftrightarrow\mbox{NAME} \right)</math>
&
\mbox{otherwise }
\end{cases}
</math>


The image <math>\beta^\prime_{\left\{ B, C, D \right\}} \left( B \mapsto C \right) \left[ f \right]</math> from the previous example is <math>\left\{f1, f2, f3\right\}\,</math>. Its definition is:
Where


<math>
<math>
\beta^\prime_{S_m} \left( C_q \mapsto C_m \right)
\mathcal{A}
   =  
   =  
\mbox {UNION} \ b \ \cdot \ \left(
\mbox {UNION} \ b \cdot \left(
   b \in \alpha_m
   b \in \alpha_m
      \ |\  
  \ | \  
   \beta_{S_{m-1}} \left( C_q \mapsto b \right)
   \phi_m \left( C_q \mapsto b \right)
      ;
  \left(
      \mbox{id} \left( \mbox{ran} \left( \beta_{S_{m-1}} \left( C_q \mapsto b \right) \right) \right)
        \ll
      \eta_{m,b}
  \right)
\right)
\right)
</math>
</math>


The second helper function <math>\theta_S</math> is again similar to the naming function but it only includes selected feature names. Its structure is:
And:
 
<math>\theta_S: \left( \mbox{TYPE} \times \mbox{TYPE} \right) \rightarrow\left( \mbox{NAME} \rightarrow\mbox{NAME} \right)</math>
 
<math>\theta_{\left\{ B, C, D \right\}}\left( B \mapsto D \right)</math> from the previous example is <math>\left\{f \mapsto f2\right\}\,</math>, whereas <math>\theta_{\left\{ B, C, D \right\}}\left( C \mapsto D \right)</math> is the empty set. Its definition is:


<math>
<math>
\theta_{S_m} \left( C_q \mapsto C_m \right)
\mathcal{B}
   =  
   =  
\mbox {UNION} \ b \ \cdot \ \left(
\mbox {UNION} \ b \cdot \left(
   b \in \alpha_m
   b \in \alpha_m
       \ |\  
       \ |\  
   \beta_{S_{m-1}} \left( C_q \mapsto b \right)
   \phi_m \left( C_q \mapsto b \right) \triangleright \sigma_{m,b}
      ;
  \left(
      \mbox{id} \left( \mbox{ran} \left( \beta_{S_{m-1}} \left( C_q \mapsto b \right) \right) \right)
        \ll
      \eta_{m,b}
  \right)
  \triangleright \sigma_{m,b}
\right)
\right)
</math>
</math>


The definition of <math>\beta_{ S_m } \left( C_q \mapsto C_m \right)</math> for <math>q<m\,</math> is then:
And:


<math>
<math>
\beta_{ S_m } \left( C_q \mapsto C_m \right)
\phi_m\left( C_q \mapsto b \right)
=
=
\beta^\prime_{S_m} \left( C_q \mapsto C_m \right)  
\beta_{S_{m-1}}  
  \ll
  \left(C_q\mapsto b\right)
\theta_{S_m} \left( C_q \mapsto C_m \right)  
;
\left(
  \beta_{S_{m-1}}\left(b \mapsto b\right)\ll\eta_{m,b}
\right)
</math>
</math>


With this we have defined the whole naming function. As a summary we present the whole definition:
====The trivial cases====
There are two trivial cases:
#When <math>q > p \,</math> then according to the definition of the order <math>C\,</math>, <math>C_q\,</math> is not an ancestor of <math>C_p\,</math>. And thus <math>\beta_{ S_{m-1} } \left( C_q \mapsto C_p \right)</math> evaluates to the empty set in this case.
#When both <math>p\,</math> and <math>q\,</math> are smaller than <math>m\,</math>, it is defined by  <math>\beta_{ S_{m-1} } \left( C_q \mapsto C_p \right)</math>. Here the recursive structure of the definition can be seen.
====The identity function====
<math>\beta_{ S_m } \left( C_m \mapsto C_m \right)</math> is the identity function over all the feature names of the class <math>C_m\,</math>. It is an identity function since a given feature name in a class has no other name in that same class.  
The set of feature names of a class <math>C_m\,</math>consists of the names of:
#The features declared in <math>C_m\,</math>
#The inherited features (after renaming) of class <math>C_m\,</math>.


<math>  
The first set is trivial, it is exactly the domain of <math>\tau_m\,</math>.
\beta_{ S_m } \left( C_q \mapsto C_p \right) =


\begin{cases}
Every base class <math>b\,</math> of class <math>C_m\,</math> contributes the set <math>\mbox{ran}\left( \beta_{ S_{m-1} } \left( b \mapsto b \right) \ll \eta_{m, b} \right)</math> to the set of inherited feature names.


\emptyset           
The whole identity function is thus:
&
\mbox{if } q > p \\
 
\beta_{ S_{m-1} } \left( C_q \mapsto C_p \right)           
&
\mbox{if } q <= p < m \\


<math>
\beta_{ S_m } \left( C_m \mapsto C_m \right)
  =
\mbox{id} \left(  
\mbox{id} \left(  
   \mbox{dom} \left( \tau_m \right)
   \mbox{dom} \left( \tau_m \right)
   \, \cup \,
   \, \cup \,
\mbox {UNION} \ b \, \cdot \, \left(
\mbox {UNION} \ b \cdot \left(
     b \in \alpha_m
     b \in \alpha_m
       \ |\ \mbox{ran}\left( \beta_{ S_{m-1} } \left( b \mapsto b \right) \ll \eta_{m, b} \right)
       \ |\ \mbox{ran}\left( \beta_{ S_{m-1} } \left( b \mapsto b \right) \ll \eta_{m, b} \right)
     \right)
     \right)
     \right)
     \right)
&
</math>
\mbox{if } q = p = m \\
 
====The helper function====
The definition of <math>\beta_{ S_m } \left( C_q \mapsto C_m \right)</math> for <math>q<m\,</math> is a little harder to construct. Helper function <math>\phi\,</math> shown here should simplify things.
 
There are <math>|\alpha_m|\,</math> paths from class <math>C_q\,</math> to class <math>C_m\,</math> that need to be considered. They are shown in the following picture:
 
{|border="0" cellpadding="2" cellspacing="0" align="center"
|-valign="top" -halign="center"
|
[[Image:DynBindingCqCm.png]]
|}
 
<math>\phi_m\left( C_q \mapsto b \right)</math> describes the naming on the path that goes through <math>b\,</math>:


\beta^\prime_{S_m} \left( C_q \mapsto C_m \right)  
<math>
  \ll
\phi_m\left( C_q \mapsto b \right)
\theta_{S_m} \left( C_q \mapsto C_m \right)  
=
&
\beta_{S_{m-1}}  
\mbox{otherwise }
  \left(C_q\mapsto b\right)
\end{cases}
;
\left(
  \beta_{S_{m-1}}\left(b \mapsto b\right)\ll\eta_{m,b}
\right)
</math>
</math>


Where
====The complex case====
The union of the helper function over all the base classes <math>b \in \alpha_m</math> for given <math>C_q\,</math> and <math>C_m\,</math>:


<math>
<math>
\beta^\prime_{S_m} \left( C_q \mapsto C_m \right)
\mathcal{A}
   =  
   =  
\mbox {UNION} \ b \ \cdot \ \left(
\mbox {UNION} \ b \cdot \left(
   b \in \alpha_m
   b \in \alpha_m
      \ |\  
  \ | \  
   \beta_{S_{m-1}} \left( C_q \mapsto b \right)
   \phi_m \left( C_q \mapsto b \right)
      ;
  \left(
      \mbox{id} \left( \mbox{ran} \left( \beta_{S_{m-1}} \left( C_q \mapsto b \right) \right) \right)
        \ll
      \eta_{m,b}
  \right)
\right)
\right)
</math>
</math>


And:
yields a relation but not a function. The selected features names are not yet taken into account. The explicitly selected features names are:


<math>
<math>
\theta_{S_m} \left( C_q \mapsto C_m \right)
\mathcal{B}
   =  
   =  
\mbox {UNION} \ b \ \cdot \ \left(
\mbox {UNION} \ b \cdot \left(
   b \in \alpha_m
   b \in \alpha_m
       \ |\  
       \ |\  
   \beta_{S_{m-1}} \left( C_q \mapsto b \right)
   \phi_m \left( C_q \mapsto b \right) \triangleright \sigma_{m,b}
      ;
  \left(
      \mbox{id} \left( \mbox{ran} \left( \beta_{S_{m-1}} \left( C_q \mapsto b \right) \right) \right)
        \ll
      \eta_{m,b}
  \right)
  \triangleright \sigma_{m,b}
\right)
\right)
</math>
So if <math>\mathcal{A}\,</math> is overridden with <math>\mathcal{B}\,</math> the result is again a function:
<math>
\beta_{S_m} \left( C_q \mapsto C_m \right)
=
\mathcal{A} \ll \mathcal{B}
</math>
</math>


===The dynamic binding function===
===The dynamic binding function===
With the naming function defined it is surprisingly simple to give the dynamic binding function. To make it even easier we define the function:
The initial goal was the definition of the dynamic binding function:
 
<math>\gamma : \left(\mbox{TYPE} \times \mbox{NAME}\right) \rightarrow \left(\mbox{TYPE} \rightarrow \mbox{FEATURE}\right) </math>
 
For the example system it is defined as:
 
{|border="0" cellpadding="2" cellspacing="0" align="center"
|-valign="top" -halign="center"
|
<math>\gamma = \{\ </math>
|
<math>
  \left( A \mapsto f_1 \right)
      \mapsto
  \left\{ A \mapsto \underline{A.f_1}, B \mapsto \underline{B.f_2}, D \mapsto \underline{B.f_2} \right\},
</math>
|-
||
|
<math>
  \left( A \mapsto g_1 \right)
      \mapsto
  \left\{ A \mapsto \underline{A.g_1}, B \mapsto \underline{B.g_2}, D \mapsto \underline{D.g_1} \right\},
</math>
|-
||
|
<math>
  \left( B \mapsto f_2 \right)
      \mapsto
  \left\{ B \mapsto \underline{B.f_2}, D \mapsto \underline{B.f_2} \right\},
</math>
|-
||
|
<math>
  \left( B \mapsto g_2 \right)
      \mapsto
  \left\{ B \mapsto \underline{B.g_2}, D \mapsto \underline{B.g_2} \right\},
</math>
|-
||
|
<math>
  \left( D \mapsto f_1 \right)
      \mapsto
  \left\{ D \mapsto \underline{D.f_1} \right\},
</math>
|-
||
|
<math>
  \left( D \mapsto g_1 \right)
      \mapsto
  \left\{ D \mapsto \underline{D.g_1} \right\},
</math>
|-
||
|
<math>
  \left( D \mapsto f_2 \right)
      \mapsto
  \left\{ D \mapsto \underline{B.f_2} \right\},
</math>
|-
||
|
<math>
  \left( D \mapsto g_2 \right)
      \mapsto
  \left\{ D \mapsto \underline{B.g_2} \right\}\ \}
</math>
|}
 
 
====The definition====
With the naming function defined it is surprisingly simple to give the dynamic binding function. To make it even easier the function:
 
<math>\delta : \left(\mbox{TYPE} \times \mbox{TYPE}\right) \rightarrow \left(\mbox{NAME} \rightarrow \mbox{FEATURE}\right) </math>
<math>\delta : \left(\mbox{TYPE} \times \mbox{TYPE}\right) \rightarrow \left(\mbox{NAME} \rightarrow \mbox{FEATURE}\right) </math>


With this function defined we can derive <math>\gamma\,</math>:
is defined. From this function, <math>\gamma\,</math> can be derived:


<math>\gamma \left( S \mapsto f_n \right) = \left\{ D \mapsto f\ |\ \delta \left( S \mapsto D \right) \left( f_n \right) = f \right\}  </math>
<math>\gamma \left( ST \mapsto f_n \right) = \left\{ DT \mapsto \underline{f}\ |\ \delta \left( ST \mapsto DT \right) \left( f_n \right) = \underline{f} \right\}  </math>


What remains is to define <math>\delta\,</math>. As with the naming function we do it recursively. We define <math>\delta_{ S_m }</math> based on <math>\delta_{ S_{m-1} }</math> since the following holds:
====The helper function====
What remains is to define <math>\delta\,</math>. As with the naming function it is done recursively. <math>\delta_{ S_m }</math> can be defined based on <math>\delta_{ S_{m-1} }</math> since the following holds:


<math>\delta_{ S_1 } \subseteq \delta_{ S_2 } \subseteq \ldots \delta_{ S }</math>
<math>\delta_{ S_1 } \subseteq \delta_{ S_2 } \subseteq \ldots \delta_{ S }</math>

Latest revision as of 10:11, 11 April 2007

Not Ready for Review: This Page is Under Development!

Author: Matthias Konrad

Related articles:

Motivation:

Eiffel's dynamic binding is somewhat more complex than that of other languages. Its structure is still very simple and is described by the function:

γ:(TYPE×NAME)→(TYPE→FEATURE)

Function γ contains both the static and dynamic binding part of the language. In the following feature:

f (a: ANY)
   do
      print (a.out)
   end

The static binding part of call a.out can be described as:

γ(ANY↦out)

Namely an evaluation of γ with a tuple containing the static type of the call and the name. The result of this is a function. This function evaluated at runtime will yield the right feature according to the dynamic type of a.

In the rest of this text, the construction of the function γ is shown, based on any given valid Eiffel system.

There is a special wiki page that shows an example calculation of the dynamic binding function for a complete system: DynBindModelExamples

Notation

This wiki uses the notation introduced in these slides by Prof. Jean-Raymond Abrial (ETHZ): notation The only difference is the symbol for override which is ≪ (This will be changed as soon as possible). The function operator → is used for partial functions.

We will give some rather informal definitions for the set-theoretic operators used here.

identity

id({e1,…,en}) ={e1↦e1,…,en↦en}

Operator: inverse

{l1↦r1,…,ln↦rn}−1={r1↦l1,…,rn↦ln}

Operator: domain

dom({l1↦r1,…,ln↦rn})={l1,…,ln}

Operator: range

ran({l1↦r1,…,ln↦rn})={r1,…,rn}

Operator: range restriction

E↦F∈r▹T is equivalent to: E↦F∈r∧F∈T

Example:

{1↦2,2↦3,3↦4}▹{3}={2↦3}

Operator: override

E↦F∈p≪q is equivalent to: E↦F∈q∨(E↦F∈p∧E∉dom(q))

Example:

{1↦2,2↦3}≪{1↦4,3↦6}={1↦4,2↦3,3↦6}

Operator: union

E∈UNION x⋅(x∈S | T) is equivalent to: ∃x⋅(x∈S ∧ E∈T)

Example:

UNION x⋅(x∈{1,2,3} | {x,x2}) is equivalent to: {1,2,3,4,9}

Unfolded forms and replication

The Eiffel ECMA standard defines semantics in two ways. A small core of the language (called CoreEiffel) is described explicitly. The rest is described by giving unfolded forms. These unfolded forms map the constructs that do not belong to CoreEiffel (but to Eiffel) to constructs that do belong to CoreEiffel.

This is especially important for replication. There is an other article that gives an unfolded form for replication. This article shows (somewhat informal) how replication can be reduced away by a similar construct. As a result CoreEiffel does not need any replication anymore.

If replication would be a valid construct of CoreEiffel this would change the very structure of the dynamic binding function γ and make it considerably more complex. Its structure would become something like:

γ′:(TYPE×NAME×CONTEXT)→(TYPE→FEATURE)

A model for an Eiffel System

First of all, the model used here does not cover generics. The concepts type and class are thus considered equal.

For making things simpler the following example system is used:

An Eiffel system is basically just a set S of classes (or a set of types). For the example system, S={A,B,D}

The features declared in a class

For all these classes there is a partial function that maps the name of the features declared in the class to the actual feature (maybe feature body would have been a better name):

τ:TYPE→(NAME→FEATURE)

For the example system the function is:

τ={A↦{f1↦A.f1_,g1↦A.g1_},B↦{f2↦B.f2_,g2↦B.g2_},D↦{f1↦D.f1_,g1↦D.g1_}}

The direct inheritance function

Eiffel classes can inherit from each other. This is described by the function α:

α:TYPE→ℙ(TYPE) For the example system:

α={A↦∅,B↦{A},D↦{A,B}}

It may surprise, that the functions range is a set of classes and not a list, since it is not reflected how may times a class inherits from a given base class. This is indeed a property of CoreEiffel assumed here but not stated in the standard. This property comes as a result of the unfolded form of replication.

The base classes of class D are expressed as: α(D)

The renaming function

The renaming function yields for every class of the system a second function that describes its renaming. This second function yields for every base class of the class a relation that describes the renaming for a given base class:

η:TYPE→(TYPE→(NAME↔NAME))

For the example system it is:

η={A↦∅,B↦{A↦{f1↦f2,g1↦g2}},D↦{A↦∅,B↦∅}}

So η(D)(B) gives the renaming in class D for the inherited class B.

Again, the fact that the final result is not a function but just a relation is surprising. Take it as a property of CoreEiffel, that for a given base class a feature can be renamed to many different names. This is also possible in Eiffel, since it allows several parent parts to refer to the same class.

The select function

The select function yields for a given class the feature names of the features that are explicitly selected for a base class:

σ:TYPE→(TYPE→ℙ(NAME))

For the example system:

  • σ={A↦∅,B↦{A↦∅},D↦{A↦{g1},B↦{f2}}}

No undefine or redefine

Undefine and redefine are not represented in this model. The latter is generally not relevant for the semantics.

This article assumes that there is an unfolded form for undefines which is needed for the join semantics of precondition.

The order

The operator > is the "ancestor of" and < the "descendant of" operator.

For every system there is at least one topological order:

C:ℕ→TYPE

Such that

∀x,y ⋅(x>y⇒¬(C(x)<C(y)))

For the example system there is only one such order:

C={1↦A,2↦B,3↦D}

In practice class C(1) is always class ANY. For simplification, in this article classes are not implicitly inherited by ANY, this simplifies the examples.

Some shortcuts

To simplify the discussion, some shortcuts are introduced:

  • Cn for C(n)
  • τn for τ(Cn)
  • ηn,b for η(Cn)(b)
  • αn for α(Cn)
  • σn,b for σ(Cn)(b)
  • Sm for {C1…Cm}

The full example

The full model of the example is thus:

S={A,B,D}

τ={A↦{f1↦A.f1_,g1↦A.g1_},B↦{f2↦B.f2_,g2↦B.g2_},D↦{f1↦D.f1_,g1↦D.g1_}}

α={A↦∅,B↦{A},D↦{A,B}}

η={A↦∅,B↦{A↦{f1↦f2,g1↦g2}},D↦{A↦∅,B↦∅}}

σ={A↦∅,B↦{A↦∅},D↦{A↦{g1},B↦{f2}}}

C={1↦A,2↦B,3↦D}

The naming function

The naming function shows for two classes how their feature names are related to each other:

βS:(TYPE×TYPE)→(NAME→NAME)

When one looks at a feature with name n in a class X and is interested in the name of the selected version of this feature in descendant class Y the naming function tells the answer:

β(X)(Y)(n)

This function simplifies the construction of the dynamic binding function.

For the example system:

β{A,B,D}={

(A↦A)↦{f1↦f1,g1↦g1},

(A↦B)↦{f1↦f2,g1↦g2},

(A↦D)↦{f1↦f2,g1↦g1},

(B↦B)↦{f2↦f2,g2↦g2},

(B↦D)↦{f2↦f2,g2↦g2},

(D↦D)↦{f1↦f1,f2↦f2,g1↦g1,g2↦g2}}

Definition of the naming function

The naming function βS is defined recursively. Meaning, that βSm is defined based on βSm−1.

This is sound since: β{C1}⊆β{C1,C2}⊆…⊆βS

The details of the functions are covered in the succeeding sections, its definition is shown here:

βSm(Cq↦Cp)={∅if q>pβSm−1(Cq↦Cp)if q<=p<mid(dom(τm)∪UNION b⋅(b∈αm | ran(βSm−1(b↦b)≪ηm,b)))if q=p=m𝒜≪ℬotherwise 

Where

𝒜=UNION b⋅(b∈αm | ϕm(Cq↦b))

And:

ℬ=UNION b⋅(b∈αm | ϕm(Cq↦b)▹σm,b)

And:

ϕm(Cq↦b)=βSm−1(Cq↦b);(βSm−1(b↦b)≪ηm,b)

The trivial cases

There are two trivial cases:

  1. When q>p then according to the definition of the order C, Cq is not an ancestor of Cp. And thus βSm−1(Cq↦Cp) evaluates to the empty set in this case.
  2. When both p and q are smaller than m, it is defined by βSm−1(Cq↦Cp). Here the recursive structure of the definition can be seen.

The identity function

βSm(Cm↦Cm) is the identity function over all the feature names of the class Cm. It is an identity function since a given feature name in a class has no other name in that same class. The set of feature names of a class Cmconsists of the names of:

  1. The features declared in Cm
  2. The inherited features (after renaming) of class Cm.

The first set is trivial, it is exactly the domain of τm.

Every base class b of class Cm contributes the set ran(βSm−1(b↦b)≪ηm,b) to the set of inherited feature names.

The whole identity function is thus:

βSm(Cm↦Cm)=id(dom(τm)∪UNION b⋅(b∈αm | ran(βSm−1(b↦b)≪ηm,b)))

The helper function

The definition of βSm(Cq↦Cm) for q<m is a little harder to construct. Helper function ϕ shown here should simplify things.

There are |αm| paths from class Cq to class Cm that need to be considered. They are shown in the following picture:

ϕm(Cq↦b) describes the naming on the path that goes through b:

ϕm(Cq↦b)=βSm−1(Cq↦b);(βSm−1(b↦b)≪ηm,b)

The complex case

The union of the helper function over all the base classes b∈αm for given Cq and Cm:

𝒜=UNION b⋅(b∈αm | ϕm(Cq↦b))

yields a relation but not a function. The selected features names are not yet taken into account. The explicitly selected features names are:

ℬ=UNION b⋅(b∈αm | ϕm(Cq↦b)▹σm,b)

So if 𝒜 is overridden with ℬ the result is again a function:

βSm(Cq↦Cm)=𝒜≪ℬ

The dynamic binding function

The initial goal was the definition of the dynamic binding function:

γ:(TYPE×NAME)→(TYPE→FEATURE)

For the example system it is defined as:

γ={ 

(A↦f1)↦{A↦A.f1_,B↦B.f2_,D↦B.f2_},

(A↦g1)↦{A↦A.g1_,B↦B.g2_,D↦D.g1_},

(B↦f2)↦{B↦B.f2_,D↦B.f2_},

(B↦g2)↦{B↦B.g2_,D↦B.g2_},

(D↦f1)↦{D↦D.f1_},

(D↦g1)↦{D↦D.g1_},

(D↦f2)↦{D↦B.f2_},

(D↦g2)↦{D↦B.g2_} }


The definition

With the naming function defined it is surprisingly simple to give the dynamic binding function. To make it even easier the function:

δ:(TYPE×TYPE)→(NAME→FEATURE)

is defined. From this function, γ can be derived:

γ(ST↦fn)={DT↦f_ | δ(ST↦DT)(fn)=f_}

The helper function

What remains is to define δ. As with the naming function it is done recursively. δSm can be defined based on δSm−1 since the following holds:

δS1⊆δS2⊆…δS

The definition:

δSm(Cq↦Cp)={∅if q>pδSm−1(Cq↦Cp)if q<=p<mβS(Cq↦Cm);((UNIONb⋅(b∈αm|(βS(b↦b);ηm,b)−1;δSm−1(b↦b)))≪τm)otherwise