comparison libinterp/corefcn/oct-map.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 a9574e3c6e9e
children 1a0a433c8263
comparison
equal deleted inserted replaced
20573:e3c0fee87493 20574:dd6345fd8a97
898 octave_map::index (const octave_value_list& idx, bool resize_ok) const 898 octave_map::index (const octave_value_list& idx, bool resize_ok) const
899 { 899 {
900 octave_idx_type n_idx = idx.length (); 900 octave_idx_type n_idx = idx.length ();
901 octave_map retval; 901 octave_map retval;
902 902
903 switch (n_idx) 903 // If we catch an indexing error in index_vector, we flag an error in
904 { 904 // index k. Ensure it is the right value befor each idx_vector call.
905 case 1: 905 // Same variable as used in the for loop in the default case.
906 { 906
907 idx_vector i = idx(0).index_vector (); 907 octave_idx_type k = 0;
908 908
909 if (! error_state) 909 try
910 retval = index (i, resize_ok); 910 {
911 } 911 switch (n_idx)
912 break; 912 {
913 913 case 1:
914 case 2:
915 {
916 idx_vector i = idx(0).index_vector ();
917
918 if (! error_state)
919 { 914 {
920 idx_vector j = idx(1).index_vector (); 915 idx_vector i = idx(0).index_vector ();
921 916
922 retval = index (i, j, resize_ok); 917 if (! error_state)
918 retval = index (i, resize_ok);
923 } 919 }
924 } 920 break;
925 break; 921
926 922 case 2:
927 default:
928 {
929 Array<idx_vector> ia (dim_vector (n_idx, 1));
930
931 for (octave_idx_type i = 0; i < n_idx; i++)
932 { 923 {
933 ia(i) = idx(i).index_vector (); 924 idx_vector i = idx(0).index_vector ();
934 925
935 if (error_state) 926 if (! error_state)
936 break; 927 {
928 k = 1;
929 idx_vector j = idx(1).index_vector ();
930
931 retval = index (i, j, resize_ok);
932 }
937 } 933 }
938 934 break;
939 if (! error_state) 935
940 retval = index (ia, resize_ok); 936 default:
941 } 937 {
942 break; 938 Array<idx_vector> ia (dim_vector (n_idx, 1));
939
940 for (k = 0; k < n_idx; k++)
941 {
942 ia(k) = idx(k).index_vector ();
943
944 if (error_state)
945 break;
946 }
947
948 if (! error_state)
949 retval = index (ia, resize_ok);
950 }
951 break;
952 }
953 }
954 catch (index_exception& e)
955 {
956 // Rethrow to allow more info to be reported later.
957 e.set_pos_if_unset (n_idx, k+1);
958 throw;
943 } 959 }
944 960
945 return retval; 961 return retval;
946 } 962 }
947 963
1092 void 1108 void
1093 octave_map::assign (const octave_value_list& idx, const octave_map& rhs) 1109 octave_map::assign (const octave_value_list& idx, const octave_map& rhs)
1094 { 1110 {
1095 octave_idx_type n_idx = idx.length (); 1111 octave_idx_type n_idx = idx.length ();
1096 1112
1097 switch (n_idx) 1113 // If we catch an indexing error in index_vector, we flag an error in
1098 { 1114 // index k. Ensure it is the right value befor each idx_vector call.
1099 case 1: 1115 // Same variable as used in the for loop in the default case.
1100 { 1116
1101 idx_vector i = idx(0).index_vector (); 1117 octave_idx_type k = 0;
1102 1118
1103 if (! error_state) 1119 try
1104 assign (i, rhs); 1120 {
1105 } 1121 switch (n_idx)
1106 break; 1122 {
1107 1123 case 1:
1108 case 2:
1109 {
1110 idx_vector i = idx(0).index_vector ();
1111
1112 if (! error_state)
1113 { 1124 {
1114 idx_vector j = idx(1).index_vector (); 1125 idx_vector i = idx(0).index_vector ();
1115 1126
1116 assign (i, j, rhs); 1127 if (! error_state)
1128 assign (i, rhs);
1117 } 1129 }
1118 } 1130 break;
1119 break; 1131
1120 1132 case 2:
1121 default:
1122 {
1123 Array<idx_vector> ia (dim_vector (n_idx, 1));
1124
1125 for (octave_idx_type i = 0; i < n_idx; i++)
1126 { 1133 {
1127 ia(i) = idx(i).index_vector (); 1134 idx_vector i = idx(0).index_vector ();
1128 1135
1129 if (error_state) 1136 if (! error_state)
1130 break; 1137 {
1138 k = 1;
1139 idx_vector j = idx(1).index_vector ();
1140
1141 assign (i, j, rhs);
1142 }
1131 } 1143 }
1132 1144 break;
1133 if (! error_state) 1145
1134 assign (ia, rhs); 1146 default:
1135 } 1147 {
1136 break; 1148 Array<idx_vector> ia (dim_vector (n_idx, 1));
1149
1150 for (k = 0; k < n_idx; k++)
1151 {
1152 ia(k) = idx(k).index_vector ();
1153
1154 if (error_state)
1155 break;
1156 }
1157
1158 if (! error_state)
1159 assign (ia, rhs);
1160 }
1161 break;
1162 }
1163 }
1164 catch (index_exception& e)
1165 {
1166 // Rethrow to allow more info to be reported later.
1167 e.set_pos_if_unset (n_idx, k+1);
1168 throw;
1137 } 1169 }
1138 } 1170 }
1139 1171
1140 void 1172 void
1141 octave_map::assign (const octave_value_list& idx, const std::string& k, 1173 octave_map::assign (const octave_value_list& idx, const std::string& k,
1242 1274
1243 Array<idx_vector> ia (dim_vector (n_idx, 1)); 1275 Array<idx_vector> ia (dim_vector (n_idx, 1));
1244 1276
1245 for (octave_idx_type i = 0; i < n_idx; i++) 1277 for (octave_idx_type i = 0; i < n_idx; i++)
1246 { 1278 {
1247 ia(i) = idx(i).index_vector (); 1279 try
1280 {
1281 ia(i) = idx(i).index_vector ();
1282 }
1283 catch (index_exception& e)
1284 {
1285 // Rethrow to allow more info to be reported later.
1286 e.set_pos_if_unset (n_idx, i+1);
1287 throw;
1288 }
1248 1289
1249 if (error_state) 1290 if (error_state)
1250 break; 1291 break;
1251 } 1292 }
1252 1293