Explorar o código

fix inheritance ordering

David Rose %!s(int64=20) %!d(string=hai) anos
pai
achega
14374eef99

+ 65 - 25
direct/src/dcparser/dcClass.cxx

@@ -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());
+      }
+
+      // Now add the local field.
+      _inherited_fields.push_back(field);
     }
   }
 
-  // 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);
-      _inherited_fields.push_back(field);
+  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;
     }
   }
 
-  // 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 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 {

+ 4 - 0
direct/src/dcparser/dcClass.h

@@ -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;

+ 5 - 1
direct/src/dcparser/dcFile.cxx

@@ -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());