changeset 23482:c9937e865768

make isargout work again for nested function calls * pt-eval.cc, pt-eval.h (tree_evaluator::ignored_fcn_outputs): Return if lvalue_list is null. (tree_evaluator::make_value_list): Now a member function instead of static file-scope function. Change all callers. (tree_evaluator::visit_index_expression, tree_evaluator::visit_cell): Push null lvalue_list on m_lvalue_list_stack. * ov-usr-fcn.cc (octave_user_function::bind_automatic_var): Always define .ignored. symbol. New tests.
author John W. Eaton <jwe@octave.org>
date Wed, 10 May 2017 13:37:43 -0400
parents 73558a835b64
children 6d5a646ede0c
files libinterp/octave-value/ov-usr-fcn.cc libinterp/parse-tree/pt-eval.cc libinterp/parse-tree/pt-eval.h
diffstat 3 files changed, 78 insertions(+), 32 deletions(-) [+]
line wrap: on
line diff
--- a/libinterp/octave-value/ov-usr-fcn.cc	Wed May 10 11:09:52 2017 -0400
+++ b/libinterp/octave-value/ov-usr-fcn.cc	Wed May 10 13:37:43 2017 -0400
@@ -726,10 +726,7 @@
 
   Matrix ignored_fcn_outputs = tw ? tw->ignored_fcn_outputs () : Matrix ();
 
-  if (ignored_fcn_outputs.is_empty ())
-    symbol_table::assign (".ignored.");
-  else
-    symbol_table::assign (".ignored.", ignored_fcn_outputs);
+  symbol_table::assign (".ignored.", ignored_fcn_outputs);
 
   symbol_table::mark_hidden (".ignored.");
   symbol_table::mark_automatic (".ignored.");
@@ -1073,6 +1070,11 @@
 %!  endif
 %!endfunction
 %!
+%!function [a, b] = try_isargout2 (x, y)
+%!  a = y;
+%!  b = {isargout(1), isargout(2), x};
+%!endfunction
+%!
 %!test
 %! [x, y] = try_isargout ();
 %! assert ([x, y], [1, 2]);
@@ -1111,4 +1113,12 @@
 %! assert (y, -2);
 %! [~, y] = c{2}();
 %! assert (y, -2);
+%!
+## Nesting, anyone?
+%!test
+%! [~, b] = try_isargout2 (try_isargout, rand);
+%! assert (b, {0, 1, -1});
+%!test
+%! [~, b] = try_isargout2 ({try_isargout, try_isargout}, rand);
+%! assert (b, {0, 1, {-1, -1}});
 */
--- a/libinterp/parse-tree/pt-eval.cc	Wed May 10 11:09:52 2017 -0400
+++ b/libinterp/parse-tree/pt-eval.cc	Wed May 10 13:37:43 2017 -0400
@@ -416,11 +416,11 @@
     if (m_lvalue_list_stack.empty ())
       return retval;
 
-    //    std::cerr << "lvalue_list_stack size: "
-    //              << m_lvalue_list_stack.size () << std::endl;
-
     const std::list<octave_lvalue> *lvalue_list = m_lvalue_list_stack.top ();
 
+    if (! lvalue_list)
+      return retval;
+
     octave_idx_type nbh = 0;
 
     for (const auto& lval : *lvalue_list)
@@ -1043,29 +1043,6 @@
   }
 }
 
-static inline octave_value_list
-make_value_list (octave::tree_evaluator *tw, octave::tree_argument_list *args,
-                 const string_vector& arg_nm,
-                 const octave_value *object, bool rvalue = true)
-{
-  octave_value_list retval;
-
-  if (args)
-    {
-      if (rvalue && object && args->has_magic_end () && object->is_undefined ())
-        err_invalid_inquiry_subscript ();
-
-      retval = args->convert_to_const_vector (tw, object);
-    }
-
-  octave_idx_type n = retval.length ();
-
-  if (n > 0)
-    retval.stash_name_tags (arg_nm);
-
-  return retval;
-}
-
 // 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?)
@@ -1132,6 +1109,16 @@
 
             if (n > 0)
               {
+                // Function calls inside an argument list can't have ignored
+                // output arguments.
+
+                unwind_protect frame;
+
+                m_lvalue_list_stack.push (0);
+
+                frame.add_method (m_lvalue_list_stack,
+                                  &value_stack<const std::list<octave_lvalue>*>::pop);
+
                 string_vector anm = *(arg_nm.begin ());
                 have_args = true;
                 first_args = al -> convert_to_const_vector (this);
@@ -1239,11 +1226,11 @@
                 have_args = false;
               }
             else
-              idx.push_back (make_value_list (this, *p_args, *p_arg_nm, &tmp));
+              idx.push_back (make_value_list (*p_args, *p_arg_nm, &tmp));
             break;
 
           case '{':
-            idx.push_back (make_value_list (this, *p_args, *p_arg_nm, &tmp));
+            idx.push_back (make_value_list (*p_args, *p_arg_nm, &tmp));
             break;
 
           case '.':
@@ -1488,6 +1475,16 @@
   {
     octave_value retval;
 
+    // Function calls inside an argument list can't have ignored
+    // output arguments.
+
+    unwind_protect frame;
+
+    m_lvalue_list_stack.push (0);
+
+    frame.add_method (m_lvalue_list_stack,
+                      &value_stack<const std::list<octave_lvalue>*>::pop);
+
     octave_idx_type nr = expr.length ();
     octave_idx_type nc = -1;
 
@@ -2509,6 +2506,40 @@
     return expr_value;
   }
 
+  octave_value_list
+  tree_evaluator::make_value_list (octave::tree_argument_list *args,
+                                   const string_vector& arg_nm,
+                                   const octave_value *object, bool rvalue)
+  {
+    octave_value_list retval;
+
+    if (args)
+      {
+        // Function calls inside an argument list can't have ignored
+        // output arguments.
+
+        unwind_protect frame;
+
+        m_lvalue_list_stack.push (0);
+
+        frame.add_method (m_lvalue_list_stack,
+                          &value_stack<const std::list<octave_lvalue>*>::pop);
+
+        if (rvalue && object && args->has_magic_end ()
+            && object->is_undefined ())
+          err_invalid_inquiry_subscript ();
+
+        retval = args->convert_to_const_vector (this, object);
+      }
+
+    octave_idx_type n = retval.length ();
+
+    if (n > 0)
+      retval.stash_name_tags (arg_nm);
+
+    return retval;
+  }
+
   std::list<octave_lvalue>
   tree_evaluator::make_lvalue_list (tree_argument_list *lhs)
   {
--- a/libinterp/parse-tree/pt-eval.h	Wed May 10 11:09:52 2017 -0400
+++ b/libinterp/parse-tree/pt-eval.h	Wed May 10 13:37:43 2017 -0400
@@ -304,6 +304,11 @@
 
     bool is_logically_true (tree_expression *expr, const char *warn_for);
 
+    octave_value_list
+    make_value_list (octave::tree_argument_list *args,
+                     const string_vector& arg_nm,
+                     const octave_value *object, bool rvalue = true);
+
     std::list<octave_lvalue> make_lvalue_list (tree_argument_list *);
 
     value_stack<octave_value_list> m_value_stack;