changeset 3204:81738e630f57

[project @ 1998-10-30 23:28:29 by jwe]
author jwe
date Fri, 30 Oct 1998 23:28:30 +0000
parents bc61b0e8d60e
children 549691faa638
files src/ChangeLog src/data.cc src/lex.l src/ov-list.cc src/ov.cc src/ov.h src/parse.y
diffstat 7 files changed, 211 insertions(+), 15 deletions(-) [+]
line wrap: on
line diff
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,5 +1,15 @@
 Fri Oct 30 08:39:30 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>
 
+	* parse.y (LEFTDIV_EQ, ELEFTDIV_EQ): New tokens.
+	(assign_expr): Add rules for them.
+	(make_assign_op): Handle them here too.
+	* lex.l: Recognize them.
+	* ov.h (octave_value::assign_op): Add ldiv_eq and el_ldiv_eq.
+	* ov.cc (octave_value::assign_op_as_string): Ditto.
+	(octave_value::op_eq_to_binary_op): Ditto.
+	(octave_value::assign): Handle OP= style operators with brute force.
+	(octave_value::simple_assign): New function.
+
 	* parse.y (matrix): Dont' forget to reset
 	lexer_flags.looking_at_matrix_or_assign_lhs.
 
--- a/src/data.cc
+++ b/src/data.cc
@@ -786,6 +786,19 @@
   return retval;
 }
 
+DEFUN (is_list, args, ,
+  "is_list (x): return nonzero if x is a list")
+{
+  octave_value retval;
+
+  if (args.length () == 1)
+    retval = args(0).is_list () ? 1.0 : 0.0;
+  else
+    print_usage ("is_list");
+
+  return retval;
+}
+
 DEFUN (is_matrix, args, ,
   "is_matrix (x): return nonzero if x can be considered a matrix")
 {
--- a/src/lex.l
+++ b/src/lex.l
@@ -629,10 +629,12 @@
 "-="	{ BIN_OP_RETURN (SUB_EQ, false); }
 "*="	{ BIN_OP_RETURN (MUL_EQ, false); }
 "/="	{ BIN_OP_RETURN (DIV_EQ, false); }
+"\\="	{ BIN_OP_RETURN (LEFTDIV_EQ, false); }
 ".+="	{ BIN_OP_RETURN (ADD_EQ, false); }
 ".-="	{ BIN_OP_RETURN (SUB_EQ, false); }
 ".*="	{ BIN_OP_RETURN (EMUL_EQ, false); }
 "./="	{ BIN_OP_RETURN (EDIV_EQ, false); }
+".\\="	{ BIN_OP_RETURN (ELEFTDIV_EQ, false); }
 "&="	{ BIN_OP_RETURN (AND_EQ, false); }
 "|="	{ BIN_OP_RETURN (OR_EQ, false); }
 "<<="	{ BIN_OP_RETURN (LSHIFT_EQ, false); }
--- a/src/ov-list.cc
+++ b/src/ov-list.cc
@@ -221,8 +221,9 @@
 splice (LIST_1, OFFSET, LENGTH)\n\
 splice (LIST_1, OFFSET)\n\
 \n\
-Replace LENGTH elements of LIST_1 beginning at OFFSET with the
-contents of LIST_2 (if any).  If LENGTH is omitted, ")
+Replace LENGTH elements of LIST_1 beginning at OFFSET with the\n\
+contents of LIST_2 (if any).  If LENGTH is omitted, all elements\n\
+from OFFSET to the end of LIST_1 are replaced.")
 {
   octave_value retval;
 
--- a/src/ov.cc
+++ b/src/ov.cc
@@ -284,6 +284,10 @@
       retval = "/=";
       break;
 
+    case ldiv_eq:
+      retval = "\\=";
+      break;
+
     case lshift_eq:
       retval = "<<=";
       break;
@@ -300,6 +304,10 @@
       retval = "./=";
       break;
 
+    case el_ldiv_eq:
+      retval = ".\\=";
+      break;
+
     case el_and_eq:
       retval = "&=";
       break;
@@ -547,17 +555,64 @@
 	 on.c_str (), tn2.c_str (), tn1.c_str ());
 }
 
+static void
+gripe_assign_failed (const string& on, const string& tn1, const string& tn2)
+{
+  error ("assignment failed for `%s %s %s'",
+	 tn1.c_str (), on.c_str (), tn2.c_str ());
+}
+
+static void
+gripe_assign_failed_or_no_method (const string& on, const string& tn1,
+				  const string& tn2)
+{
+  error ("assignment failed, or no method for `%s %s %s'",
+	 tn1.c_str (), on.c_str (), tn2.c_str ());
+}
+
 void
 octave_value::assign (assign_op op, const octave_value& rhs)
 {
-  // XXX FIXME XXX -- make this work for ops other than `='.
-
   if (op == asn_eq)
     operator = (rhs);
   else
     {
-      string on = assign_op_as_string (op);
-      error ("operator `%s' not supported yet", on.c_str ());
+      // XXX FIXME XXX -- only do the following stuff if we can't find
+      // a specific function to call to handle the op= operation for
+      // the types we have.
+
+      binary_op binop = op_eq_to_binary_op (op);
+
+      if (! error_state)
+	{
+	  octave_value t = do_binary_op (binop, *this, rhs);
+
+	  if (! error_state)
+	    operator = (t);
+	}
+
+      if (error_state)
+	gripe_assign_failed_or_no_method (assign_op_as_string (op),
+					  type_name (), rhs.type_name ());
+    }
+}
+
+void
+octave_value::simple_assign (octave_value::assign_op orig_op,
+			     const octave_value_list& idx,
+			     const octave_value& rhs)
+{
+  make_unique ();
+
+  bool assignment_ok = try_assignment (asn_eq, idx, rhs);
+
+  if (! (error_state || assignment_ok))
+    {
+      assignment_ok = try_assignment_with_conversion (asn_eq, idx, rhs);
+
+      if (! (error_state || assignment_ok))
+	gripe_no_conversion (assign_op_as_string (orig_op),
+			     type_name (), rhs.type_name ());
     }
 }
 
@@ -568,16 +623,46 @@
 {
   if (Vresize_on_range_error || is_defined ())
     {
-      make_unique ();
+      if (op == asn_eq)
+	simple_assign (op, idx, rhs);
+      else
+	{
+	  // XXX FIXME XXX -- only do the following stuff if we can't
+	  // find a specific function to call to handle the op=
+	  // operation for the types we have.
+
+	  octave_value t1 = *this;
 
-      bool assignment_ok = try_assignment (op, idx, rhs);
+	  t1 = t1.do_index_op (idx);
+
+	  if (! error_state)
+	    {
+	      binary_op binop = op_eq_to_binary_op (op);
+
+	      if (! error_state)
+		{
+		  octave_value t2 = do_binary_op (binop, t1, rhs);
 
-      if (! (error_state || assignment_ok))
-	{
-	  assignment_ok = try_assignment_with_conversion (op, idx, rhs);
+		  if (! error_state)
+		    {
+		      simple_assign (op, idx, t2);
 
-	  if (! (error_state || assignment_ok))
-	    gripe_no_conversion (assign_op_as_string (op),
+		      if (error_state)
+			gripe_assign_failed (assign_op_as_string (op),
+					     type_name (), rhs.type_name ());
+		    }
+		  else
+		    gripe_assign_failed_or_no_method (assign_op_as_string (op),
+						      type_name (),
+						      rhs.type_name ());
+		}
+	      else
+		gripe_assign_failed_or_no_method (assign_op_as_string (op),
+						  type_name (),
+						  rhs.type_name ());
+	    }
+	  else
+	    gripe_assign_failed (assign_op_as_string (op),
 				 type_name (), rhs.type_name ());
 	}
 
@@ -1190,6 +1275,71 @@
   curr_print_indent_level = 0;
 }
 
+octave_value::binary_op 
+octave_value::op_eq_to_binary_op (assign_op op)
+{
+  binary_op binop = unknown_binary_op;
+
+  switch (op)
+    {
+    case add_eq:
+      binop = add;
+      break;
+
+    case sub_eq:
+      binop = sub;
+      break;
+
+    case mul_eq:
+      binop = mul;
+      break;
+
+    case div_eq:
+      binop = div;
+      break;
+
+    case ldiv_eq:
+      binop = ldiv;
+      break;
+
+    case lshift_eq:
+      binop = lshift;
+      break;
+
+    case rshift_eq:
+      binop = rshift;
+      break;
+
+    case el_mul_eq:
+      binop = el_mul;
+      break;
+
+    case el_div_eq:
+      binop = el_div;
+      break;
+
+    case el_ldiv_eq:
+      binop = el_ldiv;
+      break;
+
+    case el_and_eq:
+      binop = el_and;
+      break;
+
+    case el_or_eq:
+      binop = el_or;
+      break;
+
+    default:
+      {
+	string on = assign_op_as_string (op);
+	error ("operator %s: no binary operator found", on.c_str ());
+      }
+    }
+
+  return binop;
+}
+
 void
 install_types (void)
 {
--- a/src/ov.h
+++ b/src/ov.h
@@ -129,10 +129,12 @@
     sub_eq,
     mul_eq,
     div_eq,
+    ldiv_eq,
     lshift_eq,
     rshift_eq,
     el_mul_eq,
     el_div_eq,
+    el_ldiv_eq,
     el_and_eq,
     el_or_eq,
     num_assign_ops,
@@ -517,6 +519,11 @@
 
   static int curr_print_indent_level;
   static bool beginning_of_line;
+
+  binary_op op_eq_to_binary_op (assign_op op);
+
+  void simple_assign (assign_op orig_op, const octave_value_list& idx,
+		      const octave_value& rhs);
 };
 
 #define OV_UNOP_FN(name) \
--- a/src/parse.y
+++ b/src/parse.y
@@ -331,7 +331,8 @@
 
 // Tokens with line and column information.
 %token <tok_val> '=' ':' '-' '+' '*' '/'
-%token <tok_val> ADD_EQ SUB_EQ MUL_EQ DIV_EQ EMUL_EQ EDIV_EQ AND_EQ OR_EQ
+%token <tok_val> ADD_EQ SUB_EQ MUL_EQ DIV_EQ LEFTDIV_EQ 
+%token <tok_val> EMUL_EQ EDIV_EQ ELEFTDIV_EQ AND_EQ OR_EQ
 %token <tok_val> LSHIFT_EQ RSHIFT_EQ LSHIFT RSHIFT
 %token <tok_val> EXPR_AND_AND EXPR_OR_OR
 %token <tok_val> EXPR_AND EXPR_OR EXPR_NOT
@@ -398,7 +399,7 @@
 
 // Precedence and associativity.
 %left ';' ',' '\n'
-%right '=' ADD_EQ SUB_EQ MUL_EQ DIV_EQ EMUL_EQ EDIV_EQ OR_EQ AND_EQ LSHIFT_EQ RSHIFT_EQ
+%right '=' ADD_EQ SUB_EQ MUL_EQ DIV_EQ LEFTDIV_EQ EMUL_EQ EDIV_EQ ELEFTDIV_EQ OR_EQ AND_EQ LSHIFT_EQ RSHIFT_EQ
 %left EXPR_AND_AND EXPR_OR_OR
 %left EXPR_AND EXPR_OR
 %left EXPR_LT EXPR_LE EXPR_EQ EXPR_NE EXPR_GE EXPR_GT
@@ -732,6 +733,8 @@
 		  { $$ = make_assign_op (MUL_EQ, $1, $2, $3); }
 		| assign_lhs DIV_EQ expression
 		  { $$ = make_assign_op (DIV_EQ, $1, $2, $3); }
+		| assign_lhs LEFTDIV_EQ expression
+		  { $$ = make_assign_op (LEFTDIV_EQ, $1, $2, $3); }
 		| assign_lhs LSHIFT_EQ expression
 		  { $$ = make_assign_op (LSHIFT_EQ, $1, $2, $3); }
 		| assign_lhs RSHIFT_EQ expression
@@ -740,6 +743,8 @@
 		  { $$ = make_assign_op (EMUL_EQ, $1, $2, $3); }
 		| assign_lhs EDIV_EQ expression
 		  { $$ = make_assign_op (EDIV_EQ, $1, $2, $3); }
+		| assign_lhs ELEFTDIV_EQ expression
+		  { $$ = make_assign_op (ELEFTDIV_EQ, $1, $2, $3); }
 		| assign_lhs AND_EQ expression
 		  { $$ = make_assign_op (AND_EQ, $1, $2, $3); }
 		| assign_lhs OR_EQ expression
@@ -2164,6 +2169,10 @@
       t = octave_value::div_eq;
       break;
 
+    case LEFTDIV_EQ:
+      t = octave_value::ldiv_eq;
+      break;
+
     case LSHIFT_EQ:
       t = octave_value::lshift_eq;
       break;
@@ -2180,6 +2189,10 @@
       t = octave_value::el_div_eq;
       break;
 
+    case ELEFTDIV_EQ:
+      t = octave_value::el_ldiv_eq;
+      break;
+
     case AND_EQ:
       t = octave_value::el_and_eq;
       break;