diff src/ov-class.cc @ 9151:d8f9588c6ba1

object exemplars
author John W. Eaton <jwe@octave.org>
date Thu, 23 Apr 2009 16:05:52 -0400
parents 69e6bbfef8c2
children b2b8ed43b922
line wrap: on
line diff
--- 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");