Mercurial > octave-nkf
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; |