changeset 5846:db0598f94c0f

[project @ 2006-06-07 18:16:16 by jwe]
author jwe
date Wed, 07 Jun 2006 18:16:16 +0000
parents 8b4a99ae3b5e
children 62e7b9307d00
files src/ChangeLog src/oct-lvalue.h src/oct-obj.cc src/oct-obj.h src/ov-cell.cc src/pt-arg-list.cc src/pt-arg-list.h src/pt-assign.cc src/pt-idx.cc
diffstat 9 files changed, 194 insertions(+), 65 deletions(-) [+]
line wrap: on
line diff
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,21 @@
+2006-06-07  John W. Eaton  <jwe@octave.org>
+
+	* ov-cell.cc (octave_cell::subsasgn): Handle c-s list object on
+	RHS if last index is '{'.
+	* pt-assign.cc (tree_multi_assignment::rvalue): Compute all LHS
+	lvalues before evaluating RHS.  If LHS lvalue expects more than
+	one output, pass octave_cs_list object to assign method.
+	* pt-idx.cc (tree_index_expression::lvalue): Compute expected
+	number of values if '{' index appears last.
+	* pt-arg-list.cc (tree_argument_list::lvalue_list): New function.
+	* pt-arg-list.h (tree_argument_list::lvalue_list): Provide decl.
+	* oct-lvalue.h (octave_lvalue::nel): New data member.
+	(octave_lvalue::numel): New functions
+	* oct-obj.cc (octave_value_list::has_magic_colon): New function.
+	* oct-obj.h (octave_value_list::has_magic_colon): Provide decl.
+	* pt-arg-list.cc (tree_argument_list::nargout_count): Delete function.
+	* pt-arg-list.h (tree_argument_list::nargout_count): Delete decl.
+
 2006-06-06  John W. Eaton  <jwe@octave.org>
 
 	* sighandlers.cc (generic_sig_handler, sigint_handler):
--- a/src/oct-lvalue.h
+++ b/src/oct-lvalue.h
@@ -45,11 +45,11 @@
 
   octave_lvalue (octave_value *v = &dummy_val,
 		 symbol_record::change_function f = 0)
-    : val (v), type (), idx (), chg_fcn (f), index_set (false) { }
+    : val (v), type (), idx (), chg_fcn (f), nel (1), index_set (false) { }
 
   octave_lvalue (const octave_lvalue& vr)
     : val (vr.val), type (vr.type), idx (vr.idx), chg_fcn (vr.chg_fcn),
-      index_set (vr.index_set) { }
+      nel (vr.nel), index_set (vr.index_set) { }
 
   octave_lvalue& operator = (const octave_lvalue& vr)
     {
@@ -59,6 +59,7 @@
 	  type = vr.type;
 	  idx = vr.idx;
 	  chg_fcn = vr.chg_fcn;
+	  nel = vr.nel;
 	  index_set = vr.index_set;
 	}
 
@@ -77,6 +78,10 @@
 
   void assign (octave_value::assign_op, const octave_value&);
 
+  void numel (octave_idx_type n) { nel = n; }
+
+  octave_idx_type numel (void) const { return nel; }
+
   void set_index (const std::string& t, const std::list<octave_value_list>& i);
 
   void clear_index (void) { type = std::string (); idx.clear (); }
@@ -97,6 +102,8 @@
 
   symbol_record::change_function chg_fcn;
 
+  octave_idx_type nel;
+
   bool index_set;
 };
 
--- a/src/oct-obj.cc
+++ b/src/oct-obj.cc
@@ -168,9 +168,21 @@
 
   for (octave_idx_type i = 0; i < n; i++)
     if (! elem(i).is_string ())
-      return 0;
+      return false;
+
+  return true;
+}
 
-  return 1;
+bool
+octave_value_list::has_magic_colon (void) const
+{
+  octave_idx_type n = length ();
+
+  for (octave_idx_type i = 0; i < n; i++)
+    if (elem(i).is_magic_colon ())
+      return true;
+
+  return false;
 }
 
 string_vector
--- a/src/oct-obj.h
+++ b/src/oct-obj.h
@@ -111,6 +111,8 @@
 
   bool all_strings_p (void) const;
 
+  bool has_magic_colon (void) const;
+
   string_vector make_argv (const std::string&) const;
 
   void stash_name_tags (const string_vector& nm) { names = nm; }
--- a/src/ov-cell.cc
+++ b/src/ov-cell.cc
@@ -222,7 +222,18 @@
 	  {
 	    octave_value_list i = idx.front ();
 
-	    octave_base_matrix<Cell>::assign (i, Cell (t_rhs));
+	    if (t_rhs.is_cs_list ())
+	      {
+		Cell tmp_cell = Cell (t_rhs.list_value ());
+
+		// FIXME -- shouldn't care if the dimensions of the
+		// RHS don't match the dimensions of the subscripted
+		// LHS.
+
+		octave_base_matrix<Cell>::assign (i, tmp_cell);
+	      }
+	    else
+	      octave_base_matrix<Cell>::assign (i, Cell (t_rhs));
 
 	    count++;
 	    retval = octave_value (this);
--- a/src/pt-arg-list.cc
+++ b/src/pt-arg-list.cc
@@ -32,6 +32,7 @@
 
 #include "defun.h"
 #include "error.h"
+#include "oct-lvalue.h"
 #include "oct-obj.h"
 #include "ov.h"
 #include "ov-usr-fcn.h"
@@ -77,25 +78,6 @@
     list_includes_magic_end = true;
 }
 
-int
-tree_argument_list::nargout_count (void) const
-{
-  int retval = 0;
-
-  for (const_iterator p = begin (); p != end (); p++)
-    {
-      tree_expression *elt = *p;
-
-      // FIXME -- need to be able to determine whether elt is
-      // an expression that could evaluate to a cs-list object, and if
-      // so, how many elements are in that list.  Ugly!
-
-      retval++;
-    }
-
-  return retval;
-}
-
 bool
 tree_argument_list::all_elements_are_constant (void) const
 {
@@ -260,6 +242,23 @@
   return args;
 }
 
+std::list<octave_lvalue>
+tree_argument_list::lvalue_list (void)
+{
+  std::list<octave_lvalue> retval;
+
+  for (tree_argument_list::iterator p = begin ();
+       p != end ();
+       p++)
+    {
+      tree_expression *elt = *p;
+
+      retval.push_back (elt->lvalue ());
+    }
+
+  return retval;
+}
+
 string_vector
 tree_argument_list::get_arg_names (void) const
 {
--- a/src/pt-arg-list.h
+++ b/src/pt-arg-list.h
@@ -24,10 +24,11 @@
 #if !defined (octave_tree_arg_list_h)
 #define octave_tree_arg_list_h 1
 
-class octave_value_list;
+#include <list>
 
+class octave_value_list;
+class octave_lvalue;
 class tree_expression;
-
 class tree_walker;
 
 #include "str-vec.h"
@@ -65,8 +66,6 @@
 
   void append (const element_type& s);
 
-  int nargout_count (void) const;
-
   void mark_as_simple_assign_lhs (void) { simple_assign_lhs = true; }
 
   bool is_simple_assign_lhs (void) { return simple_assign_lhs; }
@@ -75,6 +74,8 @@
 
   octave_value_list convert_to_const_vector (const octave_value *object = 0);
 
+  std::list<octave_lvalue> lvalue_list (void);
+
   string_vector get_arg_names (void) const;
 
   void accept (tree_walker& tw);
--- a/src/pt-assign.cc
+++ b/src/pt-assign.cc
@@ -200,11 +200,18 @@
 
   if (rhs)
     {
-      int n_out = lhs->nargout_count ();
+      std::list<octave_lvalue> lvalue_list = lhs->lvalue_list ();
 
       if (error_state)
 	return retval;
 
+      int n_out = 0;
+
+      for (std::list<octave_lvalue>::const_iterator p = lvalue_list.begin ();
+	   p != lvalue_list.end ();
+	   p++)
+	n_out += p->numel ();
+
       octave_value_list rhs_val = rhs->rvalue (n_out);
 
       if (error_state)
@@ -212,15 +219,18 @@
 
       if (rhs_val.empty ())
 	{
-	  error ("value on right hand side of assignment is undefined");
-	  eval_error ();
-	  return retval;
+	  if (n_out > 0)
+	    {
+	      error ("value on right hand side of assignment is undefined");
+	      eval_error ();
+	      return retval;
+	    }
 	}
       else
 	{
-	  int k = 0;
+	  octave_idx_type k = 0;
 
-	  int n = rhs_val.length ();
+	  octave_idx_type n = rhs_val.length ();
 
 	  if (n == 1)
 	    {
@@ -236,22 +246,52 @@
 
 	  retval.resize (n, octave_value ());
 
-	  for (tree_argument_list::iterator p = lhs->begin ();
-	       p != lhs->end ();
+	  tree_argument_list::iterator q = lhs->begin ();
+
+	  for (std::list<octave_lvalue>::iterator p = lvalue_list.begin ();
+	       p != lvalue_list.end ();
 	       p++)
 	    {
-	      tree_expression *lhs_elt = *p;
+	      tree_expression *lhs_elt = *q++;
+
+	      octave_lvalue ult = *p;
+
+	      octave_idx_type nel = ult.numel ();
 
-	      if (lhs_elt)
+	      if (nel > 1)
 		{
-		  octave_lvalue ult = lhs_elt->lvalue ();
+		  if (k + nel <= n)
+		    {
+		      if (etype == octave_value::op_asn_eq)
+			{
+			  octave_value_list ovl (nel, octave_value ());
+
+			  for (octave_idx_type j = 0; j < nel; j++)
+			    ovl(j) = rhs_val(k+j);
+
+			  ult.assign (etype, octave_value (ovl, true));
 
-		  if (error_state)
-		    {
-		      eval_error ();
-		      break;
+			  if (! error_state)
+			    {
+			      for (octave_idx_type j = 0; j < nel; j++)
+				retval(k+j) = rhs_val(k+j);
+
+			      k += nel;
+			    }
+			}
+		      else
+			{
+			  std::string op = octave_value::assign_op_as_string (etype);
+			  error ("operator %s unsupported for comma-separated list assignment",
+				 op.c_str ());
+			}
 		    }
-		  else if (k < n)
+		  else
+		    error ("some elements undefined in return list");
+		}
+	      else
+		{
+		  if (k < n)
 		    {
 		      ult.assign (etype, rhs_val(k));
 
@@ -261,39 +301,38 @@
 			    retval(k) = rhs_val(k);
 			  else
 			    retval(k) = ult.value ();
+
+			  k++;
 			}
 		    }
 		  else
 		    error ("element number %d undefined in return list", k+1);
+		}
 
-		  if (error_state)
-		    {
-		      eval_error ();
-		      break;
-		    }
-		  else if (print_result ())
-		    {
-		      // We clear any index here so that we can get
-		      // the new value of the referenced object below,
-		      // instead of the indexed value (which should be
-		      // the same as the right hand side value).
+	      if (error_state)
+		{
+		  eval_error ();
+		  break;
+		}
+	      else if (print_result ())
+		{
+		  // We clear any index here so that we can get
+		  // the new value of the referenced object below,
+		  // instead of the indexed value (which should be
+		  // the same as the right hand side value).
 
-		      ult.clear_index ();
+		  ult.clear_index ();
 
-		      octave_value lhs_val = ult.value ();
+		  octave_value lhs_val = ult.value ();
 
-		      if (! error_state)
-			lhs_val.print_with_name (octave_stdout,
-						 lhs_elt->name ());
-		    }
+		  if (! error_state)
+		    lhs_val.print_with_name (octave_stdout,
+					     lhs_elt->name ());
 		}
-	      else
-		eval_error ();
 
 	      if (error_state)
 		break;
 
-	      k++;
 	    }
 	}
     }
--- a/src/pt-idx.cc
+++ b/src/pt-idx.cc
@@ -427,7 +427,47 @@
 	      break;
 
 	    case '{':
-	      idx.push_back (make_value_list (*p_args, *p_arg_nm, &tmp));
+	      {
+		octave_value_list tidx
+		  = make_value_list (*p_args, *p_arg_nm, &tmp);
+
+		idx.push_back (tidx);
+
+		if (i == n-1)
+		  {
+		    // Last indexing element.  Will this result in a
+		    // comma-separated list?
+
+		    if (tidx.has_magic_colon ())
+		      {
+			octave_value_list tmp_list
+			  = first_retval_object.subsref (type, idx, 1);
+
+			if (! error_state)
+			  {
+			    octave_value val = tmp_list(0);
+
+			    if (val.is_cs_list ())
+			      retval.numel (val.numel ());
+			  }
+		      }
+		    else
+		      {
+			octave_idx_type nel = 1;
+
+			octave_idx_type nidx = tidx.length ();
+
+			for (octave_idx_type j = 0; j < nidx; j++)
+			  {
+			    octave_value val = tidx(j);
+
+			    nel *= val.numel ();
+			  }
+
+			retval.numel (nel);
+		      }
+		  }
+	      }
 	      break;
 
 	    case '.':