diff libinterp/parse-tree/pt-idx.cc @ 23075:4e3d47dc7e25

move parse tree classes inside octave namespace * lex.h, lex.ll, oct-parse.in.yy, parse.h, pt-all.h, pt-arg-list.cc, pt-arg-list.h, pt-array-list.cc, pt-array-list.h, pt-assign.cc, pt-assign.h, pt-binop.cc, pt-binop.h, pt-bp.cc, pt-bp.h, pt-cbinop.cc, pt-cbinop.h, pt.cc, pt-cell.cc, pt-cell.h, pt-check.cc, pt-check.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.h, pt-id.cc, pt-id.h, pt-idx.cc, pt-idx.h, 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-pr-code.cc, pt-pr-code.h, pt-select.cc, pt-select.h, pt-stmt.cc, pt-stmt.h, pt-unop.cc, pt-unop.h, pt-walk.h, token.cc, token.h: Move classes and most functions inside octave namespace. Change all uses.
author John W. Eaton <jwe@octave.org>
date Thu, 19 Jan 2017 23:41:54 -0500
parents dcbd2ceadff1
children ef4d915df748
line wrap: on
line diff
--- a/libinterp/parse-tree/pt-idx.cc	Thu Jan 19 14:47:19 2017 -0500
+++ b/libinterp/parse-tree/pt-idx.cc	Thu Jan 19 23:41:54 2017 -0500
@@ -40,111 +40,114 @@
 #include "variables.h"
 #include "errwarn.h"
 
-// Index expressions.
-
-tree_index_expression::tree_index_expression (int l, int c)
-  : tree_expression (l, c), expr (0), args (0), type (),
-    arg_nm (), dyn_field () { }
-
-tree_index_expression::tree_index_expression (tree_expression *e,
-                                              tree_argument_list *lst,
-                                              int l, int c, char t)
-  : tree_expression (l, c), expr (e), args (0), type (),
-    arg_nm (), dyn_field ()
-{
-  append (lst, t);
-}
-
-tree_index_expression::tree_index_expression (tree_expression *e,
-                                              const std::string& n,
-                                              int l, int c)
-  : tree_expression (l, c), expr (e), args (0), type (),
-    arg_nm (), dyn_field ()
-{
-  append (n);
-}
-
-tree_index_expression::tree_index_expression (tree_expression *e,
-                                              tree_expression *df,
-                                              int l, int c)
-  : tree_expression (l, c), expr (e), args (0), type (),
-    arg_nm (), dyn_field ()
-{
-  append (df);
-}
-
-void
-tree_index_expression::append (tree_argument_list *lst, char t)
-{
-  args.push_back (lst);
-  type.append (1, t);
-  arg_nm.push_back (lst ? lst->get_arg_names () : string_vector ());
-  dyn_field.push_back (static_cast<tree_expression *> (0));
-
-  if (lst && lst->has_magic_tilde ())
-    error ("invalid use of empty argument (~) in index expression");
-}
-
-void
-tree_index_expression::append (const std::string& n)
+namespace octave
 {
-  args.push_back (static_cast<tree_argument_list *> (0));
-  type.append (".");
-  arg_nm.push_back (n);
-  dyn_field.push_back (static_cast<tree_expression *> (0));
-}
+  // Index expressions.
+
+  tree_index_expression::tree_index_expression (int l, int c)
+    : tree_expression (l, c), expr (0), args (0), type (),
+      arg_nm (), dyn_field () { }
+
+  tree_index_expression::tree_index_expression (tree_expression *e,
+                                                tree_argument_list *lst,
+                                                int l, int c, char t)
+    : tree_expression (l, c), expr (e), args (0), type (),
+      arg_nm (), dyn_field ()
+  {
+    append (lst, t);
+  }
 
-void
-tree_index_expression::append (tree_expression *df)
-{
-  args.push_back (static_cast<tree_argument_list *> (0));
-  type.append (".");
-  arg_nm.push_back ("");
-  dyn_field.push_back (df);
-}
+  tree_index_expression::tree_index_expression (tree_expression *e,
+                                                const std::string& n,
+                                                int l, int c)
+    : tree_expression (l, c), expr (e), args (0), type (),
+      arg_nm (), dyn_field ()
+  {
+    append (n);
+  }
 
-tree_index_expression::~tree_index_expression (void)
-{
-  delete expr;
+  tree_index_expression::tree_index_expression (tree_expression *e,
+                                                tree_expression *df,
+                                                int l, int c)
+    : tree_expression (l, c), expr (e), args (0), type (),
+      arg_nm (), dyn_field ()
+  {
+    append (df);
+  }
 
-  while (! args.empty ())
-    {
-      std::list<tree_argument_list *>::iterator p = args.begin ();
-      delete *p;
-      args.erase (p);
-    }
+  void
+  tree_index_expression::append (tree_argument_list *lst, char t)
+  {
+    args.push_back (lst);
+    type.append (1, t);
+    arg_nm.push_back (lst ? lst->get_arg_names () : string_vector ());
+    dyn_field.push_back (static_cast<tree_expression *> (0));
+
+    if (lst && lst->has_magic_tilde ())
+      error ("invalid use of empty argument (~) in index expression");
+  }
 
-  while (! dyn_field.empty ())
-    {
-      std::list<tree_expression *>::iterator p = dyn_field.begin ();
-      delete *p;
-      dyn_field.erase (p);
-    }
-}
+  void
+  tree_index_expression::append (const std::string& n)
+  {
+    args.push_back (static_cast<tree_argument_list *> (0));
+    type.append (".");
+    arg_nm.push_back (n);
+    dyn_field.push_back (static_cast<tree_expression *> (0));
+  }
+
+  void
+  tree_index_expression::append (tree_expression *df)
+  {
+    args.push_back (static_cast<tree_argument_list *> (0));
+    type.append (".");
+    arg_nm.push_back ("");
+    dyn_field.push_back (df);
+  }
+
+  tree_index_expression::~tree_index_expression (void)
+  {
+    delete expr;
+
+    while (! args.empty ())
+      {
+        std::list<tree_argument_list *>::iterator p = args.begin ();
+        delete *p;
+        args.erase (p);
+      }
 
-bool
-tree_index_expression::has_magic_end (void) const
-{
-  for (const tree_argument_list* elt : args)
-    {
-      if (elt && elt->has_magic_end ())
-        return true;
-    }
+    while (! dyn_field.empty ())
+      {
+        std::list<tree_expression *>::iterator p = dyn_field.begin ();
+        delete *p;
+        dyn_field.erase (p);
+      }
+  }
 
-  return false;
-}
+  bool
+  tree_index_expression::has_magic_end (void) const
+  {
+    for (const tree_argument_list* elt : args)
+      {
+        if (elt && elt->has_magic_end ())
+          return true;
+      }
 
-// This is useful for printing the name of the variable in an indexed
-// assignment.
+    return false;
+  }
+
+  // This is useful for printing the name of the variable in an indexed
+  // assignment.
 
-std::string
-tree_index_expression::name (void) const
-{
-  return expr->name ();
+  std::string
+  tree_index_expression::name (void) const
+  {
+    return expr->name ();
+  }
 }
 
 static Cell
-make_subs_cell (tree_argument_list *args, const string_vector& arg_nm)
+make_subs_cell (octave::tree_argument_list *args, const string_vector& arg_nm)
 {
   Cell retval;
 
@@ -169,7 +172,7 @@
 }
 
 static inline octave_value_list
-make_value_list (tree_argument_list *args, const string_vector& arg_nm,
+make_value_list (octave::tree_argument_list *args, const string_vector& arg_nm,
                  const octave_value *object, bool rvalue = true)
 {
   octave_value_list retval;
@@ -190,79 +193,82 @@
   return retval;
 }
 
-std::string
-tree_index_expression::get_struct_index
+namespace octave
+{
+  std::string
+  tree_index_expression::get_struct_index
   (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);
+  {
+    std::string fn = (*p_arg_nm)(0);
 
-  if (fn.empty ())
-    {
-      tree_expression *df = *p_dyn_field;
+    if (fn.empty ())
+      {
+        tree_expression *df = *p_dyn_field;
 
-      if (df)
-        {
-          octave_value t = df->rvalue1 ();
+        if (df)
+          {
+            octave_value t = df->rvalue1 ();
 
-          fn = t.xstring_value ("dynamic structure field names must be strings");
-        }
-      else
-        panic_impossible ();
-    }
+            fn = t.xstring_value ("dynamic structure field names must be strings");
+          }
+        else
+          panic_impossible ();
+      }
 
-  return fn;
-}
+    return fn;
+  }
 
-octave_map
-tree_index_expression::make_arg_struct (void) const
-{
-  int n = args.size ();
+  octave_map
+  tree_index_expression::make_arg_struct (void) const
+  {
+    int n = args.size ();
 
-  Cell type_field (n, 1);
-  Cell subs_field (n, 1);
+    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 ();
+    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;
+    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;
+    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) = make_subs_cell (*p_args, *p_arg_nm);
+            break;
 
-        case '.':
-          subs_field(i) = get_struct_index (p_arg_nm, p_dyn_field);
-          break;
+          case '.':
+            subs_field(i) = get_struct_index (p_arg_nm, p_dyn_field);
+            break;
 
-        default:
-          panic_impossible ();
-        }
+          default:
+            panic_impossible ();
+          }
 
-      p_args++;
-      p_arg_nm++;
-      p_dyn_field++;
-    }
+        p_args++;
+        p_arg_nm++;
+        p_dyn_field++;
+      }
 
-  m.assign ("type", type_field);
-  m.assign ("subs", subs_field);
+    m.assign ("type", type_field);
+    m.assign ("subs", subs_field);
+
+    return m;
+  }
 
-  return m;
-}
-
-octave_value_list
-tree_index_expression::rvalue (int nargout)
-{
-  return tree_index_expression::rvalue (nargout, 0);
+  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
@@ -270,12 +276,13 @@
 // be needed by pt-lvalue, which calls subsref?)
 
 static void
-final_index_error (octave::index_exception& e, const tree_expression *expr)
+final_index_error (octave::index_exception& e,
+                   const octave::tree_expression *expr)
 {
   std::string extra_message;
 
   if (expr->is_identifier ()
-      && dynamic_cast<const tree_identifier *> (expr)->is_variable ())
+      && dynamic_cast<const octave::tree_identifier *> (expr)->is_variable ())
     {
       std::string var = expr->name ();
 
@@ -297,338 +304,379 @@
   error_with_id (e.err_id (), msg.c_str ());
 }
 
-octave_value_list
-tree_index_expression::rvalue (int nargout,
-                               const std::list<octave_lvalue> *lvalue_list)
+namespace octave
 {
-  octave_value_list retval;
+  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;
 
-  octave_value first_expr_val;
+    bool have_args = false;
+
+    if (expr->is_identifier () && type[0] == '(')
+      {
+        tree_identifier *id = dynamic_cast<tree_identifier *> (expr);
 
-  octave_value_list first_args;
+        if (! (id->is_variable () || args.empty ()))
+          {
+            tree_argument_list *al = *(args.begin ());
+
+            size_t n = al ? al->length () : 0;
 
-  bool have_args = false;
+            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);
 
-  if (expr->is_identifier () && type[0] == '(')
-    {
-      tree_identifier *id = dynamic_cast<tree_identifier *> (expr);
+                first_expr_val = id->do_lookup  (first_args);
+              }
+          }
+      }
 
-      if (! (id->is_variable () || args.empty ()))
-        {
-          tree_argument_list *al = *(args.begin ());
+    if (first_expr_val.is_undefined ())
+      first_expr_val = expr->rvalue1 ();
+
+    octave_value tmp = first_expr_val;
+    octave_idx_type tmpi = 0;
 
-          size_t n = al ? al->length () : 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 ();
 
-          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);
+    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.
+            bool force_split = type[i-1] == '(' && type[i] != '.';
 
-              first_expr_val = id->do_lookup  (first_args);
-            }
-        }
-    }
+            if (force_split || (al && al->has_magic_end ()))
+              {
+                // (we have force_split, or) we 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.
+
+                try
+                  {
+                    octave_value_list tmp_list
+                      =tmp.subsref (type.substr (tmpi, i-tmpi), idx, nargout);
 
-  if (first_expr_val.is_undefined ())
-    first_expr_val = expr->rvalue1 ();
+                    tmp = tmp_list.length () ? tmp_list(0) : octave_value ();
+                    tmpi = i;
+                    idx.clear ();
+
+                    if (tmp.is_cs_list ())
+                      err_indexed_cs_list ();
 
-  octave_value tmp = first_expr_val;
-  octave_idx_type tmpi = 0;
+                    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;
 
-  std::list<octave_value_list> idx;
-
-  int n = args.size ();
+                            tmp_list = tmp.do_multi_index_op (1, empty_args);
+                            tmp = (tmp_list.length ()
+                                   ? tmp_list(0) : octave_value ());
 
-  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 ();
+                            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);
+                  }
+              }
+          }
 
-  for (int i = 0; i < n; i++)
-    {
-      if (i > 0)
-        {
-          tree_argument_list *al = *p_args;
+        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++;
+      }
 
-          // 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.
-          bool force_split = type[i-1] == '(' && type[i] != '.';
+    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;
+  }
 
-          if (force_split || (al && al->has_magic_end ()))
+  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)
+  {
+    octave_lvalue retval;
+
+    std::list<octave_value_list> idx;
+    std::string tmp_type;
+
+    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 ();
+
+    retval = expr->lvalue ();
+
+    octave_value tmp = retval.value ();
+
+    octave_idx_type tmpi = 0;
+    std::list<octave_value_list> tmpidx;
+
+    for (int i = 0; i < n; i++)
+      {
+        if (retval.numel () != 1)
+          err_indexed_cs_list ();
+
+        if (tmpi < i)
+          {
+            try
+              {
+                tmp = tmp.subsref (type.substr (tmpi, i-tmpi), tmpidx, true);
+              }
+            catch (octave::index_exception& e)  // problems with range, invalid type etc.
+              {
+                final_index_error (e, expr);
+              }
+
+            tmpidx.clear ();
+          }
+
+        switch (type[i])
+          {
+          case '(':
             {
-              // (we have force_split, or) we 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.
+              octave_value_list tidx
+                = make_value_list (*p_args, *p_arg_nm, &tmp, false);
 
-              try
+              idx.push_back (tidx);
+
+              if (i < n - 1)
                 {
-                  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 (type[i+1] != '.')
+                    error ("() must be followed by . or close the index chain");
 
-                      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);
+                  tmpidx.push_back (tidx);
+                  tmpi = i+1;
                 }
             }
-        }
+            break;
 
-      switch (type[i])
-        {
-        case '(':
-          if (have_args)
+          case '{':
             {
-              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;
+              octave_value_list tidx
+                = make_value_list (*p_args, *p_arg_nm, &tmp, false);
 
-        default:
-          panic_impossible ();
-        }
-
-      p_args++;
-      p_arg_nm++;
-      p_dyn_field++;
-    }
+              if (tmp.is_undefined ())
+                {
+                  if (tidx.has_magic_colon ())
+                    err_invalid_inquiry_subscript ();
 
-  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);
-    }
+                  tmp = Cell ();
+                }
+              else if (tmp.is_zero_by_zero ()
+                       && (tmp.is_matrix_type () || tmp.is_string ()))
+                {
+                  tmp = Cell ();
+                }
 
-  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.numel (tmp.numel (tidx));
 
-          retval = (lvalue_list
-                    ? val.do_multi_index_op (nargout, empty_args,
-                                             lvalue_list)
-                    : val.do_multi_index_op (nargout, empty_args));
-        }
-    }
-
-  return retval;
-}
+              idx.push_back (tidx);
+              tmpidx.push_back (tidx);
+              tmpi = i;
+            }
+            break;
 
-octave_value
-tree_index_expression::rvalue1 (int nargout)
-{
-  octave_value retval;
-
-  const octave_value_list tmp = rvalue (nargout);
+          case '.':
+            {
+              octave_value tidx = get_struct_index (p_arg_nm, p_dyn_field);
 
-  if (! tmp.empty ())
-    retval = tmp(0);
-
-  return retval;
-}
-
-octave_lvalue
-tree_index_expression::lvalue (void)
-{
-  octave_lvalue retval;
+              bool autoconv = (tmp.is_zero_by_zero ()
+                               && (tmp.is_matrix_type () || tmp.is_string ()
+                                   || tmp.is_cell ()));
 
-  std::list<octave_value_list> idx;
-  std::string tmp_type;
-
-  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 ();
-
-  retval = expr->lvalue ();
-
-  octave_value tmp = retval.value ();
-
-  octave_idx_type tmpi = 0;
-  std::list<octave_value_list> tmpidx;
+              if (i > 0 && type[i-1] == '(')
+                {
+                  octave_value_list pidx = idx.back ();
 
-  for (int i = 0; i < n; i++)
-    {
-      if (retval.numel () != 1)
-        err_indexed_cs_list ();
+                  // Use octave_map, not octave_scalar_map so that the
+                  // dimensions are 0x0, not 1x1.
+                  if (tmp.is_undefined ())
+                    {
+                      if (pidx.has_magic_colon ())
+                        err_invalid_inquiry_subscript ();
 
-      if (tmpi < i)
-        {
-          try
-            {
-              tmp = tmp.subsref (type.substr (tmpi, i-tmpi), tmpidx, true);
-            }
-          catch (octave::index_exception& e)  // problems with range, invalid type etc.
-            {
-              final_index_error (e, expr);
-            }
+                      tmp = octave_map ();
+                    }
+                  else if (autoconv)
+                    tmp = octave_map ();
+
+                  retval.numel (tmp.numel (pidx));
 
-          tmpidx.clear ();
-        }
-
-      switch (type[i])
-        {
-        case '(':
-          {
-            octave_value_list tidx
-              = make_value_list (*p_args, *p_arg_nm, &tmp, false);
-
-            idx.push_back (tidx);
-
-            if (i < n - 1)
-              {
-                if (type[i+1] != '.')
-                  error ("() must be followed by . or close the index chain");
-
-                tmpidx.push_back (tidx);
-                tmpi = i+1;
-              }
-          }
-          break;
-
-        case '{':
-          {
-            octave_value_list tidx
-              = make_value_list (*p_args, *p_arg_nm, &tmp, false);
+                  tmpi = i-1;
+                  tmpidx.push_back (tidx);
+                }
+              else
+                {
+                  if (tmp.is_undefined () || autoconv)
+                    {
+                      tmpi = i+1;
+                      tmp = octave_value ();
+                    }
+                  else
+                    {
+                      retval.numel (tmp.numel (octave_value_list ()));
 
-            if (tmp.is_undefined ())
-              {
-                if (tidx.has_magic_colon ())
-                  err_invalid_inquiry_subscript ();
+                      tmpi = i;
+                      tmpidx.push_back (tidx);
+                    }
+                }
 
-                tmp = Cell ();
-              }
-            else if (tmp.is_zero_by_zero ()
-                     && (tmp.is_matrix_type () || tmp.is_string ()))
-              {
-                tmp = Cell ();
-              }
+              idx.push_back (tidx);
+            }
+            break;
 
-            retval.numel (tmp.numel (tidx));
+          default:
+            panic_impossible ();
+          }
 
-            idx.push_back (tidx);
-            tmpidx.push_back (tidx);
-            tmpi = i;
-          }
-          break;
+        if (idx.back ().empty ())
+          error ("invalid empty index list");
 
-        case '.':
-          {
-            octave_value tidx = get_struct_index (p_arg_nm, p_dyn_field);
+        p_args++;
+        p_arg_nm++;
+        p_dyn_field++;
+      }
 
-            bool autoconv = (tmp.is_zero_by_zero ()
-                             && (tmp.is_matrix_type () || tmp.is_string ()
-                                 || tmp.is_cell ()));
+    retval.set_index (type, idx);
 
-            if (i > 0 && type[i-1] == '(')
-              {
-                octave_value_list pidx = idx.back ();
+    return retval;
+  }
 
-                // Use octave_map, not octave_scalar_map so that the
-                // dimensions are 0x0, not 1x1.
-                if (tmp.is_undefined ())
-                  {
-                    if (pidx.has_magic_colon ())
-                      err_invalid_inquiry_subscript ();
+  tree_index_expression *
+  tree_index_expression::dup (symbol_table::scope_id scope,
+                              symbol_table::context_id context) const
+  {
+    tree_index_expression *new_idx_expr
+      = new tree_index_expression (line (), column ());
 
-                    tmp = octave_map ();
-                  }
-                else if (autoconv)
-                  tmp = octave_map ();
+    new_idx_expr->expr = expr ? expr->dup (scope, context) : 0;
+
+    std::list<tree_argument_list *> new_args;
 
-                retval.numel (tmp.numel (pidx));
+    for (const tree_argument_list* elt : args)
+      new_args.push_back (elt ? elt->dup (scope, context) : 0);
+
+    new_idx_expr->args = new_args;
 
-                tmpi = i-1;
-                tmpidx.push_back (tidx);
-              }
-            else
-              {
-                if (tmp.is_undefined () || autoconv)
-                  {
-                    tmpi = i+1;
-                    tmp = octave_value ();
-                  }
-                else
-                  {
-                    retval.numel (tmp.numel (octave_value_list ()));
+    new_idx_expr->type = type;
+
+    new_idx_expr->arg_nm = arg_nm;
 
-                    tmpi = i;
-                    tmpidx.push_back (tidx);
-                  }
-              }
+    std::list<tree_expression *> new_dyn_field;
+
+    for (const tree_expression* elt : dyn_field)
+      new_dyn_field.push_back (elt ? elt->dup (scope, context) : 0);
+
+    new_idx_expr->dyn_field = new_dyn_field;
 
-            idx.push_back (tidx);
-          }
-          break;
+    new_idx_expr->copy_base (*this);
 
-        default:
-          panic_impossible ();
-        }
+    return new_idx_expr;
+  }
 
-      if (idx.back ().empty ())
-        error ("invalid empty index list");
-
-      p_args++;
-      p_arg_nm++;
-      p_dyn_field++;
-    }
-
-  retval.set_index (type, idx);
-
-  return retval;
+  void
+  tree_index_expression::accept (tree_walker& tw)
+  {
+    tw.visit_index_expression (*this);
+  }
 }
 
 /*
@@ -667,42 +715,3 @@
 %! x(2).b = 1;
 %! assert (x(2).b == 1);
 */
-
-tree_index_expression *
-tree_index_expression::dup (symbol_table::scope_id scope,
-                            symbol_table::context_id context) const
-{
-  tree_index_expression *new_idx_expr
-    = new tree_index_expression (line (), column ());
-
-  new_idx_expr->expr = expr ? expr->dup (scope, context) : 0;
-
-  std::list<tree_argument_list *> new_args;
-
-  for (const tree_argument_list* elt : args)
-    new_args.push_back (elt ? elt->dup (scope, context) : 0);
-
-  new_idx_expr->args = new_args;
-
-  new_idx_expr->type = type;
-
-  new_idx_expr->arg_nm = arg_nm;
-
-  std::list<tree_expression *> new_dyn_field;
-
-  for (const tree_expression* elt : dyn_field)
-    new_dyn_field.push_back (elt ? elt->dup (scope, context) : 0);
-
-  new_idx_expr->dyn_field = new_dyn_field;
-
-  new_idx_expr->copy_base (*this);
-
-  return new_idx_expr;
-}
-
-void
-tree_index_expression::accept (tree_walker& tw)
-{
-  tw.visit_index_expression (*this);
-}
-