Expanded were hard to implement correctly because of the high requirement on the GC. It was done so that the embedded expanded reference was just treated as a normal reference except it was pointed on a subpart of the enclosing object. Therefore when within the expanded object, we were assigning a new object, we needed to go back not to the expanded header, but to the enclosing object header. Most of the bugs we had were related to an incorrect header update.
We believe there is a better solution. To describe it, we are going to take an example, with two classes A and B:
class A feature a: STRING b: expanded B f is local i: INTEGER do b.g i := b.i end end
class B feature i: INTEGER s: STRING g is do print (i) end end
For class A we can generate the following attribute layout, that does not take into account the way an instance of B is laid out.
For class B, a possibly layout is:
Don't forget that reference types have to be before the basic types.
So when we generate the code for f in A, we generate something like:
void f (EIF_REFERENCE Current) { EIF_INTEGER i; B_g (Current); // Call b.g i = Current->i; // Call b.i }
Let's see what is `B_g' in code generated for `expanded B':
void B_g (EIF_REFERENCE Current) { print (Current->(access_i (Current))) }
where `access_i' is a function returning the offset of `i' in `Current' object. This offset depends on where the expanded B is located. For the case of A, it points to the following function:
EIF_INTEGER access_i (EIF_REFERENCE Current) { return offset (Current, &Current->i) }