changeset 8785:70f5a0375afd

oct-map.h: fix think-o in previous change
author John W. Eaton <jwe@octave.org>
date Tue, 17 Feb 2009 21:41:26 -0500
parents 374cb30311a8
children dbd428efbf56
files src/ChangeLog src/oct-map.h src/ov-class.cc src/ov-class.h src/ov-fcn.h src/ov-usr-fcn.cc src/ov-usr-fcn.h src/symtab.cc
diffstat 8 files changed, 297 insertions(+), 223 deletions(-) [+]
line wrap: on
line diff
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,5 +1,36 @@
 2009-02-17  John W. Eaton  <jwe@octave.org>
 
+	* ov-fcn.h (octave_function::octave_function): Initialize data members.
+	(octave_function::dispatch_class): No longer virtual.
+	Replace with version from ov-usr-fcn.h.
+	(octave_function::xdispatch_class,
+	octave_function::stash_dispatch_class): Move here from ov-usr-fcn.h.
+	(octave_function::mark_as_private_function,
+	octave_function::is_private_function,
+	octave_function::is_private_function_of_class): New functions.
+	(octave_function::private_function): New data member.
+	* ov-usr-fcn.h (octave_user_function::xdispatch_class,
+	octave_user_function::stash_dispatch_class,
+	octave_user_function::dispatch_class): Delete.
+	* ov-usr-fcn.cc (octave_user_function::octave_user_function):
+	Don't initialize xdispatch_type.
+
+	* symtab.cc
+	(symbol_table::fcn_info::fcn_info_rep::load_private_function):
+	If private directory is subdirectory of class directory, qmark
+	function as a private directory of the class.
+
+	* ov-class.cc (octave_class::in_class_method): Also return true
+	for functions that are private to a class.
+	(octave_class::subsasgn): If not in class method, look for
+	subsasgn method.  If not found, or if not in a class method,
+	perform default struct-style subscripted indexing.
+
+	* ov-class.h (octave_class::empty_clone):
+	Preserve fields and class name.
+	* oct-map.h (Octave_map::Octave_map (const string_vector&):
+	New constructor.
+
 	* ov-class.cc (octave_class::subsref): If indexing directly and
 	result is map, return class object, not simple struct.
 
--- a/src/oct-map.h
+++ b/src/oct-map.h
@@ -56,6 +56,17 @@
     key_list.push_back (k);
   }
 
+  Octave_map (const string_vector& sv)
+    : map (), key_list (), dimensions (0, 0)
+  {
+    for (octave_idx_type i = 0; i < sv.length (); i++)
+      {
+	std::string k = sv[i];
+	map[k] = Cell ();
+	key_list.push_back (k);
+      }
+  }
+
   Octave_map (const std::string& k, const Cell& vals)
     : map (), key_list (), dimensions (vals.dims ())
   {
--- a/src/ov-class.cc
+++ b/src/ov-class.cc
@@ -321,211 +321,7 @@
 {
   octave_value retval;
 
-  if (in_class_method () && ! rhs.is_object ())
-    {
-      // FIXME -- this block of code is the same as the body of
-      // octave_struct::subsasgn.  Maybe it could be shared instead of
-      // duplicated.
-
-      int n = type.length ();
-
-      octave_value t_rhs = rhs;
-
-      if (n > 1 && ! (type.length () == 2 && type[0] == '(' && type[1] == '.'))
-	{
-	  switch (type[0])
-	    {
-	    case '(':
-	      {
-		if (type.length () > 1 && type[1] == '.')
-		  {
-		    std::list<octave_value_list>::const_iterator p = idx.begin ();
-		    octave_value_list t_idx = *p;
-
-		    octave_value_list key_idx = *++p;
-
-		    assert (key_idx.length () == 1);
-
-		    std::string key = key_idx(0).string_value ();
-
-		    octave_value u;
-
-		    if (! map.contains (key))
-		      u = octave_value::empty_conv (type.substr (2), rhs);
-		    else
-		      {
-			Cell map_val = map.contents (key);
-
-			Cell map_elt = map_val.index (idx.front (), true);
-
-			u = numeric_conv (map_elt, type.substr (2));
-		      }
-
-		    if (! error_state)
-		      {
-			std::list<octave_value_list> next_idx (idx);
-
-			// We handled two index elements, so subsasgn to
-			// needs to skip both of them.
-
-			next_idx.erase (next_idx.begin ());
-			next_idx.erase (next_idx.begin ());
-
-			u.make_unique ();
-
-			t_rhs = u.subsasgn (type.substr (2), next_idx, rhs);
-		      }
-		  }
-		else
-		  gripe_invalid_index_for_assignment ();
-	      }
-	      break;
-
-	    case '.':
-	      {
-		octave_value_list key_idx = idx.front ();
-
-		assert (key_idx.length () == 1);
-
-		std::string key = key_idx(0).string_value ();
-
-		octave_value u;
-
-		if (! map.contains (key))
-		  u = octave_value::empty_conv (type.substr (1), rhs);
-		else
-		  {
-		    Cell map_val = map.contents (key);
-
-		    u = numeric_conv (map_val, type.substr (1));
-		  }
-
-		if (! error_state)
-		  {
-		    std::list<octave_value_list> next_idx (idx);
-
-		    next_idx.erase (next_idx.begin ());
-
-		    u.make_unique ();
-
-		    t_rhs = u.subsasgn (type.substr (1), next_idx, rhs);
-		  }
-	      }
-	      break;
-
-	    case '{':
-	      gripe_invalid_index_type (type_name (), type[0]);
-	      break;
-
-	    default:
-	      panic_impossible ();
-	    }
-	}
-
-      if (! error_state)
-	{
-	  switch (type[0])
-	    {
-	    case '(':
-	      {
-		if (n > 1 && type[1] == '.')
-		  {
-		    std::list<octave_value_list>::const_iterator p = idx.begin ();
-		    octave_value_list key_idx = *++p;
-
-		    assert (key_idx.length () == 1);
-
-		    std::string key = key_idx(0).string_value ();
-
-		    if (! error_state)
-		      {
-			map.assign (idx.front (), key, t_rhs);
-
-			if (! error_state)
-			  {
-			    count++;
-			    retval = octave_value (this);
-			  }
-			else
-			  gripe_failed_assignment ();
-		      }
-		    else
-		      gripe_failed_assignment ();
-		  }
-		else
-		  {
-		    if (t_rhs.is_map())
-		      {
-			Octave_map rhs_map = t_rhs.map_value ();
-
-			if (! error_state)
-			  {
-			    map.assign (idx.front (), rhs_map);
-
-			    if (! error_state)
-			      {
-				count++;
-				retval = octave_value (this);
-			      }
-			    else
-			      gripe_failed_assignment ();
-			  }
-			else
-			  error ("invalid class assignment");
-		      }
-		    else
-		      {
-			if (t_rhs.is_empty()) 
-			  {
-			    map.maybe_delete_elements (idx.front());
-
-			    if (! error_state)
-			      {
-				count++;
-				retval = octave_value (this);
-			      }
-			    else
-			      gripe_failed_assignment ();
-			  }
-			else
-			  error ("invalid class assignment");
-		      }
-		  }
-	      }
-	      break;
-
-	    case '.':
-	      {
-		octave_value_list key_idx = idx.front ();
-
-		assert (key_idx.length () == 1);
-
-		std::string key = key_idx(0).string_value ();
-
-		map.assign (key, t_rhs);
-
-		if (! error_state)
-		  {
-		    count++;
-		    retval = octave_value (this);
-		  }
-		else
-		  gripe_failed_assignment ();
-	      }
-	      break;
-
-	    case '{':
-	      gripe_invalid_index_type (type_name (), type[0]);
-	      break;
-
-	    default:
-	      panic_impossible ();
-	    }
-	}
-      else
-	gripe_failed_assignment ();
-    }
-  else
+  if (! in_class_method ())
     {
       octave_value meth = symbol_table::find_method ("subsasgn", class_name ());
 
@@ -551,15 +347,216 @@
 	  if (tmp.length () > 1)
 	    error ("expecting single return value from @%s/subsasgn",
 		   class_name().c_str ());
+
 	  else
 	    retval = tmp(0);
 
+	  return retval;
 	}
-      else
-	error ("no subsasgn method defined for class %s",
-	       class_name().c_str ());
+    }
+
+  // FIXME -- this block of code is the same as the body of
+  // octave_struct::subsasgn.  Maybe it could be shared instead of
+  // duplicated.
+
+  int n = type.length ();
+
+  octave_value t_rhs = rhs;
+
+  if (n > 1 && ! (type.length () == 2 && type[0] == '(' && type[1] == '.'))
+    {
+      switch (type[0])
+	{
+	case '(':
+	  {
+	    if (type.length () > 1 && type[1] == '.')
+	      {
+		std::list<octave_value_list>::const_iterator p = idx.begin ();
+		octave_value_list t_idx = *p;
+
+		octave_value_list key_idx = *++p;
+
+		assert (key_idx.length () == 1);
+
+		std::string key = key_idx(0).string_value ();
+
+		octave_value u;
+
+		if (! map.contains (key))
+		  u = octave_value::empty_conv (type.substr (2), rhs);
+		else
+		  {
+		    Cell map_val = map.contents (key);
+
+		    Cell map_elt = map_val.index (idx.front (), true);
+
+		    u = numeric_conv (map_elt, type.substr (2));
+		  }
+
+		if (! error_state)
+		  {
+		    std::list<octave_value_list> next_idx (idx);
+
+		    // We handled two index elements, so subsasgn to
+		    // needs to skip both of them.
+
+		    next_idx.erase (next_idx.begin ());
+		    next_idx.erase (next_idx.begin ());
+
+		    u.make_unique ();
+
+		    t_rhs = u.subsasgn (type.substr (2), next_idx, rhs);
+		  }
+	      }
+	    else
+	      gripe_invalid_index_for_assignment ();
+	  }
+	  break;
+
+	case '.':
+	  {
+	    octave_value_list key_idx = idx.front ();
+
+	    assert (key_idx.length () == 1);
+
+	    std::string key = key_idx(0).string_value ();
+
+	    octave_value u;
+
+	    if (! map.contains (key))
+	      u = octave_value::empty_conv (type.substr (1), rhs);
+	    else
+	      {
+		Cell map_val = map.contents (key);
+
+		u = numeric_conv (map_val, type.substr (1));
+	      }
+
+	    if (! error_state)
+	      {
+		std::list<octave_value_list> next_idx (idx);
+
+		next_idx.erase (next_idx.begin ());
+
+		u.make_unique ();
+
+		t_rhs = u.subsasgn (type.substr (1), next_idx, rhs);
+	      }
+	  }
+	  break;
+
+	case '{':
+	  gripe_invalid_index_type (type_name (), type[0]);
+	  break;
+
+	default:
+	  panic_impossible ();
+	}
     }
 
+  if (! error_state)
+    {
+      switch (type[0])
+	{
+	case '(':
+	  {
+	    if (n > 1 && type[1] == '.')
+	      {
+		std::list<octave_value_list>::const_iterator p = idx.begin ();
+		octave_value_list key_idx = *++p;
+
+		assert (key_idx.length () == 1);
+
+		std::string key = key_idx(0).string_value ();
+
+		if (! error_state)
+		  {
+		    map.assign (idx.front (), key, t_rhs);
+
+		    if (! error_state)
+		      {
+			count++;
+			retval = octave_value (this);
+		      }
+		    else
+		      gripe_failed_assignment ();
+		  }
+		else
+		  gripe_failed_assignment ();
+	      }
+	    else
+	      {
+		if (t_rhs.is_object () || t_rhs.is_map ())
+		  {
+		    Octave_map rhs_map = t_rhs.map_value ();
+
+		    if (! error_state)
+		      {
+			map.assign (idx.front (), rhs_map);
+
+			if (! error_state)
+			  {
+			    count++;
+			    retval = octave_value (this);
+			  }
+			else
+			  gripe_failed_assignment ();
+		      }
+		    else
+		      error ("invalid class assignment");
+		  }
+		else
+		  {
+		    if (t_rhs.is_empty ())
+		      {
+			map.maybe_delete_elements (idx.front());
+
+			if (! error_state)
+			  {
+			    count++;
+			    retval = octave_value (this);
+			  }
+			else
+			  gripe_failed_assignment ();
+		      }
+		    else
+		      error ("invalid class assignment");
+		  }
+	      }
+	  }
+	  break;
+
+	case '.':
+	  {
+	    octave_value_list key_idx = idx.front ();
+
+	    assert (key_idx.length () == 1);
+
+	    std::string key = key_idx(0).string_value ();
+
+	    map.assign (key, t_rhs);
+
+	    if (! error_state)
+	      {
+		count++;
+		retval = octave_value (this);
+	      }
+	    else
+	      gripe_failed_assignment ();
+	  }
+	  break;
+
+	case '{':
+	  gripe_invalid_index_type (type_name (), type[0]);
+	  break;
+
+	default:
+	  panic_impossible ();
+	}
+    }
+  else
+    gripe_failed_assignment ();
+
   return retval;
 }
 
@@ -1161,7 +1158,9 @@
   octave_function *fcn = octave_call_stack::current ();
 
   return (fcn
-	  && (fcn->is_class_method () || fcn->is_class_constructor ())
+	  && (fcn->is_class_method ()
+	      || fcn->is_class_constructor ()
+	      || fcn->is_private_function_of_class (class_name ()))
 	  && fcn->dispatch_class () == class_name ());
 }
 
--- a/src/ov-class.h
+++ b/src/ov-class.h
@@ -60,7 +60,11 @@
   ~octave_class (void) { }
 
   octave_base_value *clone (void) const { return new octave_class (*this); }
-  octave_base_value *empty_clone (void) const { return new octave_class (); }
+
+  octave_base_value *empty_clone (void) const
+  {
+    return new octave_class (Octave_map (map.keys ()), class_name ());
+  }
 
   Cell dotref (const octave_value_list& idx);
 
--- a/src/ov-fcn.h
+++ b/src/ov-fcn.h
@@ -45,7 +45,9 @@
 {
 public:
 
-  octave_function (void) { }
+  octave_function (void)
+    : relative (false), locked (false), private_function (false),
+      xdispatch_class (), my_name (), my_dir_name (), doc () { }
 
   ~octave_function (void) { }
 
@@ -80,12 +82,25 @@
 
   virtual bool is_class_method (void) const { return false; }
 
-  virtual std::string dispatch_class (void) const { return std::string (); }
-
   virtual bool takes_varargs (void) const { return false; }
 
   virtual bool takes_var_return (void) const { return false; }
 
+  void stash_dispatch_class (const std::string& nm) { xdispatch_class = nm; }
+
+  std::string dispatch_class (void) const { return xdispatch_class; }
+
+  void mark_as_private_function (const std::string& cname = std::string ())
+  {
+    private_function = true;
+    xdispatch_class = cname;
+  }
+
+  bool is_private_function (void) const { return private_function; }
+
+  bool is_private_function_of_class (const std::string& nm)
+    { return private_function && xdispatch_class == nm; }
+
   std::string dir_name (void) const { return my_dir_name; }
 
   void stash_dir_name (const std::string& dir) { my_dir_name = dir; }
@@ -134,6 +149,14 @@
   // TRUE if this function is tagged so that it can't be cleared.
   bool locked;
 
+  // TRUE means this is a private function.
+  bool private_function;
+
+  // If this object is a class method or constructor, or a private
+  // function inside a class directory, this is the name of the class
+  // to which the method belongs. 
+  std::string xdispatch_class;
+
   // The name of this function.
   std::string my_name;
 
--- a/src/ov-usr-fcn.cc
+++ b/src/ov-usr-fcn.cc
@@ -183,8 +183,8 @@
     system_fcn_file (false), call_depth (-1),
     num_named_args (param_list ? param_list->length () : 0),
     nested_function (false), inline_function (false),
-    class_constructor (false), class_method (false), xdispatch_class (),
-    args_passed (), num_args_passed (0), parent_scope (-1), local_scope (sid)
+    class_constructor (false), class_method (false), args_passed (),
+    num_args_passed (0), parent_scope (-1), local_scope (sid)
 {
   if (cmd_list)
     cmd_list->mark_as_function_body ();
--- a/src/ov-usr-fcn.h
+++ b/src/ov-usr-fcn.h
@@ -260,10 +260,6 @@
 
   bool is_class_method (void) const { return class_method; }
 
-  void stash_dispatch_class (const std::string& nm) { xdispatch_class = nm; }
-
-  std::string dispatch_class (void) const { return xdispatch_class; }
-
   void save_args_passed (const octave_value_list& args)
     {
       if (call_depth > 0)
@@ -367,10 +363,6 @@
   // TRUE means this function is a method for a class.
   bool class_method;
 
-  // If this object is a class method or constructor, this is the name
-  // of the class to which the method belongs.
-  std::string xdispatch_class;
-
   // The values that were passed as arguments.
   octave_value_list args_passed;
 
--- a/src/symtab.cc
+++ b/src/symtab.cc
@@ -300,6 +300,20 @@
 
       if (fcn)
 	{
+	  std::string class_name;
+
+	  size_t pos = dir_name.find_last_of (file_ops::dir_sep_chars ());
+
+	  if (pos != std::string::npos)
+	    {
+	      std::string tmp = dir_name.substr (pos+1);
+
+	      if (tmp[0] == '@')
+		class_name = tmp.substr (1);
+	    }
+
+	  fcn->mark_as_private_function (class_name);
+
 	  retval = octave_value (fcn);
 
 	  private_functions[dir_name] = retval;