Adding new generators -- representation
ADT
typedef int element;
enum { NIL, CONS, INTERVAL };
struct list {
int tag;
element e;
union { element z; list* next; };
};
Generator
list* interval( element x, element y ) {
list* l = new list;
if ( x <= y ) {
l->tag = INTERVAL;
l->e = x; l->z = y;
}
else l->tag = NIL;
return l;
}
slide: Modules and generators
Let us first look at what happens when we add
a new generator to a data type, such as
an interval list subtype, containing the integers
in the interval between two given integers.
For the module realization of the list,
adding an generator will result in an
extension of the (hidden) representation types
with an additional representation tag type INTERVAL
and the definition of a suitable generator function.
To represent the interval list type, we employ a
union to select between the next field,
which is used by the cons generator, and the z
field, which indicates the end of the interval.
Modifying the observers
ADT
element head(list* l) { head
require( ! empty(l) );
return l->e; for both CONS and INTERVAL
}
list* tail(list* l) { tail
require( ! empty(l) );
switch( l->tag ) {
case CONS: return l->next;
case INTERVAL:
return interval((l->e)+1,l->z);
}
}
slide: Modifying the observers
Also, we need to modify the observer functions
by adding an appropriate case for the new interval
representation type, as pictured in slide [8-mod-xx].
Clearly, unless special constructs are provided,
the addition of a new generator case requires
disrupting the code implementing the given data type
manually, to extend the definition of the observers
with the new case.
In contrast, not surprisingly,
when we wish to add a new generator case
to the object realization of the list, we do not need to
disrupt the given code,
but we may simply add the definition of the generator
subtype as given in slide [8-oop-gen].
Adding new generators
OOP
class interval : public list<int> { interval
public:
interval(int x, int y) : _x(x), _y(y) { require( x <= y ); }
bool empty() { return 0; }
int head() { return _x; }
list< int >* tail() {
return (_x+1 <= _y)?
new interval(_x+1,_y):
new nil<int>;
}
bool operator==(list@lt;int>* m) {
return !m->empty() &&
_x == m->head() && tail() == m->tail();
}
protected:
int _x; int _y;
};
slide: Objects and generators
Adding a new generator subtype corresponds to
defining the realization for an abstract interface
class, which gives a method interface that its
subclasses must respect.
Observe, however, that we cannot exploit the
fact that a list is defined by an interval when
testing equality, since we cannot inspect the
type of the list as for the ADT implementation.