diff libinterp/parse-tree/pt-idx.cc @ 23435:c452180ab672

begin refactoring parse tree evaluator * libinterp/parse-tree/pt-tm-const.cc, libinterp/parse-tree/pt-tm-const.h: New files, extracted from pt-mat.h and pt-mat.cc. * libinterp/parse-tree/module.mk: Update. * interpreter.cc, ov-class.cc, ov-classdef.cc, ov-classdef.h, ov-fcn-handle.cc, ov-fcn-handle.h, ov-usr-fcn.cc, oct-parse.in.yy, pt-arg-list.cc, pt-arg-list.h, pt-array-list.h, pt-assign.cc, pt-assign.h, pt-binop.cc, pt-binop.h, pt-cbinop.cc, pt-cbinop.h, pt-cell.cc, pt-cell.h, pt-classdef.cc, pt-classdef.h, pt-cmd.cc, pt-cmd.h, pt-colon.cc, pt-colon.h, pt-const.cc, pt-const.h, pt-decl.cc, pt-decl.h, pt-eval.cc, pt-eval.h, pt-except.cc, pt-except.h, pt-exp.cc, pt-exp.h, pt-fcn-handle.cc, pt-fcn-handle.h, pt-funcall.cc, pt-funcall.h, pt-id.cc, pt-id.h, pt-idx.cc, pt-idx.h, pt-jit.cc, pt-jump.cc, pt-jump.h, pt-loop.cc, pt-loop.h, pt-mat.cc, pt-mat.h, pt-misc.cc, pt-misc.h, pt-select.cc, pt-select.h, pt-stmt.cc, pt-stmt.h, pt-unop.cc, pt-unop.h: Use tree_evaluator class to walk the parse tree instead of rvalue methods in the parse tree classes. Maintain a stack in the evaluator class to accumulate results. Pass pointer to evaluator to function objects and other classes as needed for evaluation. This is a work in progress that is not yet complete. The ultimate goal is to move all evaluation into the tree_evaluator class instead of spreading that work among many different classes. The global pointer to the current evaluator should also be eliminated.
author John W. Eaton <jwe@octave.org>
date Fri, 21 Apr 2017 18:07:40 -0400
parents 945b53af4655
children c763214a8260
line wrap: on
line diff
--- a/libinterp/parse-tree/pt-idx.cc	Mon Apr 24 21:03:38 2017 -0700
+++ b/libinterp/parse-tree/pt-idx.cc	Fri Apr 21 18:07:40 2017 -0400
@@ -33,6 +33,7 @@
 #include "pager.h"
 #include "pt-arg-list.h"
 #include "pt-bp.h"
+#include "pt-eval.h"
 #include "pt-id.h"
 #include "pt-idx.h"
 #include "pt-walk.h"
@@ -146,34 +147,10 @@
   }
 }
 
-static Cell
-make_subs_cell (octave::tree_argument_list *args, const string_vector& arg_nm)
-{
-  Cell retval;
-
-  octave_value_list arg_values;
-
-  if (args)
-    arg_values = args->convert_to_const_vector ();
-
-  int n = arg_values.length ();
-
-  if (n > 0)
-    {
-      arg_values.stash_name_tags (arg_nm);
-
-      retval.resize (dim_vector (1, n));
-
-      for (int i = 0; i < n; i++)
-        retval(0,i) = arg_values(i);
-    }
-
-  return retval;
-}
-
 static inline octave_value_list
-make_value_list (octave::tree_argument_list *args, const string_vector& arg_nm,
-                 const octave_value *object, bool rvalue = true)
+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;
 
@@ -182,7 +159,7 @@
       if (rvalue && object && args->has_magic_end () && object->is_undefined ())
         err_invalid_inquiry_subscript ();
 
-      retval = args->convert_to_const_vector (object);
+      retval = args->convert_to_const_vector (tw, object);
     }
 
   octave_idx_type n = retval.length ();
@@ -197,7 +174,8 @@
 {
   std::string
   tree_index_expression::get_struct_index
-  (std::list<string_vector>::const_iterator p_arg_nm,
+  (tree_evaluator *tw,
+   std::list<string_vector>::const_iterator p_arg_nm,
    std::list<tree_expression *>::const_iterator p_dyn_field) const
   {
     std::string fn = (*p_arg_nm)(0);
@@ -208,7 +186,7 @@
 
         if (df)
           {
-            octave_value t = df->rvalue1 ();
+            octave_value t = tw->evaluate (df);
 
             fn = t.xstring_value ("dynamic structure field names must be strings");
           }
@@ -218,57 +196,6 @@
 
     return fn;
   }
-
-  octave_map
-  tree_index_expression::make_arg_struct (void) const
-  {
-    int n = args.size ();
-
-    Cell type_field (n, 1);
-    Cell subs_field (n, 1);
-
-    std::list<tree_argument_list *>::const_iterator p_args = args.begin ();
-    std::list<string_vector>::const_iterator p_arg_nm = arg_nm.begin ();
-    std::list<tree_expression *>::const_iterator p_dyn_field = dyn_field.begin ();
-
-    octave_map m;
-
-    for (int i = 0; i < n; i++)
-      {
-        switch (type[i])
-          {
-          case '(':
-            subs_field(i) = make_subs_cell (*p_args, *p_arg_nm);
-            break;
-
-          case '{':
-            subs_field(i) = make_subs_cell (*p_args, *p_arg_nm);
-            break;
-
-          case '.':
-            subs_field(i) = get_struct_index (p_arg_nm, p_dyn_field);
-            break;
-
-          default:
-            panic_impossible ();
-          }
-
-        p_args++;
-        p_arg_nm++;
-        p_dyn_field++;
-      }
-
-    m.assign ("type", type_field);
-    m.assign ("subs", subs_field);
-
-    return m;
-  }
-
-  octave_value_list
-  tree_index_expression::rvalue (int nargout)
-  {
-    return tree_index_expression::rvalue (nargout, 0);
-  }
 }
 
 // Final step of processing an indexing error.  Add the name of the
@@ -306,203 +233,8 @@
 
 namespace octave
 {
-  octave_value_list
-  tree_index_expression::rvalue (int nargout,
-                                 const std::list<octave_lvalue> *lvalue_list)
-  {
-    octave_value_list retval;
-
-    octave_value first_expr_val;
-
-    octave_value_list first_args;
-
-    bool have_args = false;
-
-    if (expr->is_identifier () && type[0] == '(')
-      {
-        tree_identifier *id = dynamic_cast<tree_identifier *> (expr);
-
-        if (! (id->is_variable () || args.empty ()))
-          {
-            tree_argument_list *al = *(args.begin ());
-
-            size_t n = al ? al->length () : 0;
-
-            if (n > 0)
-              {
-                string_vector anm = *(arg_nm.begin ());
-                have_args = true;
-                first_args = al -> convert_to_const_vector ();
-                first_args.stash_name_tags (anm);
-
-                first_expr_val = id->do_lookup  (first_args);
-              }
-          }
-      }
-
-    if (first_expr_val.is_undefined ())
-      first_expr_val = expr->rvalue1 ();
-
-    octave_value tmp = first_expr_val;
-    octave_idx_type tmpi = 0;
-
-    std::list<octave_value_list> idx;
-
-    int n = args.size ();
-
-    std::list<tree_argument_list *>::iterator p_args = args.begin ();
-    std::list<string_vector>::iterator p_arg_nm = arg_nm.begin ();
-    std::list<tree_expression *>::iterator p_dyn_field = dyn_field.begin ();
-
-    for (int i = 0; i < n; i++)
-      {
-        if (i > 0)
-          {
-            tree_argument_list *al = *p_args;
-
-            // In Matlab, () can only be followed by '.'.  In Octave, we
-            // do not enforce this for rvalue expressions, but we'll
-            // split the evaluation at this point.  This will,
-            // hopefully, allow Octave's looser rules apply smoothly for
-            // Matlab overloaded subsref codes.
-
-            // We might have an expression like
-            //
-            //   x{end}.a(end)
-            //
-            // and we are looking at the argument list that contains the
-            // second (or third, etc.) "end" token, so we must evaluate
-            // everything up to the point of that argument list so we
-            // can pass the appropriate value to the built-in end
-            // function.
-
-            // An expression like
-            //
-            //    s.a (f (1:end))
-            //
-            // can mean a lot of different things depending on the types
-            // of s, a, and f.  Let's just say it's complicated and that
-            // the following code is definitely not correct in all
-            // cases.  That it is already so complex makes me think that
-            // there must be a better way.
-
-            bool split = ((type[i-1] == '(' && type[i] != '.')
-                          || (al && al->has_magic_end ()
-                              && ! tmp.is_classdef_object ()));
-
-            if (split)
-              {
-                try
-                  {
-                    octave_value_list tmp_list
-                      =tmp.subsref (type.substr (tmpi, i-tmpi), idx, nargout);
-
-                    tmp = tmp_list.length () ? tmp_list(0) : octave_value ();
-                    tmpi = i;
-                    idx.clear ();
-
-                    if (tmp.is_cs_list ())
-                      err_indexed_cs_list ();
-
-                    if (tmp.is_function ())
-                      {
-                        octave_function *fcn = tmp.function_value (true);
-
-                        if (fcn && ! fcn->is_postfix_index_handled (type[i]))
-                          {
-                            octave_value_list empty_args;
-
-                            tmp_list = tmp.do_multi_index_op (1, empty_args);
-                            tmp = (tmp_list.length ()
-                                   ? tmp_list(0) : octave_value ());
-
-                            if (tmp.is_cs_list ())
-                              err_indexed_cs_list ();
-                          }
-                      }
-                  }
-                catch (octave::index_exception& e)  // problems with index range, type etc.
-                  {
-                    final_index_error (e, expr);
-                  }
-              }
-          }
-
-        switch (type[i])
-          {
-          case '(':
-            if (have_args)
-              {
-                idx.push_back (first_args);
-                have_args = false;
-              }
-            else
-              idx.push_back (make_value_list (*p_args, *p_arg_nm, &tmp));
-            break;
-
-          case '{':
-            idx.push_back (make_value_list (*p_args, *p_arg_nm, &tmp));
-            break;
-
-          case '.':
-            idx.push_back (octave_value (get_struct_index (p_arg_nm,
-                                                           p_dyn_field)));
-            break;
-
-          default:
-            panic_impossible ();
-          }
-
-        p_args++;
-        p_arg_nm++;
-        p_dyn_field++;
-      }
-
-    try
-      {
-        retval = tmp.subsref (type.substr (tmpi, n - tmpi), idx, nargout,
-                              lvalue_list);
-      }
-    catch (octave::index_exception& e)  // range problems, bad index type, etc.
-      {
-        final_index_error (e, expr);
-      }
-
-    octave_value val = retval.length () ? retval(0) : octave_value ();
-
-    if (val.is_function ())
-      {
-        octave_function *fcn = val.function_value (true);
-
-        if (fcn)
-          {
-            octave_value_list empty_args;
-
-            retval = (lvalue_list
-                      ? val.do_multi_index_op (nargout, empty_args,
-                                               lvalue_list)
-                      : val.do_multi_index_op (nargout, empty_args));
-          }
-      }
-
-    return retval;
-  }
-
-  octave_value
-  tree_index_expression::rvalue1 (int nargout)
-  {
-    octave_value retval;
-
-    const octave_value_list tmp = rvalue (nargout);
-
-    if (! tmp.empty ())
-      retval = tmp(0);
-
-    return retval;
-  }
-
   octave_lvalue
-  tree_index_expression::lvalue (void)
+  tree_index_expression::lvalue (tree_evaluator *tw)
   {
     octave_lvalue retval;
 
@@ -515,7 +247,7 @@
     std::list<string_vector>::iterator p_arg_nm = arg_nm.begin ();
     std::list<tree_expression *>::iterator p_dyn_field = dyn_field.begin ();
 
-    retval = expr->lvalue ();
+    retval = expr->lvalue (tw);
 
     octave_value tmp = retval.value ();
 
@@ -546,7 +278,7 @@
           case '(':
             {
               octave_value_list tidx
-                = make_value_list (*p_args, *p_arg_nm, &tmp, false);
+                = make_value_list (tw, *p_args, *p_arg_nm, &tmp, false);
 
               idx.push_back (tidx);
 
@@ -564,7 +296,7 @@
           case '{':
             {
               octave_value_list tidx
-                = make_value_list (*p_args, *p_arg_nm, &tmp, false);
+                = make_value_list (tw, *p_args, *p_arg_nm, &tmp, false);
 
               if (tmp.is_undefined ())
                 {
@@ -589,7 +321,7 @@
 
           case '.':
             {
-              octave_value tidx = get_struct_index (p_arg_nm, p_dyn_field);
+              octave_value tidx = get_struct_index (tw, p_arg_nm, p_dyn_field);
 
               bool autoconv = (tmp.is_zero_by_zero ()
                                && (tmp.is_matrix_type () || tmp.is_string ()
@@ -684,12 +416,6 @@
 
     return new_idx_expr;
   }
-
-  void
-  tree_index_expression::accept (tree_walker& tw)
-  {
-    tw.visit_index_expression (*this);
-  }
 }
 
 /*