DynBindModel
Author: Matthias Konrad
Related articles:
- Haskel module that implements the model: DynBindModelHaskell
Contents |
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:
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:
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
Operator: inverse
Operator: domain
Operator: range
Operator: range restriction
is equivalent to:
Example:
Operator: override
is equivalent to:
Example:
Operator: union
is equivalent to:
Example:
is equivalent to:
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:
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
of classes (or a set of types). For the example system,
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):
For the example system the function is:
The direct inheritance function
Eiffel classes can inherit from each other. This is described by the function
:
For the example system:
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:
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:
For the example system it is:
So
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:
For the example system:
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:
Such that
For the example system there is only one such order:
In practice class
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:
for
for
for
for
for
for
The full example
The full model of the example is thus:
The naming function
The naming function shows for two classes how their feature names are related to each other:
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:
This function simplifies the construction of the dynamic binding function.
For the example system:
|
|
|
|
| |
|
| |
|
| |
|
| |
|
|
Definition of the naming function
The naming function
is defined recursively. Meaning, that
is defined based on
.
This is sound since:
The details of the functions are covered in the succeeding sections, its definition is shown here:
Where
And:
And:
The trivial cases
There are two trivial cases:
- When
then according to the definition of the order
,
is not an ancestor of
. And thus
evaluates to the empty set in this case.
- When both
and
are smaller than
, it is defined by
. Here the recursive structure of the definition can be seen.
The identity function
is the identity function over all the feature names of the class
. 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
consists of the names of:
- The features declared in
- The inherited features (after renaming) of class
.
The first set is trivial, it is exactly the domain of
.
Every base class
of class
contributes the set
to the set of inherited feature names.
The whole identity function is thus:
The helper function
The definition of
for
is a little harder to construct. Helper function
shown here should simplify things.
There are
paths from class
to class
that need to be considered. They are shown in the following picture:
describes the naming on the path that goes through
:
The complex case
The union of the helper function over all the base classes
for given
and
:
yields a relation but not a function. The selected features names are not yet taken into account. The explicitly selected features names are:
So if
is overridden with
the result is again a function:
The dynamic binding function
The initial goal was the definition of the dynamic binding function:
For the example system it is defined as:
|
|
|
|
| |
|
| |
|
| |
|
| |
|
| |
|
| |
|
|
The definition
With the naming function defined it is surprisingly simple to give the dynamic binding function. To make it even easier the function:
is defined. From this function,
can be derived:
The helper function
What remains is to define
. As with the naming function it is done recursively.
can be defined based on
since the following holds:
The definition:





