Browse Source

interrogatedb 3.0 to restructure make_seq, improve make_seq handling and performance

rdb 10 years ago
parent
commit
ac1c036cac

+ 0 - 20
dtool/metalibs/dtoolconfig/pydtool.cxx

@@ -83,7 +83,6 @@ static PyObject *_inP07ytf513(PyObject *self, PyObject *args);
 static PyObject *_inP07ytsqGH(PyObject *self, PyObject *args);
 static PyObject *_inP07yt7shV(PyObject *self, PyObject *args);
 static PyObject *_inP07ytA1eF(PyObject *self, PyObject *args);
-static PyObject *_inP07yt9tTm(PyObject *self, PyObject *args);
 static PyObject *_inP07yt776V(PyObject *self, PyObject *args);
 static PyObject *_inP07ytfaH0(PyObject *self, PyObject *args);
 static PyObject *_inP07ytGB9D(PyObject *self, PyObject *args);
@@ -1219,24 +1218,6 @@ _inP07ytA1eF(PyObject *, PyObject *args) {
   return (PyObject *)NULL;
 }
 
-/*
- * Python simple wrapper for
- * TypeIndex interrogate_make_seq_class(MakeSeqIndex make_seq)
- */
-static PyObject *
-_inP07yt9tTm(PyObject *, PyObject *args) {
-  int param0;
-  if (PyArg_ParseTuple(args, "i", &param0)) {
-    TypeIndex return_value = interrogate_make_seq_class((MakeSeqIndex)param0);
-#if PY_MAJOR_VERSION >= 3
-    return PyLong_FromLong(return_value);
-#else
-    return PyInt_FromLong(return_value);
-#endif
-  }
-  return (PyObject *)NULL;
-}
-
 /*
  * Python simple wrapper for
  * char const *interrogate_make_seq_seq_name(MakeSeqIndex make_seq)
@@ -2433,7 +2414,6 @@ static PyMethodDef python_simple_funcs[] = {
   { "interrogate_wrapper_pointer", &_inP07ytsqGH, METH_VARARGS },
   { "interrogate_wrapper_unique_name", &_inP07yt7shV, METH_VARARGS },
   { "interrogate_get_wrapper_by_unique_name", &_inP07ytA1eF, METH_VARARGS },
-  { "interrogate_make_seq_class", &_inP07yt9tTm, METH_VARARGS },
   { "interrogate_make_seq_seq_name", &_inP07yt776V, METH_VARARGS },
   { "interrogate_make_seq_num_name", &_inP07ytfaH0, METH_VARARGS },
   { "interrogate_make_seq_element_name", &_inP07ytGB9D, METH_VARARGS },

File diff suppressed because it is too large
+ 983 - 965
dtool/src/cppparser/cppBison.cxx.prebuilt


+ 23 - 6
dtool/src/cppparser/cppBison.yxx

@@ -502,7 +502,7 @@ declaration:
 
   CPPDeclaration *getter = $5->find_symbol(current_scope, global_scope, current_lexer);
   if (getter == (CPPDeclaration *)NULL || getter->get_subtype() != CPPDeclaration::ST_function_group) {
-    yyerror("Reference to non-existent or invalid getter: " + $5->get_fully_scoped_name(), @1);
+    yyerror("Reference to non-existent or invalid getter: " + $5->get_fully_scoped_name(), @5);
   }
 
   CPPMakeProperty *make_property = new CPPMakeProperty($3, getter->as_function_group(), NULL, current_scope, @1.file);
@@ -512,14 +512,14 @@ declaration:
 {
   CPPDeclaration *getter = $5->find_symbol(current_scope, global_scope, current_lexer);
   if (getter == (CPPDeclaration *)NULL || getter->get_subtype() != CPPDeclaration::ST_function_group) {
-    yyerror("Reference to non-existent or invalid getter: " + $5->get_fully_scoped_name(), @1);
+    yyerror("Reference to non-existent or invalid getter: " + $5->get_fully_scoped_name(), @5);
 
   } else {
     CPPDeclaration *setter = $7->find_symbol(current_scope, global_scope, current_lexer);
     CPPFunctionGroup *setter_func = NULL;
 
     if (setter == (CPPDeclaration *)NULL || setter->get_subtype() != CPPDeclaration::ST_function_group) {
-      yyerror("Reference to non-existent or invalid setter: " + $7->get_fully_scoped_name(), @1);
+      yyerror("Reference to non-existent or invalid setter: " + $7->get_fully_scoped_name(), @7);
     } else {
       setter_func = setter->as_function_group();
     }
@@ -529,10 +529,27 @@ declaration:
     current_scope->add_declaration(make_property, global_scope, current_lexer, @1);
   }
 }
-        | KW_MAKE_SEQ '(' name ',' name ',' name ')' ';'
+        | KW_MAKE_SEQ '(' IDENTIFIER ',' IDENTIFIER ',' IDENTIFIER ')' ';'
 {
-  CPPMakeSeq *make_seq = new CPPMakeSeq($3->get_simple_name(), $5->get_simple_name(), $7->get_simple_name(), @1.file);
-  current_scope->add_declaration(make_seq, global_scope, current_lexer, @1);
+  CPPDeclaration *length_getter = $5->find_symbol(current_scope, global_scope, current_lexer);
+  if (length_getter == (CPPDeclaration *)NULL || length_getter->get_subtype() != CPPDeclaration::ST_function_group) {
+    yyerror("reference to non-existent or invalid length method: " + $5->get_fully_scoped_name(), @5);
+    length_getter = NULL;
+  }
+
+  CPPDeclaration *element_getter = $7->find_symbol(current_scope, global_scope, current_lexer);
+  if (element_getter == (CPPDeclaration *)NULL || element_getter->get_subtype() != CPPDeclaration::ST_function_group) {
+    yyerror("reference to non-existent or invalid element method: " + $7->get_fully_scoped_name(), @5);
+    element_getter = NULL;
+  }
+
+  if (length_getter != (CPPDeclaration *)NULL && element_getter != (CPPDeclaration *)NULL) {
+    CPPMakeSeq *make_seq = new CPPMakeSeq($3,
+                                          length_getter->as_function_group(),
+                                          element_getter->as_function_group(),
+                                          current_scope, @1.file);
+    current_scope->add_declaration(make_seq, global_scope, current_lexer, @1);
+  }
 }
         | KW_STATIC_ASSERT '(' const_expr ',' string_literal ')'
 {

+ 42 - 7
dtool/src/cppparser/cppMakeSeq.cxx

@@ -20,13 +20,46 @@
 //  Description:
 ////////////////////////////////////////////////////////////////////
 CPPMakeSeq::
-CPPMakeSeq(const string &seq_name, const string &num_name,
-           const string &element_name, const CPPFile &file) :
+CPPMakeSeq(CPPIdentifier *ident,
+           CPPFunctionGroup *length_getter,
+           CPPFunctionGroup *element_getter,
+           CPPScope *current_scope, const CPPFile &file) :
   CPPDeclaration(file),
-  _seq_name(seq_name),
-  _num_name(num_name),
-  _element_name(element_name)
+  _ident(ident),
+  _length_getter(length_getter),
+  _element_getter(element_getter)
 {
+  _ident->_native_scope = current_scope;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: CPPMakeSeq::get_simple_name
+//       Access: Public, Virtual
+//  Description:
+////////////////////////////////////////////////////////////////////
+string CPPMakeSeq::
+get_simple_name() const {
+  return _ident->get_simple_name();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: CPPMakeSeq::get_local_name
+//       Access: Public, Virtual
+//  Description:
+////////////////////////////////////////////////////////////////////
+string CPPMakeSeq::
+get_local_name(CPPScope *scope) const {
+  return _ident->get_local_name(scope);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: CPPMakeSeq::get_fully_scoped_name
+//       Access: Public, Virtual
+//  Description:
+////////////////////////////////////////////////////////////////////
+string CPPMakeSeq::
+get_fully_scoped_name() const {
+  return _ident->get_fully_scoped_name();
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -36,8 +69,10 @@ CPPMakeSeq(const string &seq_name, const string &num_name,
 ////////////////////////////////////////////////////////////////////
 void CPPMakeSeq::
 output(ostream &out, int indent_level, CPPScope *scope, bool complete) const {
-  out << "__make_seq(" << _seq_name << ", " << _num_name << ", "
-      << _element_name << ");";
+  out << "__make_seq(" << _ident->get_local_name(scope)
+      << ", " << _length_getter->_name
+      << ", " << _element_getter->_name
+      << ");";
 }
 
 ////////////////////////////////////////////////////////////////////

+ 12 - 7
dtool/src/cppparser/cppMakeSeq.h

@@ -18,6 +18,7 @@
 #include "dtoolbase.h"
 
 #include "cppDeclaration.h"
+#include "cppIdentifier.h"
 
 ///////////////////////////////////////////////////////////////////
 //       Class : CPPMakeSeq
@@ -29,8 +30,14 @@
 ////////////////////////////////////////////////////////////////////
 class CPPMakeSeq : public CPPDeclaration {
 public:
-  CPPMakeSeq(const string &seq_name, const string &num_name,
-             const string &element_name, const CPPFile &file);
+  CPPMakeSeq(CPPIdentifier *ident,
+             CPPFunctionGroup *length_getter,
+             CPPFunctionGroup *element_getter,
+             CPPScope *current_scope, const CPPFile &file);
+
+  virtual string get_simple_name() const;
+  virtual string get_local_name(CPPScope *scope = NULL) const;
+  virtual string get_fully_scoped_name() const;
 
   virtual void output(ostream &out, int indent_level, CPPScope *scope,
                       bool complete) const;
@@ -38,11 +45,9 @@ public:
   virtual SubType get_subtype() const;
   virtual CPPMakeSeq *as_make_seq();
 
-  string _seq_name;
-  string _num_name;
-  string _element_name;
+  CPPIdentifier *_ident;
+  CPPFunctionGroup *_length_getter;
+  CPPFunctionGroup *_element_getter;
 };
 
 #endif
-
-

+ 6 - 28
dtool/src/interrogate/interfaceMaker.cxx

@@ -79,11 +79,11 @@ InterfaceMaker::Function::
 //  Description:
 ////////////////////////////////////////////////////////////////////
 InterfaceMaker::MakeSeq::
-MakeSeq(const string &name, CPPMakeSeq *cpp_make_seq) :
+MakeSeq(const string &name, const InterrogateMakeSeq &imake_seq) :
   _name(name),
-  _seq_name(cpp_make_seq->_seq_name),
-  _num_name(cpp_make_seq->_num_name),
-  _element_name(cpp_make_seq->_element_name)
+  _imake_seq(imake_seq),
+  _length_getter(NULL),
+  _element_getter(NULL)
 {
 }
 
@@ -174,30 +174,6 @@ check_protocols() {
   if (flags & FunctionRemap::F_iter) {
     _protocol_types |= PT_iter;
   }
-
-  // Now are there any make_seq requests within this class?
-  if (_itype._cpptype != NULL) {
-    CPPStructType *stype = _itype._cpptype->as_struct_type();
-    if (stype != (CPPStructType *)NULL) {
-      CPPScope *scope = stype->get_scope();
-      if (scope != (CPPScope *)NULL) {
-        CPPScope::Declarations::iterator di;
-        for (di = scope->_declarations.begin(); di != scope->_declarations.end(); ++di) {
-          CPPMakeSeq *cpp_make_seq = (*di)->as_make_seq();
-          if (cpp_make_seq != (CPPMakeSeq *)NULL) {
-            string class_name = _itype.get_scoped_name();
-            string clean_name = InterrogateBuilder::clean_identifier(class_name);
-            string wrapper_name = "MakeSeq_" + clean_name + "_" + cpp_make_seq->_seq_name;
-            MakeSeq *make_seq = new MakeSeq(wrapper_name, cpp_make_seq);
-            _make_seqs.push_back(make_seq);
-
-            // Also add to the interrogate database.
-            builder.get_make_seq(cpp_make_seq, stype);
-          }
-        }
-      }
-    }
-  }
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -637,6 +613,8 @@ get_unique_prefix() {
 ////////////////////////////////////////////////////////////////////
 InterfaceMaker::Function *InterfaceMaker::
 record_function(const InterrogateType &itype, FunctionIndex func_index) {
+  assert(func_index != 0);
+
   if (_functions.count(func_index)) {
     // Already exists.
     return _functions[func_index];

+ 5 - 4
dtool/src/interrogate/interfaceMaker.h

@@ -33,6 +33,7 @@ class CPPInstance;
 class InterrogateBuilder;
 class InterrogateElement;
 class InterrogateFunction;
+class InterrogateMakeSeq;
 class InterrogateType;
 
 ////////////////////////////////////////////////////////////////////
@@ -116,12 +117,12 @@ public:
 
   class MakeSeq {
   public:
-    MakeSeq(const string &name, CPPMakeSeq *cpp_make_seq);
+    MakeSeq(const string &name, const InterrogateMakeSeq &imake_seq);
 
+    const InterrogateMakeSeq &_imake_seq;
     string _name;
-    string _seq_name;
-    string _num_name;
-    string _element_name;
+    Function *_length_getter;
+    Function *_element_getter;
   };
   typedef vector<MakeSeq *> MakeSeqs;
 

+ 121 - 51
dtool/src/interrogate/interfaceMakerPythonNative.cxx

@@ -1099,7 +1099,17 @@ write_class_details(ostream &out, Object *obj) {
   // Write make seqs: generated methods that return a sequence of items.
   MakeSeqs::iterator msi;
   for (msi = obj->_make_seqs.begin(); msi != obj->_make_seqs.end(); ++msi) {
-    write_make_seq(out, obj, ClassName, cClassName, *msi);
+    if (is_function_legal((*msi)->_length_getter) &&
+        is_function_legal((*msi)->_element_getter)) {
+      write_make_seq(out, obj, ClassName, cClassName, *msi);
+    } else {
+      if (!is_function_legal((*msi)->_length_getter)) {
+        cerr << "illegal length function for MAKE_SEQ: " << (*msi)->_length_getter->_name << "\n";
+      }
+      if (!is_function_legal((*msi)->_element_getter)) {
+        cerr << "illegal element function for MAKE_SEQ: " << (*msi)->_element_getter->_name << "\n";
+      }
+    }
   }
 
   // Determine which external imports we will need.
@@ -1711,23 +1721,27 @@ write_module_class(ostream &out, Object *obj) {
 
   MakeSeqs::iterator msi;
   for (msi = obj->_make_seqs.begin(); msi != obj->_make_seqs.end(); ++msi) {
-    const string &seq_name = (*msi)->_seq_name;
+    MakeSeq *make_seq = (*msi);
+    if (!is_function_legal(make_seq->_length_getter) ||
+        !is_function_legal(make_seq->_element_getter)) {
+      continue;
+    }
 
-    if ((seq_name.size() > 4 && seq_name.substr(0, 4) == "get_") ||
-        (seq_name.size() > 7 && seq_name.substr(0, 7) == "modify_")) {
+    string seq_name = make_seq->_imake_seq.get_name();
 
-      string flags = "METH_NOARGS";
-      if (obj->is_static_method((*msi)->_element_name)) {
-        flags += " | METH_CLASS";
-      }
-      string name1 = methodNameFromCppName((*msi)->_seq_name, export_class_name, false);
-      string name2 = methodNameFromCppName((*msi)->_seq_name, export_class_name, true);
-      out << "  {\"" << name1
-          << "\", (PyCFunction) &" << (*msi)->_name << ", " << flags << ", NULL},\n";
-      if (name1 != name2) {
-        out << "  { \"" << name2
-            << "\", (PyCFunction) &" << (*msi)->_name << ", " << flags << ", NULL},\n";
-      }
+    string flags = "METH_NOARGS";
+    if (!make_seq->_length_getter->_has_this &&
+        !make_seq->_element_getter->_has_this) {
+      flags += " | METH_STATIC";
+    }
+
+    string name1 = methodNameFromCppName(seq_name, export_class_name, false);
+    string name2 = methodNameFromCppName(seq_name, export_class_name, true);
+    out << "  {\"" << name1
+        << "\", (PyCFunction) &" << make_seq->_name << ", " << flags << ", NULL},\n";
+    if (name1 != name2) {
+      out << "  { \"" << name2
+          << "\", (PyCFunction) &" << make_seq->_name << ", " << flags << ", NULL},\n";
     }
   }
 
@@ -6335,47 +6349,88 @@ pack_return_value(ostream &out, int indent_level, FunctionRemap *remap,
 void InterfaceMakerPythonNative::
 write_make_seq(ostream &out, Object *obj, const std::string &ClassName,
                const std::string &cClassName, MakeSeq *make_seq) {
+
   out << "/******************************************************************\n" << " * Python make_seq wrapper\n";
   out << " *******************************************************************/\n";
 
   out << "static PyObject *" << make_seq->_name + "(PyObject *self, PyObject *) {\n";
-  string element_name = methodNameFromCppName(make_seq->_element_name, ClassName, false);
 
-  // This used to be a list.  But it should really be a tuple, I think,
-  // because it probably makes more sense for it to be immutable (as
-  // changes to it won't be visible on the C++ side anyway).
+  // This used to return a list.  But it should really be a tuple, I
+  // think, because it probably makes more sense for it to be immutable
+  // (as changes to it won't be visible on the C++ side anyway).
 
-  out << "  " << cClassName  << " *local_this = NULL;\n"
-      << "  if (!Dtool_Call_ExtractThisPointer(self, Dtool_" << ClassName << ", (void **)&local_this)) {\n"
-      << "    return NULL;\n"
-      << "  }\n"
-      << "\n"
-      << "  PyObject *getter = PyDict_GetItemString(Dtool_" << ClassName << "._PyType.tp_dict, \"" << element_name << "\");\n"
-      << "  if (getter == (PyObject *)NULL) {\n"
-      << "    return Dtool_Raise_AttributeError(self, \"" << element_name << "\");\n"
-      << "  }\n"
-      << "\n"
-      << "  Py_ssize_t count = (Py_ssize_t)local_this->" << make_seq->_num_name << "();\n"
-      << "  PyObject *tuple = PyTuple_New(count);\n"
-      << "\n"
-      << "  for (Py_ssize_t i = 0; i < count; ++i) {\n"
-      << "#if PY_MAJOR_VERSION >= 3\n"
-      << "    PyObject *index = PyLong_FromSsize_t(i);\n"
-      << "#else\n"
-      << "    PyObject *index = PyInt_FromSsize_t(i);\n"
-      << "#endif\n"
-      << "    PyObject *value = PyObject_CallFunctionObjArgs(getter, self, index, NULL);\n"
-      << "    PyTuple_SET_ITEM(tuple, i, value);\n"
-      << "    Py_DECREF(index);\n"
-      << "  }\n"
-      << "\n"
-      << "  if (Dtool_CheckErrorOccurred()) {\n"
-      << "    Py_DECREF(tuple);\n"
-      << "    return NULL;\n"
-      << "  }\n"
-      << "  return tuple;\n"
-      << "}\n"
-      << "\n";
+  FunctionRemap *remap = make_seq->_length_getter->_remaps.front();
+  vector_string pexprs;
+
+  if (make_seq->_length_getter->_has_this) {
+    out <<
+      "  " << cClassName  << " *local_this = NULL;\n"
+      "  if (!Dtool_Call_ExtractThisPointer(self, Dtool_" << ClassName << ", (void **)&local_this)) {\n"
+      "    return NULL;\n"
+      "  }\n"
+      "  Py_ssize_t count = (Py_ssize_t)" << remap->get_call_str("local_this", pexprs) << ";\n";
+  } else {
+    out << "  Py_ssize_t count = (Py_ssize_t)" << remap->get_call_str("", pexprs) << ";\n";
+  }
+
+  Function *elem_getter = make_seq->_element_getter;
+
+  if ((elem_getter->_args_type & AT_varargs) == AT_varargs) {
+    // Fast way to create a temporary tuple to hold only a single item, under
+    // the assumption that the called method doesn't do anything with this tuple
+    // other than unpack it (which is a fairly safe assumption to make).
+    out << "  PyTupleObject args;\n";
+    out << "  PyObject_INIT_VAR(&args, &PyTuple_Type, 1);\n";
+  }
+
+  out <<
+    "  PyObject *tuple = PyTuple_New(count);\n"
+    "\n"
+    "  for (Py_ssize_t i = 0; i < count; ++i) {\n"
+    "#if PY_MAJOR_VERSION >= 3\n"
+    "    PyObject *index = PyLong_FromSsize_t(i);\n"
+    "#else\n"
+    "    PyObject *index = PyInt_FromSsize_t(i);\n"
+    "#endif\n";
+
+  switch (elem_getter->_args_type) {
+  case AT_keyword_args:
+    out << "    PyTuple_SET_ITEM(&args, 0, index);\n"
+           "    PyObject *value = " << elem_getter->_name << "(self, (PyObject *)&args, NULL);\n";
+    break;
+
+  case AT_varargs:
+    out << "    PyTuple_SET_ITEM(&args, 0, index);\n"
+           "    PyObject *value = " << elem_getter->_name << "(self, (PyObject *)&args);\n";
+    break;
+
+  case AT_single_arg:
+    out << "    PyObject *value = " << elem_getter->_name << "(self, index);\n";
+    break;
+
+  default:
+    out << "    PyObject *value = " << elem_getter->_name << "(self, NULL);\n";
+    break;
+  }
+
+  out <<
+    "    PyTuple_SET_ITEM(tuple, i, value);\n"
+    "    Py_DECREF(index);\n"
+    "  }\n"
+    "\n";
+
+  if ((elem_getter->_args_type & AT_varargs) == AT_varargs) {
+    out << "  _Py_ForgetReference((PyObject *)&args);\n";
+  }
+
+  out <<
+    "  if (Dtool_CheckErrorOccurred()) {\n"
+    "    Py_DECREF(tuple);\n"
+    "    return NULL;\n"
+    "  }\n"
+    "  return tuple;\n"
+    "}\n"
+    "\n";
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -6494,6 +6549,21 @@ record_object(TypeIndex type_index) {
     }
   }
 
+  int num_make_seqs = itype.number_of_make_seqs();
+  for (int msi = 0; msi < num_make_seqs; msi++) {
+    MakeSeqIndex make_seq_index = itype.get_make_seq(msi);
+    const InterrogateMakeSeq &imake_seq = idb->get_make_seq(make_seq_index);
+
+    string class_name = itype.get_scoped_name();
+    string clean_name = InterrogateBuilder::clean_identifier(class_name);
+    string wrapper_name = "MakeSeq_" + clean_name + "_" + imake_seq.get_name();
+
+    MakeSeq *make_seq = new MakeSeq(wrapper_name, imake_seq);
+    make_seq->_length_getter = record_function(itype, imake_seq.get_length_getter());
+    make_seq->_element_getter = record_function(itype, imake_seq.get_element_getter());
+    object->_make_seqs.push_back(make_seq);
+  }
+
   object->check_protocols();
 
   int num_nested = itype.number_of_nested_types();

+ 70 - 8
dtool/src/interrogate/interrogateBuilder.cxx

@@ -1998,7 +1998,7 @@ get_make_property(CPPMakeProperty *make_property, CPPStructType *struct_type) {
 ////////////////////////////////////////////////////////////////////
 MakeSeqIndex InterrogateBuilder::
 get_make_seq(CPPMakeSeq *make_seq, CPPStructType *struct_type) {
-  string make_seq_name = struct_type->get_local_name(&parser) + "::MakeSeq_" + make_seq->_seq_name;
+  string make_seq_name = make_seq->get_local_name(&parser);
 
   // First, check to see if it's already there.
   MakeSeqsByName::const_iterator tni =
@@ -2008,21 +2008,79 @@ get_make_seq(CPPMakeSeq *make_seq, CPPStructType *struct_type) {
     return index;
   }
 
+  FunctionIndex length_getter = 0;
+  FunctionIndex element_getter = 0;
+
+  CPPFunctionGroup::Instances::const_iterator fi;
+  CPPFunctionGroup *fgroup = make_seq->_length_getter;
+  if (fgroup != NULL) {
+    for (fi = fgroup->_instances.begin(); fi != fgroup->_instances.end(); ++fi) {
+      CPPInstance *function = (*fi);
+      CPPFunctionType *ftype =
+        function->_type->as_function_type();
+      if (ftype != NULL) {
+        length_getter = get_function(function, "", struct_type,
+                                     struct_type->get_scope(), 0);
+        if (length_getter != 0) {
+          break;
+        }
+      }
+    }
+    if (length_getter == 0) {
+      cerr << "No instance of length method '"
+           << fgroup->_name << "' is suitable!\n";
+      return 0;
+    }
+  } else {
+    cerr << "MAKE_SEQ " << make_seq_name << " requires a length method.\n";
+    return 0;
+  }
+
+  fgroup = make_seq->_element_getter;
+  if (fgroup != NULL) {
+    for (fi = fgroup->_instances.begin(); fi != fgroup->_instances.end(); ++fi) {
+      CPPInstance *function = (*fi);
+      CPPFunctionType *ftype =
+        function->_type->as_function_type();
+      if (ftype != NULL && ftype->_parameters->_parameters.size() >= 1 &&
+          TypeManager::is_integer(ftype->_parameters->_parameters[0]->_type)) {
+        // It really doesn't matter whether we grab the const or non-const
+        // version, since they should all return the same function anyway.
+        element_getter = get_function(function, "", struct_type,
+                                      struct_type->get_scope(), 0);
+        if (element_getter != 0) {
+          break;
+        }
+      }
+    }
+    if (element_getter == 0) {
+      cerr << "No instance of element method '"
+           << fgroup->_name << "' is suitable!\n";
+      return 0;
+    }
+  } else {
+    cerr << "MAKE_SEQ " << make_seq_name << " requires an element method.\n";
+    return 0;
+  }
+
   InterrogateDatabase *idb = InterrogateDatabase::get_ptr();
   // It isn't here, so we'll have to define it.
   MakeSeqIndex index = idb->get_next_index();
   _make_seqs_by_name[make_seq_name] = index;
 
   InterrogateMakeSeq imake_seq;
-  imake_seq._class = get_type(struct_type, false);
-  imake_seq._seq_name = make_seq->_seq_name;
-  imake_seq._num_name = make_seq->_num_name;
-  imake_seq._element_name = make_seq->_element_name;
+  imake_seq._name = make_seq->get_simple_name();
+  imake_seq._scoped_name = descope(make_seq->get_local_name(&parser));
 
-  idb->add_make_seq(index, imake_seq);
+  imake_seq._length_getter = length_getter;
+  imake_seq._element_getter = element_getter;
 
-  InterrogateType &itype = idb->update_type(imake_seq._class);
-  itype._make_seqs.push_back(index);
+  // See if there happens to be a comment before the MAKE_SEQ macro.
+  if (make_seq->_leading_comment != (CPPCommentBlock *)NULL) {
+    imake_seq._comment = trim_blanks(make_seq->_leading_comment->_comment);
+  }
+
+  idb->add_make_seq(index, imake_seq);
 
   return index;
 }
@@ -2553,6 +2611,10 @@ define_struct_type(InterrogateType &itype, CPPStructType *cpptype,
     } else if ((*di)->get_subtype() == CPPDeclaration::ST_make_property) {
       ElementIndex element_index = get_make_property((*di)->as_make_property(), cpptype);
       itype._elements.push_back(element_index);
+
+    } else if ((*di)->get_subtype() == CPPDeclaration::ST_make_seq) {
+      MakeSeqIndex make_seq_index = get_make_seq((*di)->as_make_seq(), cpptype);
+      itype._make_seqs.push_back(make_seq_index);
     }
   }
 

+ 2 - 2
dtool/src/interrogatedb/interrogateDatabase.cxx

@@ -20,8 +20,8 @@
 InterrogateDatabase *InterrogateDatabase::_global_ptr = NULL;
 int InterrogateDatabase::_file_major_version = 0;
 int InterrogateDatabase::_file_minor_version = 0;
-int InterrogateDatabase::_current_major_version = 2;
-int InterrogateDatabase::_current_minor_version = 3;
+int InterrogateDatabase::_current_major_version = 3;
+int InterrogateDatabase::_current_minor_version = 0;
 
 ////////////////////////////////////////////////////////////////////
 //     Function: InterrogateDatabase::Constructor

+ 1 - 4
dtool/src/interrogatedb/interrogateElement.cxx

@@ -45,10 +45,7 @@ input(istream &in) {
   InterrogateComponent::input(in);
   in >> _flags >> _type >> _getter >> _setter;
   idf_input_string(in, _scoped_name);
-
-  if (InterrogateDatabase::get_file_minor_version() >= 3) {
-    idf_input_string(in, _comment);
-  }
+  idf_input_string(in, _comment);
 }
 
 ////////////////////////////////////////////////////////////////////

+ 1 - 4
dtool/src/interrogatedb/interrogateFunction.cxx

@@ -93,10 +93,7 @@ input(istream &in) {
   idf_input_vector(in, _c_wrappers);
   idf_input_vector(in, _python_wrappers);
   idf_input_string(in, _comment);
-
-  if (InterrogateDatabase::get_file_minor_version() >= 2) {
-    idf_input_string(in, _prototype);
-  }
+  idf_input_string(in, _prototype);
 }
 
 ////////////////////////////////////////////////////////////////////

+ 40 - 20
dtool/src/interrogatedb/interrogateMakeSeq.I

@@ -23,7 +23,8 @@ INLINE InterrogateMakeSeq::
 InterrogateMakeSeq(InterrogateModuleDef *def) :
   InterrogateComponent(def)
 {
-  _class = 0;
+  _length_getter = 0;
+  _element_getter = 0;
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -44,52 +45,71 @@ InterrogateMakeSeq(const InterrogateMakeSeq &copy) {
 INLINE void InterrogateMakeSeq::
 operator = (const InterrogateMakeSeq &copy) {
   InterrogateComponent::operator = (copy);
-  _class = copy._class;
-  _seq_name = copy._seq_name;
-  _num_name = copy._num_name;
-  _element_name = copy._element_name;
+  _scoped_name = copy._scoped_name;
+  _comment = copy._comment;
+  _length_getter = copy._length_getter;
+  _element_getter = copy._element_getter;
 }
 
 ////////////////////////////////////////////////////////////////////
-//     Function: InterrogateMakeSeq::get_class
+//     Function: InterrogateMakeSeq::has_scoped_name
 //       Access: Public
-//  Description: Return the class that owns the make_seq.
+//  Description:
 ////////////////////////////////////////////////////////////////////
-INLINE TypeIndex InterrogateMakeSeq::
-get_class() const {
-  return _class;
+INLINE bool InterrogateMakeSeq::
+has_scoped_name() const {
+  return !_scoped_name.empty();
 }
 
 ////////////////////////////////////////////////////////////////////
-//     Function: InterrogateMakeSeq::get_seq_name
+//     Function: InterrogateMakeSeq::get_scoped_name
 //       Access: Public
 //  Description:
 ////////////////////////////////////////////////////////////////////
 INLINE const string &InterrogateMakeSeq::
-get_seq_name() const {
-  return _seq_name;
+get_scoped_name() const {
+  return _scoped_name;
 }
 
 ////////////////////////////////////////////////////////////////////
-//     Function: InterrogateMakeSeq::get_num_name
+//     Function: InterrogateMakeSeq::has_comment
 //       Access: Public
 //  Description:
 ////////////////////////////////////////////////////////////////////
-INLINE const string &InterrogateMakeSeq::
-get_num_name() const {
-  return _num_name;
+INLINE bool InterrogateMakeSeq::
+has_comment() const {
+  return !_comment.empty();
 }
 
 ////////////////////////////////////////////////////////////////////
-//     Function: InterrogateMakeSeq::get_element_name
+//     Function: InterrogateMakeSeq::get_comment
 //       Access: Public
 //  Description:
 ////////////////////////////////////////////////////////////////////
 INLINE const string &InterrogateMakeSeq::
-get_element_name() const {
-  return _element_name;
+get_comment() const {
+  return _comment;
 }
 
+////////////////////////////////////////////////////////////////////
+//      Element: InterrogateMakeSeq::get_length_getter
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE FunctionIndex InterrogateMakeSeq::
+get_length_getter() const {
+  return _length_getter;
+}
+
+////////////////////////////////////////////////////////////////////
+//      Element: InterrogateMakeSeq::get_element_getter
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE FunctionIndex InterrogateMakeSeq::
+get_element_getter() const {
+  return _element_getter;
+}
 
 INLINE ostream &
 operator << (ostream &out, const InterrogateMakeSeq &make_seq) {

+ 10 - 8
dtool/src/interrogatedb/interrogateMakeSeq.cxx

@@ -25,10 +25,10 @@
 void InterrogateMakeSeq::
 output(ostream &out) const {
   InterrogateComponent::output(out);
-  out << _class << " ";
-  idf_output_string(out, _seq_name);
-  idf_output_string(out, _num_name);
-  idf_output_string(out, _element_name);
+  out << _length_getter << " "
+      << _element_getter << " ";
+  idf_output_string(out, _scoped_name);
+  idf_output_string(out, _comment, '\n');
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -40,10 +40,10 @@ output(ostream &out) const {
 void InterrogateMakeSeq::
 input(istream &in) {
   InterrogateComponent::input(in);
-  in >> _class;
-  idf_input_string(in, _seq_name);
-  idf_input_string(in, _num_name);
-  idf_input_string(in, _element_name);
+
+  in >> _length_getter >> _element_getter;
+  idf_input_string(in, _scoped_name);
+  idf_input_string(in, _comment);
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -55,4 +55,6 @@ input(istream &in) {
 ////////////////////////////////////////////////////////////////////
 void InterrogateMakeSeq::
 remap_indices(const IndexRemapper &remap) {
+  _length_getter = remap.map_from(_length_getter);
+  _element_getter = remap.map_from(_element_getter);
 }

+ 12 - 8
dtool/src/interrogatedb/interrogateMakeSeq.h

@@ -32,10 +32,14 @@ public:
   INLINE InterrogateMakeSeq(const InterrogateMakeSeq &copy);
   INLINE void operator = (const InterrogateMakeSeq &copy);
 
-  INLINE TypeIndex get_class() const;
-  INLINE const string &get_seq_name() const;
-  INLINE const string &get_num_name() const;
-  INLINE const string &get_element_name() const;
+  INLINE bool has_scoped_name() const;
+  INLINE const string &get_scoped_name() const;
+
+  INLINE bool has_comment() const;
+  INLINE const string &get_comment() const;
+
+  INLINE FunctionIndex get_length_getter() const;
+  INLINE FunctionIndex get_element_getter() const;
 
   void output(ostream &out) const;
   void input(istream &in);
@@ -43,10 +47,10 @@ public:
   void remap_indices(const IndexRemapper &remap);
 
 private:
-  TypeIndex _class;
-  string _seq_name;
-  string _num_name;
-  string _element_name;
+  string _scoped_name;
+  string _comment;
+  FunctionIndex _length_getter;
+  FunctionIndex _element_getter;
 
   friend class InterrogateBuilder;
 };

+ 1 - 3
dtool/src/interrogatedb/interrogateType.cxx

@@ -91,9 +91,7 @@ void InterrogateType::EnumValue::
 input(istream &in) {
   idf_input_string(in, _name);
   idf_input_string(in, _scoped_name);
-  if (InterrogateDatabase::get_file_minor_version() >= 3) {
-    idf_input_string(in, _comment);
-  }
+  idf_input_string(in, _comment);
   in >> _value;
 }
 

+ 24 - 11
dtool/src/interrogatedb/interrogate_interface.cxx

@@ -414,34 +414,47 @@ interrogate_get_wrapper_by_unique_name(const char *unique_name) {
   return InterrogateDatabase::get_ptr()->get_wrapper_by_unique_name(unique_name);
 }
 
-TypeIndex 
-interrogate_make_seq_class(MakeSeqIndex make_seq) {
-  //cerr << "interrogate_make_seq_class(" << make_seq << ")\n";
-  return InterrogateDatabase::get_ptr()->get_make_seq(make_seq).get_class();
+const char *
+interrogate_make_seq_seq_name(MakeSeqIndex make_seq) {
+  //cerr << "interrogate_make_seq_seq_name(" << make_seq << ")\n";
+  static string result;
+  result = InterrogateDatabase::get_ptr()->get_make_seq(make_seq).get_name();
+  return result.c_str();
 }
 
 const char *
-interrogate_make_seq_seq_name(MakeSeqIndex make_seq) {
+interrogate_make_seq_scoped_name(MakeSeqIndex make_seq) {
   //cerr << "interrogate_make_seq_seq_name(" << make_seq << ")\n";
   static string result;
-  result = InterrogateDatabase::get_ptr()->get_make_seq(make_seq).get_seq_name();
+  result = InterrogateDatabase::get_ptr()->get_make_seq(make_seq).get_scoped_name();
   return result.c_str();
 }
 
+bool
+interrogate_make_seq_has_comment(MakeSeqIndex make_seq) {
+  //cerr << "interrogate_make_seq_has_comment(" << make_seq << ")\n";
+  return InterrogateDatabase::get_ptr()->get_make_seq(make_seq).has_comment();
+}
+
+const char *
+interrogate_make_seq_comment(MakeSeqIndex make_seq) {
+  //cerr << "interrogate_make_seq_comment(" << make_seq << ")\n";
+  return InterrogateDatabase::get_ptr()->get_make_seq(make_seq).get_comment().c_str();
+}
+
 const char *
 interrogate_make_seq_num_name(MakeSeqIndex make_seq) {
   //cerr << "interrogate_make_seq_num_name(" << make_seq << ")\n";
-  static string result;
-  result = InterrogateDatabase::get_ptr()->get_make_seq(make_seq).get_num_name();
-  return result.c_str();
+  FunctionIndex function = InterrogateDatabase::get_ptr()->get_make_seq(make_seq).get_length_getter();
+  return interrogate_function_name(function);
 }
 
 const char *
 interrogate_make_seq_element_name(MakeSeqIndex make_seq) {
   //cerr << "interrogate_make_seq_element_name(" << make_seq << ")\n";
   static string result;
-  result = InterrogateDatabase::get_ptr()->get_make_seq(make_seq).get_element_name();
-  return result.c_str();
+  FunctionIndex function = InterrogateDatabase::get_ptr()->get_make_seq(make_seq).get_element_getter();
+  return interrogate_function_name(function);
 }
 
 int

+ 3 - 4
dtool/src/interrogatedb/interrogate_interface.h

@@ -363,11 +363,10 @@ EXPCL_INTERROGATEDB FunctionWrapperIndex interrogate_get_wrapper_by_unique_name(
 // and get_thing(n) are used to synthesize a new method called
 // get_things().
 
-// The class of which the make_seq is a method.
-EXPCL_INTERROGATEDB TypeIndex interrogate_make_seq_class(MakeSeqIndex make_seq);
-
-// The name of the syntheized method, e.g. "get_things"
 EXPCL_INTERROGATEDB const char *interrogate_make_seq_seq_name(MakeSeqIndex make_seq);
+EXPCL_INTERROGATEDB const char *interrogate_make_seq_scoped_name(MakeSeqIndex make_seq);
+EXPCL_INTERROGATEDB bool interrogate_make_seq_has_comment(ElementIndex element);
+EXPCL_INTERROGATEDB const char *interrogate_make_seq_comment(ElementIndex element);
 // The name of the real method that returns the length, e.g. "get_num_things"
 EXPCL_INTERROGATEDB const char *interrogate_make_seq_num_name(MakeSeqIndex make_seq);
 // The name of the real method that returns the nth element, e.g. "get_thing"

+ 1 - 1
panda/src/parametrics/nurbsCurveResult.h

@@ -67,7 +67,7 @@ PUBLISHED:
   INLINE PN_stdfloat get_sample_t(int n) const;
   INLINE const LPoint3 &get_sample_point(int n) const;
   MAKE_SEQ(get_sample_ts, get_num_samples, get_sample_t);
-  MAKE_SEQ(get_sample_points, get_num_samples, get_sample_points);
+  MAKE_SEQ(get_sample_points, get_num_samples, get_sample_point);
 
 private:
   int find_segment(PN_stdfloat t);

Some files were not shown because too many files changed in this diff