changeset 9147:5579998f8acf

Update to OOP facilities. * scripts/general/isa.m: Fixed isa so that multiple layers of class hierarchy are reported correctly. * src/variables.cc: Make exist('obj') for objects report correctly. * src/ov-base.h: Added an assign method so ov-class is able to assign structure elements properly. * src/ov-class.h: Assign map elements. * src/ov-class.cc: - Made sure that there are no duplicate classes in parent tree. - Simplified search algorithm for parent classes. - Fixed subsasgn so cls = method(cls,value) works when properly when method is a parent-class method. - Added __isa_parent__ so isa works correctly.
author rtshort@bristlecone.phaselocked.com
date Wed, 22 Apr 2009 14:33:26 -0400
parents a48c500e48e1
children 69e6bbfef8c2
files scripts/ChangeLog scripts/general/isa.m src/ChangeLog src/ov-base.h src/ov-class.cc src/ov-class.h src/variables.cc
diffstat 7 files changed, 104 insertions(+), 52 deletions(-) [+]
line wrap: on
line diff
--- a/scripts/ChangeLog	Wed Apr 22 11:05:55 2009 +0200
+++ b/scripts/ChangeLog	Wed Apr 22 14:33:26 2009 -0400
@@ -1,3 +1,7 @@
+2009-04-22  Robert T. Short  <octave@phaselockedsystems.com>
+
+	* general/isa.m: Correctly report multiple layers of class hierarchy.
+
 2009-04-20  John W. Eaton  <jwe@octave.org>
 
 	* special-matrix/vander.m: Update tests.
--- a/scripts/general/isa.m	Wed Apr 22 11:05:55 2009 +0200
+++ b/scripts/general/isa.m	Wed Apr 22 14:33:26 2009 -0400
@@ -44,10 +44,7 @@
     class_of_x = class (x);
     retval = strcmp (class_of_x, cname);
     if (! retval && isobject (x))
-      parent_classes_of_x = __parent_classes__ (x);
-      if (! isempty (parent_classes_of_x))
-	retval = any (strcmp (parent_classes_of_x, cname));
-      endif
+      retval = __isa_parent__ (x, cname);
     endif
   endif
 
--- a/src/ChangeLog	Wed Apr 22 11:05:55 2009 +0200
+++ b/src/ChangeLog	Wed Apr 22 14:33:26 2009 -0400
@@ -1,3 +1,16 @@
+2009-04-22  Robert T. Short  <octave@phaselockedsystems.com>
+
+	* variables.cc (symbol_exist): Also return 1 for objects.
+	* ov-base.h (octave_base_value::assign): New virtual function.
+	* ov-class.h (octave_class::assign): New function.
+	* ov-class.cc (octave_class::find_parent_class): Simplify.
+	(octave_class::octave_class): Don't allow duplicate parent classes.
+	(octave_class::subsasgn): Allow cls = method (cls, value) to work
+	properly when method is a parent-class method.
+	(get_method_class): New static function.
+	(octave_class:subsasgn, octave_class::dotref): Use it.
+	(F__isa_parent__): New function.
+
 2009-04-22  Jaroslav Hajek  <highegg@gmail.com>
 
 	* ov-range.cc (octave_range::char_array_value): New virtual function
--- a/src/ov-base.h	Wed Apr 22 11:05:55 2009 +0200
+++ b/src/ov-base.h	Wed Apr 22 14:33:26 2009 -0400
@@ -171,6 +171,8 @@
   virtual octave_value_list
   do_multi_index_op (int nargout, const octave_value_list& idx);
 
+  virtual void assign (const std::string&, const octave_value&) { }
+
   virtual octave_value
   subsasgn (const std::string& type,
 	    const std::list<octave_value_list>& idx,
--- a/src/ov-class.cc	Wed Apr 22 11:05:55 2009 +0200
+++ b/src/ov-class.cc	Wed Apr 22 14:33:26 2009 -0400
@@ -78,69 +78,67 @@
 	{
 	  std::string cnm = parent.class_name ();
 
-	  parent_list.push_back (cnm);
+	  if (find_parent_class (cnm))
+	    error ("duplicate class in parent tree");
+	  else
+	    {
+	      parent_list.push_back (cnm);
 
-	  map.assign (cnm, parent);
+	      map.assign (cnm, parent);
+	    }
 	}
     }
 
-  load_path::add_to_parent_map (id, parent_list);
+  if (! error_state)
+    load_path::add_to_parent_map (id, parent_list);
 }
 
 octave_base_value *
 octave_class::find_parent_class (const std::string& parent_class_name)
 {
   octave_base_value* retval = 0;
-  std::string dbg_clsnm = class_name ();
 
   if (parent_class_name == class_name ())
     retval = this;
   else
     {
-      // Search in the list of immediate parents first, then in the
-      // ancestor tree.
-
-      std::list<std::string>::iterator 
-	p = find (parent_list.begin (), parent_list.end (), parent_class_name);
-
-      if (p != parent_list.end ())
+      for (std::list<std::string>::iterator pit = parent_list.begin ();
+	   pit != parent_list.end ();
+	   pit++)
 	{
-	  Octave_map::const_iterator pmap = map.seek (parent_class_name);
+	  Octave_map::const_iterator smap = map.seek (*pit);
 
-	  if (pmap != map.end ())
-	    {
-	      const Cell& tmp = pmap->second;
-
-	      octave_value vtmp = tmp(0);
+	  const Cell& tmp = smap->second;
 
-	      retval = vtmp.internal_rep ();
-	    }
-	}
-      else
-	{
-	  for (std::list<std::string>::iterator pit = parent_list.begin ();
-	       pit != parent_list.end ();
-	       pit++)
-	    {
-	      Octave_map::const_iterator smap = map.seek (*pit);
+	  octave_value vtmp = tmp(0);
+
+	  octave_base_value *obvp = vtmp.internal_rep ();
 
-	      const Cell& tmp = smap->second;
-
-	      octave_value vtmp = tmp(0);
-
-	      octave_base_value *obvp = vtmp.internal_rep ();
+	  retval = obvp->find_parent_class (parent_class_name);
 
-	      retval = obvp->find_parent_class (parent_class_name);
-
-	      if (retval)
-		break;
-	    }
+	  if (retval)
+	    break;
 	}
     }
 
   return retval;
 }
 
+static std::string
+get_current_method_class (void)
+{
+  // FIXME -- is there a better way to do this?
+  octave_function *fcn = octave_call_stack::current ();
+
+  std::string my_dir = fcn->dir_name ();
+
+  size_t ipos = my_dir.find_last_of ("@");
+
+  assert (ipos != std::string::npos);
+
+  return my_dir.substr (ipos+1);
+}
+
 Cell
 octave_class::dotref (const octave_value_list& idx)
 {
@@ -148,11 +146,7 @@
 
   assert (idx.length () == 1);
 
-  // FIXME -- Is there a "proper" way to do this?
-  octave_function* fcn = octave_call_stack::current ();
-  std::string my_dir = fcn->dir_name ();
-  int ipos = my_dir.find_last_of ("@");
-  std::string method_class = my_dir.substr (ipos+1);
+  std::string method_class = get_current_method_class ();
 
   // Find the class in which this method resides before attempting to access
   // the requested field.
@@ -628,15 +622,27 @@
 
 	    std::string key = key_idx(0).string_value ();
 
-	    map.assign (key, t_rhs);
+	    // Find the class in which this method resides before 
+	    // attempting to access the requested field.
+
+	    std::string method_class = get_current_method_class ();
+
+	    octave_base_value *obvp = find_parent_class (method_class);
 
-	    if (! error_state)
+	    if (obvp)
 	      {
-		count++;
-		retval = octave_value (this);
+		obvp->assign (key, t_rhs);
+
+		if (! error_state)
+		  {
+		    count++;
+		    retval = octave_value (this);
+		  }
+		else
+		  gripe_failed_assignment ();
 	      }
 	    else
-	      gripe_failed_assignment ();
+	      error ("malformed class");
 	  }
 	  break;
 
@@ -1313,6 +1319,33 @@
   return retval;
 }
 
+DEFUN (__isa_parent__, args, ,
+  "-*- texinfo -*-\n\
+@deftypefn {Built-in Function} {} __isa_parent__ (@var{class}, @var{name})\n\
+Undocumented internal function.\n\
+@end deftypefn")
+{
+  octave_value retval = false;
+
+  if (args.length () == 2)
+    {
+      octave_value cls = args(0);
+      octave_value nm = args(1);
+
+      if (! error_state)
+	{
+	  if (cls.find_parent_class (nm.string_value ()))
+	    retval = true;
+	}
+      else
+	error ("__isa_parent__: expecting arguments to be character strings");
+    }
+  else
+    print_usage ();
+
+  return retval;
+}
+
 DEFUN (__parent_classes__, args, ,
   "-*- texinfo -*-\n\
 @deftypefn {Built-in Function} {} __parent_classes__ (@var{x})\n\
--- a/src/ov-class.h	Wed Apr 22 11:05:55 2009 +0200
+++ b/src/ov-class.h	Wed Apr 22 14:33:26 2009 -0400
@@ -86,6 +86,9 @@
   static octave_value numeric_conv (const Cell& val,
 				    const std::string& type);
 
+  void assign(const std::string& k, const octave_value& rhs)
+  { map.assign (k, rhs); };
+
   octave_value subsasgn (const std::string& type,
 			 const std::list<octave_value_list>& idx,
 			 const octave_value& rhs);
--- a/src/variables.cc	Wed Apr 22 11:05:55 2009 +0200
+++ b/src/variables.cc	Wed Apr 22 14:33:26 2009 -0400
@@ -408,7 +408,7 @@
       if (! retval
 	  && var_ok
 	  && (type == "any" || type == "var")
-	  && val.is_constant ())
+	  && (val.is_constant () || val.is_object ()))
 	{
 	  retval = 1;
 	}