fix inheritance ordering

This commit is contained in:
David Rose 2006-01-13 21:30:00 +00:00
parent f04e3c9ddc
commit 14374eef99
3 changed files with 75 additions and 27 deletions

View File

@ -48,6 +48,14 @@ ConfigVariableBool dc_virtual_inheritance
"This also enables shadowing (overloading) of inherited method "
"names from a base class."));
ConfigVariableBool dc_sort_inheritance_by_file
("dc-sort-inheritance-by-file", true,
PRC_DESC("This is a temporary hack. This should be true if you are using "
"version 1.42 of the otp_server.exe binary, which sorted inherited "
"fields based on the order of the classes within the DC file, "
"rather than based on the order in which the references are made "
"within the class."));
#endif // WITHIN_PANDA
class SortFieldsByIndex {
@ -1300,49 +1308,81 @@ rebuild_inherited_fields() {
_inherited_fields.clear();
// First, get a list of all of the inherited field names.
// First, all of the inherited fields from our parent are at the top
// of the list.
Parents::const_iterator pi;
for (pi = _parents.begin(); pi != _parents.end(); ++pi) {
const DCClass *parent = (*pi);
int num_inherited_fields = parent->get_num_inherited_fields();
for (int i = 0; i < num_inherited_fields; ++i) {
const DCField *field = parent->get_inherited_field(i);
names.insert(field->get_name());
DCField *field = parent->get_inherited_field(i);
if (field->get_name().empty()) {
// Unnamed fields are always inherited. Except in the hack case.
if (!dc_sort_inheritance_by_file) {
_inherited_fields.push_back(field);
}
} else {
bool inserted = names.insert(field->get_name()).second;
if (inserted) {
// The earlier parent shadows the later parent.
_inherited_fields.push_back(field);
}
}
}
}
// Also get the local field names. Any local unnamed fields are
// immediately added to the _inherited_fields list, since the
// unnamed fields are not inherited.
// Now add the local fields at the end of the list. If any fields
// in this list were already defined by a parent, we will shadow the
// parent definition (that is, remove the parent's field from our
// list of inherited fields).
Fields::const_iterator fi;
for (fi = _fields.begin(); fi != _fields.end(); ++fi) {
DCField *field = (*fi);
if (field->get_name().empty()) {
_inherited_fields.push_back(field);
// Unnamed fields are always added.
_inherited_fields.push_back(field);
} else {
names.insert(field->get_name());
}
}
bool inserted = names.insert(field->get_name()).second;
if (!inserted) {
// This local field shadows an inherited field. Remove the
// parent's field from our list.
shadow_inherited_field(field->get_name());
}
// And now build up the table. We use get_field_by_name() to
// extract each one, to guarantee that the index we build exactly
// matches the return value of get_field_by_name().
Names::const_iterator ni;
for (ni = names.begin(); ni != names.end(); ++ni) {
// Note that we only list the named fields in the inherited field
// list. Thus, the unnamed fields, if any, are not inherited.
if (!(*ni).empty()) {
DCField *field = get_field_by_name(*ni);
nassertv(field != (DCField *)NULL);
// Now add the local field.
_inherited_fields.push_back(field);
}
}
// Finally, sort the list in global field index order. This will
// put the inherited fields at the top of the list.
sort(_inherited_fields.begin(), _inherited_fields.end(),
SortFieldsByIndex());
if (dc_sort_inheritance_by_file) {
// Temporary hack.
sort(_inherited_fields.begin(), _inherited_fields.end(), SortFieldsByIndex());
}
}
////////////////////////////////////////////////////////////////////
// Function: DCClass::shadow_inherited_field
// Access: Private
// Description: This is called only by rebuild_inherited_fields().
// It removes the named field from the list of
// _inherited_fields, presumably in preparation for
// adding a new definition below.
////////////////////////////////////////////////////////////////////
void DCClass::
shadow_inherited_field(const string &name) {
Fields::iterator fi;
for (fi = _inherited_fields.begin(); fi != _inherited_fields.end(); ++fi) {
DCField *field = (*fi);
if (field->get_name() == name) {
_inherited_fields.erase(fi);
return;
}
}
// If we get here, the named field wasn't in the list. Huh.
nassertv(false);
}
////////////////////////////////////////////////////////////////////
@ -1388,7 +1428,7 @@ add_field(DCField *field) {
}
if (_dc_file != (DCFile *)NULL &&
(dc_virtual_inheritance || !is_struct())) {
((dc_virtual_inheritance && dc_sort_inheritance_by_file) || !is_struct())) {
if (dc_multiple_inheritance) {
_dc_file->set_new_index_number(field);
} else {

View File

@ -30,11 +30,13 @@
extern ConfigVariableBool dc_multiple_inheritance;
extern ConfigVariableBool dc_virtual_inheritance;
extern ConfigVariableBool dc_sort_inheritance_by_file;
#else // WITHIN_PANDA
static const bool dc_multiple_inheritance = true;
static const bool dc_virtual_inheritance = true;
static const bool dc_sort_inheritance_by_file = false;
#endif // WITHIN_PANDA
@ -140,6 +142,8 @@ public:
void set_number(int number);
private:
void shadow_inherited_field(const string &name);
#ifdef WITHIN_PANDA
PStatCollector _class_update_pcollector;
PStatCollector _class_generate_pcollector;

View File

@ -501,7 +501,11 @@ void DCFile::
generate_hash(HashGenerator &hashgen) const {
if (dc_virtual_inheritance) {
// Just to make the hash number change in this case.
hashgen.add_int(1);
if (dc_sort_inheritance_by_file) {
hashgen.add_int(1);
} else {
hashgen.add_int(2);
}
}
hashgen.add_int(_classes.size());