changeset 9010:f914834836e7

Partial implementation of derived classes using the old form with "@" files.
author rtshort@smoketree.phaselocked.com
date Tue, 24 Mar 2009 11:29:53 -0400
parents da58ec8f62e8
children dd5725531732
files scripts/ChangeLog scripts/general/isa.m src/ChangeLog src/load-path.cc src/load-path.h src/ov-base.h src/ov-class.cc src/ov-class.h src/ov.h
diffstat 9 files changed, 247 insertions(+), 14 deletions(-) [+]
line wrap: on
line diff
--- a/scripts/ChangeLog	Mon Mar 23 19:29:01 2009 -0400
+++ b/scripts/ChangeLog	Tue Mar 24 11:29:53 2009 -0400
@@ -1,3 +1,7 @@
+2009-03-24  John W. Eaton  <jwe@octave.org>
+
+	* general/isa.m: Handle parent classes.
+
 2009-03-23  Ben Abbott <bpabbott@mac.com>
 
 	* plot/gnuplot_drawnow.m: Check that gnuplot has internal variable
--- a/scripts/general/isa.m	Mon Mar 23 19:29:01 2009 -0400
+++ b/scripts/general/isa.m	Tue Mar 24 11:29:53 2009 -0400
@@ -41,7 +41,14 @@
   elseif (strcmp (cname, "numeric"))
     retval = any (strcmp (class (x), fnum_classes));
   else
-    retval = strcmp (class (x), cname);
+    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
+    endif
   endif
 
 endfunction
--- a/src/ChangeLog	Mon Mar 23 19:29:01 2009 -0400
+++ b/src/ChangeLog	Tue Mar 24 11:29:53 2009 -0400
@@ -1,3 +1,27 @@
+2009-03-24  John W. Eaton  <jwe@octave.org>
+
+	* ov-class.cc (F__parent_classes__): New function.
+
+2009-03-24  Robert T. Short  <octave@phaselockedsystems.com>
+
+	* ov-class.h, ov-class.cc (octave_class::octave_class (const
+	Octave_map&, const std::string&, const octave_value_list&)):
+	New constructor.
+	(octave_class::find_parent_class, octave_class::parent_classes):
+	New functions.
+	(octave_class::dotref): Also look in parent class.
+	(Fclass): Handle parent class arguments.
+
+	* ov-base.h (octave_base_value::get_parent_list,
+	octave_base_value::parent_classes): New virtual functions.
+
+	* load-path.h, load-path.cc (load_path::parent_map): New data member. 
+	(load_path::add_to_parent_map): New static function.
+	(load_path::do_add_to_parent_map): New member function.
+	(load_path::do_find_method): Also look in parent classes for methods.
+	(load_path::parent_map_type, load_path::const_parent_map_iterator,
+	load_path::parent_map_iterator): New typedefs.
+
 2009-03-23  John W. Eaton  <jwe@octave.org>
 
 	* symtab.h
--- a/src/load-path.cc	Mon Mar 23 19:29:01 2009 -0400
+++ b/src/load-path.cc	Tue Mar 24 11:29:53 2009 -0400
@@ -512,6 +512,7 @@
   fcn_map.clear ();
   private_fcn_map.clear ();
   method_map.clear ();
+  parent_map.clear ();
 
   do_append (".", false);
 }
@@ -1016,7 +1017,29 @@
 
       const_fcn_map_iterator p = m.find (meth);
 
-      if (p != m.end ())
+      if (p == m.end ())
+	{
+	  // Look in parent classes.
+
+	  const_parent_map_iterator r = parent_map.find (class_name);
+
+	  if (r != parent_map.end ())
+	    {
+	      const std::list<std::string>& plist = r->second;
+	      std::list<std::string>::const_iterator it = plist.begin ();
+
+	      while (it != plist.end ())
+		{
+		  retval = do_find_method (*it, meth, dir_name, type);
+
+		  if (retval != "")
+		    break;
+
+		  it++;
+		}
+	    }
+	}
+      else
 	{
 	  const file_info_list_type& file_info_list = p->second;
 
@@ -1538,6 +1561,13 @@
 }
 
 void
+load_path::do_add_to_parent_map (const std::string& classname,
+				 const std::list<std::string>& parent_list) const
+{
+  parent_map[classname] = parent_list;
+}
+
+void
 load_path::add_to_fcn_map (const dir_info& di, bool at_end) const
 {
   std::string dir_name = di.dir_name;
--- a/src/load-path.h	Mon Mar 23 19:29:01 2009 -0400
+++ b/src/load-path.h	Tue Mar 24 11:29:53 2009 -0400
@@ -37,7 +37,8 @@
 {
 protected:
 
-  load_path (void) : dir_info_list (), fcn_map (), method_map () { }
+  load_path (void)
+    : dir_info_list (), fcn_map (), method_map (), parent_map () { }
 
 public:
 
@@ -228,6 +229,13 @@
     return instance_ok () ? instance->do_system_path () : std::string ();
   }
 
+  static void add_to_parent_map (const std::string& classname,
+				 const std::list<std::string>& parent_list)
+  {
+    if (instance_ok ())
+      instance->do_add_to_parent_map (classname, parent_list);
+  }
+
 private:
 
   static const int M_FILE = 1;
@@ -386,6 +394,12 @@
 
   typedef method_map_type::const_iterator const_method_map_iterator;
   typedef method_map_type::iterator method_map_iterator;
+ 
+  // <CLASS_NAME, PARENT_LIST>>
+  typedef std::map<std::string, std::list<std::string> > parent_map_type;
+
+  typedef parent_map_type::const_iterator const_parent_map_iterator;
+  typedef parent_map_type::iterator parent_map_iterator;
 
   mutable dir_info_list_type dir_info_list;
 
@@ -395,6 +409,8 @@
 
   mutable method_map_type method_map;
 
+  mutable parent_map_type parent_map;
+
   static load_path *instance;
 
   static hook_fcn_ptr add_hook;
@@ -493,6 +509,9 @@
 
   std::string do_get_command_line_path (void) const { return command_line_path; }
 
+  void do_add_to_parent_map (const std::string& classname,
+			     const std::list<std::string>& parent_list) const;
+
   void add_to_fcn_map (const dir_info& di, bool at_end) const;
 
   void add_to_private_fcn_map (const dir_info& di) const;
--- a/src/ov-base.h	Mon Mar 23 19:29:01 2009 -0400
+++ b/src/ov-base.h	Tue Mar 24 11:29:53 2009 -0400
@@ -450,6 +450,13 @@
 
   virtual string_vector map_keys (void) const;
 
+  virtual string_vector parent_class_names (void) const
+    { return string_vector (); }
+
+  // FIXME -- should this warn if called for a non-class type?
+  virtual octave_base_value *find_parent_class (const std::string&)
+    { return 0; }
+
   virtual octave_function *function_value (bool silent = false);
 
   virtual const octave_function *function_value (bool silent = false) const;
--- a/src/ov-class.cc	Mon Mar 23 19:29:01 2009 -0400
+++ b/src/ov-class.cc	Tue Mar 24 11:29:53 2009 -0400
@@ -62,6 +62,85 @@
     (octave_class::t_name, "<unknown>", octave_value (new octave_class ()));
 }
 
+octave_class::octave_class (const Octave_map& m, const std::string& id, 
+			    const octave_value_list& parents)
+  : octave_base_value (), map (m), c_name (id)
+{
+  octave_idx_type n = parents.length ();
+
+  for (octave_idx_type idx = 0; idx < n; idx++)
+    {
+      octave_value parent = parents(idx);
+
+      if (! parent.is_object ())
+	error ("parents must be objects");
+      else
+	{
+	  std::string cnm = parent.class_name ();
+
+	  parent_list.push_back (cnm);
+
+	  map.assign (cnm, parent);
+	}
+    }
+
+  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 ())
+	{
+	  Octave_map::const_iterator pmap = map.seek (parent_class_name);
+
+	  if (pmap != map.end ())
+	    {
+	      const Cell& tmp = pmap->second;
+
+	      octave_value vtmp = tmp(0);
+
+	      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);
+
+	      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);
+
+	      if (retval)
+		break;
+	    }
+	}
+    }
+
+  return retval;
+}
+
 Cell
 octave_class::dotref (const octave_value_list& idx)
 {
@@ -69,12 +148,27 @@
 
   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);
+
+  // Find the class in which this method resides before attempting to access
+  // the requested field.
+
+  octave_base_value *obvp = find_parent_class (method_class);
+
+  Octave_map my_map;
+
+  my_map = obvp ? obvp->map_value () : map;
+
   std::string nm = idx(0).string_value ();
 
-  Octave_map::const_iterator p = map.seek (nm);
+  Octave_map::const_iterator p = my_map.seek (nm);
 
-  if (p != map.end ())
-    retval = map.contents (p);
+  if (p != my_map.end ())
+    retval = my_map.contents (p);
   else
     error ("class has no member `%s'", nm.c_str ());
 
@@ -1168,18 +1262,22 @@
   "-*- texinfo -*-\n\
 @deftypefn {Built-in Function} {} class (@var{expr})\n\
 @deftypefnx {Built-in Function} {} class (@var{s}, @var{id})\n\
-\n\
-Return the class of the expression @var{expr}, as a string or\n\
-create a class object from the structure @var{s} with name @var{id}.\n\
+@deftypefnx {Built-in Function} {} class (@var{s}, @var{id}, @var{p}, @dots{})\n\
+Return the class of the expression @var{expr} or create a class with\n\
+fields from structure @var{s} and name (string) @var{id}.  Additional\n\
+arguments name a list of parent classes from which the new class is\n\
+derived.\n\
 @end deftypefn")
 {
   octave_value retval;
 
   int nargin = args.length ();
 
-  if (nargin == 1)
+  if (nargin == 0)
+    print_usage ();
+  else if (nargin == 1)
     retval = args(0).class_name ();
-  else if (nargin == 2)
+  else
     {
       Octave_map m = args(0).map_value ();
 
@@ -1192,7 +1290,16 @@
 	      octave_function *fcn = octave_call_stack::caller ();
 
 	      if (fcn && fcn->is_class_constructor ())
-		retval = octave_value (new octave_class (m, id));
+		{
+		  if (nargin == 2)
+		    retval = octave_value (new octave_class (m, id));
+		  else
+		    {
+		      octave_value_list parents = args.slice (2, nargin-2);
+
+		      retval = octave_value (new octave_class (m, id, parents));
+		    }
+		}
 	      else
 		error ("class: invalid call from outside class constructor");
 	    }
@@ -1202,13 +1309,31 @@
       else
 	error ("class: expecting structure as first argument");
     }
+
+  return retval;
+}
+
+DEFUN (__parent_classes__, args, ,
+  "-*- texinfo -*-\n\
+@deftypefn {Built-in Function} {} __parent_classes__ (@var{x})\n\
+Undocumented internal function.\n\
+@end deftypefn")
+{
+  octave_value retval = Cell ();
+
+  if (args.length () == 1)
+    {
+      octave_value arg = args(0);
+
+      if (arg.is_object ())
+	retval = Cell (arg.parent_class_names ());
+    }
   else
     print_usage ();
 
   return retval;
 }
 
-
 DEFUN (isobject, args, ,
   "-*- texinfo -*-\n\
 @deftypefn {Built-in Function} {} isobject (@var{x})\n\
--- a/src/ov-class.h	Mon Mar 23 19:29:01 2009 -0400
+++ b/src/ov-class.h	Tue Mar 24 11:29:53 2009 -0400
@@ -55,7 +55,11 @@
     : octave_base_value (), map (m), c_name (id) { }
 
   octave_class (const octave_class& s)
-    : octave_base_value (s), map (s.map), c_name (s.c_name) { }
+    : octave_base_value (s), map (s.map), c_name (s.c_name),
+      parent_list (s.parent_list) { }
+
+  octave_class (const Octave_map& m, const std::string& id, 
+                const octave_value_list& parents);
 
   ~octave_class (void) { }
 
@@ -118,6 +122,11 @@
 
   string_vector map_keys (void) const;
 
+  string_vector parent_class_names (void) const
+    { return string_vector (parent_list); }
+
+  octave_base_value *find_parent_class (const std::string&);
+
   void print (std::ostream& os, bool pr_as_read_syntax = false) const;
 
   void print_raw (std::ostream& os, bool pr_as_read_syntax = false) const;
@@ -165,6 +174,7 @@
 
   static const std::string t_name;
   std::string c_name;
+  std::list<std::string> parent_list;
 
   bool in_class_method (void) const;
 };
--- a/src/ov.h	Mon Mar 23 19:29:01 2009 -0400
+++ b/src/ov.h	Tue Mar 24 11:29:53 2009 -0400
@@ -830,6 +830,13 @@
   string_vector map_keys (void) const
     { return rep->map_keys (); }
 
+  string_vector parent_class_names (void) const
+    { return rep->parent_class_names (); }
+
+  octave_base_value *
+  find_parent_class (const std::string& parent_class_name)
+    { return rep->find_parent_class (parent_class_name); }
+
   octave_function *function_value (bool silent = false);
 
   const octave_function *function_value (bool silent = false) const;