diff libinterp/parse-tree/pt-idx.cc @ 20574:dd6345fd8a97

use exceptions for better invalid index error reporting (bug #45957) * lo-array-gripes.h, lo-array-gripes.cc (index_exception): New base class for indexing errors. (invalid_index, out_of_range): New classes. (gripe_index_out_of_range): New overloaded function. (gripe_invalid_index): New overloaded functions. Delete version with no arguments. (gripe_invalid_assignment_size, gripe_assignment_dimension_mismatch): Delete. Change uses of gripe functions as needed. * Cell.cc (Cell::index, Cell::assign, Cell::delete_elements): Use exceptions to collect error info about and handle indexing errors. * data.cc (Fnth_element, do_accumarray_sum, F__accumarray_sum__, do_accumarray_minmax, do_accumarray_minmax_fun, F__accumdim_sum__): Likewise. * oct-map.cc (octave_map::index, octave_map::assign, octave_map::delete_elements): Likewise. * sparse.cc (Fsparse): Likewise. * sub2ind.cc (Fsub2ind, Find2sub): Likewise. New tests. * utils.cc (dims_to_numel): Likewise. * ov-base-diag.cc (octave_base_diag<DMT, MT>::do_index_op, octave_base_diag<DMT, MT>::subsasgn): Likewise. * ov-base-mat.cc (octave_base_matrix<MT>::subsref, octave_base_matrix<MT>::assign): Likewise. * ov-base-sparse.cc (octave_base_sparse<T>::do_index_op, octave_base_sparse<T>::assign, octave_base_sparse<MT>::delete_elements): Likewise. * ov-classdef.cc (cdef_object_array::subsref, cdef_object_array::subsasgn): Likewise. * ov-java.cc (make_java_index): Likewise. * ov-perm.cc (octave_perm_matrix::do_index_op): Likewise. * ov-range.cc (octave_range::do_index_op): Likewise. * ov-re-diag.cc (octave_diag_matrix::do_index_op): Likewise. * ov-str-mat.cc (octave_char_matrix_str::do_index_op_internal): Likewise. * pt-assign.cc (tree_simple_assignment::rvalue1): Likewise. * pt-idx.cc (tree_index_expression::rvalue, tree_index_expression::lvalue): Likewise. * Array-util.cc (sub2ind): Likewise. * toplev.cc (main_loop): Also catch unhandled index_exception exceptions. * ov-base.cc (octave_base_value::index_vector): Improve error message. * ov-re-sparse.cc (octave_sparse_matrix::index_vector): Likewise. * ov-complex.cc (complex_index): New class. (gripe_complex_index): New function. (octave_complex::index_vector): Use it. * pt-id.h, pt-id.cc (tree_identifier::is_variable, tree_black_hole::is_variable): Now const. * pt-idx.cc (final_index_error): New static function. (tree_index_expression::rvalue, tree_index_expression::lvalue): Use it. * index.tst: New tests.
author Lachlan Andrew <lachlanbis@gmail.com>
date Fri, 02 Oct 2015 15:07:37 -0400
parents 4197fc428c7d
children 1a0a433c8263
line wrap: on
line diff
--- a/libinterp/parse-tree/pt-idx.cc	Fri Oct 02 12:25:39 2015 -0400
+++ b/libinterp/parse-tree/pt-idx.cc	Fri Oct 02 15:07:37 2015 -0400
@@ -284,6 +284,20 @@
   return tree_index_expression::rvalue (nargout, 0);
 }
 
+// Final step of processing an indexing error.  Add the name of the
+// variable being indexed, if any, then issue an error.  (Will this also
+// be needed by pt-lvalue, which calls subsref?)
+
+static void
+final_index_error (index_exception& e, const tree_expression *expr)
+{
+  if (expr->is_identifier ()
+      && dynamic_cast<const tree_identifier *> (expr)->is_variable ())
+    e.set_var (expr->name ());
+
+  (*current_liboctave_error_with_id_handler) (e.id (), e.err ());
+}
+
 octave_value_list
 tree_index_expression::rvalue (int nargout,
                                const std::list<octave_lvalue> *lvalue_list)
@@ -353,7 +367,7 @@
 
               if (force_split || (al && al->has_magic_end ()))
                 {
-                  // We have an expression like
+                  // (we have force_split, or) we have an expression like
                   //
                   //   x{end}.a(end)
                   //
@@ -363,38 +377,45 @@
                   // that argument list so we can pass the appropriate
                   // value to the built-in end function.
 
-                  octave_value_list tmp_list
-                    = tmp.subsref (type.substr (tmpi, i - tmpi), idx, nargout);
-
-                  tmp = tmp_list.length () ? tmp_list(0) : octave_value ();
-                  tmpi = i;
-                  idx.clear ();
-
-                  if (tmp.is_cs_list ())
-                    gripe_indexed_cs_list ();
-
-                  if (error_state)
-                    break;
-
-                  if (tmp.is_function ())
+                  try
                     {
-                      octave_function *fcn = tmp.function_value (true);
+                      octave_value_list tmp_list
+                        =tmp.subsref (type.substr (tmpi, i-tmpi), idx, nargout);
+
+                      tmp = tmp_list.length () ? tmp_list(0) : octave_value ();
+                      tmpi = i;
+                      idx.clear ();
 
-                      if (fcn && ! fcn->is_postfix_index_handled (type[i]))
+                      if (tmp.is_cs_list ())
+                        gripe_indexed_cs_list ();
+
+                      if (error_state)
+                        break;
+
+                      if (tmp.is_function ())
                         {
-                          octave_value_list empty_args;
+                          octave_function *fcn = tmp.function_value (true);
 
-                          tmp_list = tmp.do_multi_index_op (1, empty_args);
-                          tmp = (tmp_list.length ()
-                                 ? tmp_list(0) : octave_value ());
+                          if (fcn && ! fcn->is_postfix_index_handled (type[i]))
+                            {
+                              octave_value_list empty_args;
+
+                              tmp_list = tmp.do_multi_index_op (1, empty_args);
+                              tmp = (tmp_list.length ()
+                                     ? tmp_list(0) : octave_value ());
 
-                          if (tmp.is_cs_list ())
-                            gripe_indexed_cs_list ();
+                              if (tmp.is_cs_list ())
+                                gripe_indexed_cs_list ();
 
-                          if (error_state)
-                            break;
+                              if (error_state)
+                                break;
+                            }
                         }
                     }
+                  catch (index_exception& e)  // problems with index range, type etc.
+                    {
+                      final_index_error (e, expr);
+                    }
                 }
             }
 
@@ -433,8 +454,15 @@
 
       if (! error_state)
         {
-          retval = tmp.subsref (type.substr (tmpi, n - tmpi), idx, nargout,
-                                lvalue_list);
+          try
+            {
+              retval = tmp.subsref (type.substr (tmpi, n - tmpi), idx, nargout,
+                                    lvalue_list);
+            }
+          catch (index_exception& e)    // problems with range, invalid index type etc.
+            {
+              final_index_error (e, expr);
+            }
 
           octave_value val = retval.length () ? retval(0) : octave_value ();
 
@@ -500,7 +528,14 @@
             gripe_indexed_cs_list ();
           else if (tmpi < i)
             {
-              tmp = tmp.subsref (type.substr (tmpi, i - tmpi), tmpidx, true);
+              try
+                {
+                  tmp = tmp.subsref (type.substr (tmpi, i-tmpi), tmpidx, true);
+                }
+              catch (index_exception& e)  // problems with range, invalid type etc.
+                {
+                  final_index_error (e, expr);
+                }
               tmpidx.clear ();
             }