changeset 9151:d8f9588c6ba1

object exemplars
author John W. Eaton <jwe@octave.org>
date Thu, 23 Apr 2009 16:05:52 -0400
parents e716cafee800
children 4c9aff0c9a61
files src/ChangeLog src/ov-base.cc src/ov-base.h src/ov-class.cc src/ov-class.h src/ov.h src/symtab.cc
diffstat 7 files changed, 210 insertions(+), 6 deletions(-) [+]
line wrap: on
line diff
--- a/src/ChangeLog	Thu Apr 23 08:25:06 2009 +0200
+++ b/src/ChangeLog	Thu Apr 23 16:05:52 2009 -0400
@@ -1,3 +1,24 @@
+2009-04-23  John W. Eaton  <jwe@octave.org>
+
+	* ov-class.cc (Fclass): Check newly constructed classes against
+	the first constructed object of the class.
+
+	* ov-class.h, ov-class.cc (octave_class::exmplar_info): New class.
+	(exemplar_map): New static data member.
+	(exemplar_iterator, exemplar_const_iterator): New typedefs.
+
+	* ov-class.h (octave_class::nparents,
+	octave_class::parent_class_name_list): New functions.
+	* ov.h (octave_base_value::nparents,
+	octave_base_value::parent_class_name_list): New functions.
+	* ov-base.h, ov-base.cc (octave_base_value::nparents,
+	octave_base_value::parent_class_name_list): New functions.
+	(parent_class_names): Error if called for wrong type argument.
+
+	* symtab.cc (load_out_of_date_fcn): New arg, dispatch_type.
+	(out_of_date_check_internal): Pass dispatch type to
+	load_out_of_date_fcn.
+
 2009-04-22  John W. Eaton  <jwe@octave.org>
 
 	* ov-base-int.cc (octave_base_int_helper<T, false,
--- a/src/ov-base.cc	Thu Apr 23 08:25:06 2009 +0200
+++ b/src/ov-base.cc	Thu Apr 23 16:05:52 2009 -0400
@@ -851,6 +851,32 @@
   return retval;
 }
 
+size_t
+octave_base_value::nparents (void) const
+{
+  size_t retval = 0;
+  gripe_wrong_type_arg ("octave_base_value::nparents()", type_name ());
+  return retval;
+}
+
+std::list<std::string>
+octave_base_value::parent_class_name_list (void) const
+{
+  std::list<std::string> retval;
+  gripe_wrong_type_arg ("octave_base_value::parent_class_name_list()",
+			type_name ());
+  return retval;
+}
+
+string_vector
+octave_base_value::parent_class_names (void) const
+{
+  string_vector retval;
+  gripe_wrong_type_arg ("octave_base_value::parent_class_names()",
+			type_name ());
+  return retval;
+}
+
 octave_function *
 octave_base_value::function_value (bool silent)
 {
--- a/src/ov-base.h	Thu Apr 23 08:25:06 2009 +0200
+++ b/src/ov-base.h	Thu Apr 23 16:05:52 2009 -0400
@@ -452,8 +452,11 @@
 
   virtual string_vector map_keys (void) const;
 
-  virtual string_vector parent_class_names (void) const
-    { return string_vector (); }
+  virtual size_t nparents (void) const;
+
+  virtual std::list<std::string> parent_class_name_list (void) const;
+
+  virtual string_vector parent_class_names (void) const;
 
   // FIXME -- should this warn if called for a non-class type?
   virtual octave_base_value *find_parent_class (const std::string&)
--- a/src/ov-class.cc	Thu Apr 23 08:25:06 2009 +0200
+++ b/src/ov-class.cc	Thu Apr 23 16:05:52 2009 -0400
@@ -1284,6 +1284,87 @@
 	  && fcn->dispatch_class () == class_name ());
 }
 
+octave_class::exemplar_info::exemplar_info (const octave_value& obj)
+  : field_names (), parent_class_names ()
+{
+  if (obj.is_object ())
+    {
+      Octave_map m = obj.map_value ();
+      field_names = m.keys ();
+
+      parent_class_names = obj.parent_class_name_list ();
+    }
+  else
+    error ("invalid call to exmplar_info constructor");
+}
+
+
+// A map from class names to lists of fields.
+std::map<std::string, octave_class::exemplar_info> octave_class::exemplar_map;
+
+bool
+octave_class::exemplar_info::compare (const octave_value& obj) const
+{
+  bool retval = true;
+
+  if (obj.is_object ())
+    {
+      if (nfields () == obj.nfields ())
+	{
+	  Octave_map obj_map = obj.map_value ();
+	  string_vector obj_fnames = obj_map.keys ();
+	  string_vector fnames = fields ();
+
+	  for (octave_idx_type i = 0; i < nfields (); i++)
+	    {
+	      if (obj_fnames[i] != fnames[i])
+		{
+		  retval = false;
+		  error ("mismatch in field names");
+		  break;
+		}
+	    }
+
+	  if (nparents () == obj.nparents ())
+	    {
+	      std::list<std::string> obj_parents
+		= obj.parent_class_name_list ();
+	      std::list<std::string> pnames = parents ();
+
+	      std::list<std::string>::const_iterator p = obj_parents.begin ();
+	      std::list<std::string>::const_iterator q = pnames.begin ();
+
+	      while (p != obj_parents.end ())
+		{
+		  if (*p++ != *q++)
+		    {
+		      retval = false;
+		      error ("mismatch in parent classes");
+		      break;
+		    }
+		}
+	    }
+	  else
+	    {
+	      retval = false;
+	      error ("mismatch in number of parent classes");
+	    }
+	}
+      else
+	{
+	  retval = false;
+	  error ("mismatch in number of fields");
+	}
+    }
+  else
+    {
+      retval = false;
+      error ("inavlid comparison of class exemplar to non-class object");
+    }
+
+  return retval;
+}
+
 DEFUN (class, args, ,
   "-*- texinfo -*-\n\
 @deftypefn {Built-in Function} {} class (@var{expr})\n\
@@ -1325,6 +1406,18 @@
 
 		      retval = octave_value (new octave_class (m, id, parents));
 		    }
+
+		  if (! error_state)
+		    {
+		      octave_class::exemplar_const_iterator it
+			= octave_class::exemplar_map.find (id);
+
+		      if (it == octave_class::exemplar_map.end ())
+			octave_class::exemplar_map[id]
+			  = octave_class::exemplar_info (retval);
+		      else if (! it->second.compare (retval))
+			error ("class: object of class `%s' does not match previously constructed objects", id.c_str ());
+		    }
 		}
 	      else
 		error ("class: invalid call from outside class constructor");
--- a/src/ov-class.h	Thu Apr 23 08:25:06 2009 +0200
+++ b/src/ov-class.h	Thu Apr 23 16:05:52 2009 -0400
@@ -109,6 +109,8 @@
 
   octave_idx_type nfields (void) const { return map.nfields (); }
 
+  size_t nparents (void) const { return parent_list.size (); }
+
   octave_value reshape (const dim_vector& new_dims) const
     { return map.reshape (new_dims); }
 
@@ -125,6 +127,9 @@
 
   string_vector map_keys (void) const;
 
+  std::list<std::string> parent_class_name_list (void) const
+    { return parent_list; }
+
   string_vector parent_class_names (void) const
     { return string_vector (parent_list); }
 
@@ -180,6 +185,53 @@
   std::list<std::string> parent_list;
 
   bool in_class_method (void) const;
+
+public:
+  // The list of field names and parent classes defines a class.  We
+  // keep track of each class that has been created so that we know
+  class exemplar_info
+  {
+  public:
+
+    exemplar_info (void) : field_names (), parent_class_names () { }
+
+    exemplar_info (const octave_value& obj);
+
+    exemplar_info (const exemplar_info& x)
+      : field_names (x.field_names),
+	parent_class_names (x.parent_class_names) { }
+
+    exemplar_info& operator = (const exemplar_info& x)
+    {
+      if (&x != this)
+	{
+	  field_names = x.field_names;
+	  parent_class_names = x.parent_class_names;
+	}
+      return *this;
+    }
+
+    octave_idx_type nfields (void) const { return field_names.length (); }
+
+    size_t nparents (void) const { return parent_class_names.size (); }
+
+    string_vector fields (void) const { return field_names; }
+
+    std::list<std::string> parents (void) const { return parent_class_names; }
+
+    bool compare (const octave_value& obj) const;
+
+  private:
+
+    string_vector field_names;
+    std::list<std::string> parent_class_names;
+  };
+
+  // A map from class names to lists of fields.
+  static std::map<std::string, exemplar_info> exemplar_map;
+
+  typedef std::map<std::string, exemplar_info>::iterator exemplar_iterator;
+  typedef std::map<std::string, exemplar_info>::const_iterator exemplar_const_iterator;
 };
 
 #endif
--- a/src/ov.h	Thu Apr 23 08:25:06 2009 +0200
+++ b/src/ov.h	Thu Apr 23 16:05:52 2009 -0400
@@ -830,6 +830,12 @@
   string_vector map_keys (void) const
     { return rep->map_keys (); }
 
+  size_t nparents (void) const
+    { return rep->nparents (); }
+
+  std::list<std::string> parent_class_name_list (void) const
+    { return rep->parent_class_name_list (); }
+
   string_vector parent_class_names (void) const
     { return rep->parent_class_names (); }
 
--- a/src/symtab.cc	Thu Apr 23 08:25:06 2009 +0200
+++ b/src/symtab.cc	Thu Apr 23 16:05:52 2009 -0400
@@ -132,11 +132,12 @@
 
 static inline bool
 load_out_of_date_fcn (const std::string& ff, const std::string& dir_name,
-		      octave_value& function)
+		      octave_value& function,
+		      const std::string& dispatch_type = std::string ())
 {
   bool retval = false;
 
-  octave_function *fcn = load_fcn_from_file (ff, dir_name);
+  octave_function *fcn = load_fcn_from_file (ff, dir_name, dispatch_type);
 
   if (fcn)
     {
@@ -229,7 +230,8 @@
 			      if (fs.is_newer (tp))
 				{
 				  retval = load_out_of_date_fcn (ff, dir_name,
-								 function);
+								 function,
+								 dispatch_type);
 
 				  clear_breakpoints = true;
 				}
@@ -247,7 +249,8 @@
 		      // Not the same file, so load the new file in
 		      // place of the old.
 
-		      retval = load_out_of_date_fcn (file, dir_name, function);
+		      retval = load_out_of_date_fcn (file, dir_name, function,
+						     dispatch_type);
 
 		      clear_breakpoints = true;
 		    }