diff src/ov-class.cc @ 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 f914834836e7
children 69e6bbfef8c2
line wrap: on
line diff
--- 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\