diff libinterp/octave-value/cdef-object.cc @ 31607:aac27ad79be6 stable

maint: Re-indent code after switch to using namespace macros. * build-env.h, build-env.in.cc, Cell.h, __betainc__.cc, __eigs__.cc, __ftp__.cc, __ichol__.cc, __ilu__.cc, __isprimelarge__.cc, __magick_read__.cc, __pchip_deriv__.cc, amd.cc, base-text-renderer.cc, base-text-renderer.h, besselj.cc, bitfcns.cc, bsxfun.cc, c-file-ptr-stream.h, call-stack.cc, call-stack.h, ccolamd.cc, cellfun.cc, chol.cc, colamd.cc, dasrt.cc, data.cc, debug.cc, defaults.cc, defaults.h, det.cc, display.cc, display.h, dlmread.cc, dynamic-ld.cc, dynamic-ld.h, ellipj.cc, environment.cc, environment.h, error.cc, error.h, errwarn.h, event-manager.cc, event-manager.h, event-queue.cc, event-queue.h, fcn-info.cc, fcn-info.h, fft.cc, fft2.cc, file-io.cc, filter.cc, find.cc, ft-text-renderer.cc, ft-text-renderer.h, gcd.cc, gl-render.cc, gl-render.h, gl2ps-print.cc, gl2ps-print.h, graphics-toolkit.cc, graphics-toolkit.h, graphics.cc, gsvd.cc, gtk-manager.cc, gtk-manager.h, help.cc, help.h, hook-fcn.cc, hook-fcn.h, input.cc, input.h, interpreter-private.cc, interpreter-private.h, interpreter.cc, interpreter.h, inv.cc, jsondecode.cc, jsonencode.cc, latex-text-renderer.cc, latex-text-renderer.h, load-path.cc, load-path.h, load-save.cc, load-save.h, lookup.cc, ls-hdf5.cc, ls-mat4.cc, ls-mat5.cc, lsode.cc, lu.cc, mappers.cc, matrix_type.cc, max.cc, mex.cc, mexproto.h, mxarray.h, mxtypes.in.h, oct-errno.in.cc, oct-hdf5-types.cc, oct-hist.cc, oct-hist.h, oct-map.cc, oct-map.h, oct-opengl.h, oct-prcstrm.h, oct-process.cc, oct-process.h, oct-stdstrm.h, oct-stream.cc, oct-stream.h, oct-strstrm.h, octave-default-image.h, ordqz.cc, ordschur.cc, pager.cc, pager.h, pinv.cc, pow2.cc, pr-output.cc, psi.cc, qr.cc, quadcc.cc, rand.cc, regexp.cc, settings.cc, settings.h, sighandlers.cc, sighandlers.h, sparse-xpow.cc, sqrtm.cc, stack-frame.cc, stack-frame.h, stream-euler.cc, strfns.cc, svd.cc, syminfo.cc, syminfo.h, symrcm.cc, symrec.cc, symrec.h, symscope.cc, symscope.h, symtab.cc, symtab.h, sysdep.cc, sysdep.h, text-engine.cc, text-engine.h, text-renderer.cc, text-renderer.h, time.cc, toplev.cc, typecast.cc, url-handle-manager.cc, url-handle-manager.h, urlwrite.cc, utils.cc, utils.h, variables.cc, variables.h, xdiv.cc, __delaunayn__.cc, __init_fltk__.cc, __init_gnuplot__.cc, __ode15__.cc, __voronoi__.cc, audioread.cc, convhulln.cc, gzip.cc, cdef-class.cc, cdef-class.h, cdef-fwd.h, cdef-manager.cc, cdef-manager.h, cdef-method.cc, cdef-method.h, cdef-object.cc, cdef-object.h, cdef-package.cc, cdef-package.h, cdef-property.cc, cdef-property.h, cdef-utils.cc, cdef-utils.h, ov-base-diag.cc, ov-base-int.cc, ov-base-mat.cc, ov-base-mat.h, ov-base-scalar.cc, ov-base.cc, ov-base.h, ov-bool-mat.cc, ov-bool-mat.h, ov-bool-sparse.cc, ov-bool.cc, ov-builtin.h, ov-cell.cc, ov-ch-mat.cc, ov-class.cc, ov-class.h, ov-classdef.cc, ov-classdef.h, ov-complex.cc, ov-cx-diag.cc, ov-cx-mat.cc, ov-cx-sparse.cc, ov-dld-fcn.cc, ov-dld-fcn.h, ov-fcn-handle.cc, ov-fcn-handle.h, ov-fcn.h, ov-float.cc, ov-flt-complex.cc, ov-flt-cx-diag.cc, ov-flt-cx-mat.cc, ov-flt-re-diag.cc, ov-flt-re-mat.cc, ov-flt-re-mat.h, ov-intx.h, ov-java.cc, ov-lazy-idx.cc, ov-legacy-range.cc, ov-magic-int.cc, ov-mex-fcn.cc, ov-mex-fcn.h, ov-null-mat.cc, ov-perm.cc, ov-range.cc, ov-re-diag.cc, ov-re-mat.cc, ov-re-mat.h, ov-re-sparse.cc, ov-scalar.cc, ov-str-mat.cc, ov-struct.cc, ov-typeinfo.cc, ov-typeinfo.h, ov-usr-fcn.cc, ov-usr-fcn.h, ov.cc, ov.h, ovl.h, octave.cc, octave.h, op-b-sbm.cc, op-bm-sbm.cc, op-cs-scm.cc, op-fm-fcm.cc, op-fs-fcm.cc, op-s-scm.cc, op-scm-cs.cc, op-scm-s.cc, op-sm-cs.cc, ops.h, anon-fcn-validator.cc, anon-fcn-validator.h, bp-table.cc, bp-table.h, comment-list.cc, comment-list.h, filepos.h, lex.h, oct-lvalue.cc, oct-lvalue.h, parse.h, profiler.cc, profiler.h, pt-anon-scopes.cc, pt-anon-scopes.h, pt-arg-list.cc, pt-arg-list.h, pt-args-block.cc, pt-args-block.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-cell.cc, pt-cell.h, pt-check.cc, pt-check.h, pt-classdef.cc, pt-classdef.h, 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-id.cc, pt-id.h, pt-idx.cc, pt-idx.h, 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-spmd.cc, pt-spmd.h, pt-stmt.cc, pt-stmt.h, pt-tm-const.cc, pt-tm-const.h, pt-unop.cc, pt-unop.h, pt-walk.cc, pt-walk.h, pt.cc, pt.h, token.cc, token.h, Range.cc, Range.h, idx-vector.cc, idx-vector.h, range-fwd.h, CollocWt.cc, CollocWt.h, aepbalance.cc, aepbalance.h, chol.cc, chol.h, gepbalance.cc, gepbalance.h, gsvd.cc, gsvd.h, hess.cc, hess.h, lo-mappers.cc, lo-mappers.h, lo-specfun.cc, lo-specfun.h, lu.cc, lu.h, oct-convn.cc, oct-convn.h, oct-fftw.cc, oct-fftw.h, oct-norm.cc, oct-norm.h, oct-rand.cc, oct-rand.h, oct-spparms.cc, oct-spparms.h, qr.cc, qr.h, qrp.cc, qrp.h, randgamma.cc, randgamma.h, randmtzig.cc, randmtzig.h, randpoisson.cc, randpoisson.h, schur.cc, schur.h, sparse-chol.cc, sparse-chol.h, sparse-lu.cc, sparse-lu.h, sparse-qr.cc, sparse-qr.h, svd.cc, svd.h, child-list.cc, child-list.h, dir-ops.cc, dir-ops.h, file-ops.cc, file-ops.h, file-stat.cc, file-stat.h, lo-sysdep.cc, lo-sysdep.h, lo-sysinfo.cc, lo-sysinfo.h, mach-info.cc, mach-info.h, oct-env.cc, oct-env.h, oct-group.cc, oct-group.h, oct-password.cc, oct-password.h, oct-syscalls.cc, oct-syscalls.h, oct-time.cc, oct-time.h, oct-uname.cc, oct-uname.h, action-container.cc, action-container.h, base-list.h, cmd-edit.cc, cmd-edit.h, cmd-hist.cc, cmd-hist.h, f77-fcn.h, file-info.cc, file-info.h, lo-array-errwarn.cc, lo-array-errwarn.h, lo-hash.cc, lo-hash.h, lo-ieee.h, lo-regexp.cc, lo-regexp.h, lo-utils.cc, lo-utils.h, oct-base64.cc, oct-base64.h, oct-glob.cc, oct-glob.h, oct-inttypes.h, oct-mutex.cc, oct-mutex.h, oct-refcount.h, oct-shlib.cc, oct-shlib.h, oct-sparse.cc, oct-sparse.h, oct-string.h, octave-preserve-stream-state.h, pathsearch.cc, pathsearch.h, quit.cc, quit.h, unwind-prot.cc, unwind-prot.h, url-transfer.cc, url-transfer.h: Re-indent code after switch to using namespace macros.
author Rik <rik@octave.org>
date Thu, 01 Dec 2022 18:02:15 -0800
parents e88a07dec498
children 597f3ee61a48
line wrap: on
line diff
--- a/libinterp/octave-value/cdef-object.cc	Thu Dec 01 14:23:45 2022 -0800
+++ b/libinterp/octave-value/cdef-object.cc	Thu Dec 01 18:02:15 2022 -0800
@@ -40,201 +40,298 @@
 
 OCTAVE_BEGIN_NAMESPACE(octave)
 
-  void
-  cdef_object_rep::release (const cdef_object& obj)
-  {
-    // We need to be careful to keep a reference to the object if we are
-    // calling the delete method.  The object is passed to the delete
-    // method as an argument and if the count is already zero when we
-    // do that, then we will increment the count while creating the
-    // argument list for the delete method and then it will be decremented
-    // back to zero and we'll find ourselves in an infinite loop.
+void
+cdef_object_rep::release (const cdef_object& obj)
+{
+  // We need to be careful to keep a reference to the object if we are
+  // calling the delete method.  The object is passed to the delete
+  // method as an argument and if the count is already zero when we
+  // do that, then we will increment the count while creating the
+  // argument list for the delete method and then it will be decremented
+  // back to zero and we'll find ourselves in an infinite loop.
+
+  if (m_count - 1 > static_count ())
+    {
+      --m_count;
+      return;
+    }
+
+  if (is_handle_object () && ! is_meta_object ())
+    {
+      unwind_protect frame;
+
+      // Clear interrupts.
+      frame.protect_var (octave_interrupt_state);
+      octave_interrupt_state = 0;
+
+      // Disallow quit().
+      frame.protect_var (quit_allowed);
+      quit_allowed = false;
+
+      interpreter& interp = __get_interpreter__ ();
+
+      interpreter_try (frame);
+
+      try
+        {
+          // Call classdef "delete()" method on object
+          get_class ().delete_object (obj);
+        }
+      catch (const interrupt_exception&)
+        {
+          interp.recover_from_exception ();
+
+          warning ("interrupt occurred in handle class delete method");
+        }
+      catch (const execution_exception& ee)
+        {
+          interp.recover_from_exception ();
+
+          std::string msg = ee.message ();
 
-    if (m_count - 1 > static_count ())
-      {
-        --m_count;
-        return;
-      }
+          warning ("error caught while executing handle class delete method:\n%s\n",
+                   msg.c_str ());
+        }
+      catch (const exit_exception&)
+        {
+          // This shouldn't happen since we disabled quit above.
+          warning ("exit disabled while executing handle class delete method");
+        }
+      catch (...) // Yes, the black hole.  We're in a d-tor.
+        {
+          // This shouldn't happen, in theory.
+          warning ("internal error: unhandled exception in handle class delete method");
+        }
+    }
 
-    if (is_handle_object () && ! is_meta_object ())
-      {
-        unwind_protect frame;
+  // Now it is safe to set the count to zero.
+  m_count--;
+
+  destroy ();
+}
+
+cdef_class
+cdef_object_rep::get_class (void) const
+{
+  err_invalid_object ("get_class");
+}
 
-        // Clear interrupts.
-        frame.protect_var (octave_interrupt_state);
-        octave_interrupt_state = 0;
+std::string
+cdef_object_rep::class_name (void) const
+{
+  return get_class ().get_name ();
+}
+
+string_vector
+cdef_object_rep::map_keys (void) const
+{
+  cdef_class cls = get_class ();
+
+  if (cls.ok ())
+    return cls.get_names ();
+
+  return string_vector ();
+}
 
-        // Disallow quit().
-        frame.protect_var (quit_allowed);
-        quit_allowed = false;
+octave_map
+cdef_object::map_value (void) const
+{
+  octave_map retval;
 
-        interpreter& interp = __get_interpreter__ ();
+  warning_with_id ("Octave:classdef-to-struct",
+                   "struct: converting a classdef object into a struct "
+                   "overrides the access restrictions defined for properties. "
+                   "All properties are returned, including private and "
+                   "protected ones.");
+
+  cdef_class cls = get_class ();
+
+  if (cls.ok ())
+    {
+      std::map<std::string, cdef_property> props;
+
+      props = cls.get_property_map (cdef_class::property_all);
 
-        interpreter_try (frame);
+      // FIXME: Why not const here?
+      for (auto& prop_val : props)
+        {
+          if (is_array ())
+            {
+              Array<cdef_object> a_obj = array_value ();
+
+              Cell cvalue (a_obj.dims ());
+
+              for (octave_idx_type i = 0; i < a_obj.numel (); i++)
+                cvalue (i) = prop_val.second.get_value (a_obj(i), false);
+
+              retval.setfield (prop_val.first, cvalue);
+            }
+          else
+            {
+              Cell cvalue (dim_vector (1, 1),
+                           prop_val.second.get_value (*this, false));
+
+              retval.setfield (prop_val.first, cvalue);
+            }
+        }
+    }
+
+  return retval;
+}
+
+cdef_class
+cdef_object::get_class (void) const
+{
+  return m_rep->get_class ();
+}
+
+cdef_class
+cdef_object_base::get_class (void) const
+{
+  return cdef_class (m_klass);
+}
 
-        try
-          {
-            // Call classdef "delete()" method on object
-            get_class ().delete_object (obj);
-          }
-        catch (const interrupt_exception&)
-          {
-            interp.recover_from_exception ();
+void
+cdef_object_base::set_class (const cdef_class& cls)
+{
+  if ((m_klass.ok () && cls.ok () && cls != get_class ())
+      || (m_klass.ok () && ! cls.ok ())
+      || (! m_klass.ok () && cls.ok ()))
+    {
+      m_klass = cls;
+    }
+}
+
+cdef_object_rep *
+cdef_object_base::make_array (void) const
+{
+  cdef_object_rep *r = new cdef_object_array ();
+
+  r->set_class (get_class ());
 
-            warning ("interrupt occurred in handle class delete method");
-          }
-        catch (const execution_exception& ee)
+  return r;
+}
+
+octave_value_list
+cdef_object_array::subsref (const std::string& type,
+                            const std::list<octave_value_list>& idx,
+                            int /* nargout */, std::size_t& skip,
+                            const cdef_class& /* context */, bool auto_add)
+{
+  octave_value_list retval;
+
+  skip = 1;
+
+  switch (type[0])
+    {
+    case '(':
+      {
+        const octave_value_list& ival = idx.front ();
+
+        if (ival.empty ())
           {
-            interp.recover_from_exception ();
-
-            std::string msg = ee.message ();
-
-            warning ("error caught while executing handle class delete method:\n%s\n",
-                     msg.c_str ());
+            m_count++;
+            retval(0) = to_ov (cdef_object (this));
+            break;
           }
-        catch (const exit_exception&)
+
+        bool is_scalar = true;
+        Array<idx_vector> iv (dim_vector (1, ival.length ()));
+
+        for (int i = 0; i < ival.length (); i++)
           {
-            // This shouldn't happen since we disabled quit above.
-            warning ("exit disabled while executing handle class delete method");
+            try
+              {
+                iv(i) = ival(i).index_vector ();
+              }
+            catch (index_exception& ie)
+              {
+                // Rethrow to allow more info to be reported later.
+                ie.set_pos_if_unset (ival.length (), i+1);
+                throw;
+              }
+
+            is_scalar = is_scalar && iv(i).is_scalar ();
           }
-        catch (...) // Yes, the black hole.  We're in a d-tor.
+
+        Array<cdef_object> ires = m_array.index (iv, auto_add);
+
+        // If resizing is enabled (auto_add = true), it's possible
+        // indexing was out-of-bound and the result array contains
+        // invalid cdef_objects.
+
+        if (auto_add)
+          fill_empty_values (ires);
+
+        if (is_scalar)
+          retval(0) = to_ov (ires(0));
+        else
           {
-            // This shouldn't happen, in theory.
-            warning ("internal error: unhandled exception in handle class delete method");
+            cdef_object array_obj (new cdef_object_array (ires));
+
+            array_obj.set_class (get_class ());
+
+            retval(0) = to_ov (array_obj);
           }
       }
-
-    // Now it is safe to set the count to zero.
-    m_count--;
-
-    destroy ();
-  }
-
-  cdef_class
-  cdef_object_rep::get_class (void) const
-  {
-    err_invalid_object ("get_class");
-  }
-
-  std::string
-  cdef_object_rep::class_name (void) const
-  {
-    return get_class ().get_name ();
-  }
-
-  string_vector
-  cdef_object_rep::map_keys (void) const
-  {
-    cdef_class cls = get_class ();
-
-    if (cls.ok ())
-      return cls.get_names ();
-
-    return string_vector ();
-  }
+      break;
 
-  octave_map
-  cdef_object::map_value (void) const
-  {
-    octave_map retval;
-
-    warning_with_id ("Octave:classdef-to-struct",
-                     "struct: converting a classdef object into a struct "
-                     "overrides the access restrictions defined for properties. "
-                     "All properties are returned, including private and "
-                     "protected ones.");
-
-    cdef_class cls = get_class ();
+    case '.':
+      if (type.size () == 1 && idx.size () == 1)
+        {
+          Cell c (dims ());
 
-    if (cls.ok ())
-      {
-        std::map<std::string, cdef_property> props;
-
-        props = cls.get_property_map (cdef_class::property_all);
-
-        // FIXME: Why not const here?
-        for (auto& prop_val : props)
-          {
-            if (is_array ())
-              {
-                Array<cdef_object> a_obj = array_value ();
-
-                Cell cvalue (a_obj.dims ());
-
-                for (octave_idx_type i = 0; i < a_obj.numel (); i++)
-                  cvalue (i) = prop_val.second.get_value (a_obj(i), false);
+          octave_idx_type n = m_array.numel ();
 
-                retval.setfield (prop_val.first, cvalue);
-              }
-            else
-              {
-                Cell cvalue (dim_vector (1, 1),
-                             prop_val.second.get_value (*this, false));
-
-                retval.setfield (prop_val.first, cvalue);
-              }
-          }
-      }
-
-    return retval;
-  }
-
-  cdef_class
-  cdef_object::get_class (void) const
-  {
-    return m_rep->get_class ();
-  }
-
-  cdef_class
-  cdef_object_base::get_class (void) const
-  {
-    return cdef_class (m_klass);
-  }
+          // dummy variables
+          std::size_t dummy_skip;
+          cdef_class dummy_cls;
 
-  void
-  cdef_object_base::set_class (const cdef_class& cls)
-  {
-    if ((m_klass.ok () && cls.ok () && cls != get_class ())
-        || (m_klass.ok () && ! cls.ok ())
-        || (! m_klass.ok () && cls.ok ()))
-      {
-        m_klass = cls;
-      }
-  }
-
-  cdef_object_rep *
-  cdef_object_base::make_array (void) const
-  {
-    cdef_object_rep *r = new cdef_object_array ();
-
-    r->set_class (get_class ());
-
-    return r;
-  }
+          for (octave_idx_type i = 0; i < n; i++)
+            {
+              octave_value_list r = m_array(i).subsref (type, idx, 1,
+                                    dummy_skip,
+                                    dummy_cls);
 
-  octave_value_list
-  cdef_object_array::subsref (const std::string& type,
-                              const std::list<octave_value_list>& idx,
-                              int /* nargout */, std::size_t& skip,
-                              const cdef_class& /* context */, bool auto_add)
-  {
-    octave_value_list retval;
-
-    skip = 1;
-
-    switch (type[0])
-      {
-      case '(':
-        {
-          const octave_value_list& ival = idx.front ();
-
-          if (ival.empty ())
-            {
-              m_count++;
-              retval(0) = to_ov (cdef_object (this));
-              break;
+              if (r.length () > 0)
+                c(i) = r(0);
             }
 
+          retval(0) = octave_value (c, true);
+
+          break;
+        }
+      OCTAVE_FALLTHROUGH;
+
+    default:
+      error ("can't perform indexing operation on array of %s objects",
+             class_name ().c_str ());
+      break;
+    }
+
+  return retval;
+}
+
+octave_value
+cdef_object_array::subsasgn (const std::string& type,
+                             const std::list<octave_value_list>& idx,
+                             const octave_value& rhs)
+{
+  octave_value retval;
+
+  switch (type[0])
+    {
+    case '(':
+      if (type.length () == 1)
+        {
+          cdef_object rhs_obj = to_cdef (rhs);
+
+          if (rhs_obj.get_class () != get_class ())
+            error ("can't assign %s object into array of %s objects",
+                   rhs_obj.class_name ().c_str (),
+                   class_name ().c_str ());
+
+          const octave_value_list& ival = idx.front ();
           bool is_scalar = true;
           Array<idx_vector> iv (dim_vector (1, ival.length ()));
 
@@ -246,509 +343,412 @@
                 }
               catch (index_exception& ie)
                 {
+                  ie.set_pos_if_unset (ival.length (), i+1);
+                  throw;   // var name set in pt-idx.cc / pt-assign.cc
+                }
+
+              is_scalar = is_scalar && iv(i).is_scalar ();
+            }
+
+          Array<cdef_object> rhs_mat;
+
+          if (! rhs_obj.is_array ())
+            {
+              rhs_mat = Array<cdef_object> (dim_vector (1, 1));
+              rhs_mat(0) = rhs_obj;
+            }
+          else
+            rhs_mat = rhs_obj.array_value ();
+
+          octave_idx_type n = m_array.numel ();
+
+          m_array.assign (iv, rhs_mat, cdef_object ());
+
+          if (m_array.numel () > n)
+            fill_empty_values ();
+
+          m_count++;
+          retval = to_ov (cdef_object (this));
+        }
+      else
+        {
+          const octave_value_list& ivl = idx.front ();
+
+          // Fill in trailing singleton dimensions so that
+          // array.index doesn't create a new blank entry (bug #46660).
+          const octave_idx_type one = static_cast<octave_idx_type> (1);
+          const octave_value_list& ival = ivl.length () >= 2
+                                          ? ivl : ((m_array.dims ()(0) == 1)
+                                              ? ovl (one, ivl(0))
+                                              : ovl (ivl(0), one));
+
+          bool is_scalar = true;
+
+          Array<idx_vector> iv (dim_vector (1, ival.length ()));
+
+          for (int i = 0; i < ival.length (); i++)
+            {
+              try
+                {
+                  iv(i) = ival(i).index_vector ();
+                }
+              catch (index_exception& ie)
+                {
                   // Rethrow to allow more info to be reported later.
                   ie.set_pos_if_unset (ival.length (), i+1);
                   throw;
                 }
 
               is_scalar = is_scalar && iv(i).is_scalar ();
+
+              if (! is_scalar)
+                error ("subsasgn: invalid indexing for object array assignment"
+                       ", the index must reference a single object in the "
+                       "array.");
+            }
+
+          Array<cdef_object> a = m_array.index (iv, true);
+
+          if (a.numel () != 1)
+            error ("subsasgn: invalid indexing for object array assignment");
+
+          cdef_object obj = a(0);
+
+          int ignore_copies = 0;
+
+          // If the object in 'a' is not valid, this means the index
+          // was out-of-bound and we need to create a new object.
+
+          if (! obj.ok ())
+            obj = get_class ().construct_object (octave_value_list ());
+          else
+            // Optimize the subsasgn call to come.  There are 2 copies
+            // that we can safely ignore:
+            // - 1 in "array"
+            // - 1 in "a"
+            ignore_copies = 2;
+
+          std::list<octave_value_list> next_idx (idx);
+
+          next_idx.erase (next_idx.begin ());
+
+          octave_value tmp = obj.subsasgn (type.substr (1), next_idx,
+                                           rhs, ignore_copies);
+
+          cdef_object robj = to_cdef (tmp);
+
+          if (! robj.ok ()
+              || robj.is_array ()
+              || robj.get_class () != get_class ())
+            error ("subsasgn: invalid assignment into array of %s objects",
+                   class_name ().c_str ());
+
+          // Small optimization, when dealing with handle
+          // objects, we don't need to re-assign the result
+          // of subsasgn back into the array.
+
+          if (! robj.is (a(0)))
+            {
+              Array<cdef_object> rhs_a (dim_vector (1, 1),
+                                        robj);
+
+              octave_idx_type n = m_array.numel ();
+
+              m_array.assign (iv, rhs_a);
+
+              if (m_array.numel () > n)
+                fill_empty_values ();
             }
 
-          Array<cdef_object> ires = m_array.index (iv, auto_add);
+          m_count++;
 
-          // If resizing is enabled (auto_add = true), it's possible
-          // indexing was out-of-bound and the result array contains
-          // invalid cdef_objects.
-
-          if (auto_add)
-            fill_empty_values (ires);
+          retval = to_ov (cdef_object (this));
+        }
+      break;
 
-          if (is_scalar)
-            retval(0) = to_ov (ires(0));
-          else
-            {
-              cdef_object array_obj (new cdef_object_array (ires));
+    default:
+      error ("can't perform indexing operation on array of %s objects",
+             class_name ().c_str ());
+      break;
+    }
 
-              array_obj.set_class (get_class ());
+  return retval;
+}
 
-              retval(0) = to_ov (array_obj);
-            }
-        }
-        break;
+void
+cdef_object_array::fill_empty_values (Array<cdef_object>& arr)
+{
+  cdef_class cls = get_class ();
 
-      case '.':
-        if (type.size () == 1 && idx.size () == 1)
-          {
-            Cell c (dims ());
+  cdef_object obj;
 
-            octave_idx_type n = m_array.numel ();
-
-            // dummy variables
-            std::size_t dummy_skip;
-            cdef_class dummy_cls;
+  int n = arr.numel ();
 
-            for (octave_idx_type i = 0; i < n; i++)
-              {
-                octave_value_list r = m_array(i).subsref (type, idx, 1,
-                                                          dummy_skip,
-                                                          dummy_cls);
+  for (int i = 0; i < n; i++)
+    {
+      if (! arr.xelem (i).ok ())
+        {
+          if (! obj.ok ())
+            {
+              obj = cls.construct_object (octave_value_list ());
 
-                if (r.length () > 0)
-                  c(i) = r(0);
-              }
-
-            retval(0) = octave_value (c, true);
+              arr.xelem (i) = obj;
+            }
+          else
+            arr.xelem (i) = obj.copy ();
+        }
+    }
+}
 
-            break;
-          }
-        OCTAVE_FALLTHROUGH;
+void
+cdef_object_scalar::break_closure_cycles (const std::shared_ptr<stack_frame>& frame)
+{
+  for (octave_idx_type i = 0; i < m_map.nfields (); i++)
+    m_map.contents(i).break_closure_cycles (frame);
+}
 
-      default:
-        error ("can't perform indexing operation on array of %s objects",
-               class_name ().c_str ());
-        break;
-      }
+octave_value_list
+cdef_object_scalar::subsref (const std::string& type,
+                             const std::list<octave_value_list>& idx,
+                             int nargout, std::size_t& skip,
+                             const cdef_class& context, bool auto_add)
+{
+  skip = 0;
 
+  cdef_class cls = (context.ok () ? context : get_class ());
+
+  octave_value_list retval;
+
+  if (! cls.ok ())
     return retval;
-  }
 
-  octave_value
-  cdef_object_array::subsasgn (const std::string& type,
-                               const std::list<octave_value_list>& idx,
-                               const octave_value& rhs)
-  {
-    octave_value retval;
+  switch (type[0])
+    {
+    case '.':
+      {
+        std::string name = (idx.front ())(0).string_value ();
 
-    switch (type[0])
-      {
-      case '(':
-        if (type.length () == 1)
+        cdef_method meth = cls.find_method (name);
+
+        if (meth.ok ())
           {
-            cdef_object rhs_obj = to_cdef (rhs);
+            int _nargout = (type.length () > 2 ? 1 : nargout);
 
-            if (rhs_obj.get_class () != get_class ())
-              error ("can't assign %s object into array of %s objects",
-                     rhs_obj.class_name ().c_str (),
-                     class_name ().c_str ());
+            octave_value_list args;
 
-            const octave_value_list& ival = idx.front ();
-            bool is_scalar = true;
-            Array<idx_vector> iv (dim_vector (1, ival.length ()));
+            skip = 1;
 
-            for (int i = 0; i < ival.length (); i++)
+            if (type.length () > 1 && type[1] == '(')
               {
-                try
-                  {
-                    iv(i) = ival(i).index_vector ();
-                  }
-                catch (index_exception& ie)
-                  {
-                    ie.set_pos_if_unset (ival.length (), i+1);
-                    throw;   // var name set in pt-idx.cc / pt-assign.cc
-                  }
+                auto it = idx.begin ();
 
-                is_scalar = is_scalar && iv(i).is_scalar ();
+                args = *++it;
+
+                skip++;
               }
 
-            Array<cdef_object> rhs_mat;
-
-            if (! rhs_obj.is_array ())
-              {
-                rhs_mat = Array<cdef_object> (dim_vector (1, 1));
-                rhs_mat(0) = rhs_obj;
-              }
+            if (meth.is_static ())
+              retval = meth.execute (args, _nargout, true, "subsref");
             else
-              rhs_mat = rhs_obj.array_value ();
-
-            octave_idx_type n = m_array.numel ();
-
-            m_array.assign (iv, rhs_mat, cdef_object ());
-
-            if (m_array.numel () > n)
-              fill_empty_values ();
-
-            m_count++;
-            retval = to_ov (cdef_object (this));
+              {
+                m_count++;
+                retval = meth.execute (cdef_object (this), args, _nargout,
+                                       true, "subsref");
+              }
           }
-        else
-          {
-            const octave_value_list& ivl = idx.front ();
 
-            // Fill in trailing singleton dimensions so that
-            // array.index doesn't create a new blank entry (bug #46660).
-            const octave_idx_type one = static_cast<octave_idx_type> (1);
-            const octave_value_list& ival = ivl.length () >= 2
-                                            ? ivl : ((m_array.dims ()(0) == 1)
-                                                     ? ovl (one, ivl(0))
-                                                     : ovl (ivl(0), one));
+        if (skip == 0)
+          {
+            cdef_property prop = cls.find_property (name);
 
-            bool is_scalar = true;
+            if (! prop.ok ())
+              error ("subsref: unknown method or property: %s", name.c_str ());
 
-            Array<idx_vector> iv (dim_vector (1, ival.length ()));
-
-            for (int i = 0; i < ival.length (); i++)
+            if (prop.is_constant ())
+              retval(0) = prop.get_value (true, "subsref");
+            else
               {
-                try
-                  {
-                    iv(i) = ival(i).index_vector ();
-                  }
-                catch (index_exception& ie)
-                  {
-                    // Rethrow to allow more info to be reported later.
-                    ie.set_pos_if_unset (ival.length (), i+1);
-                    throw;
-                  }
-
-                is_scalar = is_scalar && iv(i).is_scalar ();
-
-                if (! is_scalar)
-                  error ("subsasgn: invalid indexing for object array assignment"
-                         ", the index must reference a single object in the "
-                         "array.");
+                m_count++;
+                retval(0) = prop.get_value (cdef_object (this),
+                                            true, "subsref");
               }
 
-            Array<cdef_object> a = m_array.index (iv, true);
-
-            if (a.numel () != 1)
-              error ("subsasgn: invalid indexing for object array assignment");
-
-            cdef_object obj = a(0);
-
-            int ignore_copies = 0;
-
-            // If the object in 'a' is not valid, this means the index
-            // was out-of-bound and we need to create a new object.
-
-            if (! obj.ok ())
-              obj = get_class ().construct_object (octave_value_list ());
-            else
-              // Optimize the subsasgn call to come.  There are 2 copies
-              // that we can safely ignore:
-              // - 1 in "array"
-              // - 1 in "a"
-              ignore_copies = 2;
-
-            std::list<octave_value_list> next_idx (idx);
-
-            next_idx.erase (next_idx.begin ());
-
-            octave_value tmp = obj.subsasgn (type.substr (1), next_idx,
-                                             rhs, ignore_copies);
-
-            cdef_object robj = to_cdef (tmp);
-
-            if (! robj.ok ()
-                || robj.is_array ()
-                || robj.get_class () != get_class ())
-              error ("subsasgn: invalid assignment into array of %s objects",
-                     class_name ().c_str ());
-
-            // Small optimization, when dealing with handle
-            // objects, we don't need to re-assign the result
-            // of subsasgn back into the array.
-
-            if (! robj.is (a(0)))
-              {
-                Array<cdef_object> rhs_a (dim_vector (1, 1),
-                                          robj);
-
-                octave_idx_type n = m_array.numel ();
-
-                m_array.assign (iv, rhs_a);
-
-                if (m_array.numel () > n)
-                  fill_empty_values ();
-              }
-
-            m_count++;
-
-            retval = to_ov (cdef_object (this));
+            skip = 1;
           }
         break;
-
-      default:
-        error ("can't perform indexing operation on array of %s objects",
-               class_name ().c_str ());
-        break;
       }
 
-    return retval;
-  }
+    case '(':
+      {
+        const octave_value_list& ival = idx.front ();
+
+        m_count++;
+        cdef_object this_obj (this);
+
+        if (ival.empty ())
+          {
+            skip++;
+            retval(0) = to_ov (this_obj);
+          }
+        else
+          {
+            Array<cdef_object> arr (dim_vector (1, 1), this_obj);
+
+            cdef_object new_obj = cdef_object (new cdef_object_array (arr));
+
+            new_obj.set_class (get_class ());
 
-  void
-  cdef_object_array::fill_empty_values (Array<cdef_object>& arr)
-  {
-    cdef_class cls = get_class ();
+            retval = new_obj.subsref (type, idx, nargout, skip, cls, auto_add);
+          }
+      }
+      break;
+
+    default:
+      error ("object cannot be indexed with '%c'", type[0]);
+      break;
+    }
 
-    cdef_object obj;
+  return retval;
+}
 
-    int n = arr.numel ();
+octave_value
+cdef_object_scalar::subsasgn (const std::string& type,
+                              const std::list<octave_value_list>& idx,
+                              const octave_value& rhs)
+{
+  octave_value retval;
+
+  cdef_class cls = get_class ();
 
-    for (int i = 0; i < n; i++)
+  switch (type[0])
+    {
+    case '.':
       {
-        if (! arr.xelem (i).ok ())
+        std::string name = (idx.front ())(0).string_value ();
+
+        cdef_property prop = cls.find_property (name);
+
+        if (! prop.ok ())
+          error ("subsasgn: unknown property: %s", name.c_str ());
+
+        if (prop.is_constant ())
+          error ("subsasgn: cannot assign constant property: %s",
+                 name.c_str ());
+
+        m_count++;
+
+        cdef_object obj (this);
+
+        if (type.length () == 1)
           {
-            if (! obj.ok ())
-              {
-                obj = cls.construct_object (octave_value_list ());
+            prop.set_value (obj, rhs, true, "subsasgn");
+
+            retval = to_ov (obj);
+          }
+        else
+          {
+            octave_value val = prop.get_value (obj, true, "subsasgn");
+
+            std::list<octave_value_list> args (idx);
 
-                arr.xelem (i) = obj;
-              }
-            else
-              arr.xelem (i) = obj.copy ();
+            args.erase (args.begin ());
+
+            val = val.assign (octave_value::op_asn_eq,
+                              type.substr (1), args, rhs);
+
+            if (val.class_name () != "object"
+                || ! to_cdef (val).is_handle_object ())
+              prop.set_value (obj, val, true, "subsasgn");
+
+            retval = to_ov (obj);
           }
       }
-  }
-
-  void
-  cdef_object_scalar::break_closure_cycles (const std::shared_ptr<stack_frame>& frame)
-  {
-    for (octave_idx_type i = 0; i < m_map.nfields (); i++)
-      m_map.contents(i).break_closure_cycles (frame);
-  }
+      break;
 
-  octave_value_list
-  cdef_object_scalar::subsref (const std::string& type,
-                               const std::list<octave_value_list>& idx,
-                               int nargout, std::size_t& skip,
-                               const cdef_class& context, bool auto_add)
-  {
-    skip = 0;
-
-    cdef_class cls = (context.ok () ? context : get_class ());
-
-    octave_value_list retval;
-
-    if (! cls.ok ())
-      return retval;
+    case '(':
+      {
+        m_count++;
 
-    switch (type[0])
-      {
-      case '.':
-        {
-          std::string name = (idx.front ())(0).string_value ();
-
-          cdef_method meth = cls.find_method (name);
-
-          if (meth.ok ())
-            {
-              int _nargout = (type.length () > 2 ? 1 : nargout);
+        cdef_object this_obj (this);
 
-              octave_value_list args;
-
-              skip = 1;
+        Array<cdef_object> arr (dim_vector (1, 1), this_obj);
 
-              if (type.length () > 1 && type[1] == '(')
-                {
-                  auto it = idx.begin ();
-
-                  args = *++it;
-
-                  skip++;
-                }
+        cdef_object new_obj = cdef_object (new cdef_object_array (arr));
 
-              if (meth.is_static ())
-                retval = meth.execute (args, _nargout, true, "subsref");
-              else
-                {
-                  m_count++;
-                  retval = meth.execute (cdef_object (this), args, _nargout,
-                                         true, "subsref");
-                }
-            }
+        new_obj.set_class (get_class ());
 
-          if (skip == 0)
-            {
-              cdef_property prop = cls.find_property (name);
-
-              if (! prop.ok ())
-                error ("subsref: unknown method or property: %s", name.c_str ());
-
-              if (prop.is_constant ())
-                retval(0) = prop.get_value (true, "subsref");
-              else
-                {
-                  m_count++;
-                  retval(0) = prop.get_value (cdef_object (this),
-                                              true, "subsref");
-                }
+        octave_value tmp = new_obj.subsasgn (type, idx, rhs);
 
-              skip = 1;
-            }
-          break;
-        }
-
-      case '(':
-        {
-          const octave_value_list& ival = idx.front ();
-
-          m_count++;
-          cdef_object this_obj (this);
+        retval = tmp;
+      }
+      break;
 
-          if (ival.empty ())
-            {
-              skip++;
-              retval(0) = to_ov (this_obj);
-            }
-          else
-            {
-              Array<cdef_object> arr (dim_vector (1, 1), this_obj);
-
-              cdef_object new_obj = cdef_object (new cdef_object_array (arr));
-
-              new_obj.set_class (get_class ());
-
-              retval = new_obj.subsref (type, idx, nargout, skip, cls, auto_add);
-            }
-        }
-        break;
-
-      default:
-        error ("object cannot be indexed with '%c'", type[0]);
-        break;
-      }
+    default:
+      error ("subsasgn: object cannot be index with '%c'", type[0]);
+      break;
+    }
 
-    return retval;
-  }
-
-  octave_value
-  cdef_object_scalar::subsasgn (const std::string& type,
-                                const std::list<octave_value_list>& idx,
-                                const octave_value& rhs)
-  {
-    octave_value retval;
-
-    cdef_class cls = get_class ();
-
-    switch (type[0])
-      {
-      case '.':
-        {
-          std::string name = (idx.front ())(0).string_value ();
-
-          cdef_property prop = cls.find_property (name);
-
-          if (! prop.ok ())
-            error ("subsasgn: unknown property: %s", name.c_str ());
+  return retval;
+}
 
-          if (prop.is_constant ())
-            error ("subsasgn: cannot assign constant property: %s",
-                   name.c_str ());
-
-          m_count++;
-
-          cdef_object obj (this);
-
-          if (type.length () == 1)
-            {
-              prop.set_value (obj, rhs, true, "subsasgn");
+void
+cdef_object_scalar::mark_for_construction (const cdef_class& cls)
+{
+  std::string cls_name = cls.get_name ();
 
-              retval = to_ov (obj);
-            }
-          else
-            {
-              octave_value val = prop.get_value (obj, true, "subsasgn");
-
-              std::list<octave_value_list> args (idx);
+  Cell supcls = cls.get ("SuperClasses").cell_value ();
 
-              args.erase (args.begin ());
+  std::list<cdef_class> supcls_list = lookup_classes (supcls);
 
-              val = val.assign (octave_value::op_asn_eq,
-                                type.substr (1), args, rhs);
-
-              if (val.class_name () != "object"
-                  || ! to_cdef (val).is_handle_object ())
-                prop.set_value (obj, val, true, "subsasgn");
+  m_ctor_list[cls] = supcls_list;
+}
 
-              retval = to_ov (obj);
-            }
-        }
-        break;
-
-      case '(':
-        {
-          m_count++;
-
-          cdef_object this_obj (this);
-
-          Array<cdef_object> arr (dim_vector (1, 1), this_obj);
-
-          cdef_object new_obj = cdef_object (new cdef_object_array (arr));
-
-          new_obj.set_class (get_class ());
-
-          octave_value tmp = new_obj.subsasgn (type, idx, rhs);
-
-          retval = tmp;
-        }
-        break;
-
-      default:
-        error ("subsasgn: object cannot be index with '%c'", type[0]);
-        break;
-      }
+bool
+cdef_object_scalar::is_constructed_for (const cdef_class& cls) const
+{
+  return (is_constructed ()
+          || m_ctor_list.find (cls) == m_ctor_list.end ());
+}
 
-    return retval;
-  }
-
-  void
-  cdef_object_scalar::mark_for_construction (const cdef_class& cls)
-  {
-    std::string cls_name = cls.get_name ();
-
-    Cell supcls = cls.get ("SuperClasses").cell_value ();
-
-    std::list<cdef_class> supcls_list = lookup_classes (supcls);
-
-    m_ctor_list[cls] = supcls_list;
-  }
+bool
+cdef_object_scalar::is_partially_constructed_for (const cdef_class& cls) const
+{
+  if (is_constructed ())
+    return true;
 
-  bool
-  cdef_object_scalar::is_constructed_for (const cdef_class& cls) const
-  {
-    return (is_constructed ()
-            || m_ctor_list.find (cls) == m_ctor_list.end ());
-  }
-
-  bool
-  cdef_object_scalar::is_partially_constructed_for (const cdef_class& cls) const
-  {
-    if (is_constructed ())
-      return true;
-
-    std::map<cdef_class, std::list<cdef_class>>::const_iterator it
+  std::map<cdef_class, std::list<cdef_class>>::const_iterator it
       = m_ctor_list.find (cls);
 
-    if (it == m_ctor_list.end () || it->second.empty ())
-      return true;
-
-    for (const auto& cdef_cls : it->second)
-      if (! is_partially_constructed_for (cdef_cls))
-        return false;
-
+  if (it == m_ctor_list.end () || it->second.empty ())
     return true;
-  }
+
+  for (const auto& cdef_cls : it->second)
+    if (! is_partially_constructed_for (cdef_cls))
+      return false;
 
-  void
-  cdef_object_scalar::mark_as_constructed (const cdef_class& cls)
-  {
-    m_ctor_list.erase (cls);
-  }
+  return true;
+}
+
+void
+cdef_object_scalar::mark_as_constructed (const cdef_class& cls)
+{
+  m_ctor_list.erase (cls);
+}
 
-  handle_cdef_object::~handle_cdef_object (void)
-  {
+handle_cdef_object::~handle_cdef_object (void)
+{
 #if DEBUG_TRACE
-    std::cerr << "deleting " << get_class ().get_name ()
-              << " object (handle)" << std::endl;
+  std::cerr << "deleting " << get_class ().get_name ()
+            << " object (handle)" << std::endl;
 #endif
-  }
+}
 
-  value_cdef_object::~value_cdef_object (void)
-  {
+value_cdef_object::~value_cdef_object (void)
+{
 #if DEBUG_TRACE
-    std::cerr << "deleting " << get_class ().get_name ()
-              << " object (value)" << std::endl;
+  std::cerr << "deleting " << get_class ().get_name ()
+            << " object (value)" << std::endl;
 #endif
-  }
+}
 
 OCTAVE_END_NAMESPACE(octave)