comparison 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
comparison
equal deleted inserted replaced
31605:e88a07dec498 31607:aac27ad79be6
38 // Define to 1 to enable debugging statements. 38 // Define to 1 to enable debugging statements.
39 #define DEBUG_TRACE 0 39 #define DEBUG_TRACE 0
40 40
41 OCTAVE_BEGIN_NAMESPACE(octave) 41 OCTAVE_BEGIN_NAMESPACE(octave)
42 42
43 void 43 void
44 cdef_object_rep::release (const cdef_object& obj) 44 cdef_object_rep::release (const cdef_object& obj)
45 { 45 {
46 // We need to be careful to keep a reference to the object if we are 46 // We need to be careful to keep a reference to the object if we are
47 // calling the delete method. The object is passed to the delete 47 // calling the delete method. The object is passed to the delete
48 // method as an argument and if the count is already zero when we 48 // method as an argument and if the count is already zero when we
49 // do that, then we will increment the count while creating the 49 // do that, then we will increment the count while creating the
50 // argument list for the delete method and then it will be decremented 50 // argument list for the delete method and then it will be decremented
51 // back to zero and we'll find ourselves in an infinite loop. 51 // back to zero and we'll find ourselves in an infinite loop.
52 52
53 if (m_count - 1 > static_count ()) 53 if (m_count - 1 > static_count ())
54 {
55 --m_count;
56 return;
57 }
58
59 if (is_handle_object () && ! is_meta_object ())
60 {
61 unwind_protect frame;
62
63 // Clear interrupts.
64 frame.protect_var (octave_interrupt_state);
65 octave_interrupt_state = 0;
66
67 // Disallow quit().
68 frame.protect_var (quit_allowed);
69 quit_allowed = false;
70
71 interpreter& interp = __get_interpreter__ ();
72
73 interpreter_try (frame);
74
75 try
76 {
77 // Call classdef "delete()" method on object
78 get_class ().delete_object (obj);
79 }
80 catch (const interrupt_exception&)
81 {
82 interp.recover_from_exception ();
83
84 warning ("interrupt occurred in handle class delete method");
85 }
86 catch (const execution_exception& ee)
87 {
88 interp.recover_from_exception ();
89
90 std::string msg = ee.message ();
91
92 warning ("error caught while executing handle class delete method:\n%s\n",
93 msg.c_str ());
94 }
95 catch (const exit_exception&)
96 {
97 // This shouldn't happen since we disabled quit above.
98 warning ("exit disabled while executing handle class delete method");
99 }
100 catch (...) // Yes, the black hole. We're in a d-tor.
101 {
102 // This shouldn't happen, in theory.
103 warning ("internal error: unhandled exception in handle class delete method");
104 }
105 }
106
107 // Now it is safe to set the count to zero.
108 m_count--;
109
110 destroy ();
111 }
112
113 cdef_class
114 cdef_object_rep::get_class (void) const
115 {
116 err_invalid_object ("get_class");
117 }
118
119 std::string
120 cdef_object_rep::class_name (void) const
121 {
122 return get_class ().get_name ();
123 }
124
125 string_vector
126 cdef_object_rep::map_keys (void) const
127 {
128 cdef_class cls = get_class ();
129
130 if (cls.ok ())
131 return cls.get_names ();
132
133 return string_vector ();
134 }
135
136 octave_map
137 cdef_object::map_value (void) const
138 {
139 octave_map retval;
140
141 warning_with_id ("Octave:classdef-to-struct",
142 "struct: converting a classdef object into a struct "
143 "overrides the access restrictions defined for properties. "
144 "All properties are returned, including private and "
145 "protected ones.");
146
147 cdef_class cls = get_class ();
148
149 if (cls.ok ())
150 {
151 std::map<std::string, cdef_property> props;
152
153 props = cls.get_property_map (cdef_class::property_all);
154
155 // FIXME: Why not const here?
156 for (auto& prop_val : props)
157 {
158 if (is_array ())
159 {
160 Array<cdef_object> a_obj = array_value ();
161
162 Cell cvalue (a_obj.dims ());
163
164 for (octave_idx_type i = 0; i < a_obj.numel (); i++)
165 cvalue (i) = prop_val.second.get_value (a_obj(i), false);
166
167 retval.setfield (prop_val.first, cvalue);
168 }
169 else
170 {
171 Cell cvalue (dim_vector (1, 1),
172 prop_val.second.get_value (*this, false));
173
174 retval.setfield (prop_val.first, cvalue);
175 }
176 }
177 }
178
179 return retval;
180 }
181
182 cdef_class
183 cdef_object::get_class (void) const
184 {
185 return m_rep->get_class ();
186 }
187
188 cdef_class
189 cdef_object_base::get_class (void) const
190 {
191 return cdef_class (m_klass);
192 }
193
194 void
195 cdef_object_base::set_class (const cdef_class& cls)
196 {
197 if ((m_klass.ok () && cls.ok () && cls != get_class ())
198 || (m_klass.ok () && ! cls.ok ())
199 || (! m_klass.ok () && cls.ok ()))
200 {
201 m_klass = cls;
202 }
203 }
204
205 cdef_object_rep *
206 cdef_object_base::make_array (void) const
207 {
208 cdef_object_rep *r = new cdef_object_array ();
209
210 r->set_class (get_class ());
211
212 return r;
213 }
214
215 octave_value_list
216 cdef_object_array::subsref (const std::string& type,
217 const std::list<octave_value_list>& idx,
218 int /* nargout */, std::size_t& skip,
219 const cdef_class& /* context */, bool auto_add)
220 {
221 octave_value_list retval;
222
223 skip = 1;
224
225 switch (type[0])
226 {
227 case '(':
54 { 228 {
55 --m_count; 229 const octave_value_list& ival = idx.front ();
56 return; 230
231 if (ival.empty ())
232 {
233 m_count++;
234 retval(0) = to_ov (cdef_object (this));
235 break;
236 }
237
238 bool is_scalar = true;
239 Array<idx_vector> iv (dim_vector (1, ival.length ()));
240
241 for (int i = 0; i < ival.length (); i++)
242 {
243 try
244 {
245 iv(i) = ival(i).index_vector ();
246 }
247 catch (index_exception& ie)
248 {
249 // Rethrow to allow more info to be reported later.
250 ie.set_pos_if_unset (ival.length (), i+1);
251 throw;
252 }
253
254 is_scalar = is_scalar && iv(i).is_scalar ();
255 }
256
257 Array<cdef_object> ires = m_array.index (iv, auto_add);
258
259 // If resizing is enabled (auto_add = true), it's possible
260 // indexing was out-of-bound and the result array contains
261 // invalid cdef_objects.
262
263 if (auto_add)
264 fill_empty_values (ires);
265
266 if (is_scalar)
267 retval(0) = to_ov (ires(0));
268 else
269 {
270 cdef_object array_obj (new cdef_object_array (ires));
271
272 array_obj.set_class (get_class ());
273
274 retval(0) = to_ov (array_obj);
275 }
57 } 276 }
58 277 break;
59 if (is_handle_object () && ! is_meta_object ()) 278
60 { 279 case '.':
61 unwind_protect frame; 280 if (type.size () == 1 && idx.size () == 1)
62 281 {
63 // Clear interrupts. 282 Cell c (dims ());
64 frame.protect_var (octave_interrupt_state); 283
65 octave_interrupt_state = 0; 284 octave_idx_type n = m_array.numel ();
66 285
67 // Disallow quit(). 286 // dummy variables
68 frame.protect_var (quit_allowed); 287 std::size_t dummy_skip;
69 quit_allowed = false; 288 cdef_class dummy_cls;
70 289
71 interpreter& interp = __get_interpreter__ (); 290 for (octave_idx_type i = 0; i < n; i++)
72 291 {
73 interpreter_try (frame); 292 octave_value_list r = m_array(i).subsref (type, idx, 1,
74 293 dummy_skip,
75 try 294 dummy_cls);
76 { 295
77 // Call classdef "delete()" method on object 296 if (r.length () > 0)
78 get_class ().delete_object (obj); 297 c(i) = r(0);
79 } 298 }
80 catch (const interrupt_exception&) 299
81 { 300 retval(0) = octave_value (c, true);
82 interp.recover_from_exception (); 301
83 302 break;
84 warning ("interrupt occurred in handle class delete method"); 303 }
85 } 304 OCTAVE_FALLTHROUGH;
86 catch (const execution_exception& ee) 305
87 { 306 default:
88 interp.recover_from_exception (); 307 error ("can't perform indexing operation on array of %s objects",
89 308 class_name ().c_str ());
90 std::string msg = ee.message (); 309 break;
91 310 }
92 warning ("error caught while executing handle class delete method:\n%s\n", 311
93 msg.c_str ()); 312 return retval;
94 } 313 }
95 catch (const exit_exception&) 314
96 { 315 octave_value
97 // This shouldn't happen since we disabled quit above. 316 cdef_object_array::subsasgn (const std::string& type,
98 warning ("exit disabled while executing handle class delete method"); 317 const std::list<octave_value_list>& idx,
99 } 318 const octave_value& rhs)
100 catch (...) // Yes, the black hole. We're in a d-tor. 319 {
101 { 320 octave_value retval;
102 // This shouldn't happen, in theory. 321
103 warning ("internal error: unhandled exception in handle class delete method"); 322 switch (type[0])
104 } 323 {
105 } 324 case '(':
106 325 if (type.length () == 1)
107 // Now it is safe to set the count to zero. 326 {
108 m_count--; 327 cdef_object rhs_obj = to_cdef (rhs);
109 328
110 destroy (); 329 if (rhs_obj.get_class () != get_class ())
111 } 330 error ("can't assign %s object into array of %s objects",
112 331 rhs_obj.class_name ().c_str (),
113 cdef_class 332 class_name ().c_str ());
114 cdef_object_rep::get_class (void) const 333
115 {
116 err_invalid_object ("get_class");
117 }
118
119 std::string
120 cdef_object_rep::class_name (void) const
121 {
122 return get_class ().get_name ();
123 }
124
125 string_vector
126 cdef_object_rep::map_keys (void) const
127 {
128 cdef_class cls = get_class ();
129
130 if (cls.ok ())
131 return cls.get_names ();
132
133 return string_vector ();
134 }
135
136 octave_map
137 cdef_object::map_value (void) const
138 {
139 octave_map retval;
140
141 warning_with_id ("Octave:classdef-to-struct",
142 "struct: converting a classdef object into a struct "
143 "overrides the access restrictions defined for properties. "
144 "All properties are returned, including private and "
145 "protected ones.");
146
147 cdef_class cls = get_class ();
148
149 if (cls.ok ())
150 {
151 std::map<std::string, cdef_property> props;
152
153 props = cls.get_property_map (cdef_class::property_all);
154
155 // FIXME: Why not const here?
156 for (auto& prop_val : props)
157 {
158 if (is_array ())
159 {
160 Array<cdef_object> a_obj = array_value ();
161
162 Cell cvalue (a_obj.dims ());
163
164 for (octave_idx_type i = 0; i < a_obj.numel (); i++)
165 cvalue (i) = prop_val.second.get_value (a_obj(i), false);
166
167 retval.setfield (prop_val.first, cvalue);
168 }
169 else
170 {
171 Cell cvalue (dim_vector (1, 1),
172 prop_val.second.get_value (*this, false));
173
174 retval.setfield (prop_val.first, cvalue);
175 }
176 }
177 }
178
179 return retval;
180 }
181
182 cdef_class
183 cdef_object::get_class (void) const
184 {
185 return m_rep->get_class ();
186 }
187
188 cdef_class
189 cdef_object_base::get_class (void) const
190 {
191 return cdef_class (m_klass);
192 }
193
194 void
195 cdef_object_base::set_class (const cdef_class& cls)
196 {
197 if ((m_klass.ok () && cls.ok () && cls != get_class ())
198 || (m_klass.ok () && ! cls.ok ())
199 || (! m_klass.ok () && cls.ok ()))
200 {
201 m_klass = cls;
202 }
203 }
204
205 cdef_object_rep *
206 cdef_object_base::make_array (void) const
207 {
208 cdef_object_rep *r = new cdef_object_array ();
209
210 r->set_class (get_class ());
211
212 return r;
213 }
214
215 octave_value_list
216 cdef_object_array::subsref (const std::string& type,
217 const std::list<octave_value_list>& idx,
218 int /* nargout */, std::size_t& skip,
219 const cdef_class& /* context */, bool auto_add)
220 {
221 octave_value_list retval;
222
223 skip = 1;
224
225 switch (type[0])
226 {
227 case '(':
228 {
229 const octave_value_list& ival = idx.front (); 334 const octave_value_list& ival = idx.front ();
230 335 bool is_scalar = true;
231 if (ival.empty ()) 336 Array<idx_vector> iv (dim_vector (1, ival.length ()));
337
338 for (int i = 0; i < ival.length (); i++)
232 { 339 {
233 m_count++; 340 try
234 retval(0) = to_ov (cdef_object (this)); 341 {
235 break; 342 iv(i) = ival(i).index_vector ();
343 }
344 catch (index_exception& ie)
345 {
346 ie.set_pos_if_unset (ival.length (), i+1);
347 throw; // var name set in pt-idx.cc / pt-assign.cc
348 }
349
350 is_scalar = is_scalar && iv(i).is_scalar ();
236 } 351 }
237 352
353 Array<cdef_object> rhs_mat;
354
355 if (! rhs_obj.is_array ())
356 {
357 rhs_mat = Array<cdef_object> (dim_vector (1, 1));
358 rhs_mat(0) = rhs_obj;
359 }
360 else
361 rhs_mat = rhs_obj.array_value ();
362
363 octave_idx_type n = m_array.numel ();
364
365 m_array.assign (iv, rhs_mat, cdef_object ());
366
367 if (m_array.numel () > n)
368 fill_empty_values ();
369
370 m_count++;
371 retval = to_ov (cdef_object (this));
372 }
373 else
374 {
375 const octave_value_list& ivl = idx.front ();
376
377 // Fill in trailing singleton dimensions so that
378 // array.index doesn't create a new blank entry (bug #46660).
379 const octave_idx_type one = static_cast<octave_idx_type> (1);
380 const octave_value_list& ival = ivl.length () >= 2
381 ? ivl : ((m_array.dims ()(0) == 1)
382 ? ovl (one, ivl(0))
383 : ovl (ivl(0), one));
384
238 bool is_scalar = true; 385 bool is_scalar = true;
386
239 Array<idx_vector> iv (dim_vector (1, ival.length ())); 387 Array<idx_vector> iv (dim_vector (1, ival.length ()));
240 388
241 for (int i = 0; i < ival.length (); i++) 389 for (int i = 0; i < ival.length (); i++)
242 { 390 {
243 try 391 try
250 ie.set_pos_if_unset (ival.length (), i+1); 398 ie.set_pos_if_unset (ival.length (), i+1);
251 throw; 399 throw;
252 } 400 }
253 401
254 is_scalar = is_scalar && iv(i).is_scalar (); 402 is_scalar = is_scalar && iv(i).is_scalar ();
403
404 if (! is_scalar)
405 error ("subsasgn: invalid indexing for object array assignment"
406 ", the index must reference a single object in the "
407 "array.");
255 } 408 }
256 409
257 Array<cdef_object> ires = m_array.index (iv, auto_add); 410 Array<cdef_object> a = m_array.index (iv, true);
258 411
259 // If resizing is enabled (auto_add = true), it's possible 412 if (a.numel () != 1)
260 // indexing was out-of-bound and the result array contains 413 error ("subsasgn: invalid indexing for object array assignment");
261 // invalid cdef_objects. 414
262 415 cdef_object obj = a(0);
263 if (auto_add) 416
264 fill_empty_values (ires); 417 int ignore_copies = 0;
265 418
266 if (is_scalar) 419 // If the object in 'a' is not valid, this means the index
267 retval(0) = to_ov (ires(0)); 420 // was out-of-bound and we need to create a new object.
421
422 if (! obj.ok ())
423 obj = get_class ().construct_object (octave_value_list ());
268 else 424 else
425 // Optimize the subsasgn call to come. There are 2 copies
426 // that we can safely ignore:
427 // - 1 in "array"
428 // - 1 in "a"
429 ignore_copies = 2;
430
431 std::list<octave_value_list> next_idx (idx);
432
433 next_idx.erase (next_idx.begin ());
434
435 octave_value tmp = obj.subsasgn (type.substr (1), next_idx,
436 rhs, ignore_copies);
437
438 cdef_object robj = to_cdef (tmp);
439
440 if (! robj.ok ()
441 || robj.is_array ()
442 || robj.get_class () != get_class ())
443 error ("subsasgn: invalid assignment into array of %s objects",
444 class_name ().c_str ());
445
446 // Small optimization, when dealing with handle
447 // objects, we don't need to re-assign the result
448 // of subsasgn back into the array.
449
450 if (! robj.is (a(0)))
269 { 451 {
270 cdef_object array_obj (new cdef_object_array (ires)); 452 Array<cdef_object> rhs_a (dim_vector (1, 1),
271 453 robj);
272 array_obj.set_class (get_class ()); 454
273 455 octave_idx_type n = m_array.numel ();
274 retval(0) = to_ov (array_obj); 456
457 m_array.assign (iv, rhs_a);
458
459 if (m_array.numel () > n)
460 fill_empty_values ();
275 } 461 }
276 } 462
277 break; 463 m_count++;
278 464
279 case '.': 465 retval = to_ov (cdef_object (this));
280 if (type.size () == 1 && idx.size () == 1) 466 }
281 { 467 break;
282 Cell c (dims ()); 468
283 469 default:
284 octave_idx_type n = m_array.numel (); 470 error ("can't perform indexing operation on array of %s objects",
285 471 class_name ().c_str ());
286 // dummy variables 472 break;
287 std::size_t dummy_skip; 473 }
288 cdef_class dummy_cls; 474
289 475 return retval;
290 for (octave_idx_type i = 0; i < n; i++) 476 }
477
478 void
479 cdef_object_array::fill_empty_values (Array<cdef_object>& arr)
480 {
481 cdef_class cls = get_class ();
482
483 cdef_object obj;
484
485 int n = arr.numel ();
486
487 for (int i = 0; i < n; i++)
488 {
489 if (! arr.xelem (i).ok ())
490 {
491 if (! obj.ok ())
492 {
493 obj = cls.construct_object (octave_value_list ());
494
495 arr.xelem (i) = obj;
496 }
497 else
498 arr.xelem (i) = obj.copy ();
499 }
500 }
501 }
502
503 void
504 cdef_object_scalar::break_closure_cycles (const std::shared_ptr<stack_frame>& frame)
505 {
506 for (octave_idx_type i = 0; i < m_map.nfields (); i++)
507 m_map.contents(i).break_closure_cycles (frame);
508 }
509
510 octave_value_list
511 cdef_object_scalar::subsref (const std::string& type,
512 const std::list<octave_value_list>& idx,
513 int nargout, std::size_t& skip,
514 const cdef_class& context, bool auto_add)
515 {
516 skip = 0;
517
518 cdef_class cls = (context.ok () ? context : get_class ());
519
520 octave_value_list retval;
521
522 if (! cls.ok ())
523 return retval;
524
525 switch (type[0])
526 {
527 case '.':
528 {
529 std::string name = (idx.front ())(0).string_value ();
530
531 cdef_method meth = cls.find_method (name);
532
533 if (meth.ok ())
534 {
535 int _nargout = (type.length () > 2 ? 1 : nargout);
536
537 octave_value_list args;
538
539 skip = 1;
540
541 if (type.length () > 1 && type[1] == '(')
291 { 542 {
292 octave_value_list r = m_array(i).subsref (type, idx, 1, 543 auto it = idx.begin ();
293 dummy_skip, 544
294 dummy_cls); 545 args = *++it;
295 546
296 if (r.length () > 0) 547 skip++;
297 c(i) = r(0);
298 } 548 }
299 549
300 retval(0) = octave_value (c, true); 550 if (meth.is_static ())
301 551 retval = meth.execute (args, _nargout, true, "subsref");
302 break; 552 else
303 } 553 {
304 OCTAVE_FALLTHROUGH; 554 m_count++;
305 555 retval = meth.execute (cdef_object (this), args, _nargout,
306 default: 556 true, "subsref");
307 error ("can't perform indexing operation on array of %s objects", 557 }
308 class_name ().c_str ()); 558 }
559
560 if (skip == 0)
561 {
562 cdef_property prop = cls.find_property (name);
563
564 if (! prop.ok ())
565 error ("subsref: unknown method or property: %s", name.c_str ());
566
567 if (prop.is_constant ())
568 retval(0) = prop.get_value (true, "subsref");
569 else
570 {
571 m_count++;
572 retval(0) = prop.get_value (cdef_object (this),
573 true, "subsref");
574 }
575
576 skip = 1;
577 }
309 break; 578 break;
310 } 579 }
311 580
312 return retval; 581 case '(':
313 }
314
315 octave_value
316 cdef_object_array::subsasgn (const std::string& type,
317 const std::list<octave_value_list>& idx,
318 const octave_value& rhs)
319 {
320 octave_value retval;
321
322 switch (type[0])
323 { 582 {
324 case '(': 583 const octave_value_list& ival = idx.front ();
584
585 m_count++;
586 cdef_object this_obj (this);
587
588 if (ival.empty ())
589 {
590 skip++;
591 retval(0) = to_ov (this_obj);
592 }
593 else
594 {
595 Array<cdef_object> arr (dim_vector (1, 1), this_obj);
596
597 cdef_object new_obj = cdef_object (new cdef_object_array (arr));
598
599 new_obj.set_class (get_class ());
600
601 retval = new_obj.subsref (type, idx, nargout, skip, cls, auto_add);
602 }
603 }
604 break;
605
606 default:
607 error ("object cannot be indexed with '%c'", type[0]);
608 break;
609 }
610
611 return retval;
612 }
613
614 octave_value
615 cdef_object_scalar::subsasgn (const std::string& type,
616 const std::list<octave_value_list>& idx,
617 const octave_value& rhs)
618 {
619 octave_value retval;
620
621 cdef_class cls = get_class ();
622
623 switch (type[0])
624 {
625 case '.':
626 {
627 std::string name = (idx.front ())(0).string_value ();
628
629 cdef_property prop = cls.find_property (name);
630
631 if (! prop.ok ())
632 error ("subsasgn: unknown property: %s", name.c_str ());
633
634 if (prop.is_constant ())
635 error ("subsasgn: cannot assign constant property: %s",
636 name.c_str ());
637
638 m_count++;
639
640 cdef_object obj (this);
641
325 if (type.length () == 1) 642 if (type.length () == 1)
326 { 643 {
327 cdef_object rhs_obj = to_cdef (rhs); 644 prop.set_value (obj, rhs, true, "subsasgn");
328 645
329 if (rhs_obj.get_class () != get_class ()) 646 retval = to_ov (obj);
330 error ("can't assign %s object into array of %s objects",
331 rhs_obj.class_name ().c_str (),
332 class_name ().c_str ());
333
334 const octave_value_list& ival = idx.front ();
335 bool is_scalar = true;
336 Array<idx_vector> iv (dim_vector (1, ival.length ()));
337
338 for (int i = 0; i < ival.length (); i++)
339 {
340 try
341 {
342 iv(i) = ival(i).index_vector ();
343 }
344 catch (index_exception& ie)
345 {
346 ie.set_pos_if_unset (ival.length (), i+1);
347 throw; // var name set in pt-idx.cc / pt-assign.cc
348 }
349
350 is_scalar = is_scalar && iv(i).is_scalar ();
351 }
352
353 Array<cdef_object> rhs_mat;
354
355 if (! rhs_obj.is_array ())
356 {
357 rhs_mat = Array<cdef_object> (dim_vector (1, 1));
358 rhs_mat(0) = rhs_obj;
359 }
360 else
361 rhs_mat = rhs_obj.array_value ();
362
363 octave_idx_type n = m_array.numel ();
364
365 m_array.assign (iv, rhs_mat, cdef_object ());
366
367 if (m_array.numel () > n)
368 fill_empty_values ();
369
370 m_count++;
371 retval = to_ov (cdef_object (this));
372 } 647 }
373 else 648 else
374 { 649 {
375 const octave_value_list& ivl = idx.front (); 650 octave_value val = prop.get_value (obj, true, "subsasgn");
376 651
377 // Fill in trailing singleton dimensions so that 652 std::list<octave_value_list> args (idx);
378 // array.index doesn't create a new blank entry (bug #46660). 653
379 const octave_idx_type one = static_cast<octave_idx_type> (1); 654 args.erase (args.begin ());
380 const octave_value_list& ival = ivl.length () >= 2 655
381 ? ivl : ((m_array.dims ()(0) == 1) 656 val = val.assign (octave_value::op_asn_eq,
382 ? ovl (one, ivl(0)) 657 type.substr (1), args, rhs);
383 : ovl (ivl(0), one)); 658
384 659 if (val.class_name () != "object"
385 bool is_scalar = true; 660 || ! to_cdef (val).is_handle_object ())
386 661 prop.set_value (obj, val, true, "subsasgn");
387 Array<idx_vector> iv (dim_vector (1, ival.length ())); 662
388 663 retval = to_ov (obj);
389 for (int i = 0; i < ival.length (); i++) 664 }
390 {
391 try
392 {
393 iv(i) = ival(i).index_vector ();
394 }
395 catch (index_exception& ie)
396 {
397 // Rethrow to allow more info to be reported later.
398 ie.set_pos_if_unset (ival.length (), i+1);
399 throw;
400 }
401
402 is_scalar = is_scalar && iv(i).is_scalar ();
403
404 if (! is_scalar)
405 error ("subsasgn: invalid indexing for object array assignment"
406 ", the index must reference a single object in the "
407 "array.");
408 }
409
410 Array<cdef_object> a = m_array.index (iv, true);
411
412 if (a.numel () != 1)
413 error ("subsasgn: invalid indexing for object array assignment");
414
415 cdef_object obj = a(0);
416
417 int ignore_copies = 0;
418
419 // If the object in 'a' is not valid, this means the index
420 // was out-of-bound and we need to create a new object.
421
422 if (! obj.ok ())
423 obj = get_class ().construct_object (octave_value_list ());
424 else
425 // Optimize the subsasgn call to come. There are 2 copies
426 // that we can safely ignore:
427 // - 1 in "array"
428 // - 1 in "a"
429 ignore_copies = 2;
430
431 std::list<octave_value_list> next_idx (idx);
432
433 next_idx.erase (next_idx.begin ());
434
435 octave_value tmp = obj.subsasgn (type.substr (1), next_idx,
436 rhs, ignore_copies);
437
438 cdef_object robj = to_cdef (tmp);
439
440 if (! robj.ok ()
441 || robj.is_array ()
442 || robj.get_class () != get_class ())
443 error ("subsasgn: invalid assignment into array of %s objects",
444 class_name ().c_str ());
445
446 // Small optimization, when dealing with handle
447 // objects, we don't need to re-assign the result
448 // of subsasgn back into the array.
449
450 if (! robj.is (a(0)))
451 {
452 Array<cdef_object> rhs_a (dim_vector (1, 1),
453 robj);
454
455 octave_idx_type n = m_array.numel ();
456
457 m_array.assign (iv, rhs_a);
458
459 if (m_array.numel () > n)
460 fill_empty_values ();
461 }
462
463 m_count++;
464
465 retval = to_ov (cdef_object (this));
466 }
467 break;
468
469 default:
470 error ("can't perform indexing operation on array of %s objects",
471 class_name ().c_str ());
472 break;
473 } 665 }
474 666 break;
475 return retval; 667
476 } 668 case '(':
477
478 void
479 cdef_object_array::fill_empty_values (Array<cdef_object>& arr)
480 {
481 cdef_class cls = get_class ();
482
483 cdef_object obj;
484
485 int n = arr.numel ();
486
487 for (int i = 0; i < n; i++)
488 { 669 {
489 if (! arr.xelem (i).ok ()) 670 m_count++;
490 { 671
491 if (! obj.ok ()) 672 cdef_object this_obj (this);
492 { 673
493 obj = cls.construct_object (octave_value_list ()); 674 Array<cdef_object> arr (dim_vector (1, 1), this_obj);
494 675
495 arr.xelem (i) = obj; 676 cdef_object new_obj = cdef_object (new cdef_object_array (arr));
496 } 677
497 else 678 new_obj.set_class (get_class ());
498 arr.xelem (i) = obj.copy (); 679
499 } 680 octave_value tmp = new_obj.subsasgn (type, idx, rhs);
681
682 retval = tmp;
500 } 683 }
501 } 684 break;
502 685
503 void 686 default:
504 cdef_object_scalar::break_closure_cycles (const std::shared_ptr<stack_frame>& frame) 687 error ("subsasgn: object cannot be index with '%c'", type[0]);
505 { 688 break;
506 for (octave_idx_type i = 0; i < m_map.nfields (); i++) 689 }
507 m_map.contents(i).break_closure_cycles (frame); 690
508 } 691 return retval;
509 692 }
510 octave_value_list 693
511 cdef_object_scalar::subsref (const std::string& type, 694 void
512 const std::list<octave_value_list>& idx, 695 cdef_object_scalar::mark_for_construction (const cdef_class& cls)
513 int nargout, std::size_t& skip, 696 {
514 const cdef_class& context, bool auto_add) 697 std::string cls_name = cls.get_name ();
515 { 698
516 skip = 0; 699 Cell supcls = cls.get ("SuperClasses").cell_value ();
517 700
518 cdef_class cls = (context.ok () ? context : get_class ()); 701 std::list<cdef_class> supcls_list = lookup_classes (supcls);
519 702
520 octave_value_list retval; 703 m_ctor_list[cls] = supcls_list;
521 704 }
522 if (! cls.ok ()) 705
523 return retval; 706 bool
524 707 cdef_object_scalar::is_constructed_for (const cdef_class& cls) const
525 switch (type[0]) 708 {
526 { 709 return (is_constructed ()
527 case '.': 710 || m_ctor_list.find (cls) == m_ctor_list.end ());
528 { 711 }
529 std::string name = (idx.front ())(0).string_value (); 712
530 713 bool
531 cdef_method meth = cls.find_method (name); 714 cdef_object_scalar::is_partially_constructed_for (const cdef_class& cls) const
532 715 {
533 if (meth.ok ()) 716 if (is_constructed ())
534 { 717 return true;
535 int _nargout = (type.length () > 2 ? 1 : nargout); 718
536 719 std::map<cdef_class, std::list<cdef_class>>::const_iterator it
537 octave_value_list args;
538
539 skip = 1;
540
541 if (type.length () > 1 && type[1] == '(')
542 {
543 auto it = idx.begin ();
544
545 args = *++it;
546
547 skip++;
548 }
549
550 if (meth.is_static ())
551 retval = meth.execute (args, _nargout, true, "subsref");
552 else
553 {
554 m_count++;
555 retval = meth.execute (cdef_object (this), args, _nargout,
556 true, "subsref");
557 }
558 }
559
560 if (skip == 0)
561 {
562 cdef_property prop = cls.find_property (name);
563
564 if (! prop.ok ())
565 error ("subsref: unknown method or property: %s", name.c_str ());
566
567 if (prop.is_constant ())
568 retval(0) = prop.get_value (true, "subsref");
569 else
570 {
571 m_count++;
572 retval(0) = prop.get_value (cdef_object (this),
573 true, "subsref");
574 }
575
576 skip = 1;
577 }
578 break;
579 }
580
581 case '(':
582 {
583 const octave_value_list& ival = idx.front ();
584
585 m_count++;
586 cdef_object this_obj (this);
587
588 if (ival.empty ())
589 {
590 skip++;
591 retval(0) = to_ov (this_obj);
592 }
593 else
594 {
595 Array<cdef_object> arr (dim_vector (1, 1), this_obj);
596
597 cdef_object new_obj = cdef_object (new cdef_object_array (arr));
598
599 new_obj.set_class (get_class ());
600
601 retval = new_obj.subsref (type, idx, nargout, skip, cls, auto_add);
602 }
603 }
604 break;
605
606 default:
607 error ("object cannot be indexed with '%c'", type[0]);
608 break;
609 }
610
611 return retval;
612 }
613
614 octave_value
615 cdef_object_scalar::subsasgn (const std::string& type,
616 const std::list<octave_value_list>& idx,
617 const octave_value& rhs)
618 {
619 octave_value retval;
620
621 cdef_class cls = get_class ();
622
623 switch (type[0])
624 {
625 case '.':
626 {
627 std::string name = (idx.front ())(0).string_value ();
628
629 cdef_property prop = cls.find_property (name);
630
631 if (! prop.ok ())
632 error ("subsasgn: unknown property: %s", name.c_str ());
633
634 if (prop.is_constant ())
635 error ("subsasgn: cannot assign constant property: %s",
636 name.c_str ());
637
638 m_count++;
639
640 cdef_object obj (this);
641
642 if (type.length () == 1)
643 {
644 prop.set_value (obj, rhs, true, "subsasgn");
645
646 retval = to_ov (obj);
647 }
648 else
649 {
650 octave_value val = prop.get_value (obj, true, "subsasgn");
651
652 std::list<octave_value_list> args (idx);
653
654 args.erase (args.begin ());
655
656 val = val.assign (octave_value::op_asn_eq,
657 type.substr (1), args, rhs);
658
659 if (val.class_name () != "object"
660 || ! to_cdef (val).is_handle_object ())
661 prop.set_value (obj, val, true, "subsasgn");
662
663 retval = to_ov (obj);
664 }
665 }
666 break;
667
668 case '(':
669 {
670 m_count++;
671
672 cdef_object this_obj (this);
673
674 Array<cdef_object> arr (dim_vector (1, 1), this_obj);
675
676 cdef_object new_obj = cdef_object (new cdef_object_array (arr));
677
678 new_obj.set_class (get_class ());
679
680 octave_value tmp = new_obj.subsasgn (type, idx, rhs);
681
682 retval = tmp;
683 }
684 break;
685
686 default:
687 error ("subsasgn: object cannot be index with '%c'", type[0]);
688 break;
689 }
690
691 return retval;
692 }
693
694 void
695 cdef_object_scalar::mark_for_construction (const cdef_class& cls)
696 {
697 std::string cls_name = cls.get_name ();
698
699 Cell supcls = cls.get ("SuperClasses").cell_value ();
700
701 std::list<cdef_class> supcls_list = lookup_classes (supcls);
702
703 m_ctor_list[cls] = supcls_list;
704 }
705
706 bool
707 cdef_object_scalar::is_constructed_for (const cdef_class& cls) const
708 {
709 return (is_constructed ()
710 || m_ctor_list.find (cls) == m_ctor_list.end ());
711 }
712
713 bool
714 cdef_object_scalar::is_partially_constructed_for (const cdef_class& cls) const
715 {
716 if (is_constructed ())
717 return true;
718
719 std::map<cdef_class, std::list<cdef_class>>::const_iterator it
720 = m_ctor_list.find (cls); 720 = m_ctor_list.find (cls);
721 721
722 if (it == m_ctor_list.end () || it->second.empty ()) 722 if (it == m_ctor_list.end () || it->second.empty ())
723 return true;
724
725 for (const auto& cdef_cls : it->second)
726 if (! is_partially_constructed_for (cdef_cls))
727 return false;
728
729 return true; 723 return true;
730 } 724
731 725 for (const auto& cdef_cls : it->second)
732 void 726 if (! is_partially_constructed_for (cdef_cls))
733 cdef_object_scalar::mark_as_constructed (const cdef_class& cls) 727 return false;
734 { 728
735 m_ctor_list.erase (cls); 729 return true;
736 } 730 }
737 731
738 handle_cdef_object::~handle_cdef_object (void) 732 void
739 { 733 cdef_object_scalar::mark_as_constructed (const cdef_class& cls)
734 {
735 m_ctor_list.erase (cls);
736 }
737
738 handle_cdef_object::~handle_cdef_object (void)
739 {
740 #if DEBUG_TRACE 740 #if DEBUG_TRACE
741 std::cerr << "deleting " << get_class ().get_name () 741 std::cerr << "deleting " << get_class ().get_name ()
742 << " object (handle)" << std::endl; 742 << " object (handle)" << std::endl;
743 #endif 743 #endif
744 } 744 }
745 745
746 value_cdef_object::~value_cdef_object (void) 746 value_cdef_object::~value_cdef_object (void)
747 { 747 {
748 #if DEBUG_TRACE 748 #if DEBUG_TRACE
749 std::cerr << "deleting " << get_class ().get_name () 749 std::cerr << "deleting " << get_class ().get_name ()
750 << " object (value)" << std::endl; 750 << " object (value)" << std::endl;
751 #endif 751 #endif
752 } 752 }
753 753
754 OCTAVE_END_NAMESPACE(octave) 754 OCTAVE_END_NAMESPACE(octave)