changeset 28317:ac87763b1949 stable

capture dynamic field variable values in anonymous functions (bug #58389) * pt-walk.cc (tree_walker::visit_index_expression): Also visit dynamic field name expressions. * ov-fcn-handle.cc: New test.
author John W. Eaton <jwe@octave.org>
date Mon, 18 May 2020 12:30:41 -0400
parents 768ae9b1a67c
children 08229481b65f
files libinterp/octave-value/ov-fcn-handle.cc libinterp/parse-tree/pt-walk.cc
diffstat 2 files changed, 49 insertions(+), 6 deletions(-) [+]
line wrap: on
line diff
--- a/libinterp/octave-value/ov-fcn-handle.cc	Sat May 16 15:53:42 2020 +0200
+++ b/libinterp/octave-value/ov-fcn-handle.cc	Mon May 18 12:30:41 2020 -0400
@@ -2136,6 +2136,16 @@
 */
 
 /*
+%!test <*58389>
+%! s = "x";
+%! a.(s) = [e, pi];
+%! f = @(x) a.(s)(x);
+%! assert (f(1), e);
+%! assert (f(2), pi);
+%! assert (f([2,1]), [pi, e]);
+*/
+
+/*
 %!function r = __f (g, i)
 %!  r = g(i);
 %!endfunction
--- a/libinterp/parse-tree/pt-walk.cc	Sat May 16 15:53:42 2020 +0200
+++ b/libinterp/parse-tree/pt-walk.cc	Mon May 18 12:30:41 2020 -0400
@@ -285,16 +285,49 @@
     if (e)
       e->accept (*this);
 
-    std::list<tree_argument_list *> lst = expr.arg_lists ();
+    std::list<tree_argument_list *> arg_lists = expr.arg_lists ();
+    std::list<string_vector> arg_names = expr.arg_names ();
+    std::list<tree_expression *> dyn_fields = expr.dyn_fields ();
 
-    auto p = lst.begin ();
+    auto p_arg_lists = arg_lists.begin ();
+    auto p_arg_names = arg_names.begin ();
+    auto p_dyn_fields = dyn_fields.begin ();
+
+    std::string type_tags = expr.type_tags ();
+    int n = type_tags.length ();
 
-    while (p != lst.end ())
+    for (int i = 0; i < n; i++)
       {
-        tree_argument_list *elt = *p++;
+        switch (type_tags[i])
+          {
+          case '(':
+          case '{':
+            {
+              tree_argument_list *l = *p_arg_lists;
+              if (l)
+                l->accept (*this);
+            }
+            break;
 
-        if (elt)
-          elt->accept (*this);
+          case '.':
+            {
+              std::string fn = (*p_arg_names)(0);
+              if (fn.empty ())
+                {
+                  tree_expression *df = *p_dyn_fields;
+                  if (df)
+                    df->accept (*this);
+                }
+            }
+            break;
+
+          default:
+            panic_impossible ();
+          }
+
+        p_arg_lists++;
+        p_arg_names++;
+        p_dyn_fields++;
       }
   }