diff src/pt-exp.cc @ 2971:f2be17e6f1ea

[project @ 1997-05-15 18:55:44 by jwe]
author jwe
date Thu, 15 May 1997 18:55:47 +0000
parents 194b50e4725b
children 49de01238638
line wrap: on
line diff
--- a/src/pt-exp.cc	Thu May 15 18:08:21 1997 +0000
+++ b/src/pt-exp.cc	Thu May 15 18:55:47 1997 +0000
@@ -44,7 +44,6 @@
 #include "pt-id.h"
 #include "pt-indir.h"
 #include "pt-misc.h"
-#include "pt-mvr.h"
 #include "pt-pr-code.h"
 #include "pt-walk.h"
 #include "utils.h"
@@ -62,8 +61,22 @@
 
 // Prefix expressions.
 
+octave_value_list
+tree_prefix_expression::rvalue (int nargout)
+{
+  octave_value_list retval;
+
+  if (nargout > 1)
+    error ("prefix operator `%s': invalid number of output arguments",
+	   oper () . c_str ());
+  else
+    retval = rvalue ();
+
+  return retval;
+}
+
 octave_value
-tree_prefix_expression::eval (bool)
+tree_prefix_expression::rvalue (void)
 {
   octave_value retval;
 
@@ -74,28 +87,40 @@
     {
       if (etype == unot || etype == uminus)
 	{
-	  octave_value val = op->eval ();
+	  octave_value val = op->rvalue ();
 
 	  if (! error_state)
 	    {
-	      if (etype == unot)
-		retval = val.not ();
+	      if (val.is_defined ())
+		{
+		  if (etype == unot)
+		    retval = val.not ();
+		  else
+		    retval = val.uminus ();
+		}
 	      else
-		retval = val.uminus ();
+		error ("argument to prefix operator `%s' undefined",
+		       oper () . c_str ());
 	    }
 	}
       else if (etype == increment || etype == decrement)
 	{
-	  octave_variable_reference ref = op->reference ();
+	  octave_variable_reference ref = op->lvalue ();
 
 	  if (! error_state)
 	    {
-	      if (etype == increment)
-		ref.increment ();
+	      if (ref.is_defined ())
+		{
+		  if (etype == increment)
+		    ref.increment ();
+		  else
+		    ref.decrement ();
+
+		  retval = ref.value ();
+		}
 	      else
-		ref.decrement ();
-
-	      retval = ref.value ();
+		error ("argument to prefix operator `%s' undefined",
+		       oper () . c_str ());
 	    }
 	}
       else
@@ -105,6 +130,14 @@
   return retval;
 }
 
+void
+tree_prefix_expression::eval_error (void)
+{
+  if (error_state > 0)
+    ::error ("evaluating prefix operator `%s' near line %d, column %d",
+	     oper () . c_str (), line (), column ());
+}
+
 string
 tree_prefix_expression::oper (void) const
 {
@@ -136,14 +169,6 @@
 }
 
 void
-tree_prefix_expression::eval_error (void)
-{
-  if (error_state > 0)
-    ::error ("evaluating prefix operator `%s' near line %d, column %d",
-	     oper () . c_str (), line (), column ());
-}
-
-void
 tree_prefix_expression::accept (tree_walker& tw)
 {
   tw.visit_prefix_expression (*this);
@@ -151,8 +176,22 @@
 
 // Postfix expressions.
 
+octave_value_list
+tree_postfix_expression::rvalue (int nargout)
+{
+  octave_value_list retval;
+
+  if (nargout > 1)
+    error ("postfix operator `%s': invalid number of output arguments",
+	   oper () . c_str ());
+  else
+    retval = rvalue ();
+
+  return retval;
+}
+
 octave_value
-tree_postfix_expression::eval (bool)
+tree_postfix_expression::rvalue (void)
 {
   octave_value retval;
 
@@ -163,28 +202,40 @@
     {
       if (etype == transpose || etype == hermitian)
 	{
-	  octave_value val = op->eval ();
+	  octave_value val = op->rvalue ();
 
 	  if (! error_state)
 	    {
-	      if (etype == transpose)
-		retval = val.transpose ();
+	      if (val.is_defined ())
+		{
+		  if (etype == transpose)
+		    retval = val.transpose ();
+		  else
+		    retval = val.hermitian ();
+		}
 	      else
-		retval = val.hermitian ();
+		error ("argument to postfix operator `%s' undefined",
+		       oper () . c_str ());
 	    }
 	}
       else if (etype == increment || etype == decrement)
 	{
-	  octave_variable_reference ref = op->reference ();
+	  octave_variable_reference ref = op->lvalue ();
 
 	  if (! error_state)
 	    {
-	      retval = ref.value ();
+	      if (ref.is_defined ())
+		{
+		  retval = ref.value ();
 
-	      if (etype == increment)
-		ref.increment ();
+		  if (etype == increment)
+		    ref.increment ();
+		  else
+		    ref.decrement ();
+		}
 	      else
-		ref.decrement ();
+		error ("argument to postfix operator `%s' undefined",
+		       oper () . c_str ());
 	    }
 	}
       else
@@ -194,6 +245,14 @@
   return retval;
 }
 
+void
+tree_postfix_expression::eval_error (void)
+{
+  if (error_state > 0)
+    ::error ("evaluating postfix operator `%s' near line %d, column %d",
+	     oper () . c_str (), line (), column ());
+}
+
 string
 tree_postfix_expression::oper (void) const
 {
@@ -225,14 +284,6 @@
 }
 
 void
-tree_postfix_expression::eval_error (void)
-{
-  if (error_state > 0)
-    ::error ("evaluating postfix operator `%s' near line %d, column %d",
-	     oper () . c_str (), line (), column ());
-}
-
-void
 tree_postfix_expression::accept (tree_walker& tw)
 {
   tw.visit_postfix_expression (*this);
@@ -240,8 +291,22 @@
 
 // Binary expressions.
  
+octave_value_list
+tree_binary_expression::rvalue (int nargout)
+{
+  octave_value_list retval;
+
+  if (nargout > 1)
+    error ("binary operator `%s': invalid number of output arguments",
+	   oper () . c_str ());
+  else
+    retval = rvalue ();
+
+  return retval;
+}
+
 octave_value
-tree_binary_expression::eval (bool /* print */)
+tree_binary_expression::rvalue (void)
 {
   octave_value retval;
 
@@ -250,13 +315,13 @@
 
   if (op_lhs)
     {
-      octave_value a = op_lhs->eval ();
+      octave_value a = op_lhs->rvalue ();
 
       if (error_state)
 	eval_error ();
       else if (a.is_defined () && op_rhs)
 	{
-	  octave_value b = op_rhs->eval ();
+	  octave_value b = op_rhs->rvalue ();
 
 	  if (error_state)
 	    eval_error ();
@@ -282,12 +347,6 @@
   return retval;
 }
 
-string
-tree_binary_expression::oper (void) const
-{
-  return octave_value::binary_op_as_string (etype);
-}
-
 void
 tree_binary_expression::eval_error (void)
 {
@@ -296,6 +355,12 @@
 	     oper () . c_str (), line (), column ());
 }
 
+string
+tree_binary_expression::oper (void) const
+{
+  return octave_value::binary_op_as_string (etype);
+}
+
 void
 tree_binary_expression::accept (tree_walker& tw)
 {
@@ -304,8 +369,22 @@
 
 // Boolean expressions.
  
+octave_value_list
+tree_boolean_expression::rvalue (int nargout)
+{
+  octave_value_list retval;
+
+  if (nargout > 1)
+    error ("binary operator `%s': invalid number of output arguments",
+	   oper () . c_str ());
+  else
+    retval = rvalue ();
+
+  return retval;
+}
+
 octave_value
-tree_boolean_expression::eval (bool /* print */)
+tree_boolean_expression::rvalue (void)
 {
   octave_value retval;
 
@@ -316,7 +395,7 @@
 
   if (op_lhs)
     {
-      octave_value a = op_lhs->eval ();
+      octave_value a = op_lhs->rvalue ();
 
       if (error_state)
 	eval_error ();
@@ -344,7 +423,7 @@
 
 	      if (op_rhs)
 		{
-		  octave_value b = op_rhs->eval ();
+		  octave_value b = op_rhs->rvalue ();
 
 		  if (error_state)
 		    eval_error ();
@@ -396,50 +475,29 @@
 
 // Simple assignment expressions.
 
-tree_simple_assignment_expression::tree_simple_assignment_expression
-  (tree_identifier *i, tree_expression *r, bool plhs, bool ans_assign,
-   int l, int c, octave_value::assign_op t)
-    : tree_expression (l, c), lhs_idx_expr (0),
-      lhs (new tree_indirect_ref (i)), index (0), rhs (r),
-      preserve (plhs), ans_ass (ans_assign), etype (t) { }
-
-tree_simple_assignment_expression::tree_simple_assignment_expression
-  (tree_index_expression *idx_expr, tree_expression *r, bool plhs,
-   bool ans_assign, int l, int c, octave_value::assign_op t)
-    : tree_expression (l, c), lhs_idx_expr (idx_expr),
-      lhs (idx_expr->ident ()), index (idx_expr->arg_list ()), rhs (r),
-      preserve (plhs), ans_ass (ans_assign), etype (t) { }
-
-tree_simple_assignment_expression::~tree_simple_assignment_expression (void)
+tree_simple_assignment::~tree_simple_assignment (void)
 {
   if (! preserve)
-    {
-      if (lhs_idx_expr)
-	delete lhs_idx_expr;
-      else
-	delete lhs;
-    }
+    delete lhs;
 
   delete rhs;
 }
 
-bool
-tree_simple_assignment_expression::left_hand_side_is_identifier_only (void)
+octave_value_list
+tree_simple_assignment::rvalue (int nargout)
 {
-  return lhs->is_identifier_only ();
+  octave_value_list retval;
+
+  if (nargout > 1)
+    error ("invalid number of output arguments for expression X = RHS");
+  else
+    retval = rvalue ();
+
+  return retval;
 }
 
-tree_identifier *
-tree_simple_assignment_expression::left_hand_side_id (void)
-{
-  return lhs->ident ();
-}
-
-// ??? FIXME ??? -- should octave_value::assign return the right thing
-// for us to return?
-
 octave_value
-tree_simple_assignment_expression::eval (bool print)
+tree_simple_assignment::rvalue (void)
 {
   octave_value rhs_val;
 
@@ -448,12 +506,12 @@
 
   if (rhs)
     {
-      octave_value lhs_val;
+      octave_value_list tmp = rhs->rvalue ();
 
-      rhs_val = rhs->eval ();
+      if (! (error_state || tmp.empty ()))
+	{
+	  rhs_val = tmp(0);
 
-      if (! error_state)
-	{
 	  if (rhs_val.is_undefined ())
 	    {
 	      error ("value on right hand side of assignment is undefined");
@@ -461,89 +519,55 @@
 	    }
 	  else
 	    {
-	      octave_variable_reference ult = lhs->reference ();
+	      octave_variable_reference ult = lhs->lvalue ();
 
 	      if (error_state)
 		eval_error ();
 	      else
 		{
-		  if (index)
-		    {
-		      // Extract the arguments into a simple vector.
+		  ult.assign (etype, rhs_val);
 
-		      octave_value_list args
-			= index->convert_to_const_vector ();
-
-		      if (! error_state)
-			{
-			  int nargin = args.length ();
+		  if (error_state)
+		    eval_error ();
+		  else if (! Vprint_rhs_assign_val)
+		    {
+		      octave_value lhs_val = ult.value ();
 
-			  if (nargin > 0)
+		      if (! error_state && print_result ())
+			{
+			  if (Vprint_rhs_assign_val)
 			    {
-			      ult.index (args);
+			      ostrstream buf;
+
+			      tree_print_code tpc (buf);
 
-			      ult.assign (etype, rhs_val);
+			      lhs->accept (tpc);
+
+			      buf << ends;
 
-			      if (error_state)
-				eval_error ();
-			      else if (! Vprint_rhs_assign_val)
-				lhs_val = ult.value ();
+			      const char *tag = buf.str ();
+
+			      rhs_val.print_with_name (octave_stdout, tag);
+
+			      delete [] tag;
 			    }
 			  else
-			    error ("??? invalid index list ???");
+			    lhs_val.print_with_name (octave_stdout,
+						     lhs->name ());
 			}
-		      else
-			eval_error ();
-		    }
-		  else
-		    {
-		      ult.assign (etype, rhs_val);
-
-		      if (error_state)
-			eval_error ();
-		      else if (! Vprint_rhs_assign_val)
-			lhs_val = ult.value ();
 		    }
 		}
 	    }
 	}
       else
 	eval_error ();
-
-      if (! error_state && print)
-	{
-	  if (Vprint_rhs_assign_val)
-	    {
-	      ostrstream buf;
-
-	      buf << lhs->name ();
-
-	      if (index)
-		{
-		  buf << " (";
-		  tree_print_code tpc (buf);
-		  index->accept (tpc);
-		  buf << ")";
-		}
-
-	      buf << ends;
-
-	      const char *tag = buf.str ();
-
-	      rhs_val.print_with_name (octave_stdout, tag);
-
-	      delete [] tag;
-	    }
-	  else
-	    lhs_val.print_with_name (octave_stdout, lhs->name ());
-	}
     }
 
   return rhs_val;
 }
 
 void
-tree_simple_assignment_expression::eval_error (void)
+tree_simple_assignment::eval_error (void)
 {
   if (error_state > 0)
     {
@@ -557,49 +581,90 @@
 }
 
 string
-tree_simple_assignment_expression::oper (void) const
+tree_simple_assignment::oper (void) const
 {
   return octave_value::assign_op_as_string (etype);
 }
 
 void
-tree_simple_assignment_expression::accept (tree_walker& tw)
+tree_simple_assignment::accept (tree_walker& tw)
 {
-  tw.visit_simple_assignment_expression (*this);
+  tw.visit_simple_assignment (*this);
 }
 
 // Colon expressions.
 
 tree_colon_expression *
-tree_colon_expression::chain (tree_expression *t)
+tree_colon_expression::append (tree_expression *t)
 {
   tree_colon_expression *retval = 0;
-  if (! op_base || op_increment)
-    ::error ("invalid colon expression");
-  else
+
+  if (op_base)
     {
-      // Stupid syntax:
-      //
-      // base : limit
-      // base : increment : limit
+      if (op_limit)
+	{
+	  if (op_increment)
+	    ::error ("invalid colon expression");
+	  else
+	    {
+	      // Stupid syntax:
+	      //
+	      // base : limit
+	      // base : increment : limit
 
-      op_increment = op_limit;
-      op_limit = t;
+	      op_increment = op_limit;
+	      op_limit = t;
+	    }
+	}
+      else
+	op_limit = t;
 
       retval = this;
     }
+  else
+    ::error ("invalid colon expression");
+
+  return retval;
+}
+
+octave_value_list
+tree_colon_expression::rvalue (int nargout)
+{
+  octave_value_list retval;
+
+  if (nargout > 1)
+    error ("invalid number of output arguments for colon expression");
+  else
+    retval = rvalue ();
+
   return retval;
 }
 
 octave_value
-tree_colon_expression::eval (bool /* print */)
+tree_colon_expression::rvalue (void)
 {
   octave_value retval;
 
   if (error_state || ! op_base || ! op_limit)
     return retval;
 
-  octave_value tmp = op_base->eval ();
+  octave_value tmp = op_base->rvalue ();
+
+  if (tmp.is_undefined ())
+    {
+      eval_error ("invalid null value in colon expression");
+      return retval;
+    }
+
+  double xbase = tmp.double_value ();
+
+  if (error_state)
+    {
+      eval_error ("colon expression elements must be scalars");
+      return retval;
+    }
+
+  tmp = op_limit->rvalue ();
 
   if (tmp.is_undefined ())
     {
@@ -607,37 +672,19 @@
       return retval;
     }
 
-  double base = tmp.double_value ();
+  double xlimit = tmp.double_value ();
 
   if (error_state)
     {
-      error ("colon expression elements must be scalars");
-      eval_error ("evaluating colon expression");
+      eval_error ("colon expression elements must be scalars");
       return retval;
     }
 
-  tmp = op_limit->eval ();
-
-  if (tmp.is_undefined ())
-    {
-      eval_error ("invalid null value in colon expression");
-      return retval;
-    }
-
-  double limit = tmp.double_value ();
-
-  if (error_state)
-    {
-      error ("colon expression elements must be scalars");
-      eval_error ("evaluating colon expression");
-      return retval;
-    }
-
-  double inc = 1.0;
+  double xinc = 1.0;
 
   if (op_increment)
     {
-      tmp = op_increment->eval ();
+      tmp = op_increment->rvalue ();
 
       if (tmp.is_undefined ())
 	{
@@ -645,22 +692,22 @@
 	  return retval;
 	}
 
-      inc = tmp.double_value ();
+      xinc = tmp.double_value ();
 
       if (error_state)
 	{
-	  error ("colon expression elements must be scalars");
-	  eval_error ("evaluating colon expression");
+	  eval_error ("colon expression elements must be scalars");
 	  return retval;
 	}
     }
 
-  retval = octave_value (base, limit, inc);
+  retval = octave_value (xbase, xlimit, xinc);
 
   if (error_state)
     {
       if (error_state)
-	eval_error ("evaluating colon expression");
+	eval_error ();
+
       return octave_value ();
     }
 
@@ -668,10 +715,16 @@
 }
 
 void
-tree_colon_expression::eval_error (const char *s)
+tree_colon_expression::eval_error (const string& s)
 {
   if (error_state > 0)
-    ::error ("%s near line %d column %d", s, line (), column ());
+    {
+      if (! s.empty ())
+	::error ("%s", s.c_str ());
+
+      ::error ("evaluating colon expression near line %d column %d",
+	       line (), column ());
+    }
 }
 
 void
@@ -680,6 +733,253 @@
   tw.visit_colon_expression (*this);
 }
 
+tree_index_expression::~tree_index_expression (void)
+{
+  delete expr;
+  delete list;
+}
+
+octave_value_list
+tree_index_expression::rvalue (int nargout)
+{
+  octave_value_list retval;
+
+  if (error_state)
+    return retval;
+
+  octave_value tmp = expr->rvalue ();
+
+  if (! error_state)
+    {
+      octave_value_list args;
+
+      if (list)
+	args = list->convert_to_const_vector ();
+
+      if (! error_state)
+	{
+	  if (! args.empty ())
+	    args.stash_name_tags (arg_nm);
+
+	  // XXX FIXME XXX -- is this the right thing to do?
+	  if (tmp.is_constant ())
+	    retval = tmp.do_index_op (args);
+	  else
+	    retval = tmp.do_index_op (nargout, args);
+	}
+      else
+	eval_error ();
+    }
+  else
+    eval_error ();
+
+  return retval;
+}
+
+octave_value
+tree_index_expression::rvalue (void)
+{
+  octave_value retval;
+
+  octave_value_list tmp = rvalue (1);
+
+  if (! tmp.empty ())
+    retval = tmp(0);
+
+  return retval;
+}
+
+octave_variable_reference
+tree_index_expression::lvalue (void)
+{
+  octave_variable_reference retval;
+
+  if (! error_state)
+    {
+      retval = expr->lvalue ();
+
+      if (! error_state)
+	{
+	  octave_value_list args;
+	  
+	  if (list)
+	    args = list->convert_to_const_vector ();
+
+	  retval.index (args);
+	}
+    }
+
+  return retval;
+}
+
+void
+tree_index_expression::eval_error (void)
+{
+  if (error_state > 0)
+    {
+      int l = line ();
+      int c = column ();
+
+      if (l != -1 && c != -1)
+	{
+	  if (list)
+	    ::error ("evaluating index expression near line %d, column %d",
+		     l, c);
+	  else
+	    ::error ("evaluating expression near line %d, column %d", l, c);
+	}
+      else
+	{
+	  if (list)
+	    ::error ("evaluating index expression");
+	  else
+	    ::error ("evaluating expression");
+	}
+    }
+}
+
+void
+tree_index_expression::accept (tree_walker& tw)
+{
+  tw.visit_index_expression (*this);
+}
+
+tree_multi_assignment::~tree_multi_assignment (void)
+{
+  if (! preserve)
+    delete lhs;
+
+  delete rhs;
+}
+
+octave_value
+tree_multi_assignment::rvalue (void)
+{
+  octave_value retval;
+
+  octave_value_list tmp = rvalue (1);
+
+  if (! tmp.empty ())
+    retval = tmp(0);
+
+  return retval;
+}
+
+octave_value_list
+tree_multi_assignment::rvalue (int nargout)
+{
+  octave_value_list rhs_val;
+
+  if (error_state)
+    return rhs_val;
+
+  if (rhs)
+    {
+      int n_out = lhs->length ();
+
+      rhs_val = rhs->rvalue (n_out);
+
+      if (! (error_state || rhs_val.empty ()))
+	{
+	  if (rhs_val.empty ())
+	    {
+	      error ("value on right hand side of assignment is undefined");
+	      eval_error ();
+	    }
+	  else
+	    {
+	      int k = 0;
+
+	      int n = rhs_val.length ();
+
+	      for (Pix p = lhs->first (); p != 0; lhs->next (p))
+		{
+		  tree_expression *lhs_elt = lhs->operator () (p);
+
+		  if (lhs_elt)
+		    {
+		      octave_variable_reference ult = lhs_elt->lvalue ();
+
+		      if (error_state)
+			eval_error ();
+		      else
+			{
+			  octave_value tmp = k < n
+			    ? rhs_val(k++) : octave_value ();
+
+			  if (tmp.is_defined ())
+			    {
+			      // XXX FIXME XXX -- handle other assignment ops.
+			      ult.assign (octave_value::asn_eq, tmp);
+			    }
+			  else
+			    error ("element number %d undefined in return list", k+1);
+
+			  if (error_state)
+			    eval_error ();
+			  else if (! Vprint_rhs_assign_val)
+			    {
+			      octave_value lhs_val = ult.value ();
+
+			      if (! error_state && print_result ())
+				{
+				  if (Vprint_rhs_assign_val)
+				    {
+				      ostrstream buf;
+
+				      tree_print_code tpc (buf);
+
+				      lhs_elt->accept (tpc);
+
+				      buf << ends;
+
+				      const char *tag = buf.str ();
+
+				      tmp.print_with_name
+					(octave_stdout, tag);
+
+				      delete [] tag;
+				    }
+				  else
+				    lhs_val.print_with_name (octave_stdout,
+							     lhs_elt->name ());
+				}
+			    }
+			}
+		    }
+
+		  if (error_state)
+		    break;
+		}
+	    }
+	}
+      else
+	eval_error ();
+    }
+
+  return rhs_val;
+}
+
+void
+tree_multi_assignment::eval_error (void)
+{
+  if (error_state > 0)
+    {
+      int l = line ();
+      int c = column ();
+
+      if (l != -1 && c != -1)
+	::error ("evaluating assignment expression near line %d, column %d",
+		 l, c);
+    }
+}
+
+void
+tree_multi_assignment::accept (tree_walker& tw)
+{
+  tw.visit_multi_assignment (*this);
+}
+
 static int
 print_rhs_assign_val (void)
 {