comparison 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
comparison
equal deleted inserted replaced
20573:e3c0fee87493 20574:dd6345fd8a97
282 tree_index_expression::rvalue (int nargout) 282 tree_index_expression::rvalue (int nargout)
283 { 283 {
284 return tree_index_expression::rvalue (nargout, 0); 284 return tree_index_expression::rvalue (nargout, 0);
285 } 285 }
286 286
287 // Final step of processing an indexing error. Add the name of the
288 // variable being indexed, if any, then issue an error. (Will this also
289 // be needed by pt-lvalue, which calls subsref?)
290
291 static void
292 final_index_error (index_exception& e, const tree_expression *expr)
293 {
294 if (expr->is_identifier ()
295 && dynamic_cast<const tree_identifier *> (expr)->is_variable ())
296 e.set_var (expr->name ());
297
298 (*current_liboctave_error_with_id_handler) (e.id (), e.err ());
299 }
300
287 octave_value_list 301 octave_value_list
288 tree_index_expression::rvalue (int nargout, 302 tree_index_expression::rvalue (int nargout,
289 const std::list<octave_lvalue> *lvalue_list) 303 const std::list<octave_lvalue> *lvalue_list)
290 { 304 {
291 octave_value_list retval; 305 octave_value_list retval;
351 // codes. 365 // codes.
352 bool force_split = type[i-1] == '(' && type[i] != '.'; 366 bool force_split = type[i-1] == '(' && type[i] != '.';
353 367
354 if (force_split || (al && al->has_magic_end ())) 368 if (force_split || (al && al->has_magic_end ()))
355 { 369 {
356 // We have an expression like 370 // (we have force_split, or) we have an expression like
357 // 371 //
358 // x{end}.a(end) 372 // x{end}.a(end)
359 // 373 //
360 // and we are looking at the argument list that 374 // and we are looking at the argument list that
361 // contains the second (or third, etc.) "end" token, 375 // contains the second (or third, etc.) "end" token,
362 // so we must evaluate everything up to the point of 376 // so we must evaluate everything up to the point of
363 // that argument list so we can pass the appropriate 377 // that argument list so we can pass the appropriate
364 // value to the built-in end function. 378 // value to the built-in end function.
365 379
366 octave_value_list tmp_list 380 try
367 = tmp.subsref (type.substr (tmpi, i - tmpi), idx, nargout);
368
369 tmp = tmp_list.length () ? tmp_list(0) : octave_value ();
370 tmpi = i;
371 idx.clear ();
372
373 if (tmp.is_cs_list ())
374 gripe_indexed_cs_list ();
375
376 if (error_state)
377 break;
378
379 if (tmp.is_function ())
380 { 381 {
381 octave_function *fcn = tmp.function_value (true); 382 octave_value_list tmp_list
382 383 =tmp.subsref (type.substr (tmpi, i-tmpi), idx, nargout);
383 if (fcn && ! fcn->is_postfix_index_handled (type[i])) 384
385 tmp = tmp_list.length () ? tmp_list(0) : octave_value ();
386 tmpi = i;
387 idx.clear ();
388
389 if (tmp.is_cs_list ())
390 gripe_indexed_cs_list ();
391
392 if (error_state)
393 break;
394
395 if (tmp.is_function ())
384 { 396 {
385 octave_value_list empty_args; 397 octave_function *fcn = tmp.function_value (true);
386 398
387 tmp_list = tmp.do_multi_index_op (1, empty_args); 399 if (fcn && ! fcn->is_postfix_index_handled (type[i]))
388 tmp = (tmp_list.length () 400 {
389 ? tmp_list(0) : octave_value ()); 401 octave_value_list empty_args;
390 402
391 if (tmp.is_cs_list ()) 403 tmp_list = tmp.do_multi_index_op (1, empty_args);
392 gripe_indexed_cs_list (); 404 tmp = (tmp_list.length ()
393 405 ? tmp_list(0) : octave_value ());
394 if (error_state) 406
395 break; 407 if (tmp.is_cs_list ())
408 gripe_indexed_cs_list ();
409
410 if (error_state)
411 break;
412 }
396 } 413 }
414 }
415 catch (index_exception& e) // problems with index range, type etc.
416 {
417 final_index_error (e, expr);
397 } 418 }
398 } 419 }
399 } 420 }
400 421
401 switch (type[i]) 422 switch (type[i])
431 p_dyn_field++; 452 p_dyn_field++;
432 } 453 }
433 454
434 if (! error_state) 455 if (! error_state)
435 { 456 {
436 retval = tmp.subsref (type.substr (tmpi, n - tmpi), idx, nargout, 457 try
437 lvalue_list); 458 {
459 retval = tmp.subsref (type.substr (tmpi, n - tmpi), idx, nargout,
460 lvalue_list);
461 }
462 catch (index_exception& e) // problems with range, invalid index type etc.
463 {
464 final_index_error (e, expr);
465 }
438 466
439 octave_value val = retval.length () ? retval(0) : octave_value (); 467 octave_value val = retval.length () ? retval(0) : octave_value ();
440 468
441 if (! error_state && val.is_function ()) 469 if (! error_state && val.is_function ())
442 { 470 {
498 { 526 {
499 if (retval.numel () != 1) 527 if (retval.numel () != 1)
500 gripe_indexed_cs_list (); 528 gripe_indexed_cs_list ();
501 else if (tmpi < i) 529 else if (tmpi < i)
502 { 530 {
503 tmp = tmp.subsref (type.substr (tmpi, i - tmpi), tmpidx, true); 531 try
532 {
533 tmp = tmp.subsref (type.substr (tmpi, i-tmpi), tmpidx, true);
534 }
535 catch (index_exception& e) // problems with range, invalid type etc.
536 {
537 final_index_error (e, expr);
538 }
504 tmpidx.clear (); 539 tmpidx.clear ();
505 } 540 }
506 541
507 if (error_state) 542 if (error_state)
508 break; 543 break;