# HG changeset patch # User John W. Eaton # Date 1361577670 18000 # Node ID 1785493171ac416b918b7029975f9acb9121adad # Parent 63163e8eaef3bf03d5f82bc966f758f588499315 pass lvalue_list to more subsref calls (bug #38374) * pt-id.h, pt-id.cc (tree_identifier::rvalue): Handle lvalue_list. * ov-cell.h, ov-cell.cc (octave_cell::subsref): Likewise. * ov.h, ov.cc (octave_value::next_subsref): Likewise. * ov-usr-fcn.cc (octave_usr_function::do_multi_index_op): Forward lvalue_list to rvalue call for special expression. (Fisargout): New tests. diff --git a/libinterp/octave-value/ov-cell.cc b/libinterp/octave-value/ov-cell.cc --- a/libinterp/octave-value/ov-cell.cc +++ b/libinterp/octave-value/ov-cell.cc @@ -136,7 +136,8 @@ octave_value_list octave_cell::subsref (const std::string& type, const std::list& idx, - int nargout) + int nargout, + const std::list *lvalue_list) { octave_value_list retval; @@ -178,7 +179,9 @@ // octave_user_function::subsref. if (idx.size () > 1) - retval = retval(0).next_subsref (nargout, type, idx); + retval = (lvalue_list + ? retval(0).next_subsref (nargout, type, idx, lvalue_list) + : retval(0).next_subsref (nargout, type, idx)); return retval; } diff --git a/libinterp/octave-value/ov-cell.h b/libinterp/octave-value/ov-cell.h --- a/libinterp/octave-value/ov-cell.h +++ b/libinterp/octave-value/ov-cell.h @@ -79,7 +79,16 @@ } octave_value_list subsref (const std::string& type, - const std::list& idx, int); + const std::list& idx, + int nargout) + { + return subsref (type, idx, nargout, 0); + } + + octave_value_list subsref (const std::string& type, + const std::list& idx, + int nargout, + const std::list *lvalue_list); octave_value subsref (const std::string& type, const std::list& idx, diff --git a/libinterp/octave-value/ov-usr-fcn.cc b/libinterp/octave-value/ov-usr-fcn.cc --- a/libinterp/octave-value/ov-usr-fcn.cc +++ b/libinterp/octave-value/ov-usr-fcn.cc @@ -481,7 +481,9 @@ tree_expression *expr = special_expr (); if (expr) - retval = expr->rvalue (nargout); + retval = (lvalue_list + ? expr->rvalue (nargout, lvalue_list) + : expr->rvalue (nargout)); } else cmd_list->accept (*current_evaluator); @@ -1006,4 +1008,24 @@ %!test %! [x, y] = try_isargout (); %! assert ([x, y], [1, 2]); +%! +%% It should work without (): +%!test +%! [~, y] = try_isargout; +%! assert (y, -2); +%! +%% It should work in function handles, anonymous functions, and cell +%% arrays of handles or anonymous functions. +%!test +%! fh = @try_isargout; +%! af = @() try_isargout; +%! c = {fh, af}; +%! [~, y] = fh (); +%! assert (y, -2); +%! [~, y] = af (); +%! assert (y, -2); +%! [~, y] = c{1}(); +%! assert (y, -2); +%! [~, y] = c{2}(); +%! assert (y, -2); */ diff --git a/libinterp/octave-value/ov.cc b/libinterp/octave-value/ov.cc --- a/libinterp/octave-value/ov.cc +++ b/libinterp/octave-value/ov.cc @@ -1312,6 +1312,23 @@ return *this; } +octave_value_list +octave_value::next_subsref (int nargout, const std::string& type, + const std::list& idx, + const std::list *lvalue_list, + size_t skip) +{ + if (! error_state && idx.size () > skip) + { + std::list new_idx (idx); + for (size_t i = 0; i < skip; i++) + new_idx.erase (new_idx.begin ()); + return subsref (type.substr (skip), new_idx, nargout, lvalue_list); + } + else + return *this; +} + octave_value octave_value::next_subsref (bool auto_add, const std::string& type, const std::list& idx, diff --git a/libinterp/octave-value/ov.h b/libinterp/octave-value/ov.h --- a/libinterp/octave-value/ov.h +++ b/libinterp/octave-value/ov.h @@ -419,6 +419,12 @@ std::list& idx, size_t skip = 1); + octave_value_list next_subsref (int nargout, + const std::string& type, const + std::list& idx, + const std::list *lvalue_list, + size_t skip = 1); + octave_value next_subsref (bool auto_add, const std::string& type, const std::list& idx, size_t skip = 1); diff --git a/libinterp/parse-tree/pt-id.cc b/libinterp/parse-tree/pt-id.cc --- a/libinterp/parse-tree/pt-id.cc +++ b/libinterp/parse-tree/pt-id.cc @@ -59,7 +59,8 @@ } octave_value_list -tree_identifier::rvalue (int nargout) +tree_identifier::rvalue (int nargout, + const std::list *lvalue_list) { octave_value_list retval; @@ -85,7 +86,9 @@ { octave_value_list tmp_args; - retval = val.do_multi_index_op (nargout, tmp_args); + retval = (lvalue_list + ? val.do_multi_index_op (nargout, tmp_args, lvalue_list) + : val.do_multi_index_op (nargout, tmp_args)); } else { diff --git a/libinterp/parse-tree/pt-id.h b/libinterp/parse-tree/pt-id.h --- a/libinterp/parse-tree/pt-id.h +++ b/libinterp/parse-tree/pt-id.h @@ -103,7 +103,13 @@ octave_value rvalue1 (int nargout = 1); - octave_value_list rvalue (int nargout); + octave_value_list rvalue (int nargout) + { + return rvalue (nargout, 0); + } + + octave_value_list rvalue (int nargout, + const std::list *lvalue_list); octave_lvalue lvalue (void);