Next: 3.2 Software cocktail mixers
Up: 3 Position: Compose software
Previous: 3 Position: Compose software
In order to construct more complex components from simpler ones and to extend definitions, our model uses definition composition operators.
A definition composition operator is an associative operator which combines two component-definitions and produces a new one with a given name. A view merge operator is a specific definition composition operator which combines component-definitions with the same name, yielding a new component-definition with the same name.
Composition operators compose component-definitions.
They take two components, and add a new one to the definition-universe.
Operators merge operand subcomponent-sets to determine the content and
layout of the subcomponent-sets of the new component-definition.
View merge operators extend components.
They delete two component-definitions from the definition-universe, and
produce a new one with the same name.
They are necessary because components may be defined several times, and
we have to unite all definitions of a component to a final component
layout.
Example
4 A typical example for composition operators is standard inheritance.
Classes have two kinds of
subcomponents: attributes and methods.
Standard inheritance
extends a superclass by new attributes and methods, yielding a
new subclass.
Here we show an example from a fictive object-oriented language where a
superclass person
is extended to a subclass worker
by
adding a new attribute employer
as well as a new method
get_employer
:
class worker extends person is attributes employer: STR methods get_employer: -> STR end;Because the standard inheritance unions attributes and methods of extensions, we can interpret the
extends
keyword as operator with set-union semantics.
Then the definition can be re-written in an operator-oriented style:
worker = person workerparts{ attributes{employer:STR}, methods{get_employer:->STR} }where is a structured set-union operator which works in parallel on the subcomponent-sets.
When component-definitions are combined with composition operators, trees and forests of operator applications result.
Let be a set of composition operators and a set of definition components. A composition forest is a forest of composition operator applications: inner nodes of the trees are composition operators from O, leaves are elements from D1 and Ident. All leaves of the forest from D1 form the definition-input of the composition forest. A composition sequence QF is a linearization of a composition forest F. Applying a QF to D1 yields a new set of component-definitions D2, the definition-output of QF. Thus QF is also a function .If QF(D1) contains only one component-definition with the same name, it is called view-resolved.
In our model compilers have to analyze the specifications to construct a composition forest on the definition universe. In essence this forest is an abstract syntax tree of the source code, containing all relevant component definitions. Since these can be scattered over the entire source code which has to be translated the compiler has to investigate the entire program. Then the definition forest has to be evaluated to find the number and form of defined components (the definition-output). To this end the compiler has to linearize the forest to find a sequential order of all compositions. Of course one linearization is determined by the source code; but there might be other valid ones.
Then the compiler has to analyze the composition forest to determine the component layouts. Because view merge operators remove their operands from the set of considered component-definitions, the output of a composition sequence may contain a different number of component-definitions with the same name. For view-resolved composition sequences, the definition-output is unique for a certain component name.
In a composition forest with view-resolved composition sequence,
the compiler can analyze the way from a leave of the forest to its root
to calculate an appropriate view mapping for a component-definition.
This can be done for all component-uses and visible component-definitions,
according to the visibility rules of the language.
Example
5 In our example sequencing means further subtyping from super- to
subclasses. If we define
driver = worker driverparts{ attributes{kind_of_licence: STR} }then the composition forest consists of the tree
In case of simple inheritance the inheritance operator on object attributes can be represented by attribute union. To compute the view mapping, the compiler calculates the offsets of the attributes in the object. In case of static binding for methods the value of get is the called function address. In case of dynamic dispatch this address is calculated at runtime using the name and type information of parameters.
Uwe Assmann and Rainer Schmidt