changeset 25382:749d9e858553

move convert_to_const_vector from tree_argument_list to tree_evaluator * pt-eval.h, pt-eval.cc (tree_evaluator::convert_to_const_vector): Move here from pt-arg-list.h and pt-arg-list.cc: Change all uses. (tree_evaluator::m_indexed_object, tree_evaluator::m_index_position, tree_evaluator::m_num_indices): Move here from (tree_evaluator::m_indexed_object, tree_evaluator::m_index_position, tree_evaluator::num_indices): Provide accessors for corresponding member variables. (Fend): Move here from pt-arg-list.cc. Access indexed_object, index_position, and num_indices from evaluator instead of file scope static variables. * pt-arg-list.h (tree_argument_list::includes_magic_end): New function.
author John W. Eaton <jwe@octave.org>
date Tue, 15 May 2018 17:05:47 -0400
parents 072494014e76
children d3a035528c9a
files libinterp/parse-tree/pt-arg-list.cc libinterp/parse-tree/pt-arg-list.h libinterp/parse-tree/pt-eval.cc libinterp/parse-tree/pt-eval.h libinterp/parse-tree/pt-idx.cc
diffstat 5 files changed, 187 insertions(+), 164 deletions(-) [+]
line wrap: on
line diff
--- a/libinterp/parse-tree/pt-arg-list.cc	Tue May 15 15:34:09 2018 -0400
+++ b/libinterp/parse-tree/pt-arg-list.cc	Tue May 15 17:05:47 2018 -0400
@@ -29,21 +29,13 @@
 
 #include "str-vec.h"
 
-#include "defun.h"
-#include "error.h"
 #include "ovl.h"
 #include "ov.h"
-#include "ov-usr-fcn.h"
-#include "parse.h"
 #include "pt-arg-list.h"
-#include "pt-eval.h"
 #include "pt-exp.h"
 #include "pt-id.h"
 #include "pt-idx.h"
 #include "pt-pr-code.h"
-#include "pt-walk.h"
-#include "interpreter.h"
-#include "unwind-prot.h"
 
 namespace octave
 {
@@ -117,152 +109,6 @@
 
     return retval;
   }
-}
-
-// FIXME: Is there a way to do this job without global data?
-
-static const octave_value *indexed_object = nullptr;
-static int index_position = 0;
-static int num_indices = 0;
-
-// END is documented in op-kw-docs.
-DEFCONSTMETHOD (end, interp, , ,
-                doc: /* -*- texinfo -*-
-@deftypefn {} {} end
-Last element of an array or the end of any @code{for}, @code{parfor},
-@code{if}, @code{do}, @code{while}, @code{function}, @code{switch},
-@code{try}, or @code{unwind_protect} block.
-
-As an index of an array, the magic index @qcode{"end"} refers to the
-last valid entry in an indexing operation.
-
-Example:
-
-@example
-@group
-@var{x} = [ 1 2 3; 4 5 6 ];
-@var{x}(1,end)
-   @result{} 3
-@var{x}(end,1)
-   @result{} 4
-@var{x}(end,end)
-   @result{} 6
-@end group
-@end example
-@seealso{for, parfor, if, do, while, function, switch, try, unwind_protect}
-@end deftypefn */)
-{
-  octave_value retval;
-
-  if (! indexed_object)
-    error ("invalid use of end");
-
-  if (indexed_object->isobject ())
-    {
-      octave_value_list args;
-
-      args(2) = num_indices;
-      args(1) = index_position + 1;
-      args(0) = *indexed_object;
-
-      std::string class_name = indexed_object->class_name ();
-
-      octave::symbol_table& symtab = interp.get_symbol_table ();
-
-      octave_value meth = symtab.find_method ("end", class_name);
-
-      if (meth.is_defined ())
-        return octave::feval (meth.function_value (), args, 1);
-    }
-
-  dim_vector dv = indexed_object->dims ();
-  int ndims = dv.ndims ();
-
-  if (num_indices < ndims)
-    {
-      for (int i = num_indices; i < ndims; i++)
-        dv(num_indices-1) *= dv(i);
-
-      if (num_indices == 1)
-        {
-          ndims = 2;
-          dv.resize (ndims);
-          dv(1) = 1;
-        }
-      else
-        {
-          ndims = num_indices;
-          dv.resize (ndims);
-        }
-    }
-
-  if (index_position < ndims)
-    retval = dv(index_position);
-  else
-    retval = 1;
-
-  return retval;
-}
-
-namespace octave
-{
-  octave_value_list
-  tree_argument_list::convert_to_const_vector (tree_evaluator *tw,
-                                               const octave_value *object)
-  {
-    // END doesn't make sense for functions.  Maybe we need a different
-    // way of asking an octave_value object this question?
-
-    bool stash_object = (m_list_includes_magic_end
-                         && object
-                         && ! (object->is_function ()
-                               || object->is_function_handle ()));
-
-    unwind_protect frame;
-
-    if (stash_object)
-      {
-        frame.protect_var (indexed_object);
-
-        indexed_object = object;
-      }
-
-    int len = length ();
-
-    std::list<octave_value_list> args;
-
-    auto p = begin ();
-    for (int k = 0; k < len; k++)
-      {
-        if (stash_object)
-          {
-            frame.protect_var (index_position);
-            frame.protect_var (num_indices);
-
-            index_position = k;
-            num_indices = len;
-          }
-
-        tree_expression *elt = *p++;
-
-        if (elt)
-          {
-            octave_value tmp = tw->evaluate (elt);
-
-            if (tmp.is_cs_list ())
-              args.push_back (tmp.list_value ());
-            else if (tmp.is_defined ())
-              args.push_back (tmp);
-          }
-        else
-          {
-            args.push_back (octave_value ());
-            break;
-          }
-      }
-
-    return args;
-  }
 
   string_vector
   tree_argument_list::get_arg_names (void) const
--- a/libinterp/parse-tree/pt-arg-list.h	Tue May 15 15:34:09 2018 -0400
+++ b/libinterp/parse-tree/pt-arg-list.h	Tue May 15 17:05:47 2018 -0400
@@ -67,10 +67,24 @@
 
     ~tree_argument_list (void);
 
+    // FIXME: This does not recursively check elements of the list
+    // that are also index expressions.
     bool has_magic_end (void) const;
 
+    bool includes_magic_end (void) const
+    {
+      return m_list_includes_magic_end;
+    }
+
     bool has_magic_tilde (void) const
-    { return m_list_includes_magic_tilde; }
+    {
+      return m_list_includes_magic_tilde;
+    }
+
+    bool includes_magic_tilde (void) const
+    {
+      return m_list_includes_magic_tilde;
+    }
 
     tree_expression * remove_front (void)
     {
@@ -90,10 +104,6 @@
 
     bool is_valid_lvalue_list (void) const;
 
-    octave_value_list
-    convert_to_const_vector (tree_evaluator *tw,
-                             const octave_value *object = nullptr);
-
     string_vector get_arg_names (void) const;
 
     std::list<std::string> variable_names (void) const;
--- a/libinterp/parse-tree/pt-eval.cc	Tue May 15 15:34:09 2018 -0400
+++ b/libinterp/parse-tree/pt-eval.cc	Tue May 15 17:05:47 2018 -0400
@@ -583,6 +583,154 @@
         ref.assign (octave_value::op_asn_eq, octave_value ());
       }
   }
+}
+
+// END is documented in op-kw-docs.
+DEFCONSTMETHOD (end, interp, , ,
+                doc: /* -*- texinfo -*-
+@deftypefn {} {} end
+Last element of an array or the end of any @code{for}, @code{parfor},
+@code{if}, @code{do}, @code{while}, @code{function}, @code{switch},
+@code{try}, or @code{unwind_protect} block.
+
+As an index of an array, the magic index @qcode{"end"} refers to the
+last valid entry in an indexing operation.
+
+Example:
+
+@example
+@group
+@var{x} = [ 1 2 3; 4 5 6 ];
+@var{x}(1,end)
+   @result{} 3
+@var{x}(end,1)
+   @result{} 4
+@var{x}(end,end)
+   @result{} 6
+@end group
+@end example
+@seealso{for, parfor, if, do, while, function, switch, try, unwind_protect}
+@end deftypefn */)
+{
+  octave_value retval;
+
+  octave::tree_evaluator& tw = interp.get_evaluator ();
+
+  const octave_value *indexed_object = tw.indexed_object ();
+  int index_position = tw.index_position ();
+  int num_indices = tw.num_indices ();
+
+  if (! indexed_object)
+    error ("invalid use of end");
+
+  if (indexed_object->isobject ())
+    {
+      octave_value_list args;
+
+      args(2) = num_indices;
+      args(1) = index_position + 1;
+      args(0) = *indexed_object;
+
+      std::string class_name = indexed_object->class_name ();
+
+      octave::symbol_table& symtab = interp.get_symbol_table ();
+
+      octave_value meth = symtab.find_method ("end", class_name);
+
+      if (meth.is_defined ())
+        return octave::feval (meth.function_value (), args, 1);
+    }
+
+  dim_vector dv = indexed_object->dims ();
+  int ndims = dv.ndims ();
+
+  if (num_indices < ndims)
+    {
+      for (int i = num_indices; i < ndims; i++)
+        dv(num_indices-1) *= dv(i);
+
+      if (num_indices == 1)
+        {
+          ndims = 2;
+          dv.resize (ndims);
+          dv(1) = 1;
+        }
+      else
+        {
+          ndims = num_indices;
+          dv.resize (ndims);
+        }
+    }
+
+  if (index_position < ndims)
+    retval = dv(index_position);
+  else
+    retval = 1;
+
+  return retval;
+}
+
+namespace octave
+{
+  octave_value_list
+  tree_evaluator::convert_to_const_vector (tree_argument_list *arg_list,
+                                           const octave_value *object)
+  {
+    // END doesn't make sense as a direct argument for a function (i.e.,
+    // "fcn (end)" is invalid but "fcn (array (end))" is OK).  Maybe we
+    // need a different way of asking an octave_value object this
+    // question?
+
+    bool stash_object = (arg_list->includes_magic_end ()
+                         && object
+                         && ! (object->is_function ()
+                               || object->is_function_handle ()));
+
+    unwind_protect frame;
+
+    if (stash_object)
+      {
+        frame.protect_var (m_indexed_object);
+
+        m_indexed_object = object;
+      }
+
+    int len = arg_list->length ();
+
+    std::list<octave_value_list> args;
+
+    auto p = arg_list->begin ();
+    for (int k = 0; k < len; k++)
+      {
+        if (stash_object)
+          {
+            frame.protect_var (m_index_position);
+            frame.protect_var (m_num_indices);
+
+            m_index_position = k;
+            m_num_indices = len;
+          }
+
+        tree_expression *elt = *p++;
+
+        if (elt)
+          {
+            octave_value tmp = evaluate (elt);
+
+            if (tmp.is_cs_list ())
+              args.push_back (tmp.list_value ());
+            else if (tmp.is_defined ())
+              args.push_back (tmp);
+          }
+        else
+          {
+            args.push_back (octave_value ());
+            break;
+          }
+      }
+
+    return args;
+  }
 
   octave_value_list
   tree_evaluator::convert_return_list_to_const_vector
@@ -1315,7 +1463,7 @@
                                   &value_stack<const std::list<octave_lvalue>*>::pop);
 
                 string_vector anm = *p_arg_nm;
-                first_args = al->convert_to_const_vector (this);
+                first_args = convert_to_const_vector (al);
                 first_args.stash_name_tags (anm);
               }
 
@@ -1769,7 +1917,7 @@
 
     for (tree_argument_list *elt : expr)
       {
-        octave_value_list row = elt->convert_to_const_vector (this);
+        octave_value_list row = convert_to_const_vector (elt);
 
         if (nr == 1)
           // Optimize the single row case.
@@ -2917,7 +3065,7 @@
             && object->is_undefined ())
           err_invalid_inquiry_subscript ();
 
-        retval = args->convert_to_const_vector (this, object);
+        retval = convert_to_const_vector (args, object);
       }
 
     octave_idx_type n = retval.length ();
--- a/libinterp/parse-tree/pt-eval.h	Tue May 15 15:34:09 2018 -0400
+++ b/libinterp/parse-tree/pt-eval.h	Tue May 15 17:05:47 2018 -0400
@@ -134,7 +134,8 @@
         m_silent_functions (false), m_string_fill_char (' '),
         m_PS4 ("+ "), m_dbstep_flag (0), m_echo (ECHO_OFF),
         m_echo_state (false), m_echo_file_name (), m_echo_file_pos (1),
-        m_echo_files (), m_in_loop_command (false)
+        m_echo_files (), m_in_loop_command (false),
+        m_indexed_object (nullptr), m_index_position (0), m_num_indices (0)
     { }
 
     // No copying!
@@ -359,6 +360,10 @@
     void undefine_parameter_list (tree_parameter_list *param_list);
 
     octave_value_list
+    convert_to_const_vector (tree_argument_list *arg_list,
+                             const octave_value *object = nullptr);
+
+    octave_value_list
     convert_return_list_to_const_vector
       (tree_parameter_list *ret_list, int nargout, const Cell& varargout);
 
@@ -423,6 +428,15 @@
       return val;
     }
 
+    const octave_value * indexed_object (void) const
+    {
+      return m_indexed_object;
+    }
+
+    int index_position (void) const { return m_index_position; }
+
+    int num_indices (void) const { return m_num_indices; }
+
     octave_value echo (const octave_value_list& args, int nargout);
 
     int echo (void) const { return m_echo; }
@@ -545,6 +559,11 @@
 
     // TRUE means we are evaluating some kind of looping construct.
     bool m_in_loop_command;
+
+    // Used by END function.
+    const octave_value *m_indexed_object;
+    int m_index_position;
+    int m_num_indices;
   };
 }
 
--- a/libinterp/parse-tree/pt-idx.cc	Tue May 15 15:34:09 2018 -0400
+++ b/libinterp/parse-tree/pt-idx.cc	Tue May 15 17:05:47 2018 -0400
@@ -158,7 +158,7 @@
             && object->is_undefined ())
           err_invalid_inquiry_subscript ();
 
-        retval = m_args->convert_to_const_vector (tw, object);
+        retval = tw->convert_to_const_vector (m_args, object);
       }
 
     octave_idx_type n = retval.length ();