changeset 2971:f2be17e6f1ea

[project @ 1997-05-15 18:55:44 by jwe]
author jwe
date Thu, 15 May 1997 18:55:47 +0000
parents b9e64477f703
children ae2471c4e5c0
files src/pt-const.cc src/pt-const.h src/pt-exp-base.cc src/pt-exp-base.h src/pt-exp.cc src/pt-exp.h src/pt-id.cc src/pt-id.h src/pt-indir.cc src/pt-indir.h src/pt-mat.cc src/pt-mat.h
diffstat 12 files changed, 861 insertions(+), 643 deletions(-) [+]
line wrap: on
line diff
--- a/src/pt-const.cc
+++ b/src/pt-const.cc
@@ -30,6 +30,7 @@
 
 #include <iostream.h>
 
+#include "error.h"
 #include "oct-obj.h"
 #include "pager.h"
 #include "pt-const.h"
@@ -59,19 +60,17 @@
     val.print_raw (os, pr_as_read_syntax);
 }
 
-octave_value
-tree_constant::eval (bool print_result)
+octave_value_list
+tree_constant::rvalue (int nargout)
 {
-  if (print_result)
-    val.print (octave_stdout);
+  octave_value_list retval;
 
-  return val;
-}
+  if (nargout > 1)
+    error ("invalid number of output arguments for constant expression");
+  else
+    retval = rvalue ();
 
-octave_value_list
-tree_constant::eval (bool, int, const octave_value_list& idx)
-{
-  return (idx.length () > 0) ? val.do_index_op (idx) : val;
+  return retval;
 }
 
 void
--- a/src/pt-const.h
+++ b/src/pt-const.h
@@ -33,7 +33,7 @@
 
 #include "oct-alloc.h"
 
-#include "pt-mvr-base.h"
+#include "pt-exp-base.h"
 
 class octave_value_list;
 
@@ -42,18 +42,18 @@
 #include "ov.h"
 
 class
-tree_constant : public tree_multi_val_ret
+tree_constant : public tree_expression
 {
 public:
 
   tree_constant (int l = -1, int c = -1)
-    : tree_multi_val_ret (l, c), val (), orig_text () { }
+    : tree_expression (l, c), val (), orig_text () { }
 
   tree_constant (const octave_value& v, int l = -1, int c = -1)
-    : tree_multi_val_ret (l, c), val (v), orig_text () { }
+    : tree_expression (l, c), val (v), orig_text () { }
 
   tree_constant (const tree_constant& a)
-    : tree_multi_val_ret (-1, -1), val (a.val), orig_text () { }
+    : tree_expression (-1, -1), val (a.val), orig_text () { }
 
   ~tree_constant (void) { }
 
@@ -61,7 +61,7 @@
     {
       if (this != &a)
 	{
-	  tree_multi_val_ret::operator = (a);
+	  tree_expression::operator = (a);
 	  val = a.val;
 	}
       return *this;
@@ -75,7 +75,8 @@
 
   // Type.  It would be nice to eliminate the need for this.
 
-  bool is_constant (void) const { return true; }
+  bool is_constant (void) const
+    { return true; }
 
   void maybe_mutate (void)
     { val.maybe_mutate (); }
@@ -86,10 +87,15 @@
   void print_raw (ostream& os, bool pr_as_read_syntax = false,
 		  bool pr_orig_txt = true);
 
-  octave_value eval (bool print = false);
+  bool rvalue_ok (void) const
+    { return true; }
 
-  octave_value_list
-  eval (bool print, int nargout, const octave_value_list& args);
+  octave_value rvalue (void)
+    { return val; }
+
+  octave_value_list rvalue (int nargout);
+
+  void accept (tree_walker& tw);
 
   // Store the original text corresponding to this constant for later
   // pretty printing.
@@ -100,8 +106,6 @@
   string original_text (void) const
     { return orig_text; }
 
-  void accept (tree_walker& tw);
-
 private:
 
   // For custom memory management.
--- a/src/pt-exp-base.cc
+++ b/src/pt-exp-base.cc
@@ -46,7 +46,7 @@
 {
   bool expr_value = false;
 
-  octave_value t1 = eval ();
+  octave_value t1 = rvalue ();
 
   if (! error_state)
     {
@@ -62,23 +62,24 @@
   return expr_value;
 }
 
-void
-tree_expression::mark_for_possible_ans_assign (void)
+octave_value
+tree_expression::rvalue (void)
 {
-  panic_impossible ();
-}
-
-octave_value
-tree_expression::eval (bool /* print */)
-{
-  panic ("invalid evaluation of generic expression");
+  ::error ("invalid rvalue function called in expression");
   return octave_value ();
 }
 
+octave_value_list
+tree_expression::rvalue (int nargout)
+{
+  ::error ("invalid rvalue function called in expression");
+  return octave_value_list ();
+}
+
 octave_variable_reference
-tree_expression::reference (void)
+tree_expression::lvalue (void)
 {
-  panic ("invalid attempt to convert generic expression to lvalue");
+  ::error ("invalid lvalue function called in expression");
   return octave_variable_reference ();
 }
 
--- a/src/pt-exp-base.h
+++ b/src/pt-exp-base.h
@@ -42,7 +42,8 @@
 public:
 
   tree_expression (int l = -1, int c = -1)
-    : tree (l, c), num_parens (0) { }
+    : tree (l, c), num_parens (0), postfix_indexed (false),
+      print_flag (false) { }
 
   virtual ~tree_expression (void) { }
 
@@ -52,16 +53,13 @@
   virtual bool is_matrix_constant (void) const
     { return false; }
 
-  virtual bool is_multi_val_ret_expression (void) const
-    { return false; }
-
   virtual bool is_identifier (void) const
     { return false; }
 
-  virtual bool is_indirect_ref (void) const
+  virtual bool is_index_expression (void) const
     { return false; }
 
-  virtual bool is_index_expression (void) const
+  virtual bool is_indirect_ref (void) const
     { return false; }
 
   virtual bool is_assignment_expression (void) const
@@ -72,18 +70,33 @@
 
   virtual bool is_logically_true (const char *);
 
-  virtual int paren_count (void) const
+  virtual bool lvalue_ok (void) const
+    { return false; }
+
+  virtual bool rvalue_ok (void) const
+    { return false; }
+
+  virtual octave_value rvalue (void);
+
+  virtual octave_value_list rvalue (int nargout);
+
+  virtual octave_variable_reference lvalue (void);
+
+  int paren_count (void) const
     { return num_parens; }
 
-  virtual void mark_for_possible_ans_assign (void);
+  bool is_postfix_indexed (void) const
+    { return postfix_indexed; }
 
-  virtual octave_value eval (bool print = false) = 0;
-
-  virtual octave_variable_reference reference (void);
+  bool print_result (void) const
+    { return print_flag; }
 
   virtual string oper (void) const
     { return "<unknown>"; }
 
+  virtual string name (void) const
+    { return "<unknown>"; }
+
   virtual string original_text (void) const;
 
   tree_expression *mark_in_parens (void)
@@ -92,6 +105,18 @@
       return this;
     }
 
+  tree_expression *mark_postfix_indexed (void)
+    {
+      postfix_indexed = true;
+      return this;
+    }
+
+  tree_expression *set_print_flag (bool print)
+    {
+      print_flag = print;
+      return this;
+    }
+
 protected:
 
   // A count of the number of times this expression appears directly
@@ -101,6 +126,13 @@
   //                  ==> 1 for expression ((e1)) + e2
   //                  ==> 0 for expression e2
   int num_parens;
+
+  // A flag that says whether this expression has an index associated
+  // with it.  See the code in tree_identifier::rvalue for the rationale.
+  bool postfix_indexed;
+
+  // Print result of rvalue for this expression?
+  bool print_flag;
 };
 
 #endif
--- a/src/pt-exp.cc
+++ b/src/pt-exp.cc
@@ -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)
 {
--- a/src/pt-exp.h
+++ b/src/pt-exp.h
@@ -33,6 +33,7 @@
 class tree_index_expression;
 class tree_indirect_ref;
 class tree_argument_list;
+class tree_assignment_lhs;
 
 class tree_walker;
 
@@ -40,6 +41,7 @@
 class octave_value_list;
 class octave_variable_reference;
 
+#include "oct-obj.h"
 #include "pt-exp-base.h"
 
 // Unary expressions.
@@ -90,7 +92,12 @@
 
   ~tree_prefix_expression (void) { }
 
-  octave_value eval (bool print = false);
+  bool rvalue_ok (void) const
+    { return true; }
+
+  octave_value rvalue (void);
+
+  octave_value_list rvalue (int nargou);
 
   void eval_error (void);
 
@@ -129,7 +136,12 @@
 
   ~tree_postfix_expression (void) { }
 
-  octave_value eval (bool print = false);
+  bool rvalue_ok (void) const
+    { return true; }
+
+  octave_value rvalue (void);
+
+  octave_value_list rvalue (int nargout);
 
   void eval_error (void);
 
@@ -167,7 +179,12 @@
       delete op_rhs;
     }
 
-  octave_value eval (bool print = false);
+  bool rvalue_ok (void) const
+    { return true; }
+
+  octave_value rvalue (void);
+
+  octave_value_list rvalue (int nargou);
 
   void eval_error (void);
 
@@ -213,7 +230,12 @@
 
   ~tree_boolean_expression (void) { }
 
-  octave_value eval (bool print = false);
+  bool rvalue_ok (void) const
+    { return true; }
+
+  octave_value rvalue (void);
+
+  octave_value_list rvalue (int nargout);
 
   string oper (void) const;
 
@@ -226,43 +248,28 @@
 // Simple assignment expressions.
 
 class
-tree_simple_assignment_expression : public tree_expression
+tree_simple_assignment : public tree_expression
 {
 public:
 
-  tree_simple_assignment_expression
-    (bool plhs = false, bool ans_assign = false, int l = -1, int c = -1,
-     octave_value::assign_op t = octave_value::asn_eq)
-    : tree_expression (l, c), lhs_idx_expr (0), lhs (0), index (0),
-      rhs (0), preserve (plhs), ans_ass (ans_assign), etype (t) { }
-
-  tree_simple_assignment_expression
-    (tree_identifier *i, tree_expression *r, bool plhs = false,
-     bool ans_assign = false, int l = -1, int c = -1,
-     octave_value::assign_op t = octave_value::asn_eq);
+  tree_simple_assignment (bool plhs = false, int l = -1, int c = -1,
+			  octave_value::assign_op t = octave_value::asn_eq)
+    : tree_expression (l, c), lhs (0), rhs (0), preserve (plhs), etype (t) { }
 
-  tree_simple_assignment_expression
-    (tree_indirect_ref *i, tree_expression *r, bool plhs = false,
-     bool ans_assign = false, int l = -1, int c = -1,
-     octave_value::assign_op t = octave_value::asn_eq)
-    : tree_expression (l, c), lhs_idx_expr (0), lhs (i), index (0),
-      rhs (r), preserve (plhs), ans_ass (ans_assign), etype (t) { }
+  tree_simple_assignment (tree_expression *le, tree_expression *re,
+			  bool plhs = false, int l = -1, int c = -1,
+			  octave_value::assign_op t = octave_value::asn_eq)
+    : tree_expression (l, c), lhs (le), rhs (re), preserve (plhs),
+      etype (t) { }
 
-  tree_simple_assignment_expression
-    (tree_index_expression *idx_expr, tree_expression *r,
-     bool plhs = false, bool ans_assign = false, int l = -1, int c = -1,
-     octave_value::assign_op t = octave_value::asn_eq);
-
-  ~tree_simple_assignment_expression (void);
+  ~tree_simple_assignment (void);
 
-  bool left_hand_side_is_identifier_only (void);
-
-  tree_identifier *left_hand_side_id (void);
+  bool rvalue_ok (void) const
+    { return true; }
 
-  bool is_ans_assign (void)
-    { return ans_ass; }
+  octave_value rvalue (void);
 
-  octave_value eval (bool print = false);
+  octave_value_list rvalue (int nargout);
 
   bool is_assignment_expression (void) const
     { return true; }
@@ -271,9 +278,7 @@
 
   string oper (void) const;
 
-  tree_indirect_ref *left_hand_side (void) { return lhs; }
-
-  tree_argument_list *lhs_index (void) { return index; }
+  tree_expression *left_hand_side (void) { return lhs; }
 
   tree_expression *right_hand_side (void) { return rhs; }
 
@@ -288,17 +293,8 @@
   void do_assign (octave_variable_reference& ult,
 		  const octave_value& rhs_val);
 
-  // The left hand side of the assignment, as an index expression.  If
-  // the assignment is constructed from an index expression, the index
-  // expression is split into the its components in the constructor.
-  tree_index_expression *lhs_idx_expr;
-
-  // The indirect reference (id or structure reference) on the left
-  // hand side of the assignemnt.
-  tree_indirect_ref *lhs;
-
-  // The index of the left hand side of the assignment, if any.
-  tree_argument_list *index;
+  // The left hand side of the assignment.
+  tree_expression *lhs;
 
   // The right hand side of the assignment.
   tree_expression *rhs;
@@ -323,9 +319,8 @@
   tree_colon_expression (int l = -1, int c = -1)
     : tree_expression (l, c), op_base (0), op_limit (0), op_increment (0) { }
 
-  tree_colon_expression (tree_expression *a, tree_expression *b,
-			 int l = -1, int c = -1)
-    : tree_expression (l, c), op_base (a), op_limit (b), op_increment (0) { }
+  tree_colon_expression (tree_expression *e, int l = -1, int c = -1)
+    : tree_expression (l, c), op_base (e), op_limit (0), op_increment (0) { }
 
   ~tree_colon_expression (void)
     {
@@ -334,11 +329,16 @@
       delete op_increment;
     }
 
-  tree_colon_expression *chain (tree_expression *t);
+  tree_colon_expression *append (tree_expression *t);
+
+  bool rvalue_ok (void) const
+    { return true; }
 
-  octave_value eval (bool print = false);
+  octave_value rvalue (void);
 
-  void eval_error (const char *s);
+  octave_value_list rvalue (int nargout);
+
+  void eval_error (const string& s = string ());
 
   tree_expression *base (void) { return op_base; }
   tree_expression *limit (void) { return op_limit; }
@@ -354,6 +354,91 @@
   tree_expression *op_increment;
 };
 
+// Index expressions.
+
+class
+tree_index_expression : public tree_expression
+{
+public:
+
+  tree_index_expression (tree_expression *e = 0, tree_argument_list *lst = 0,
+			 int l = -1, int c = -1)
+    : tree_expression (l, c), expr (e), list (lst), arg_nm () { }
+
+  ~tree_index_expression (void);
+
+  bool is_index_expression (void) const
+    { return true; }
+
+  tree_expression *expression (void)
+    { return expr; }
+
+  tree_argument_list *arg_list (void)
+    { return list; }
+
+  bool rvalue_ok (void) const
+    { return true; }
+
+  octave_value rvalue (void);
+
+  octave_value_list rvalue (int nargout);
+
+  octave_variable_reference lvalue (void);
+
+  void eval_error (void);
+
+  void accept (tree_walker& tw);
+
+private:
+
+  tree_expression *expr;
+
+  tree_argument_list *list;
+
+  string_vector arg_nm;
+};
+
+// Multi-valued assignment expressions.
+
+class
+tree_multi_assignment : public tree_expression
+{
+public:
+
+  tree_multi_assignment (bool plhs = false, int l = -1, int c = -1)
+    : tree_expression (l, c), preserve (plhs), lhs (0), rhs (0) { }
+
+  tree_multi_assignment (tree_argument_list *lst, tree_expression *r,
+			 bool plhs = false, int l = -1, int c = -1)
+    : tree_expression (l, c), preserve (plhs), lhs (lst), rhs (r) { }
+
+  ~tree_multi_assignment (void);
+
+  bool is_assignment_expression (void) const
+    { return true; }
+
+  bool rvalue_ok (void) const
+    { return true; }
+
+  octave_value rvalue (void);
+
+  octave_value_list rvalue (int nargout);
+
+  void eval_error (void);
+
+  tree_argument_list *left_hand_side (void) { return lhs; }
+
+  tree_expression *right_hand_side (void) { return rhs; }
+
+  void accept (tree_walker& tw);
+
+private:
+
+  bool preserve;
+  tree_argument_list *lhs;
+  tree_expression *rhs;
+};
+
 #endif
 
 /*
--- a/src/pt-id.cc
+++ b/src/pt-id.cc
@@ -30,8 +30,6 @@
 
 #include "error.h"
 #include "oct-obj.h"
-#include "oct-fcn.h"
-#include "oct-sym.h"
 #include "oct-var-ref.h"
 #include "pager.h"
 #include "pt-const.h"
@@ -72,6 +70,12 @@
   return (sym && sym->is_defined ());
 }
 
+bool
+tree_identifier::is_function (void)
+{
+  return (sym && sym->is_function ());
+}
+
 void
 tree_identifier::eval_undefined_error (void)
 {
@@ -100,17 +104,14 @@
 //   * On systems that support dynamic linking, we prefer .oct files
 //     over .m files.
 
-octave_symbol *
+octave_value
 tree_identifier::do_lookup (bool& script_file_executed, bool exec_script)
 {
+  static octave_value foo;
+
   script_file_executed = lookup (sym, exec_script);
 
-  octave_symbol *retval = 0;
-
-  if (! script_file_executed)
-    retval = sym->def ();
-
-  return retval;
+  return script_file_executed ? foo : sym->def ();
 }
 
 void
@@ -134,57 +135,8 @@
     sym->mark_as_formal_parameter ();
 }
 
-octave_value
-tree_identifier::eval (bool print)
-{
-  octave_value retval;
-
-  if (error_state)
-    return retval;
-
-  bool script_file_executed = false;
-
-  octave_symbol *object_to_eval = do_lookup (script_file_executed);
-
-  if (! script_file_executed)
-    {
-      if (object_to_eval)
-	{
-	  int nargout = maybe_do_ans_assign ? 0 : 1;
-
-	  if (nargout)
-	    {
-	      octave_value_list tmp_args;
-	      octave_value_list tmp = object_to_eval->eval (nargout, tmp_args);
-
-	      if (tmp.length () > 0)
-		retval = tmp(0);
-	    }
-	  else
-	    retval = object_to_eval->eval ();
-	}
-      else
-	eval_undefined_error ();
-    }
-
-  if (! error_state)
-    {
-      if (retval.is_defined ())
-	{
-	  if (maybe_do_ans_assign && ! object_to_eval->is_constant ())
-	    bind_ans (retval, print);
-	  else if (print)
-	    retval.print_with_name (octave_stdout, name ());
-	}
-      else if (object_to_eval && object_to_eval->is_constant ())
-	eval_undefined_error ();
-    }
-
-  return retval;
-}
-
 octave_value_list
-tree_identifier::eval (bool print, int nargout, const octave_value_list& args)
+tree_identifier::rvalue (int nargout)
 {
   octave_value_list retval;
 
@@ -193,26 +145,36 @@
 
   bool script_file_executed = false;
 
-  octave_symbol *object_to_eval = do_lookup (script_file_executed);
+  octave_value val = do_lookup (script_file_executed);
 
   if (! script_file_executed)
     {
-      if (object_to_eval)
+      if (val.is_defined ())
 	{
-	  if (maybe_do_ans_assign && nargout == 1)
-	    {
-	      // Don't count the output arguments that we create
-	      // automatically.
+	  // XXX GAGME XXX -- this would be cleaner if we required
+	  // parens to indicate function calls.
+	  //
+	  // If this identifier refers to a function, we need to know
+	  // whether it is indexed so that we can do the same thing
+	  // for `f' and `f()'.  If the index is present, return the
+	  // function object and let tree_index_expression::rvalue
+	  // handle indexing.  Otherwise, arrange to call the function
+	  // here, so that we don't return the function definition as
+	  // a value.
 
-	      nargout = 0;
+	  if (val.is_function () && ! is_postfix_indexed ())
+	    {
+	      octave_value_list tmp_args;
 
-	      retval = object_to_eval->eval (nargout, args);
-
-	      if (retval.length () > 0 && retval(0).is_defined ())
-		bind_ans (retval(0), print);
+	      retval = val.do_index_op (nargout, tmp_args);
 	    }
 	  else
-	    retval = object_to_eval->eval (nargout, args);
+	    {
+	      if (print_result () && nargout == 0)
+		val.print_with_name (octave_stdout, name ());
+
+	      retval = val;
+	    }
 	}
       else
 	eval_undefined_error ();
@@ -221,24 +183,31 @@
   return retval;
 }
 
+octave_value
+tree_identifier::rvalue (void)
+{
+  octave_value retval;
+
+  octave_value_list tmp = rvalue (1);
+
+  if (! tmp.empty ())
+    retval = tmp(0);
+
+  return retval;
+}
+
+octave_variable_reference
+tree_identifier::lvalue (void)
+{
+  return sym->variable_reference ();
+}
+
 void
 tree_identifier::accept (tree_walker& tw)
 {
   tw.visit_identifier (*this);
 }
 
-octave_value
-tree_identifier::value (void) const
-{
-  return sym->variable_value ();
-}
-
-octave_variable_reference
-tree_identifier::reference (void)
-{
-  return sym->variable_reference ();
-}
-
 /*
 ;;; Local Variables: ***
 ;;; mode: C++ ***
--- a/src/pt-id.h
+++ b/src/pt-id.h
@@ -33,28 +33,27 @@
 
 class octave_value;
 class octave_value_list;
-class octave_symbol;
 class octave_function;
 class symbol_record;
 
 class tree_walker;
 
-#include "pt-mvr-base.h"
+#include "pt-exp-base.h"
 
 // Symbols from the symbol table.
 
 class
-tree_identifier : public tree_multi_val_ret
+tree_identifier : public tree_expression
 {
   friend class tree_index_expression;
 
 public:
 
   tree_identifier (int l = -1, int c = -1)
-    : tree_multi_val_ret (l, c), sym (0), maybe_do_ans_assign (false) { }
+    : tree_expression (l, c), sym (0) { }
 
   tree_identifier (symbol_record *s, int l = -1, int c = -1)
-    : tree_multi_val_ret (l, c), sym (s), maybe_do_ans_assign (false) { }
+    : tree_expression (l, c), sym (s) { }
 
   ~tree_identifier (void) { }
 
@@ -69,8 +68,10 @@
 
   bool is_defined (void);
 
-  octave_symbol *do_lookup (bool& script_file_executed, bool
-			    exec_script = true);
+  bool is_function (void);
+
+  octave_value
+  do_lookup (bool& script_file_executed, bool exec_script = true);
 
   void link_to_global (void);
 
@@ -78,30 +79,20 @@
 
   void mark_as_formal_parameter (void);
 
-  void mark_for_possible_ans_assign (void)
-    { maybe_do_ans_assign = true; }
+  octave_value rvalue (void);
 
-  octave_value eval (bool print = false);
+  octave_value_list rvalue (int nargout);
 
-  octave_value_list
-  eval (bool print, int nargout, const octave_value_list& args);
+  octave_variable_reference lvalue (void);
 
   void eval_undefined_error (void);
 
   void accept (tree_walker& tw);
 
-  octave_value value (void) const;
-
-  octave_variable_reference reference (void);
-
 private:
 
   // The symbol record that this identifier references.
   symbol_record *sym;
-
-  // True if we should consider assigning the result of evaluating
-  // this identifier to the built-in variable ans.
-  bool maybe_do_ans_assign;
 };
 
 #endif
--- a/src/pt-indir.cc
+++ b/src/pt-indir.cc
@@ -32,7 +32,6 @@
 #include "gripes.h"
 #include "oct-map.h"
 #include "oct-obj.h"
-#include "oct-sym.h"
 #include "oct-var-ref.h"
 #include "pager.h"
 #include "pt-const.h"
@@ -47,126 +46,72 @@
 
 tree_indirect_ref::~tree_indirect_ref (void)
 {
-  if (! preserve_ident)
-    delete id;
-
-  if (! preserve_indir)
-    delete indir;
-}
-
-void
-tree_indirect_ref::mark_for_possible_ans_assign (void)
-{
-  maybe_do_ans_assign = true;
-
-  if (is_identifier_only ())
-    id->mark_for_possible_ans_assign ();
+  delete expr;
 }
 
 string
 tree_indirect_ref::name (void) const
 {
-  string retval;
+  return expr->name () + "." + nm;
+}
 
-  if (is_identifier_only ())
-    retval = id->name ();
+octave_value_list
+tree_indirect_ref::rvalue (int nargout)
+{
+  octave_value_list retval;
+
+  if (nargout > 1)
+    error ("%s, %s", __FILE__, __LINE__);
   else
     {
-      if (id)
-	retval = id->name ();
-      else if (indir)
-	retval = indir->name ();
-      else
-	panic_impossible ();
-
-      retval.append (".");
-      retval.append (nm);
-    }
-	
-  return retval;
-}
+      octave_value_list tmp = expr->rvalue (nargout);
 
-octave_value
-tree_indirect_ref::eval (bool print)
-{
-  octave_value retval;
+      if (tmp.empty ())
+	error ("%s, %s", __FILE__, __LINE__);
+      else
+	{
+	  octave_value val = tmp(0).do_struct_elt_index_op (nm);
 
-  if (is_identifier_only ())
-    retval = id->eval (print);
-  else
-    {
-      octave_variable_reference tmp = reference ();
+	  if (print_result () && nargout == 0 && val.is_defined ())
+	    val.print_with_name (octave_stdout, name ());
 
-      if (! (error_state || tmp.is_undefined ()))
-	{
-	  retval = tmp.value ();
-
-	  if (! error_state && maybe_do_ans_assign && retval.is_defined ())
-	    bind_ans (retval, print);
+	  retval = val;
 	}
     }
 
   return retval;
 }
 
-octave_value_list
-tree_indirect_ref::eval (bool print, int nargout,
-			 const octave_value_list& args)
+octave_value
+tree_indirect_ref::rvalue (void)
 {
-  octave_value_list retval;
-
-  if (is_identifier_only ())
-    retval = id->eval (print, nargout, args);
-  else
-    {
-      octave_variable_reference tmp = reference ();
+  octave_value retval;
 
-      if (! (error_state || tmp.is_undefined ()))
-	{
-	  tmp.index (args);
-
-	  retval = tmp.value ();
+  octave_value_list tmp = rvalue (1);
 
-	  if (! error_state && maybe_do_ans_assign && nargout == 1
-	      && retval.length () > 0 && retval(0).is_defined ())
-	    {
-	      bind_ans (retval(0), print);
-	    }
-	}
-    }
+  if (! tmp.empty ())
+    retval = tmp(0);
 
   return retval;
 }
 
+octave_variable_reference
+tree_indirect_ref::lvalue (void)
+{
+  octave_variable_reference tmp = expr->lvalue ();
+
+  if (tmp.is_undefined () || ! tmp.is_map ())
+    tmp.define (Octave_map ());
+
+  return tmp.struct_elt_ref (nm);
+}
+
 void
 tree_indirect_ref::accept (tree_walker& tw)
 {
   tw.visit_indirect_ref (*this);
 }
 
-octave_variable_reference
-tree_indirect_ref::reference (void)
-{
-  if (is_identifier_only ())
-    return id->reference ();
-  else
-    {
-      octave_variable_reference tmp;
-
-      if (id)
-	tmp = id->reference ();
-      else if (indir)
-	tmp = indir->reference ();
-      else
-	panic_impossible ();
-
-      if (tmp.is_undefined ())
-	tmp.define (Octave_map ());
-
-      return tmp.struct_elt_ref (nm);
-    }
-}
-
 /*
 ;;; Local Variables: ***
 ;;; mode: C++ ***
--- a/src/pt-indir.h
+++ b/src/pt-indir.h
@@ -33,64 +33,42 @@
 
 class octave_value;
 class octave_value_list;
-class tree_identifier;
 class tree_walker;
 
-#include "pt-mvr-base.h"
+#include "pt-exp-base.h"
 
 // Indirect references to values (structure references).
 
 class
-tree_indirect_ref : public tree_multi_val_ret
+tree_indirect_ref : public tree_expression
 {
 public:
 
   tree_indirect_ref (int l = -1, int c = -1)
-    : tree_multi_val_ret (l, c), id (0), indir (0), nm (),
-      preserve_ident (false), preserve_indir (false),
-      maybe_do_ans_assign (false) { }
+    : tree_expression (l, c), expr (0), nm () { }
 
-  tree_indirect_ref (tree_identifier *i, int l = -1, int c = -1)
-    : tree_multi_val_ret (l, c), id (i), indir (0), nm (),
-      preserve_ident (false), preserve_indir (false),
-      maybe_do_ans_assign (false) { }
-
-  tree_indirect_ref (tree_indirect_ref *i, const string& n,
+  tree_indirect_ref (tree_expression *e, const string& n,
 		     int l = -1, int c = -1)
-    : tree_multi_val_ret (l, c), id (0), indir (i), nm (n),
-      preserve_ident (false), preserve_indir (false),
-      maybe_do_ans_assign (false) { }
+    : tree_expression (l, c), expr (e), nm (n) { }
 
   ~tree_indirect_ref (void);
 
   bool is_indirect_ref (void) const
     { return true; }
 
-  bool is_identifier_only (void) const
-    { return (id && nm.empty ()); }
-
-  tree_identifier *ident (void)
-    { return id; }
-
-  tree_indirect_ref *indirect (void)
-    { return indir; }
-
-  void preserve_identifier (void)
-    { preserve_ident = true; }
-
-  void preserve_indirect (void)
-    { preserve_indir = true; }
-
-  void mark_for_possible_ans_assign (void);
-
   string name (void) const;
 
-  octave_value eval (bool print = false);
+  bool rvalue_ok (void) const
+    { return true; }
+
+  octave_value rvalue (void);
 
-  octave_value_list
-  eval (bool print, int nargout, const octave_value_list& args);
+  octave_value_list rvalue (int nargout);
 
-  octave_variable_reference reference (void);
+  octave_variable_reference lvalue (void);
+
+  tree_expression *expression (void)
+    { return expr; }
 
   string elt_name (void)
     { return nm; }
@@ -99,25 +77,11 @@
 
 private:
 
-  // The identifier for this structure reference.  For example, in
-  // a.b.c, a is the id.
-  tree_identifier *id;
-
-  // This element just points to another indirect reference.
-  tree_indirect_ref *indir;
+  // The LHS of this structure reference.
+  tree_expression *expr;
 
   // The sub-element name.
   string nm;
-
-  // True if we should not delete the identifier.
-  bool preserve_ident;
-
-  // True if we should not delete the indirect reference.
-  bool preserve_indir;
-
-  // True if we should consider assigning the result of evaluating
-  // this identifier to the built-in variable ans.
-  bool maybe_do_ans_assign;
 };
 
 #endif
--- a/src/pt-mat.cc
+++ b/src/pt-mat.cc
@@ -37,7 +37,6 @@
 #include "pt-exp.h"
 #include "pt-mat.h"
 #include "pt-misc.h"
-#include "pt-mvr.h"
 #include "pt-walk.h"
 #include "utils.h"
 #include "ov.h"
@@ -72,10 +71,10 @@
       : SLList<octave_value> (), count (1), nr (0), nc (0),
 	all_str (false), is_cmplx (false), all_mt (true), ok (false) { }
 
-    tm_row_const_rep (const tree_matrix_row& mr)
+    tm_row_const_rep (const tree_argument_list& row)
       : SLList<octave_value> (), count (1), nr (0), nc (0),
 	all_str (false), is_cmplx (false), all_mt (true), ok (false)
-        { init (mr); }
+        { init (row); }
 
     ~tm_row_const_rep (void) { }
 
@@ -90,15 +89,13 @@
 
     bool ok;
 
-    void init (const tree_matrix_row&);
+    void init (const tree_argument_list&);
 
   private:
 
     tm_row_const_rep (const tm_row_const_rep&);
 
-    tm_row_const_rep& operator =
-      (const tm_row_const_rep&);
-
+    tm_row_const_rep& operator = (const tm_row_const_rep&);
 
     void eval_error (const char *msg, int l, int c) const;
 
@@ -109,8 +106,8 @@
 
   tm_row_const (void) : rep (0) { }
 
-  tm_row_const (const tree_matrix_row& mr)
-    : rep (new tm_row_const_rep (mr)) { }
+  tm_row_const (const tree_argument_list& row)
+    : rep (new tm_row_const_rep (row)) { }
 
   tm_row_const (const tm_row_const& x) : rep (x.rep)
     {
@@ -167,17 +164,17 @@
 };
 
 void
-tm_row_const::tm_row_const_rep::init (const tree_matrix_row& mr)
+tm_row_const::tm_row_const_rep::init (const tree_argument_list& row)
 {
   all_str = true;
 
   bool first_elem = true;
 
-  for (Pix p = mr.first (); p != 0; mr.next (p))
+  for (Pix p = row.first (); p != 0; row.next (p))
     {
-      tree_expression *elt = mr (p);
+      tree_expression *elt = row (p);
 
-      octave_value tmp = elt->eval ();
+      octave_value tmp = elt->rvalue ();
 
       if (error_state || tmp.is_undefined ())
 	break;
@@ -313,7 +310,7 @@
 
   for (Pix p = tm.first (); p != 0; tm.next (p))
     {
-      tree_matrix_row *elt = tm (p);
+      tree_argument_list *elt = tm (p);
 
       tm_row_const tmp (*elt);
 
@@ -383,78 +380,11 @@
 }
 
 bool
-tree_matrix_row::all_elements_are_constant (void) const
-{
-  for (Pix p = first (); p != 0; next (p))
-    {
-      tree_expression *elt = this->operator () (p);
-
-      if (! elt->is_constant ())
-	return false;
-    }
-
-  return true;
-}
-
-tree_return_list *
-tree_matrix_row::to_return_list (void)
-{
-  tree_return_list *retval = 0;
-
-  bool first_elem = true;
-
-  for (Pix p = first (); p != 0; next (p))
-    {
-      tree_expression *elt = this->operator () (p);
-
-      bool is_id = elt->is_identifier ();
-
-      bool is_idx_expr = elt->is_index_expression ();
-
-      if (is_id || is_idx_expr)
-	{
-	  tree_index_expression *idx_expr;
-
-	  if (is_id)
-	    {
-	      tree_identifier *id = static_cast<tree_identifier *> (elt);
-	      idx_expr = new tree_index_expression (id);
-	    }
-	  else
-	    idx_expr = static_cast<tree_index_expression *> (elt);
-
-	  if (first_elem)
-	    {
-	      first_elem = false;
-
-	      retval = new tree_return_list (idx_expr);
-	    }
-	  else
-	    retval->append (idx_expr);
-	}
-      else
-	{
-	  delete retval;
-	  retval = 0;
-	  break;
-	}
-    }
-
-  return retval;
-}
-
-void
-tree_matrix_row::accept (tree_walker& tw)
-{
-  tw.visit_matrix_row (*this);
-}
-
-bool
 tree_matrix::all_elements_are_constant (void) const
 {
   for (Pix p = first (); p != 0; next (p))
     {
-      tree_matrix_row *elt = this->operator () (p);
+      tree_argument_list *elt = this->operator () (p);
 
       if (! elt->all_elements_are_constant ())
 	return false;
@@ -467,8 +397,21 @@
 // Less ugly than before, anyway.
 // Looking better all the time.
 
+octave_value_list
+tree_matrix::rvalue (int nargout)
+{
+  octave_value_list retval;
+
+  if (nargout > 1)
+    error ("invalid number of output arguments for matrix list");
+  else
+    retval = rvalue ();
+
+  return retval;
+}
+
 octave_value
-tree_matrix::eval (bool /* print */)
+tree_matrix::rvalue (void)
 {
   octave_value retval;
 
--- a/src/pt-mat.h
+++ b/src/pt-mat.h
@@ -42,42 +42,27 @@
 // other matrices, variables, and functions.
 
 class
-tree_matrix_row : public SLList<tree_expression *>
+tree_matrix : public tree_expression, public SLList<tree_argument_list *>
 {
 public:
 
-  tree_matrix_row (tree_expression *e = 0) : SLList<tree_expression *> ()
-    {
-      if (e)
-	append (e);
-    }
-
-  ~tree_matrix_row (void) { }
-
-  bool all_elements_are_constant (void) const;
-
-  tree_return_list *to_return_list (void);
-
-  void accept (tree_walker& tw);
-};
-
-class
-tree_matrix : public tree_expression, public SLList<tree_matrix_row *>
-{
-public:
-
-  tree_matrix (tree_matrix_row *mr = 0)
-    : tree_expression (), SLList<tree_matrix_row *> ()
+  tree_matrix (tree_argument_list *row = 0)
+    : tree_expression (), SLList<tree_argument_list *> ()
       {
-	if (mr)
-	  append (mr);
+	if (row)
+	  append (row);
       }
 
   ~tree_matrix (void) { }
 
   bool all_elements_are_constant (void) const;
 
-  octave_value eval (bool print = false);
+  bool rvalue_ok (void) const
+    { return true; }
+
+  octave_value rvalue (void);
+
+  octave_value_list rvalue (int nargout);
 
   void accept (tree_walker& tw);
 };