GNU Octave  4.4.1
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
ov-classdef.cc
Go to the documentation of this file.
1 /*
2 
3 Copyright (C) 2012-2018 Michael Goffioul
4 
5 This file is part of Octave.
6 
7 Octave is free software: you can redistribute it and/or modify it
8 under the terms of the GNU General Public License as published by
9 the Free Software Foundation, either version 3 of the License, or
10 (at your option) any later version.
11 
12 Octave is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16 
17 You should have received a copy of the GNU General Public License
18 along with Octave; see the file COPYING. If not, see
19 <https://www.gnu.org/licenses/>.
20 
21 */
22 
23 #if defined (HAVE_CONFIG_H)
24 # include "config.h"
25 #endif
26 
27 #include <algorithm>
28 
29 #include "call-stack.h"
30 #include "defun.h"
31 #include "interpreter-private.h"
32 #include "interpreter.h"
33 #include "load-path.h"
34 #include "ov-builtin.h"
35 #include "ov-classdef.h"
36 #include "ov-fcn-handle.h"
37 #include "ov-typeinfo.h"
38 #include "ov-usr-fcn.h"
39 #include "pt-assign.h"
40 #include "pt-classdef.h"
41 #include "pt-eval.h"
42 #include "pt-funcall.h"
43 #include "pt-idx.h"
44 #include "pt-misc.h"
45 #include "pt-stmt.h"
46 #include "pt-walk.h"
47 #include "symtab.h"
48 
49 // Define to 1 to enable debugging statements.
50 #define DEBUG_TRACE 0
51 
52 OCTAVE_NORETURN static
53 void
54 err_method_access (const std::string& from, const cdef_method& meth)
55 {
56  octave_value acc = meth.get ("Access");
57  std::string acc_s;
58 
59  if (acc.is_string ())
60  acc_s = acc.string_value ();
61  else
62  acc_s = "class-restricted";
63 
64  error ("%s: method `%s' has %s access and cannot be run in this context",
65  from.c_str (), meth.get_name ().c_str (), acc_s.c_str ());
66 }
67 
68 OCTAVE_NORETURN static
69 void
70 err_property_access (const std::string& from, const cdef_property& prop,
71  bool is_set = false)
72 {
73  octave_value acc = (prop.get (is_set ? "SetAccess" : "GetAccess"));
74  std::string acc_s;
75 
76  if (acc.is_string ())
77  acc_s = acc.string_value ();
78  else
79  acc_s = "class-restricted";
80 
81  if (is_set)
82  error ("%s: property `%s' has %s access and cannot be set in this context",
83  from.c_str (), prop.get_name ().c_str (), acc_s.c_str ());
84  else
85  error ("%s: property `%s' has %s access and cannot be obtained in this context",
86  from.c_str (), prop.get_name ().c_str (), acc_s.c_str ());
87 }
88 
89 static std::string
91 {
92  std::string::size_type pos = nm.find_last_of ('.');
93 
94  if (pos != std::string::npos)
95  return nm.substr (pos + 1);
96 
97  return nm;
98 }
99 
100 static void
102  const octave_value& fcn)
103 {
105 
106  of->stash_dispatch_class (class_name);
107 
108  octave_user_function *uf = of->user_function_value (true);
109 
110  if (uf)
111  {
112  if (get_base_name (class_name) == uf->name ())
113  {
116  }
117  else
118  uf->mark_as_class_method ();
119  }
120 }
121 
122 static void
124 {
126 }
127 
128 static octave_value
130 {
131  octave_value fcn (new octave_builtin (ff, nm));
132 
133  octave_value fcn_handle (new octave_fcn_handle (fcn, nm));
134 
135  return fcn_handle;
136 }
137 
138 static octave_value
140 {
142 
143  if (fcn.is_defined ())
145 
146  return retval;
147 }
148 
149 static cdef_class
150 lookup_class (const std::string& name, bool error_if_not_found = true,
151  bool load_if_not_found = true)
152 {
153  cdef_manager& cdm = octave::__get_cdef_manager__ ("lookup_class");
154 
155  return cdm.find_class (name, error_if_not_found, load_if_not_found);
156 }
157 
158 static cdef_class
160 {
161  // FIXME: placeholder for the time being, the purpose
162  // is to centralized any class update activity here.
163 
164  return cls;
165 }
166 
167 static cdef_class
169 {
170  if (ov.is_string())
171  return lookup_class (ov.string_value ());
172  else
173  {
174  cdef_class cls (to_cdef (ov));
175 
176  return lookup_class (cls);
177  }
178 
179  return cdef_class ();
180 }
181 
182 static std::list<cdef_class>
183 lookup_classes (const Cell& cls_list)
184 {
185  std::list<cdef_class> retval;
186 
187  for (int i = 0; i < cls_list.numel (); i++)
188  {
189  cdef_class c = lookup_class (cls_list(i));
190 
191  retval.push_back (c);
192  }
193 
194  return retval;
195 }
196 
197 static octave_value
198 to_ov (const std::list<cdef_class>& class_list)
199 {
200  Cell cls (class_list.size (), 1);
201  int i = 0;
202 
203  for (const auto& cdef_cls : class_list)
204  cls(i++) = to_ov (cdef_cls);
205 
206  return octave_value (cls);
207 }
208 
209 static bool
210 is_superclass (const cdef_class& clsa, const cdef_class& clsb,
211  bool allow_equal = true, int max_depth = -1)
212 {
213  bool retval = false;
214 
215  if (allow_equal && clsa == clsb)
216  retval = true;
217  else if (max_depth != 0)
218  {
219  Cell c = clsb.get ("SuperClasses").cell_value ();
220 
221  for (int i = 0; ! retval && i < c.numel (); i++)
222  {
223  cdef_class cls = lookup_class (c(i));
224 
225  retval = is_superclass (clsa, cls, true,
226  max_depth < 0 ? max_depth : max_depth-1);
227  }
228  }
229 
230  return retval;
231 }
232 
233 inline bool
234 is_strict_superclass (const cdef_class& clsa, const cdef_class& clsb)
235 { return is_superclass (clsa, clsb, false); }
236 
237 inline bool
238 is_direct_superclass (const cdef_class& clsa, const cdef_class& clsb)
239 { return is_superclass (clsa, clsb, false, 1); }
240 
241 static octave_value_list
242 class_get_properties (const octave_value_list& args, int /* nargout */)
243 {
245 
246  if (args.length () == 1 && args(0).type_name () == "object")
247  {
248  cdef_class cls (to_cdef (args(0)));
249 
250  retval(0) = cls.get_properties ();
251  }
252 
253  return retval;
254 }
255 
256 static cdef_class
257 get_class_context (std::string& name, bool& in_constructor)
258 {
259  cdef_class cls;
260 
261  octave::call_stack& cs = octave::__get_call_stack__ ("get_class_context");
262 
264 
265  in_constructor = false;
266 
267  if (fcn && (fcn->is_class_method ()
270  || (fcn->is_private_function ()
271  && ! fcn->dispatch_class ().empty ())))
272  {
273  cls = lookup_class (fcn->dispatch_class ());
274 
275  name = fcn->name ();
276  in_constructor = fcn->is_classdef_constructor ();
277  }
278 
279  return cls;
280 }
281 
282 inline cdef_class
284 {
285  std::string dummy_string;
286  bool dummy_bool;
287 
288  return get_class_context (dummy_string, dummy_bool);
289 }
290 
291 static bool
293 {
294  cdef_class ctx = get_class_context ();
295 
296  return (ctx.ok () && is_superclass (ctx, cls));
297 }
298 
299 static bool
300 check_access (const cdef_class& cls, const octave_value& acc,
301  const std::string& meth_name = "",
302  const std::string& prop_name = "",
303  bool is_prop_set = false)
304 {
305  if (acc.is_string ())
306  {
307  std::string acc_s = acc.string_value ();
308 
309  if (acc_s == "public")
310  return true;
311 
312  cdef_class ctx = get_class_context ();
313 
314  // The access is private or protected, this requires a
315  // valid class context.
316 
317  if (ctx.ok ())
318  {
319  if (acc_s == "private")
320  return (ctx == cls);
321  else if (acc_s == "protected")
322  {
323  if (is_superclass (cls, ctx))
324  // Calling a protected method in a superclass.
325  return true;
326  else if (is_strict_superclass (ctx, cls))
327  {
328  // Calling a protected method or property in a derived class.
329  // This is only allowed if the context class knows about it
330  // and has access to it.
331 
332  if (! meth_name.empty ())
333  {
334  cdef_method m = ctx.find_method (meth_name);
335 
336  if (m.ok ())
337  return check_access (ctx, m.get ("Access"), meth_name);
338 
339  return false;
340  }
341  else if (! prop_name.empty ())
342  {
343  cdef_property p = ctx.find_property (prop_name);
344 
345  if (p.ok ())
346  {
347  octave_value p_access = p.get (is_prop_set ?
348  "SetAccess" :
349  "GetAccess");
350 
351  return check_access (ctx, p_access, meth_name,
352  prop_name, is_prop_set);
353  }
354 
355  return false;
356  }
357  else
358  panic_impossible ();
359  }
360 
361  return false;
362  }
363  else
364  panic_impossible ();
365  }
366  }
367  else if (acc.iscell ())
368  {
369  Cell acc_c = acc.cell_value ();
370 
371  cdef_class ctx = get_class_context ();
372 
373  // At this point, a class context is always required.
374 
375  if (ctx.ok ())
376  {
377  if (ctx == cls)
378  return true;
379 
380  for (int i = 0; i < acc.numel (); i++)
381  {
382  cdef_class acc_cls (to_cdef (acc_c(i)));
383 
384  if (is_superclass (acc_cls, ctx))
385  return true;
386  }
387  }
388  }
389  else
390  error ("invalid property/method access in class `%s'",
391  cls.get_name ().c_str ());
392 
393  return false;
394 }
395 
396 static bool
398 {
399  bool retval = false;
400 
401  if (fcn.is_defined ())
402  {
403  if (fcn.is_user_function ())
404  {
406 
407  if (! uf || ! uf->body ())
408  retval = true;
409  }
410  }
411  else
412  retval = true;
413 
414  return retval;
415 }
416 
417 static bool
419 {
421  = octave::__get_evaluator__ ("is_method_executing");
422 
423  octave::call_stack& cs = octave::__get_call_stack__ ("is_method_executing");
424 
425  octave_function *stack_fcn = cs.current ();
426 
427  octave_function *method_fcn = ov.function_value (true);
428 
429  // Does the top of the call stack match our target function?
430 
431  if (stack_fcn && stack_fcn == method_fcn)
432  {
433  octave_user_function *uf = method_fcn->user_function_value (true);
434 
435  // We can only check the context object for user-function (not builtin),
436  // where we have access to the parameters (arguments and return values).
437  // That's ok as there's no need to call this function for builtin
438  // methods.
439 
440  if (uf)
441  {
442  // At this point, the method is executing, but we still need to
443  // check the context object for which the method is executing. For
444  // methods, it's the first argument of the function; for ctors, it
445  // is the first return value.
446 
448  ? uf->return_list () : uf->parameter_list ();
449 
450  if (pl && pl->size () > 0)
451  {
452  octave::tree_decl_elt *elt = pl->front ();
453 
454  octave_value arg0 = tw.evaluate (elt);
455 
456  if (arg0.is_defined () && arg0.type_name () == "object")
457  {
458  cdef_object arg0_obj = to_cdef (arg0);
459 
460  return obj.is (arg0_obj);
461  }
462  }
463  }
464  }
465 
466  return false;
467 }
468 
469 static octave_value_list
470 class_get_methods (const octave_value_list& args, int /* nargout */)
471 {
473 
474  if (args.length () == 1 && args(0).type_name () == "object")
475  {
476  cdef_class cls (to_cdef (args(0)));
477 
478  retval(0) = cls.get_methods ();
479  }
480 
481  return retval;
482 }
483 
484 static octave_value_list
485 class_get_superclasses (const octave_value_list& args, int /* nargout */)
486 {
488 
489  if (args.length () == 1 && args(0).type_name () == "object"
490  && args(0).class_name () == "meta.class")
491  {
492  cdef_class cls (to_cdef (args(0)));
493 
494  Cell classes = cls.get ("SuperClasses").cell_value ();
495 
496  retval(0) = to_ov (lookup_classes (classes));
497  }
498 
499  return retval;
500 }
501 
502 static octave_value_list
503 class_get_inferiorclasses (const octave_value_list& args, int /* nargout */)
504 {
506 
507  if (args.length () == 1 && args(0).type_name () == "object"
508  && args(0).class_name () == "meta.class")
509  {
510  cdef_class cls (to_cdef (args(0)));
511 
512  Cell classes = cls.get ("InferiorClasses").cell_value ();
513 
514  retval(0) = to_ov (lookup_classes (classes));
515  }
516 
517  return retval;
518 }
519 
520 static octave_value_list
521 class_fromName (const octave_value_list& args, int /* nargout */)
522 {
524 
525  if (args.length () != 1)
526  error ("fromName: invalid number of parameters");
527 
528  std::string name = args(0).xstring_value ("fromName: CLASS_NAME must be a string");
529 
530  retval(0) = to_ov (lookup_class (name, false));
531 
532  return retval;
533 }
534 
535 static octave_value_list
537 {
538  if (args.length () <= 1 || args(0).type_name () != "object")
539  error ("fevalStatic: first argument must be a meta.class object");
540 
541  cdef_class cls (to_cdef (args(0)));
542 
543  std::string meth_name = args(1).xstring_value ("fevalStatic: method name must be a string");
544 
545  cdef_method meth = cls.find_method (meth_name);
546 
547  if (! meth.ok ())
548  error ("fevalStatic: method not found: %s", meth_name.c_str ());
549 
550  if (! meth.is_static ())
551  error ("fevalStatic: method `%s' is not static", meth_name.c_str ());
552 
553  return meth.execute (args.splice (0, 2), nargout, true, "fevalStatic");
554 }
555 
556 static octave_value_list
557 class_getConstant (const octave_value_list& args, int /* nargout */)
558 {
560 
561  if (args.length () != 2 || args(0).type_name () != "object"
562  || args(0).class_name () != "meta.class")
563  error ("getConstant: first argument must be a meta.class object");
564 
565  cdef_class cls = to_cdef (args(0));
566 
567  std::string prop_name = args(1).xstring_value ("getConstant: property name must be a string");
568 
569  cdef_property prop = cls.find_property (prop_name);
570 
571  if (! prop.ok ())
572  error ("getConstant: property not found: %s",
573  prop_name.c_str ());
574 
575  if (! prop.is_constant ())
576  error ("getConstant: property `%s' is not constant",
577  prop_name.c_str ());
578 
579  retval(0) = prop.get_value (true, "getConstant");
580 
581  return retval;
582 }
583 
584 #define META_CLASS_CMP(OP, CLSA, CLSB, FUN) \
585  static octave_value_list \
586  class_ ## OP (const octave_value_list& args, int /* nargout */) \
587  { \
588  octave_value_list retval; \
589  \
590  if (args.length () != 2 \
591  || args(0).type_name () != "object" \
592  || args(1).type_name () != "object" \
593  || args(0).class_name () != "meta.class" \
594  || args(1).class_name () != "meta.class") \
595  error (#OP ": invalid arguments"); \
596  \
597  cdef_class clsa = to_cdef (args(0)); \
598  \
599  cdef_class clsb = to_cdef (args(1)); \
600  \
601  retval(0) = FUN (CLSA, CLSB); \
602  \
603  return retval; \
604  }
605 
607 META_CLASS_CMP (le, clsb, clsa, is_superclass)
609 META_CLASS_CMP (ge, clsa, clsb, is_superclass)
610 META_CLASS_CMP (eq, clsa, clsb, operator==)
611 META_CLASS_CMP (ne, clsa, clsb, operator!=)
612 
614 property_get_defaultvalue (const octave_value_list& args, int /* nargout */)
615 {
617 
618  if (args.length () == 1 && args(0).type_name () == "object")
619  {
620  cdef_property prop (to_cdef (args(0)));
621 
622  retval(0) = prop.get ("DefaultValue");
623 
624  if (! retval(0).is_defined ())
625  error_with_id ("Octave:class:NotDefaultDefined",
626  "no default value for property `%s'",
627  prop.get_name ().c_str ());
628  }
629 
630  return retval;
631 }
632 
633 static octave_value_list
634 handle_delete (const octave_value_list& /* args */, int /* nargout */)
635 {
637 
638  // FIXME: implement this. Wait, what is this supposed to do?
639 
640  return retval;
641 }
642 
645  const std::list<cdef_class>& super_list)
646 {
647  cdef_class cls (name, super_list);
648 
649  cls.set_class (meta_class ());
650 
651  cls.put ("Abstract", false);
652  cls.put ("ConstructOnLoad", false);
653  cls.put ("ContainingPackage", Matrix ());
654  cls.put ("Description", "");
655  cls.put ("DetailedDescription", "");
656  cls.put ("Events", Cell ());
657  cls.put ("Hidden", false);
658  cls.put ("InferiorClasses", Cell ());
659  cls.put ("Methods", Cell ());
660  cls.put ("Properties", Cell ());
661  cls.put ("Sealed", false);
662 
663  if (name == "handle")
664  {
665  cls.put ("HandleCompatible", true);
666  cls.mark_as_handle_class ();
667  }
668  else if (super_list.empty ())
669  {
670  cls.put ("HandleCompatible", false);
671  }
672  else
673  {
674  bool all_handle_compatible = true;
675  bool has_handle_class = false;
676 
677  for (const auto& cl : super_list)
678  {
679  all_handle_compatible = all_handle_compatible
680  && cl.get ("HandleCompatible").bool_value ();
681  has_handle_class = has_handle_class || cl.is_handle_class ();
682  }
683 
684  if (has_handle_class && ! all_handle_compatible)
685  error ("%s: cannot mix handle and non-HandleCompatible classes",
686  name.c_str ());
687 
688  cls.put ("HandleCompatible", all_handle_compatible);
689  if (has_handle_class)
690  cls.mark_as_handle_class ();
691  }
692 
693  if (! name.empty ())
694  register_class (cls);
695 
696  return cls;
697 }
698 
701  const cdef_class& super)
702 {
703  return make_class (name, std::list<cdef_class> (1, super));
704 }
705 
708  const cdef_class& super)
709 {
710  cdef_class cls = make_class (name, super);
711 
712  cls.put ("Sealed", true);
713  cls.mark_as_meta_class ();
714 
715  return cls;
716 }
717 
720  const octave_value& get_method,
721  const std::string& get_access,
722  const octave_value& set_method,
723  const std::string& set_access)
724 {
725  cdef_property prop (name);
726 
727  prop.set_class (meta_property ());
728 
729  prop.put ("Description", "");
730  prop.put ("DetailedDescription", "");
731  prop.put ("Abstract", false);
732  prop.put ("Constant", false);
733  prop.put ("GetAccess", get_access);
734  prop.put ("SetAccess", set_access);
735  prop.put ("Dependent", false);
736  prop.put ("Transient", false);
737  prop.put ("Hidden", false);
738  prop.put ("GetObservable", false);
739  prop.put ("SetObservable", false);
740  prop.put ("GetMethod", get_method);
741  prop.put ("SetMethod", set_method);
742  prop.put ("DefiningClass", to_ov (cls));
743  prop.put ("DefaultValue", octave_value ());
744  prop.put ("HasDefault", false);
745 
746  std::string class_name = cls.get_name ();
747 
748  if (! get_method.isempty ())
749  make_function_of_class (class_name, get_method);
750  if (! set_method.isempty ())
751  make_function_of_class (class_name, set_method);
752 
753  return prop;
754 }
755 
758 {
759  return make_property (cls, name, Matrix (), "public", Matrix (), "private");
760 }
761 
764  const octave_value& fcn,
765  const std::string& m_access, bool is_static)
766 {
767  cdef_method meth (name);
768 
769  meth.set_class (meta_method ());
770 
771  meth.put ("Abstract", false);
772  meth.put ("Access", m_access);
773  meth.put ("DefiningClass", to_ov (cls));
774  meth.put ("Description", "");
775  meth.put ("DetailedDescription", "");
776  meth.put ("Hidden", false);
777  meth.put ("Sealed", true);
778  meth.put ("Static", is_static);
779 
780  if (fcn.is_defined ())
782 
783  meth.set_function (fcn);
784 
785  if (is_dummy_method (fcn))
786  meth.mark_as_external (cls.get_name ());
787 
788  return meth;
789 }
790 
794  const std::string& m_access, bool is_static)
795 {
796  octave_value fcn (new octave_builtin (ff, name));
797 
798  return make_method (cls, name, fcn, m_access, is_static);
799 }
800 
804  const std::string& m_access, bool is_static)
805 {
806  octave_value fcn (new octave_builtin (mm, name));
807 
808  return make_method (cls, name, fcn, m_access, is_static);
809 }
810 
813 {
814  cdef_package pack (nm);
815 
816  pack.set_class (meta_package ());
817 
818  if (parent.empty ())
819  pack.put ("ContainingPackage", Matrix ());
820  else
821  pack.put ("ContainingPackage", to_ov (find_package (parent)));
822 
823  if (! nm.empty ())
824  register_package (pack);
825 
826  return pack;
827 }
828 
829 //----------------------------------------------------------------------------
830 
831 int octave_classdef::t_id (-1);
832 
833 const std::string octave_classdef::t_name ("object");
834 
835 void
837 {
838  t_id = ti.register_type (octave_classdef::t_name, "<unknown>",
839  octave_value (new octave_classdef ()));
840 }
841 
844  const std::list<octave_value_list>& idx,
845  int nargout)
846 {
847  size_t skip = 0;
849 
850  cdef_class cls = object.get_class ();
851 
852  if (! in_class_method (cls) && ! called_from_builtin ())
853  {
854  cdef_method meth = cls.find_method ("subsref");
855 
856  if (meth.ok ())
857  {
858  octave_value_list args;
859 
860  args(1) = make_idx_args (type, idx, "subsref");
861 
862  count++;
863  args(0) = octave_value (this);
864 
865  retval = meth.execute (args, nargout, true, "subsref");
866 
867  return retval;
868  }
869  }
870 
871  // At this point, the default subsref mechanism must be used.
872 
873  retval = object.subsref (type, idx, nargout, skip, cdef_class ());
874 
875  if (type.length () > skip && idx.size () > skip)
876  retval = retval(0).next_subsref (nargout, type, idx, skip);
877 
878  return retval;
879 }
880 
883  const std::list<octave_value_list>& idx,
884  bool auto_add)
885 {
886  size_t skip = 0;
888 
889  // This variant of subsref is used to create temporary values when doing
890  // assignment with multi-level indexing. AFAIK this is only used for internal
891  // purpose (not sure we should even implement this) and any overload subsref
892  // should not be called.
893 
894  retval = object.subsref (type, idx, 1, skip, cdef_class (), auto_add);
895 
896  if (type.length () > skip && idx.size () > skip)
897  retval = retval(0).next_subsref (1, type, idx, skip);
898 
899  return retval.length () > 0 ? retval(0) : octave_value ();
900 }
901 
904  const std::list<octave_value_list>& idx,
905  const octave_value& rhs)
906 {
908 
909  cdef_class cls = object.get_class ();
910 
911  if (! in_class_method (cls) && ! called_from_builtin ())
912  {
913  cdef_method meth = cls.find_method ("subsasgn");
914 
915  if (meth.ok ())
916  {
917  octave_value_list args;
918 
919  args(1) = make_idx_args (type, idx, "subsasgn");
920 
921  count++;
922  args(0) = octave_value (this);
923  args(2) = rhs;
924 
925  octave_value_list retlist;
926 
927  retlist = meth.execute (args, 1, true, "subsasgn");
928 
929  if (retlist.empty ())
930  error ("overloaded method `subsasgn' did not return any value");
931 
932  retval = retlist(0);
933  }
934  }
935 
936  if (! retval.is_defined ())
937  retval = object.subsasgn (type, idx, rhs);
938 
939  return retval;
940 }
941 
944  const std::list<octave_value_list>& idx,
945  const octave_value& rhs)
946 {
947  if (type.length () == 1 && type[0] == '(')
948  {
949  object = object.make_array ();
950 
951  return subsasgn (type, idx, rhs);
952  }
953  else
954  return octave_base_value::undef_subsasgn (type, idx, rhs);
955 
956  return octave_value ();
957 }
958 
961 {
962  octave_idx_type retval = -1;
963 
964  cdef_class cls = object.get_class ();
965 
966  if (! in_class_method (cls) && ! called_from_builtin ())
967  {
968  cdef_method meth = cls.find_method ("numel");
969 
970  if (meth.ok ())
971  {
972  octave_value_list args (idx.length () + 1, octave_value ());
973 
974  count++;
975  args(0) = octave_value (this);
976 
977  for (octave_idx_type i = 0; i < idx.length (); i++)
978  args(i+1) = idx(i);
979 
980  octave_value_list lv = meth.execute (args, 1, true, "numel");
981  if (lv.length () != 1 || ! lv(0).is_scalar_type ())
982  error ("@%s/numel: invalid return value", cls.get_name ().c_str ());
983 
984  retval = lv(0).idx_type_value (true);
985 
986  return retval;
987  }
988  }
989 
991 
992  return retval;
993 }
994 
995 void
996 octave_classdef::print (std::ostream& os, bool)
997 {
998  print_raw (os);
999 }
1000 
1001 void
1002 octave_classdef::print_raw (std::ostream& os, bool) const
1003 {
1004  indent (os);
1005  os << "<object ";
1006  if (object.is_array ())
1007  os << "array ";
1008  os << class_name () << '>';
1009  newline (os);
1010 }
1011 
1012 bool
1013 octave_classdef::print_name_tag (std::ostream& os,
1014  const std::string& name) const
1015 {
1016  return octave_base_value::print_name_tag (os, name);
1017 }
1018 
1019 void
1020 octave_classdef::print_with_name (std::ostream& os, const std::string& name,
1021  bool print_padding)
1022 {
1023  octave_base_value::print_with_name (os, name, print_padding);
1024 }
1025 
1026 bool
1027 octave_classdef::is_instance_of (const std::string& cls_name) const
1028 {
1029  cdef_class cls = lookup_class (cls_name, false, false);
1030 
1031  if (cls.ok ())
1032  return is_superclass (cls, object.get_class ());
1033 
1034  return false;
1035 }
1036 
1037 //----------------------------------------------------------------------------
1038 
1039 class octave_classdef_meta : public octave_function
1040 {
1041 public:
1042  octave_classdef_meta (const cdef_meta_object& obj)
1043  : object (obj) { }
1044 
1045  ~octave_classdef_meta (void)
1046  { object.meta_release (); }
1047 
1048  bool is_classdef_meta (void) const { return true; }
1049 
1050  bool is_package (void) const { return object.is_package(); }
1051 
1052  octave_function * function_value (bool = false) { return this; }
1053 
1054  octave_value_list
1055  subsref (const std::string& type,
1056  const std::list<octave_value_list>& idx,
1057  int nargout)
1058  {
1059  return object.meta_subsref (type, idx, nargout);
1060  }
1061 
1062  octave_value_list call (octave::tree_evaluator&, int nargout,
1063  const octave_value_list& args)
1064  {
1065  // Emulate ()-type meta subsref
1066 
1067  std::list<octave_value_list> idx (1, args);
1068  std::string type ("(");
1069 
1070  return subsref (type, idx, nargout);
1071  }
1072 
1073  bool accepts_postfix_index (char type) const
1074  { return object.meta_accepts_postfix_index (type); }
1075 
1076  bool
1077  is_classdef_constructor (const std::string& cname = "") const
1078  {
1079  bool retval = false;
1080 
1081  if (object.is_class ())
1082  {
1083  if (cname.empty ())
1084  retval = true;
1085  else
1086  {
1087  cdef_class cls (object);
1088 
1089  if (cls.get_name () == cname)
1090  retval = true;
1091  }
1092  }
1093 
1094  return retval;
1095  }
1096 
1097 private:
1098  cdef_meta_object object;
1099 };
1100 
1101 //----------------------------------------------------------------------------
1102 
1103 class octave_classdef_superclass_ref : public octave_function
1104 {
1105 public:
1106  octave_classdef_superclass_ref (const octave_value_list& a)
1107  : octave_function (), args (a) { }
1108 
1109  ~octave_classdef_superclass_ref (void) = default;
1110 
1111  bool is_classdef_superclass_ref (void) const { return true; }
1112 
1113  octave_function * function_value (bool = false) { return this; }
1114 
1115  octave_value_list
1116  call (octave::tree_evaluator&, int nargout, const octave_value_list& idx)
1117  {
1118  octave_value_list retval;
1119 
1120  std::string meth_name;
1121  bool in_constructor;
1122  cdef_class ctx;
1123 
1124  ctx = get_class_context (meth_name, in_constructor);
1125 
1126  if (! ctx.ok ())
1127  error ("superclass calls can only occur in methods or constructors");
1128 
1129  std::string mname = args(0).string_value ();
1130  std::string cname = args(1).string_value ();
1131 
1132  cdef_class cls = lookup_class (cname);
1133 
1134  if (in_constructor)
1135  {
1136  if (! is_direct_superclass (cls, ctx))
1137  error ("`%s' is not a direct superclass of `%s'",
1138  cname.c_str (), ctx.get_name ().c_str ());
1139 
1140  if (! is_constructed_object (mname))
1141  error ("cannot call superclass constructor with variable `%s'",
1142  mname.c_str ());
1143 
1144  octave::symbol_scope scope
1145  = octave::__require_current_scope__ ("octave_classdef_superclass_ref::call");
1146 
1147  octave_value sym = scope.varval (mname);
1148 
1149  cls.run_constructor (to_cdef_ref (sym), idx);
1150 
1151  retval(0) = sym;
1152  }
1153  else
1154  {
1155  if (mname != meth_name)
1156  error ("method name mismatch (`%s' != `%s')",
1157  mname.c_str (), meth_name.c_str ());
1158 
1159  if (! is_strict_superclass (cls, ctx))
1160  error ("`%s' is not a superclass of `%s'",
1161  cname.c_str (), ctx.get_name ().c_str ());
1162 
1163  // I see 2 possible implementations here:
1164  // 1) use cdef_object::subsref with a different class
1165  // context; this avoids duplicating code, but
1166  // assumes the object is always the first argument
1167  // 2) lookup the method manually and call
1168  // cdef_method::execute; this duplicates part of
1169  // logic in cdef_object::subsref, but avoid the
1170  // assumption of 1)
1171  // Not being sure about the assumption of 1), I
1172  // go with option 2) for the time being.
1173 
1174  cdef_method meth = cls.find_method (meth_name, false);
1175 
1176  if (! meth.ok ())
1177  error ("no method `%s' found in superclass `%s'",
1178  meth_name.c_str (), cname.c_str ());
1179 
1180  retval = meth.execute (idx, nargout, true,
1181  meth_name);
1182  }
1183 
1184  return retval;
1185  }
1186 
1187 private:
1188  bool is_constructed_object (const std::string nm)
1189  {
1190  octave::call_stack& cs
1191  = octave::__get_call_stack__ ("octave_classdef_superclass_ref::is_constructed_object");
1192 
1193  octave_function *of = cs.current ();
1194 
1195  if (of->is_classdef_constructor ())
1196  {
1197  octave_user_function *uf = of->user_function_value (true);
1198 
1199  if (uf)
1200  {
1201  octave::tree_parameter_list *ret_list = uf->return_list ();
1202 
1203  if (ret_list && ret_list->length () == 1)
1204  return (ret_list->front ()->name () == nm);
1205  }
1206  }
1207 
1208  return false;
1209  }
1210 
1211 private:
1212  octave_value_list args;
1213 };
1214 
1215 //----------------------------------------------------------------------------
1216 
1217 void
1218 cdef_object_rep::release (const cdef_object& obj)
1219 {
1220  // We need to be careful to keep a reference to the object if we are
1221  // calling the delete method. The object is passed to the delete
1222  // method as an argument and if the count is already zero when we
1223  // do that, then we will increment the count while creating the
1224  // argument list for the delete method and then it will be decremented
1225  // back to zero and we'll find ourselves in an infinite loop.
1226 
1227  if (refcount - 1 > static_count ())
1228  {
1229  --refcount;
1230  return;
1231  }
1232 
1233  if (is_handle_object () && ! is_meta_object ())
1234  {
1235  octave::unwind_protect frame;
1236 
1237  // Clear interrupts.
1238  frame.protect_var (octave_interrupt_state);
1239  octave_interrupt_state = 0;
1240 
1241  // Disallow quit().
1242  frame.protect_var (quit_allowed);
1243  quit_allowed = false;
1244 
1245  interpreter_try (frame);
1246 
1247  try
1248  {
1249  // Call classdef "delete()" method on object
1250  get_class ().delete_object (obj);
1251  }
1252  catch (const octave::interrupt_exception&)
1253  {
1254  octave::interpreter::recover_from_exception ();
1255 
1256  warning ("interrupt occurred in handle class delete method");
1257  }
1258  catch (const octave::execution_exception&)
1259  {
1260  std::string msg = last_error_message ();
1261  warning ("error caught while executing handle class delete method:\n%s\n",
1262  msg.c_str ());
1263 
1264  }
1265  catch (const octave::exit_exception&)
1266  {
1267  // This shouldn't happen since we disabled quit above.
1268  warning ("exit disabled while executing handle class delete method");
1269  }
1270  catch (...) // Yes, the black hole. We're in a d-tor.
1271  {
1272  // This shouldn't happen, in theory.
1273  warning ("internal error: unhandled exception in handle class delete method");
1274  }
1275  }
1276 
1277  // Now it is safe to set the count to zero.
1278  refcount--;
1279 
1280  destroy ();
1281 }
1282 
1283 octave_map
1284 cdef_object::map_value (void) const
1285 {
1286  octave_map retval;
1287 
1288  warning_with_id ("Octave:classdef-to-struct",
1289  "struct: converting a classdef object into a struct "
1290  "overrides the access restrictions defined for properties. "
1291  "All properties are returned, including private and "
1292  "protected ones.");
1293 
1294  cdef_class cls = get_class ();
1295 
1296  if (cls.ok ())
1297  {
1298  std::map<std::string, cdef_property> props;
1299 
1300  props = cls.get_property_map (cdef_class::property_all);
1301 
1302  // FIXME: Why not const here?
1303  for (auto& prop_val : props)
1304  {
1305  if (is_array ())
1306  {
1307  Array<cdef_object> a_obj = array_value ();
1308 
1309  Cell cvalue (a_obj.dims ());
1310 
1311  for (octave_idx_type i = 0; i < a_obj.numel (); i++)
1312  cvalue (i) = prop_val.second.get_value (a_obj(i), false);
1313 
1314  retval.setfield (prop_val.first, cvalue);
1315  }
1316  else
1317  {
1318  Cell cvalue (dim_vector (1, 1),
1319  prop_val.second.get_value (*this, false));
1320 
1321  retval.setfield (prop_val.first, cvalue);
1322  }
1323  }
1324  }
1325 
1326  return retval;
1327 }
1328 
1329 string_vector
1330 cdef_object_rep::map_keys (void) const
1331 {
1332  cdef_class cls = get_class ();
1333 
1334  if (cls.ok ())
1335  return cls.get_names ();
1336 
1337  return string_vector ();
1338 }
1339 
1340 octave_value_list
1341 cdef_object_scalar::subsref (const std::string& type,
1342  const std::list<octave_value_list>& idx,
1343  int nargout, size_t& skip,
1344  const cdef_class& context, bool auto_add)
1345 {
1346  skip = 0;
1347 
1348  cdef_class cls = (context.ok () ? context : get_class ());
1349 
1350  octave_value_list retval;
1351 
1352  if (! cls.ok ())
1353  return retval;
1354 
1355  switch (type[0])
1356  {
1357  case '.':
1358  {
1359  std::string name = (idx.front ())(0).string_value ();
1360 
1361  cdef_method meth = cls.find_method (name);
1362 
1363  if (meth.ok ())
1364  {
1365  int _nargout = (type.length () > 2 ? 1 : nargout);
1366 
1367  octave_value_list args;
1368 
1369  skip = 1;
1370 
1371  if (type.length () > 1 && type[1] == '(')
1372  {
1373  std::list<octave_value_list>::const_iterator it = idx.begin ();
1374 
1375  args = *++it;
1376 
1377  skip++;
1378  }
1379 
1380  if (meth.is_static ())
1381  retval = meth.execute (args, _nargout, true, "subsref");
1382  else
1383  {
1384  refcount++;
1385  retval = meth.execute (cdef_object (this), args, _nargout,
1386  true, "subsref");
1387  }
1388  }
1389 
1390  if (skip == 0)
1391  {
1392  cdef_property prop = cls.find_property (name);
1393 
1394  if (! prop.ok ())
1395  error ("subsref: unknown method or property: %s", name.c_str ());
1396 
1397  if (prop.is_constant ())
1398  retval(0) = prop.get_value (true, "subsref");
1399  else
1400  {
1401  refcount++;
1402  retval(0) = prop.get_value (cdef_object (this),
1403  true, "subsref");
1404  }
1405 
1406  skip = 1;
1407  }
1408  break;
1409  }
1410 
1411  case '(':
1412  {
1413  const octave_value_list& ival = idx.front ();
1414 
1415  refcount++;
1416  cdef_object this_obj (this);
1417 
1418  if (ival.empty ())
1419  {
1420  skip++;
1421  retval(0) = to_ov (this_obj);
1422  }
1423  else
1424  {
1425  Array<cdef_object> arr (dim_vector (1, 1), this_obj);
1426 
1427  cdef_object new_obj = cdef_object (new cdef_object_array (arr));
1428 
1429  new_obj.set_class (get_class ());
1430 
1431  retval = new_obj.subsref (type, idx, nargout, skip, cls, auto_add);
1432  }
1433  }
1434  break;
1435 
1436  default:
1437  error ("object cannot be indexed with `%c'", type[0]);
1438  break;
1439  }
1440 
1441  return retval;
1442 }
1443 
1444 octave_value
1445 cdef_object_scalar::subsasgn (const std::string& type,
1446  const std::list<octave_value_list>& idx,
1447  const octave_value& rhs)
1448 {
1449  octave_value retval;
1450 
1451  cdef_class cls = get_class ();
1452 
1453  switch (type[0])
1454  {
1455  case '.':
1456  {
1457  std::string name = (idx.front ())(0).string_value ();
1458 
1459  cdef_property prop = cls.find_property (name);
1460 
1461  if (! prop.ok ())
1462  error ("subsasgn: unknown property: %s", name.c_str ());
1463 
1464  if (prop.is_constant ())
1465  error ("subsasgn: cannot assign constant property: %s",
1466  name.c_str ());
1467 
1468  refcount++;
1469 
1470  cdef_object obj (this);
1471 
1472  if (type.length () == 1)
1473  {
1474  prop.set_value (obj, rhs, true, "subsasgn");
1475 
1476  retval = to_ov (obj);
1477  }
1478  else
1479  {
1480  octave_value val =
1481  prop.get_value (obj, true, "subsasgn");
1482 
1483  std::list<octave_value_list> args (idx);
1484 
1485  args.erase (args.begin ());
1486 
1487  val = val.assign (octave_value::op_asn_eq,
1488  type.substr (1), args, rhs);
1489 
1490  if (val.class_name () != "object"
1491  || ! to_cdef (val).is_handle_object ())
1492  prop.set_value (obj, val, true, "subsasgn");
1493 
1494  retval = to_ov (obj);
1495  }
1496  }
1497  break;
1498 
1499  case '(':
1500  {
1501  refcount++;
1502 
1503  cdef_object this_obj (this);
1504 
1505  Array<cdef_object> arr (dim_vector (1, 1), this_obj);
1506 
1507  cdef_object new_obj = cdef_object (new cdef_object_array (arr));
1508 
1509  new_obj.set_class (get_class ());
1510 
1511  octave_value tmp = new_obj.subsasgn (type, idx, rhs);
1512 
1513  retval = tmp;
1514  }
1515  break;
1516 
1517  default:
1518  error ("subsasgn: object cannot be index with `%c'", type[0]);
1519  break;
1520  }
1521 
1522  return retval;
1523 }
1524 
1525 void
1526 cdef_object_scalar::mark_for_construction (const cdef_class& cls)
1527 {
1528  std::string cls_name = cls.get_name ();
1529 
1530  Cell supcls = cls.get ("SuperClasses").cell_value ();
1531 
1532  std::list<cdef_class> supcls_list = lookup_classes (supcls);
1533 
1534  ctor_list[cls] = supcls_list;
1535 }
1536 
1537 octave_value_list
1538 cdef_object_array::subsref (const std::string& type,
1539  const std::list<octave_value_list>& idx,
1540  int /* nargout */, size_t& skip,
1541  const cdef_class& /* context */, bool auto_add)
1542 {
1543  octave_value_list retval;
1544 
1545  skip = 1;
1546 
1547  switch (type[0])
1548  {
1549  case '(':
1550  {
1551  const octave_value_list& ival = idx.front ();
1552 
1553  if (ival.empty ())
1554  {
1555  refcount++;
1556  retval(0) = to_ov (cdef_object (this));
1557  break;
1558  }
1559 
1560  bool is_scalar = true;
1561  Array<idx_vector> iv (dim_vector (1, ival.length ()));
1562 
1563  for (int i = 0; i < ival.length (); i++)
1564  {
1565  try
1566  {
1567  iv(i) = ival(i).index_vector ();
1568  }
1569  catch (octave::index_exception& e)
1570  {
1571  // Rethrow to allow more info to be reported later.
1572  e.set_pos_if_unset (ival.length (), i+1);
1573  throw;
1574  }
1575 
1576  is_scalar = is_scalar && iv(i).is_scalar ();
1577  }
1578 
1579  Array<cdef_object> ires = array.index (iv, auto_add);
1580 
1581  // If resizing is enabled (auto_add = true), it's possible
1582  // indexing was out-of-bound and the result array contains
1583  // invalid cdef_objects.
1584 
1585  if (auto_add)
1586  fill_empty_values (ires);
1587 
1588  if (is_scalar)
1589  retval(0) = to_ov (ires(0));
1590  else
1591  {
1592  cdef_object array_obj (new cdef_object_array (ires));
1593 
1594  array_obj.set_class (get_class ());
1595 
1596  retval(0) = to_ov (array_obj);
1597  }
1598  }
1599  break;
1600 
1601  case '.':
1602  if (type.size () == 1 && idx.size () == 1)
1603  {
1604  Cell c (dims ());
1605 
1606  octave_idx_type n = array.numel ();
1607 
1608  // dummy variables
1609  size_t dummy_skip;
1610  cdef_class dummy_cls;
1611 
1612  for (octave_idx_type i = 0; i < n; i++)
1613  {
1614  octave_value_list r = array(i).subsref (type, idx, 1, dummy_skip,
1615  dummy_cls);
1616 
1617  if (r.length () > 0)
1618  c(i) = r(0);
1619  }
1620 
1621  retval(0) = octave_value (c, true);
1622 
1623  break;
1624  }
1625  OCTAVE_FALLTHROUGH;
1626 
1627  default:
1628  error ("can't perform indexing operation on array of %s objects",
1629  class_name ().c_str ());
1630  break;
1631  }
1632 
1633  return retval;
1634 }
1635 
1636 octave_value
1637 cdef_object_array::subsasgn (const std::string& type,
1638  const std::list<octave_value_list>& idx,
1639  const octave_value& rhs)
1640 {
1641  octave_value retval;
1642 
1643  switch (type[0])
1644  {
1645  case '(':
1646  if (type.length () == 1)
1647  {
1648  cdef_object rhs_obj = to_cdef (rhs);
1649 
1650  if (rhs_obj.get_class () != get_class ())
1651  error ("can't assign %s object into array of %s objects.",
1652  rhs_obj.class_name ().c_str (),
1653  class_name ().c_str ());
1654 
1655  const octave_value_list& ival = idx.front ();
1656  bool is_scalar = true;
1657  Array<idx_vector> iv (dim_vector (1, ival.length ()));
1658 
1659  for (int i = 0; i < ival.length (); i++)
1660  {
1661  try
1662  {
1663  iv(i) = ival(i).index_vector ();
1664  }
1665  catch (octave::index_exception& e)
1666  {
1667  e.set_pos_if_unset (ival.length (), i+1);
1668  throw; // var name set in pt-idx.cc / pt-assign.cc
1669  }
1670 
1671  is_scalar = is_scalar && iv(i).is_scalar ();
1672  }
1673 
1674  Array<cdef_object> rhs_mat;
1675 
1676  if (! rhs_obj.is_array ())
1677  {
1678  rhs_mat = Array<cdef_object> (dim_vector (1, 1));
1679  rhs_mat(0) = rhs_obj;
1680  }
1681  else
1682  rhs_mat = rhs_obj.array_value ();
1683 
1684  octave_idx_type n = array.numel ();
1685 
1686  array.assign (iv, rhs_mat, cdef_object ());
1687 
1688  if (array.numel () > n)
1689  fill_empty_values ();
1690 
1691  refcount++;
1692  retval = to_ov (cdef_object (this));
1693  }
1694  else
1695  {
1696  const octave_value_list& ivl = idx.front ();
1697 
1698  // Fill in trailing singleton dimensions so that
1699  // array.index doesn't create a new blank entry (bug #46660).
1700  const octave_idx_type one = static_cast<octave_idx_type> (1);
1701  const octave_value_list& ival = ivl.length () >= 2
1702  ? ivl : ((array.dims ()(0) == 1)
1703  ? ovl (one, ivl(0))
1704  : ovl (ivl(0), one));
1705 
1706  bool is_scalar = true;
1707 
1708  Array<idx_vector> iv (dim_vector (1, ival.length ()));
1709 
1710  for (int i = 0; i < ival.length (); i++)
1711  {
1712  try
1713  {
1714  iv(i) = ival(i).index_vector ();
1715  }
1716  catch (octave::index_exception& e)
1717  {
1718  // Rethrow to allow more info to be reported later.
1719  e.set_pos_if_unset (ival.length (), i+1);
1720  throw;
1721  }
1722 
1723  is_scalar = is_scalar && iv(i).is_scalar ();
1724 
1725  if (! is_scalar)
1726  error ("subsasgn: invalid indexing for object array assignment"
1727  ", the index must reference a single object in the "
1728  "array.");
1729  }
1730 
1731  Array<cdef_object> a = array.index (iv, true);
1732 
1733  if (a.numel () != 1)
1734  error ("subsasgn: invalid indexing for object array assignment");
1735 
1736  cdef_object obj = a(0);
1737 
1738  int ignore_copies = 0;
1739 
1740  // If the object in 'a' is not valid, this means the index
1741  // was out-of-bound and we need to create a new object.
1742 
1743  if (! obj.ok ())
1744  obj = get_class ().construct_object (octave_value_list ());
1745  else
1746  // Optimize the subsasgn call to come. There are 2 copies
1747  // that we can safely ignore:
1748  // - 1 in "array"
1749  // - 1 in "a"
1750  ignore_copies = 2;
1751 
1752  std::list<octave_value_list> next_idx (idx);
1753 
1754  next_idx.erase (next_idx.begin ());
1755 
1756  octave_value tmp = obj.subsasgn (type.substr (1), next_idx,
1757  rhs, ignore_copies);
1758 
1759  cdef_object robj = to_cdef (tmp);
1760 
1761  if (! robj.ok ()
1762  || robj.is_array ()
1763  || robj.get_class () != get_class ())
1764  error ("subasgn: invalid assignment into array of %s objects",
1765  class_name ().c_str ());
1766 
1767  // Small optimization, when dealing with handle
1768  // objects, we don't need to re-assign the result
1769  // of subsasgn back into the array.
1770 
1771  if (! robj.is (a(0)))
1772  {
1773  Array<cdef_object> rhs_a (dim_vector (1, 1),
1774  robj);
1775 
1776  octave_idx_type n = array.numel ();
1777 
1778  array.assign (iv, rhs_a);
1779 
1780  if (array.numel () > n)
1781  fill_empty_values ();
1782  }
1783 
1784  refcount++;
1785 
1786  retval = to_ov (cdef_object (this));
1787  }
1788  break;
1789 
1790  default:
1791  error ("can't perform indexing operation on array of %s objects",
1792  class_name ().c_str ());
1793  break;
1794  }
1795 
1796  return retval;
1797 }
1798 
1799 void
1800 cdef_object_array::fill_empty_values (Array<cdef_object>& arr)
1801 {
1802  cdef_class cls = get_class ();
1803 
1804  cdef_object obj;
1805 
1806  int n = arr.numel ();
1807 
1808  for (int i = 0; i < n; i++)
1809  {
1810  if (! arr.xelem (i).ok ())
1811  {
1812  if (! obj.ok ())
1813  {
1814  obj = cls.construct_object (octave_value_list ());
1815 
1816  arr.xelem (i) = obj;
1817  }
1818  else
1819  arr.xelem (i) = obj.copy ();
1820  }
1821  }
1822 }
1823 
1824 bool
1825 cdef_object_scalar::is_constructed_for (const cdef_class& cls) const
1826 {
1827  return (is_constructed ()
1828  || ctor_list.find (cls) == ctor_list.end ());
1829 }
1830 
1831 bool
1832 cdef_object_scalar::is_partially_constructed_for (const cdef_class& cls) const
1833 {
1834  std::map< cdef_class, std::list<cdef_class>>::const_iterator it;
1835 
1836  if (is_constructed ())
1837  return true;
1838  else if ((it = ctor_list.find (cls)) == ctor_list.end ()
1839  || it->second.empty ())
1840  return true;
1841 
1842  for (const auto& cdef_cls : it->second)
1843  if (! is_constructed_for (cdef_cls))
1844  return false;
1845 
1846  return true;
1847 }
1848 
1849 inline void
1850 cdef_object_scalar::mark_as_constructed (const cdef_class& cls)
1851 {
1852  ctor_list.erase (cls);
1853 }
1854 
1855 handle_cdef_object::~handle_cdef_object (void)
1856 {
1857 #if DEBUG_TRACE
1858  std::cerr << "deleting " << get_class ().get_name ()
1859  << " object (handle)" << std::endl;
1860 #endif
1861 }
1862 
1863 value_cdef_object::~value_cdef_object (void)
1864 {
1865 #if DEBUG_TRACE
1866  std::cerr << "deleting " << get_class ().get_name ()
1867  << " object (value)" << std::endl;
1868 #endif
1869 }
1870 
1871 cdef_class::cdef_class_rep::cdef_class_rep (const std::list<cdef_class>& superclasses)
1872  : cdef_meta_object_rep (), member_count (0), handle_class (false),
1873  object_count (0), meta (false)
1874 {
1875  put ("SuperClasses", to_ov (superclasses));
1876  implicit_ctor_list = superclasses;
1877 }
1878 
1879 cdef_method
1880 cdef_class::cdef_class_rep::find_method (const std::string& nm, bool local)
1881 {
1882  method_iterator it = method_map.find (nm);
1883 
1884  if (it == method_map.end ())
1885  {
1886  // FIXME: look into class directory
1887  }
1888  else
1889  {
1890  cdef_method& meth = it->second;
1891 
1892  // FIXME: check if method reload needed
1893 
1894  if (meth.ok ())
1895  return meth;
1896  }
1897 
1898  if (! local)
1899  {
1900  // Look into superclasses
1901 
1902  Cell super_classes = get ("SuperClasses").cell_value ();
1903 
1904  for (int i = 0; i < super_classes.numel (); i++)
1905  {
1906  cdef_class cls = lookup_class (super_classes(i));
1907 
1908  cdef_method meth = cls.find_method (nm);
1909 
1910  if (meth.ok ())
1911  return meth;
1912  }
1913  }
1914 
1915  return cdef_method ();
1916 }
1917 
1918 class ctor_analyzer : public octave::tree_walker
1919 {
1920 public:
1921  ctor_analyzer (const std::string& ctor, const std::string& obj)
1922  : octave::tree_walker (), who (ctor), obj_name (obj) { }
1923 
1924  void visit_statement_list (octave::tree_statement_list& t)
1925  {
1926  for (const auto& stmt_p : t)
1927  stmt_p->accept (*this);
1928  }
1929 
1930  void visit_statement (octave::tree_statement& t)
1931  {
1932  if (t.is_expression ())
1933  t.expression ()->accept (*this);
1934  }
1935 
1936  void visit_simple_assignment (octave::tree_simple_assignment& t)
1937  {
1938  t.right_hand_side ()->accept (*this);
1939  }
1940 
1941  void visit_multi_assignment (octave::tree_multi_assignment& t)
1942  {
1943  t.right_hand_side ()->accept (*this);
1944  }
1945 
1946  void visit_index_expression (octave::tree_index_expression& t)
1947  {
1948  t.expression ()->accept (*this);
1949  }
1950 
1951  void visit_funcall (octave::tree_funcall& t)
1952  {
1953  octave_value fcn = t.function ();
1954 
1955  if (fcn.is_function ())
1956  {
1957  octave_function *of = fcn.function_value (true);
1958 
1959  if (of)
1960  {
1961  if (of->name () == "__superclass_reference__")
1962  {
1963  octave_value_list args = t.arguments ();
1964 
1965  if (args(0).string_value () == obj_name)
1966  {
1967  std::string class_name = args(1).string_value ();
1968 
1969  cdef_class cls = lookup_class (class_name, false);
1970 
1971  if (cls.ok ())
1972  ctor_list.push_back (cls);
1973  }
1974  }
1975  }
1976  }
1977  }
1978 
1979  std::list<cdef_class> get_constructor_list (void) const
1980  { return ctor_list; }
1981 
1982  // NO-OP
1983  void visit_anon_fcn_handle (octave::tree_anon_fcn_handle&) { }
1984  void visit_argument_list (octave::tree_argument_list&) { }
1985  void visit_binary_expression (octave::tree_binary_expression&) { }
1986  void visit_break_command (octave::tree_break_command&) { }
1987  void visit_colon_expression (octave::tree_colon_expression&) { }
1988  void visit_continue_command (octave::tree_continue_command&) { }
1989  void visit_decl_command (octave::tree_decl_command&) { }
1990  void visit_decl_init_list (octave::tree_decl_init_list&) { }
1991  void visit_decl_elt (octave::tree_decl_elt&) { }
1992  void visit_simple_for_command (octave::tree_simple_for_command&) { }
1993  void visit_complex_for_command (octave::tree_complex_for_command&) { }
1994  void visit_octave_user_script (octave_user_script&) { }
1995  void visit_octave_user_function (octave_user_function&) { }
1996  void visit_function_def (octave::tree_function_def&) { }
1997  void visit_identifier (octave::tree_identifier&) { }
1998  void visit_if_clause (octave::tree_if_clause&) { }
1999  void visit_if_command (octave::tree_if_command&) { }
2000  void visit_if_command_list (octave::tree_if_command_list&) { }
2001  void visit_switch_case (octave::tree_switch_case&) { }
2002  void visit_switch_case_list (octave::tree_switch_case_list&) { }
2003  void visit_switch_command (octave::tree_switch_command&) { }
2004  void visit_matrix (octave::tree_matrix&) { }
2005  void visit_cell (octave::tree_cell&) { }
2006  void visit_no_op_command (octave::tree_no_op_command&) { }
2007  void visit_constant (octave::tree_constant&) { }
2008  void visit_fcn_handle (octave::tree_fcn_handle&) { }
2009  void visit_parameter_list (octave::tree_parameter_list&) { }
2010  void visit_postfix_expression (octave::tree_postfix_expression&) { }
2011  void visit_prefix_expression (octave::tree_prefix_expression&) { }
2012  void visit_return_command (octave::tree_return_command&) { }
2013  void visit_return_list (octave::tree_return_list&) { }
2014  void visit_try_catch_command (octave::tree_try_catch_command&) { }
2015  void visit_unwind_protect_command (octave::tree_unwind_protect_command&) { }
2016  void visit_while_command (octave::tree_while_command&) { }
2017  void visit_do_until_command (octave::tree_do_until_command&) { }
2018 
2019 private:
2020  // The name of the constructor being analyzed.
2021  std::string who;
2022 
2023  // The name of the first output argument of the constructor.
2024  std::string obj_name;
2025 
2026  // The list of superclass constructors that are explicitly called.
2027  std::list<cdef_class> ctor_list;
2028 };
2029 
2030 void
2031 cdef_class::cdef_class_rep::install_method (const cdef_method& meth)
2032 {
2033  method_map[meth.get_name ()] = meth;
2034 
2035  member_count++;
2036 
2037  if (meth.is_constructor ())
2038  {
2039  // Analyze the constructor code to determine what superclass
2040  // constructors are called explicitly.
2041 
2042  octave_function *of = meth.get_function ().function_value (true);
2043 
2044  if (of)
2045  {
2046  octave_user_function *uf = of->user_function_value (true);
2047 
2048  if (uf)
2049  {
2050  octave::tree_parameter_list *ret_list = uf->return_list ();
2051  octave::tree_statement_list *body = uf->body ();
2052 
2053  if (! ret_list || ret_list->size () != 1)
2054  error ("%s: invalid constructor output arguments",
2055  meth.get_name ().c_str ());
2056 
2057  std::string obj_name = ret_list->front ()->name ();
2058  ctor_analyzer a (meth.get_name (), obj_name);
2059 
2060  body->accept (a);
2061 
2062  std::list<cdef_class> explicit_ctor_list
2063  = a.get_constructor_list ();
2064 
2065  for (const auto& cdef_cls : explicit_ctor_list)
2066  {
2067 #if DEBUG_TRACE
2068  std::cerr << "explicit superclass constructor: "
2069  << cdef_cls.get_name () << std::endl;
2070 #endif
2071 
2072  implicit_ctor_list.remove (cdef_cls);
2073  }
2074  }
2075  }
2076  }
2077 }
2078 
2079 void
2080 cdef_class::cdef_class_rep::load_all_methods (void)
2081 {
2082  // FIXME: re-scan class directory
2083 }
2084 
2085 Cell
2086 cdef_class::cdef_class_rep::get_methods (void)
2087 {
2088  std::map<std::string,cdef_method> meths;
2089 
2090  find_methods (meths, false);
2091 
2092  Cell c (meths.size (), 1);
2093 
2094  int idx = 0;
2095 
2096  for (const auto& nm_mthd : meths)
2097  c(idx++, 0) = to_ov (nm_mthd.second);
2098 
2099  return c;
2100 }
2101 
2102 void
2103 cdef_class::cdef_class_rep::find_methods (std::map<std::string,
2104  cdef_method>& meths,
2105  bool only_inherited)
2106 {
2107  load_all_methods ();
2108 
2109  method_const_iterator it;
2110 
2111  for (it = method_map.begin (); it != method_map.end (); ++it)
2112  {
2113  if (! it->second.is_constructor ())
2114  {
2115  std::string nm = it->second.get_name ();
2116 
2117  if (meths.find (nm) == meths.end ())
2118  {
2119  if (only_inherited)
2120  {
2121  octave_value acc = it->second.get ("Access");
2122 
2123  if (! acc.is_string ()
2124  || acc.string_value () == "private")
2125  continue;
2126  }
2127 
2128  meths[nm] = it->second;
2129  }
2130  }
2131  }
2132 
2133  // Look into superclasses
2134 
2135  Cell super_classes = get ("SuperClasses").cell_value ();
2136 
2137  for (int i = 0; i < super_classes.numel (); i++)
2138  {
2139  cdef_class cls = lookup_class (super_classes(i));
2140 
2141  cls.get_rep ()->find_methods (meths, true);
2142  }
2143 }
2144 
2145 cdef_property
2146 cdef_class::cdef_class_rep::find_property (const std::string& nm)
2147 {
2148  property_iterator it = property_map.find (nm);
2149 
2150  if (it != property_map.end ())
2151  {
2152  cdef_property& prop = it->second;
2153 
2154  if (prop.ok ())
2155  return prop;
2156  }
2157 
2158  // Look into superclasses
2159 
2160  Cell super_classes = get ("SuperClasses").cell_value ();
2161 
2162  for (int i = 0; i < super_classes.numel (); i++)
2163  {
2164  cdef_class cls = lookup_class (super_classes(i));
2165 
2166  cdef_property prop = cls.find_property (nm);
2167 
2168  if (prop.ok ())
2169  return prop;
2170  }
2171 
2172  return cdef_property ();
2173 }
2174 
2175 void
2176 cdef_class::cdef_class_rep::install_property (const cdef_property& prop)
2177 {
2178  property_map[prop.get_name ()] = prop;
2179 
2180  member_count++;
2181 }
2182 
2183 Cell
2184 cdef_class::cdef_class_rep::get_properties (int mode)
2185 {
2186  std::map<std::string,cdef_property> props;
2187 
2188  props = get_property_map (mode);
2189 
2190  Cell c (props.size (), 1);
2191 
2192  int idx = 0;
2193 
2194  for (const auto& pname_prop : props)
2195  c(idx++, 0) = to_ov (pname_prop.second);
2196 
2197  return c;
2198 }
2199 
2200 std::map<std::string, cdef_property>
2201 cdef_class::cdef_class_rep::get_property_map (int mode)
2202 {
2203  std::map<std::string,cdef_property> props;
2204 
2205  find_properties (props, mode);
2206 
2207  return props;
2208 }
2209 
2210 void
2211 cdef_class::cdef_class_rep::find_properties (std::map<std::string,
2212  cdef_property>& props,
2213  int mode)
2214 {
2215  property_const_iterator it;
2216 
2217  for (it = property_map.begin (); it != property_map.end (); ++it)
2218  {
2219  std::string nm = it->second.get_name ();
2220 
2221  if (props.find (nm) == props.end ())
2222  {
2223  if (mode == property_inherited)
2224  {
2225  octave_value acc = it->second.get ("GetAccess");
2226 
2227  if (! acc.is_string ()
2228  || acc.string_value () == "private")
2229  continue;
2230  }
2231 
2232  props[nm] = it->second;
2233  }
2234  }
2235 
2236  // Look into superclasses
2237 
2238  Cell super_classes = get ("SuperClasses").cell_value ();
2239 
2240  for (int i = 0; i < super_classes.numel (); i++)
2241  {
2242  cdef_class cls = lookup_class (super_classes(i));
2243 
2244  cls.get_rep ()->find_properties (props,
2245  (mode == property_all
2246  ? property_all
2247  : property_inherited));
2248  }
2249 }
2250 
2251 void
2252 cdef_class::cdef_class_rep::find_names (std::set<std::string>& names,
2253  bool all)
2254 {
2255  load_all_methods ();
2256 
2257  for (const auto& cls_fnmap : method_map)
2258  {
2259  if (! cls_fnmap.second.is_constructor ())
2260  {
2261  std::string nm = cls_fnmap.second.get_name ();
2262 
2263  if (! all)
2264  {
2265  octave_value acc = cls_fnmap.second.get ("Access");
2266 
2267  if (! acc.is_string()
2268  || acc.string_value () != "public")
2269  continue;
2270  }
2271 
2272  names.insert (nm);
2273  }
2274  }
2275 
2276  for (const auto& pname_prop : property_map)
2277  {
2278  std::string nm = pname_prop.second.get_name ();
2279 
2280  if (! all)
2281  {
2282  octave_value acc = pname_prop.second.get ("GetAccess");
2283 
2284  if (! acc.is_string()
2285  || acc.string_value () != "public")
2286  continue;
2287  }
2288 
2289  names.insert (nm);
2290  }
2291 
2292  // Look into superclasses
2293 
2294  Cell super_classes = get ("SuperClasses").cell_value ();
2295 
2296  for (int i = 0; i < super_classes.numel (); i++)
2297  {
2298  cdef_class cls = lookup_class (super_classes(i));
2299 
2300  cls.get_rep ()->find_names (names, all);
2301  }
2302 }
2303 
2304 string_vector
2305 cdef_class::cdef_class_rep::get_names (void)
2306 {
2307  std::set<std::string> names;
2308 
2309  find_names (names, false);
2310 
2311  string_vector v (names);
2312 
2313  return v.sort (true);
2314 }
2315 
2316 void
2317 cdef_class::cdef_class_rep::delete_object (const cdef_object& obj)
2318 {
2319  cdef_method dtor = find_method ("delete");
2320 
2321  if (dtor.ok ())
2322  dtor.execute (obj, octave_value_list (), 0, true, "destructor");
2323 
2324  // FIXME: should we destroy corresponding properties here?
2325 
2326  // Call "delete" in super classes
2327 
2328  Cell super_classes = get ("SuperClasses").cell_value ();
2329 
2330  for (int i = 0; i < super_classes.numel (); i++)
2331  {
2332  cdef_class cls = lookup_class (super_classes(i));
2333 
2334  if (cls.get_name () != "handle")
2335  cls.delete_object (obj);
2336  }
2337 }
2338 
2339 octave_value_list
2340 cdef_class::cdef_class_rep::meta_subsref (const std::string& type,
2341  const std::list<octave_value_list>& idx,
2342  int nargout)
2343 {
2344  size_t skip = 1;
2345 
2346  octave_value_list retval;
2347 
2348  switch (type[0])
2349  {
2350  case '(':
2351  // Constructor call
2352 
2353 #if DEBUG_TRACE
2354  std::cerr << "constructor" << std::endl;
2355 #endif
2356 
2357  retval(0) = construct (idx.front ());
2358  break;
2359 
2360  case '.':
2361  {
2362  // Static method, constant (or property?)
2363 
2364 #if DEBUG_TRACE
2365  std::cerr << "static method/property" << std::endl;
2366 #endif
2367 
2368  if (idx.front ().length () != 1)
2369  error ("invalid meta.class indexing");
2370 
2371  std::string nm = idx.front ()(0).xstring_value ("invalid meta.class indexing, expected a method or property name");
2372 
2373  cdef_method meth = find_method (nm);
2374 
2375  if (meth.ok ())
2376  {
2377  if (! meth.is_static ())
2378  error ("method `%s' is not static", nm.c_str ());
2379 
2380  octave_value_list args;
2381 
2382  if (type.length () > 1 && idx.size () > 1
2383  && type[1] == '(')
2384  {
2385  args = *(++(idx.begin ()));
2386  skip++;
2387  }
2388 
2389  retval = meth.execute (args, (type.length () > skip
2390  ? 1 : nargout), true,
2391  "meta.class");
2392  }
2393  else
2394  {
2395  cdef_property prop = find_property (nm);
2396 
2397  if (! prop.ok ())
2398  error ("no such method or property `%s'", nm.c_str ());
2399 
2400  if (! prop.is_constant ())
2401  error ("property `%s' is not constant", nm.c_str ());
2402 
2403  retval(0) = prop.get_value (true, "meta.class");
2404  }
2405  }
2406  break;
2407 
2408  default:
2409  error ("invalid meta.class indexing");
2410  break;
2411  }
2412 
2413  if (type.length () > skip && idx.size () > skip && ! retval.empty ())
2414  retval = retval(0).next_subsref (nargout, type, idx, skip);
2415 
2416  return retval;
2417 }
2418 
2419 void
2420 cdef_class::cdef_class_rep::meta_release (void)
2421 {
2422  cdef_manager& cdm
2423  = octave::__get_cdef_manager__ ("cdef_class::cdef_class_rep::meta_release");
2424 
2425  cdm.unregister_class (wrap ());
2426 }
2427 
2428 void
2429 cdef_class::cdef_class_rep::initialize_object (cdef_object& obj)
2430 {
2431  // Populate the object with default property values
2432 
2433  std::list<cdef_class> super_classes = lookup_classes (
2434  get ("SuperClasses").cell_value ());
2435 
2436  for (auto& cls : super_classes)
2437  cls.initialize_object (obj);
2438 
2439  for (const auto& pname_prop : property_map)
2440  {
2441  if (! pname_prop.second.get ("Dependent").bool_value ())
2442  {
2443  octave_value pvalue = pname_prop.second.get ("DefaultValue");
2444 
2445  if (pvalue.is_defined ())
2446  obj.put (pname_prop.first, pvalue);
2447  else
2448  obj.put (pname_prop.first, octave_value (Matrix ()));
2449  }
2450  }
2451 
2452  refcount++;
2453  obj.mark_for_construction (cdef_class (this));
2454 }
2455 
2456 void
2457 cdef_class::cdef_class_rep::run_constructor (cdef_object& obj,
2458  const octave_value_list& args)
2459 {
2460  octave_value_list empty_args;
2461 
2462  for (const auto& cls : implicit_ctor_list)
2463  {
2464  cdef_class supcls = lookup_class (cls);
2465 
2466  supcls.run_constructor (obj, empty_args);
2467  }
2468 
2469  std::string cls_name = get_name ();
2470  std::string ctor_name = get_base_name (cls_name);
2471 
2472  cdef_method ctor = find_method (ctor_name);
2473 
2474  if (ctor.ok ())
2475  {
2476  octave_value_list ctor_args (args);
2477  octave_value_list ctor_retval;
2478 
2479  ctor_args.prepend (to_ov (obj));
2480  ctor_retval = ctor.execute (ctor_args, 1, true, "constructor");
2481 
2482  if (ctor_retval.length () != 1)
2483  error ("%s: invalid number of output arguments for classdef constructor",
2484  ctor_name.c_str ());
2485 
2486  obj = to_cdef (ctor_retval(0));
2487  }
2488 
2489  obj.mark_as_constructed (wrap ());
2490 }
2491 
2492 octave_value
2493 cdef_class::cdef_class_rep::construct (const octave_value_list& args)
2494 {
2495  cdef_object obj = construct_object (args);
2496 
2497  if (obj.ok ())
2498  return to_ov (obj);
2499 
2500  return octave_value ();
2501 }
2502 
2503 cdef_object
2504 cdef_class::cdef_class_rep::construct_object (const octave_value_list& args)
2505 {
2506  if (is_abstract ())
2507  error ("cannot instantiate object for abstract class `%s'",
2508  get_name ().c_str ());
2509 
2510  cdef_object obj;
2511 
2512  if (is_meta_class ())
2513  {
2514  // This code path is only used to create empty meta objects
2515  // as filler for the empty values within a meta object array.
2516 
2517  cdef_class this_cls = wrap ();
2518 
2519  static cdef_object empty_class;
2520 
2521  cdef_manager& cdm
2522  = octave::__get_cdef_manager__ ("cdef_class::cdef_class_rep::construct_object");
2523 
2524  if (this_cls == cdm.meta_class ())
2525  {
2526  if (! empty_class.ok ())
2527  empty_class = cdm.make_class ("", std::list<cdef_class> ());
2528  obj = empty_class;
2529  }
2530  else if (this_cls == cdm.meta_property ())
2531  {
2532  static cdef_property empty_property;
2533 
2534  if (! empty_class.ok ())
2535  empty_class = cdm.make_class ("", std::list<cdef_class> ());
2536  if (! empty_property.ok ())
2537  empty_property = cdm.make_property (empty_class, "");
2538  obj = empty_property;
2539  }
2540  else if (this_cls == cdm.meta_method ())
2541  {
2542  static cdef_method empty_method;
2543 
2544  if (! empty_class.ok ())
2545  empty_class = cdm.make_class ("", std::list<cdef_class> ());
2546  if (! empty_method.ok ())
2547  empty_method = cdm.make_method (empty_class, "", octave_value ());
2548  obj = empty_method;
2549  }
2550  else if (this_cls == cdm.meta_package ())
2551  {
2552  static cdef_package empty_package;
2553 
2554  if (! empty_package.ok ())
2555  empty_package = cdm.make_package ("");
2556  obj = empty_package;
2557  }
2558  else
2559  panic_impossible ();
2560 
2561  return obj;
2562  }
2563  else
2564  {
2565  if (is_handle_class ())
2566  obj = cdef_object (new handle_cdef_object ());
2567  else
2568  obj = cdef_object (new value_cdef_object ());
2569  obj.set_class (wrap ());
2570 
2571  initialize_object (obj);
2572 
2573  run_constructor (obj, args);
2574 
2575  return obj;
2576  }
2577 
2578  return cdef_object ();
2579 }
2580 
2581 static octave_value
2582 compute_attribute_value (octave::tree_evaluator& tw,
2583  octave::tree_classdef_attribute *t)
2584 {
2585  octave::tree_expression *expr = t->expression ();
2586 
2587  if (expr)
2588  {
2589  if (expr->is_identifier ())
2590  {
2591  std::string s = expr->name ();
2592 
2593  if (s == "public")
2594  return std::string ("public");
2595  else if (s == "protected")
2596  return std::string ("protected");
2597  else if (s == "private")
2598  return std::string ("private");
2599  }
2600 
2601  return tw.evaluate (expr);
2602  }
2603  else
2604  return octave_value (true);
2605 }
2606 
2607 template <typename T>
2608 static std::string
2609 attribute_value_to_string (T *t, octave_value v)
2610 {
2611  if (v.is_string ())
2612  return v.string_value ();
2613  else if (t->expression ())
2614  return t->expression ()->original_text ();
2615  else
2616  return "true";
2617 }
2618 
2619 cdef_class
2620 cdef_class::make_meta_class (octave::interpreter& interp,
2621  octave::tree_classdef *t, bool is_at_folder)
2622 {
2623  cdef_class retval;
2624  std::string class_name, full_class_name;
2625 
2626  // Class creation
2627 
2628  class_name = full_class_name = t->ident ()->name ();
2629  if (! t->package_name ().empty ())
2630  full_class_name = t->package_name () + '.' + full_class_name;
2631 
2632 #if DEBUG_TRACE
2633  std::cerr << "class: " << full_class_name << std::endl;
2634 #endif
2635 
2636  std::list<cdef_class> slist;
2637 
2638  if (t->superclass_list ())
2639  {
2640  for (auto& scls : (*t->superclass_list ()))
2641  {
2642  std::string sclass_name = (scls)->class_name ();
2643 
2644 #if DEBUG_TRACE
2645  std::cerr << "superclass: " << sclass_name << std::endl;
2646 #endif
2647 
2648  cdef_class sclass = lookup_class (sclass_name);
2649 
2650  if (sclass.get ("Sealed").bool_value ())
2651  error ("`%s' cannot inherit from `%s', because it is sealed",
2652  full_class_name.c_str (), sclass_name.c_str ());
2653 
2654  slist.push_back (sclass);
2655  }
2656  }
2657 
2658  cdef_manager& cdm
2659  = octave::__get_cdef_manager__ ("cdef_class::make_meta_class");
2660 
2661  retval = cdm.make_class (full_class_name, slist);
2662 
2663  // Package owning this class
2664 
2665  if (! t->package_name ().empty ())
2666  {
2667  cdef_package pack = cdm.find_package (t->package_name ());
2668 
2669  if (pack.ok ())
2670  retval.put ("ContainingPackage", to_ov (pack));
2671  }
2672 
2673  // Class attributes
2674 
2675  octave::tree_evaluator& tw = interp.get_evaluator ();
2676 
2677  if (t->attribute_list ())
2678  {
2679  for (const auto& attr : (*t->attribute_list ()))
2680  {
2681  std::string aname = attr->ident ()->name ();
2682  octave_value avalue = compute_attribute_value (tw, attr);
2683 
2684 #if DEBUG_TRACE
2685  std::cerr << "class attribute: " << aname << " = "
2686  << attribute_value_to_string (attr, avalue) << std::endl;
2687 #endif
2688 
2689  retval.put (aname, avalue);
2690  }
2691  }
2692 
2693  octave::tree_classdef_body *b = t->body ();
2694 
2695  if (b)
2696  {
2697  // Keep track of the get/set accessor methods. They will be used
2698  // later on when creating properties.
2699 
2700  std::map<std::string, octave_value> get_methods;
2701  std::map<std::string, octave_value> set_methods;
2702 
2703  // Method blocks
2704 
2705  std::list<octave::tree_classdef_methods_block *> mb_list = b->methods_list ();
2706 
2707  octave::load_path& lp = interp.get_load_path ();
2708 
2709  for (auto& mb_p : mb_list)
2710  {
2711  std::map<std::string, octave_value> amap;
2712 
2713 #if DEBUG_TRACE
2714  std::cerr << "method block" << std::endl;
2715 #endif
2716 
2717  // Method attributes
2718 
2719  if (mb_p->attribute_list ())
2720  {
2721  for (auto& attr_p : *mb_p->attribute_list ())
2722  {
2723  std::string aname = attr_p->ident ()->name ();
2724  octave_value avalue = compute_attribute_value (tw, attr_p);
2725 
2726 #if DEBUG_TRACE
2727  std::cerr << "method attribute: " << aname << " = "
2728  << attribute_value_to_string (attr_p, avalue)
2729  << std::endl;
2730 #endif
2731 
2732  amap[aname] = avalue;
2733  }
2734  }
2735 
2736  // Methods
2737 
2738  if (mb_p->element_list ())
2739  {
2740  for (auto& mtd : *mb_p->element_list ())
2741  {
2742  std::string mname = mtd.function_value ()->name ();
2743  std::string mprefix = mname.substr (0, 4);
2744 
2745  if (mprefix == "get.")
2746  get_methods[mname.substr (4)] =
2747  make_fcn_handle (mtd, full_class_name + '>' + mname);
2748  else if (mprefix == "set.")
2749  set_methods[mname.substr (4)] =
2750  make_fcn_handle (mtd, full_class_name + '>' + mname);
2751  else
2752  {
2753  cdef_method meth = cdm.make_method (retval, mname, mtd);
2754 
2755 #if DEBUG_TRACE
2756  std::cerr << (mname == class_name ? "constructor"
2757  : "method")
2758  << ": " << mname << std::endl;
2759 #endif
2760 
2761  for (auto& attrnm_val : amap)
2762  meth.put (attrnm_val.first, attrnm_val.second);
2763 
2764  retval.install_method (meth);
2765  }
2766  }
2767  }
2768  }
2769 
2770  if (is_at_folder)
2771  {
2772  // Look for all external methods visible on octave path at the
2773  // time of loading of the class.
2774  //
2775  // FIXME: This is an "extension" to Matlab behavior, which only looks
2776  // in the @-folder containing the original classdef file. However,
2777  // this is easier to implement it that way at the moment.
2778 
2779  std::list<std::string> external_methods
2780  = lp.methods (full_class_name);
2781 
2782  for (const auto& mtdnm : external_methods)
2783  {
2784  // FIXME: should we issue a warning if the method is already
2785  // defined in the classdef file?
2786 
2787  if (mtdnm != class_name
2788  && ! retval.find_method (mtdnm, true).ok ())
2789  {
2790  // Create a dummy method that is used until the actual
2791  // method is loaded.
2792  octave_user_function *fcn = new octave_user_function ();
2793 
2794  fcn->stash_function_name (mtdnm);
2795 
2796  cdef_method meth
2797  = cdm.make_method (retval, mtdnm, octave_value (fcn));
2798 
2799  retval.install_method (meth);
2800  }
2801  }
2802  }
2803 
2804  // Property blocks
2805 
2806  // FIXME: default property expression should be able to call static
2807  // methods of the class being constructed. A restricted CLASSNAME
2808  // symbol should be added to the scope before evaluating default
2809  // value expressions.
2810 
2811  std::list<octave::tree_classdef_properties_block *> pb_list
2812  = b->properties_list ();
2813 
2814  for (auto& pb_p : pb_list)
2815  {
2816  std::map<std::string, octave_value> amap;
2817 
2818 #if DEBUG_TRACE
2819  std::cerr << "property block" << std::endl;
2820 #endif
2821 
2822  // Property attributes
2823 
2824  if (pb_p->attribute_list ())
2825  {
2826  for (auto& attr_p : *pb_p->attribute_list ())
2827  {
2828  std::string aname = attr_p->ident ()->name ();
2829  octave_value avalue = compute_attribute_value (tw, attr_p);
2830 
2831 #if DEBUG_TRACE
2832  std::cerr << "property attribute: " << aname << " = "
2833  << attribute_value_to_string (attr_p, avalue)
2834  << std::endl;
2835 #endif
2836 
2837  if (aname == "Access")
2838  {
2839  amap["GetAccess"] = avalue;
2840  amap["SetAccess"] = avalue;
2841  }
2842  else
2843  amap[aname] = avalue;
2844  }
2845  }
2846 
2847  // Properties
2848 
2849  if (pb_p->element_list ())
2850  {
2851  for (auto& prop_p : *pb_p->element_list ())
2852  {
2853  std::string prop_name = prop_p->ident ()->name ();
2854 
2855  cdef_property prop = cdm.make_property (retval, prop_name);
2856 
2857 #if DEBUG_TRACE
2858  std::cerr << "property: " << prop_p->ident ()->name ()
2859  << std::endl;
2860 #endif
2861 
2862  octave::tree_expression *expr = prop_p->expression ();
2863  if (expr)
2864  {
2865  octave_value pvalue = tw.evaluate (expr);
2866 
2867 #if DEBUG_TRACE
2868  std::cerr << "property default: "
2869  << attribute_value_to_string (*pit, pvalue)
2870  << std::endl;
2871 #endif
2872 
2873  prop.put ("DefaultValue", pvalue);
2874  }
2875 
2876  // Install property attributes. This is done before assigning
2877  // the property accessors so we can do validation by using
2878  // cdef_property methods.
2879 
2880  for (auto& attrnm_val : amap)
2881  prop.put (attrnm_val.first, attrnm_val.second);
2882 
2883  // Install property access methods, if any. Remove the
2884  // accessor methods from the temporary storage map, so we can
2885  // detect which ones are invalid and do not correspond to a
2886  // defined property.
2887 
2888  std::map<std::string, octave_value>::iterator git =
2889  get_methods.find (prop_name);
2890 
2891  if (git != get_methods.end ())
2892  {
2893  make_function_of_class (retval, git->second);
2894  prop.put ("GetMethod", git->second);
2895  get_methods.erase (git);
2896  }
2897 
2898  std::map<std::string, octave_value>::iterator sit =
2899  set_methods.find (prop_name);
2900 
2901  if (sit != set_methods.end ())
2902  {
2903  make_function_of_class (retval, sit->second);
2904  prop.put ("SetMethod", sit->second);
2905  set_methods.erase (sit);
2906  }
2907 
2908  retval.install_property (prop);
2909  }
2910  }
2911  }
2912  }
2913 
2914  return retval;
2915 }
2916 
2917 octave_function*
2918 cdef_class::get_method_function (const std::string& /* nm */)
2919 {
2920  octave_classdef_meta *p = new octave_classdef_meta (*this);
2921 
2922  return p;
2923 }
2924 
2925 octave_value
2926 cdef_property::cdef_property_rep::get_value (const cdef_object& obj,
2927  bool do_check_access,
2928  const std::string& who)
2929 {
2930  octave_value retval;
2931 
2932  if (do_check_access && ! check_get_access ())
2933  err_property_access (who, wrap (), false);
2934 
2935  if (! obj.is_constructed ())
2936  {
2937  cdef_class cls (to_cdef (get ("DefiningClass")));
2938 
2939  if (! obj.is_partially_constructed_for (cls))
2940  error ("cannot reference properties of class `%s' for non-constructed object",
2941  cls.get_name ().c_str ());
2942  }
2943 
2944  octave_value get_fcn = get ("GetMethod");
2945 
2946  // FIXME: should check whether we're already in get accessor method
2947 
2948  if (get_fcn.isempty () || is_method_executing (get_fcn, obj))
2949  retval = obj.get (get ("Name").string_value ());
2950  else
2951  {
2952  octave_value_list args;
2953 
2954  args(0) = to_ov (obj);
2955 
2956  args = octave::feval (get_fcn, args, 1);
2957 
2958  retval = args(0);
2959  }
2960 
2961  return retval;
2962 }
2963 
2964 octave_value
2965 cdef_property::cdef_property_rep::get_value (bool do_check_access,
2966  const std::string& who)
2967 {
2968  if (do_check_access && ! check_get_access ())
2969  err_property_access (who, wrap (), false);
2970 
2971  return get ("DefaultValue");
2972 }
2973 
2974 bool
2975 cdef_property::cdef_property_rep::is_recursive_set (const cdef_object& /* obj */) const
2976 {
2977  // FIXME: implement
2978  return false;
2979 }
2980 
2981 void
2982 cdef_property::cdef_property_rep::set_value (cdef_object& obj,
2983  const octave_value& val,
2984  bool do_check_access,
2985  const std::string& who)
2986 {
2987  if (do_check_access && ! check_set_access ())
2988  err_property_access (who, wrap (), true);
2989 
2990  if (! obj.is_constructed ())
2991  {
2992  cdef_class cls (to_cdef (get ("DefiningClass")));
2993 
2994  if (! obj.is_partially_constructed_for (cls))
2995  error ("cannot reference properties of class `%s' for non-constructed object",
2996  cls.get_name ().c_str ());
2997  }
2998 
2999  octave_value set_fcn = get ("SetMethod");
3000 
3001  if (set_fcn.isempty () || is_method_executing (set_fcn, obj))
3002  obj.put (get ("Name").string_value (), val);
3003  else
3004  {
3005  octave_value_list args;
3006 
3007  args(0) = to_ov (obj);
3008  args(1) = val;
3009 
3010  args = octave::feval (set_fcn, args, 1);
3011 
3012  if (args.length () > 0 && args(0).is_defined ())
3013  {
3014  if (args (0).is_classdef_object ())
3015  {
3016  cdef_object new_obj = to_cdef (args(0));
3017 
3018  obj = new_obj;
3019  }
3020  else
3021  ::warning ("set-method of property `%s' returned a non-classdef object",
3022  get_name ().c_str ());
3023  }
3024  }
3025 }
3026 
3027 bool
3028 cdef_property::cdef_property_rep::check_get_access (void) const
3029 {
3030  cdef_class cls (to_cdef (get ("DefiningClass")));
3031 
3032  return ::check_access (cls, get ("GetAccess"), "",
3033  get_name (), false);
3034 
3035  return false;
3036 }
3037 
3038 bool
3039 cdef_property::cdef_property_rep::check_set_access (void) const
3040 {
3041  cdef_class cls (to_cdef (get ("DefiningClass")));
3042 
3043  return ::check_access (cls, get ("SetAccess"), "",
3044  get_name (), true);
3045 
3046  return false;
3047 }
3048 
3049 void
3050 cdef_method::cdef_method_rep::check_method (void)
3051 {
3052  if (is_external ())
3053  {
3054  if (is_dummy_method (function))
3055  {
3056  octave::load_path& lp
3057  = octave::__get_load_path__ ("cdef_method::cdef_method_rep::check_method");
3058 
3059  std::string name = get_name ();
3060  std::string cls_name = dispatch_type;
3061  std::string pack_name;
3062 
3063  size_t pos = cls_name.rfind ('.');
3064 
3065  if (pos != std::string::npos)
3066  {
3067  pack_name = cls_name.substr (0, pos);
3068  cls_name = cls_name.substr (pos + 1);
3069  }
3070 
3071  std::string dir_name;
3072  std::string file_name = lp.find_method (cls_name, name,
3073  dir_name, pack_name);
3074 
3075  if (! file_name.empty ())
3076  {
3077  octave_value ov_fcn
3078  = octave::load_fcn_from_file (file_name, dir_name,
3079  dispatch_type, pack_name);
3080 
3081  if (ov_fcn.is_defined ())
3082  {
3083  function = ov_fcn;
3084 
3085  make_function_of_class (dispatch_type, function);
3086  }
3087  }
3088  }
3089  else
3090  {
3091  // FIXME: check out-of-date status
3092  }
3093 
3094  if (is_dummy_method (function))
3095  error ("no definition found for method `%s' of class `%s'",
3096  get_name ().c_str (), dispatch_type.c_str ());
3097  }
3098 }
3099 
3100 octave_value_list
3101 cdef_method::cdef_method_rep::execute (const octave_value_list& args,
3102  int nargout, bool do_check_access,
3103  const std::string& who)
3104 {
3105  octave_value_list retval;
3106 
3107  if (do_check_access && ! check_access ())
3108  err_method_access (who, wrap ());
3109 
3110  if (get ("Abstract").bool_value ())
3111  error ("%s: cannot execute abstract method",
3112  get ("Name").string_value ().c_str ());
3113 
3114  check_method ();
3115 
3116  if (function.is_defined ())
3117  retval = octave::feval (function, args, nargout);
3118 
3119  return retval;
3120 }
3121 
3122 octave_value_list
3123 cdef_method::cdef_method_rep::execute (const cdef_object& obj,
3124  const octave_value_list& args,
3125  int nargout, bool do_check_access,
3126  const std::string& who)
3127 {
3128  octave_value_list retval;
3129 
3130  if (do_check_access && ! check_access ())
3131  err_method_access (who, wrap ());
3132 
3133  if (get ("Abstract").bool_value ())
3134  error ("%s: cannot execute abstract method",
3135  get ("Name").string_value ().c_str ());
3136 
3137  check_method ();
3138 
3139  if (function.is_defined ())
3140  {
3141  octave_value_list new_args;
3142 
3143  new_args.resize (args.length () + 1);
3144 
3145  new_args(0) = to_ov (obj);
3146  for (int i = 0; i < args.length (); i++)
3147  new_args(i+1) = args(i);
3148 
3149  retval = octave::feval (function, new_args, nargout);
3150  }
3151 
3152  return retval;
3153 }
3154 
3155 bool
3156 cdef_method::cdef_method_rep::is_constructor (void) const
3157 {
3158  if (function.is_function())
3159  return function.function_value ()->is_classdef_constructor ();
3160 
3161  return false;
3162 }
3163 
3164 bool
3165 cdef_method::cdef_method_rep::check_access (void) const
3166 {
3167  cdef_class cls (to_cdef (get ("DefiningClass")));
3168 
3169  return ::check_access (cls, get ("Access"), get_name ());
3170 }
3171 
3172 octave_value_list
3173 cdef_method::cdef_method_rep::meta_subsref
3174  (const std::string& type, const std::list<octave_value_list>& idx,
3175  int nargout)
3176 {
3177  octave_value_list retval;
3178 
3179  switch (type[0])
3180  {
3181  case '(':
3182  retval = (execute (idx.front (), type.length () > 1 ? 1 : nargout, true));
3183  break;
3184 
3185  default:
3186  error ("invalid meta.method indexing");
3187  break;
3188  }
3189 
3190  if (type.length () > 1 && idx.size () > 1 && ! retval.empty ())
3191  retval = retval(0).next_subsref (nargout, type, idx, 1);
3192 
3193  return retval;
3194 }
3195 
3196 static cdef_package
3197 lookup_package (const std::string& name, bool error_if_not_found = true,
3198  bool load_if_not_found = true)
3199 {
3200  cdef_manager& cdm = octave::__get_cdef_manager__ ("lookup_package");
3201 
3202  return cdm.find_package (name, error_if_not_found, load_if_not_found);
3203 }
3204 
3205 static octave_value_list
3206 package_fromName (const octave_value_list& args, int /* nargout */)
3207 {
3208  octave_value_list retval;
3209 
3210  if (args.length () != 1)
3211  error ("fromName: invalid number of parameters");
3212 
3213  std::string name = args(0).xstring_value ("fromName: PACKAGE_NAME must be a string");
3214 
3215  retval(0) = to_ov (lookup_package (name, false));
3216 
3217  return retval;
3218 }
3219 
3220 static octave_value_list
3221 package_get_classes (const octave_value_list& args, int /* nargout */)
3222 {
3223  octave_value_list retval (1, Matrix ());
3224 
3225  if (args.length () == 1 && args(0).type_name () == "object"
3226  && args(0).class_name () == "meta.package")
3227  {
3228  cdef_package pack (to_cdef (args(0)));
3229 
3230  retval(0) = pack.get_classes ();
3231  }
3232 
3233  return retval;
3234 }
3235 
3236 static octave_value_list
3237 package_get_functions (const octave_value_list& args, int /* nargout */)
3238 {
3239  octave_value_list retval (1, Matrix ());
3240 
3241  if (args.length () == 0 && args(0).type_name () == "object"
3242  && args(0).class_name () == "meta.package")
3243  {
3244  cdef_package pack (to_cdef (args(0)));
3245 
3246  retval(0) = pack.get_functions ();
3247  }
3248 
3249  return retval;
3250 }
3251 
3252 static octave_value_list
3253 package_get_packages (const octave_value_list& args, int /* nargout */)
3254 {
3255  octave_value_list retval (1, Matrix ());
3256 
3257  if (args.length () == 0 && args(0).type_name () == "object"
3258  && args(0).class_name () == "meta.package")
3259  {
3260  cdef_package pack (to_cdef (args(0)));
3261 
3262  retval(0) = pack.get_packages ();
3263  }
3264 
3265  return retval;
3266 }
3267 
3268 static octave_value_list
3269 package_getAllPackages (octave::interpreter& interp,
3270  const octave_value_list& /* args */, int /* nargout */)
3271 {
3272  std::map<std::string, cdef_package> toplevel_packages;
3273 
3274  octave::load_path& lp = interp.get_load_path ();
3275 
3276  std::list<std::string> names = lp.get_all_package_names ();
3277 
3278  cdef_manager& cdm = octave::__get_cdef_manager__ ("package_getAllPackages");
3279 
3280  toplevel_packages["meta"] = cdm.find_package ("meta", false, false);
3281 
3282  for (const auto& nm : names)
3283  toplevel_packages[nm] = cdm.find_package (nm, false, true);
3284 
3285  Cell c (toplevel_packages.size (), 1);
3286 
3287  int i = 0;
3288 
3289  for (const auto& nm_pkg : toplevel_packages)
3290  c(i++,0) = to_ov (nm_pkg.second);
3291 
3292  return octave_value_list (octave_value (c));
3293 }
3294 
3295 void
3296 cdef_package::cdef_package_rep::install_class (const cdef_class& cls,
3297  const std::string& nm)
3298 {
3299  class_map[nm] = cls;
3300 
3301  member_count++;
3302 }
3303 
3304 void
3305 cdef_package::cdef_package_rep::install_function (const octave_value& fcn,
3306  const std::string& nm)
3307 {
3308  function_map[nm] = fcn;
3309 }
3310 
3311 void
3312 cdef_package::cdef_package_rep::install_package (const cdef_package& pack,
3313  const std::string& nm)
3314 {
3315  package_map[nm] = pack;
3316 
3317  member_count++;
3318 }
3319 
3320 template <typename T1, typename T2>
3321 Cell
3322 map2Cell (const std::map<T1, T2>& m)
3323 {
3324  Cell retval (1, m.size ());
3325  int i = 0;
3326 
3327  for (typename std::map<T1, T2>::const_iterator it = m.begin ();
3328  it != m.end (); ++it, ++i)
3329  {
3330  retval(i) = to_ov (it->second);
3331  }
3332 
3333  return retval;
3334 }
3335 
3336 Cell
3337 cdef_package::cdef_package_rep::get_classes (void) const
3338 { return map2Cell (class_map); }
3339 
3340 Cell
3341 cdef_package::cdef_package_rep::get_functions (void) const
3342 { return map2Cell (function_map); }
3343 
3344 Cell
3345 cdef_package::cdef_package_rep::get_packages (void) const
3346 { return map2Cell (package_map); }
3347 
3348 octave_value
3349 cdef_package::cdef_package_rep::find (const std::string& nm)
3350 {
3351  std::string symbol_name = get_name () + '.' + nm;
3352 
3353  octave::symbol_table& symtab
3354  = octave::__get_symbol_table__ ("cdef_package::cdef_package_rep::find");
3355 
3356  return symtab.find (symbol_name, octave_value_list (), true, false);
3357 }
3358 
3359 octave_value_list
3360 cdef_package::cdef_package_rep::meta_subsref
3361  (const std::string& type, const std::list<octave_value_list>& idx,
3362  int nargout)
3363 {
3364  octave_value_list retval;
3365 
3366  switch (type[0])
3367  {
3368  case '.':
3369  {
3370  if (idx.front ().length () != 1)
3371  error ("invalid meta.package indexing");
3372 
3373  std::string nm = idx.front ()(0).xstring_value ("invalid meta.package indexing, expected a symbol name");
3374 
3375 #if DEBUG_TRACE
3376  std::cerr << "meta.package query: " << nm << std::endl;
3377 #endif
3378 
3379  octave_value o = find (nm);
3380 
3381  if (! o.is_defined ())
3382  error ("member `%s' in package `%s' does not exist",
3383  nm.c_str (), get_name ().c_str ());
3384 
3385  if (o.is_function ())
3386  {
3387  octave_function *fcn = o.function_value ();
3388 
3389  // NOTE: the case where the package query is the last
3390  // part of this subsref index is handled in the parse
3391  // tree, because there is some logic to handle magic
3392  // "end" that makes it impossible to execute the
3393  // function call at this stage.
3394 
3395  if (type.size () > 1
3396  && ! fcn->accepts_postfix_index (type[1]))
3397  {
3398  octave_value_list tmp_args;
3399 
3400  retval = octave::feval (o, tmp_args, nargout);
3401  }
3402  else
3403  retval(0) = o;
3404 
3405  if (type.size () > 1 && idx.size () > 1)
3406  retval = retval(0).next_subsref (nargout, type,
3407  idx, 1);
3408  }
3409  else if (type.size () > 1 && idx.size () > 1)
3410  retval = o.next_subsref (nargout, type, idx, 1);
3411  else
3412  retval(0) = o;
3413  }
3414  break;
3415 
3416  default:
3417  error ("invalid meta.package indexing");
3418  break;
3419  }
3420 
3421  return retval;
3422 }
3423 
3424 void
3425 cdef_package::cdef_package_rep::meta_release (void)
3426 {
3427  // FIXME: Do we really want to unregister the package, as it
3428  // could still be referenced by classes or sub-packages?
3429  // If the package object is recreated later on, it won't
3430  // match the one already referenced by those classes or
3431  // sub-packages.
3432 
3433  cdef_manager& cdm
3434  = octave::__get_cdef_manager__ ("cdef_package::cdef_package_rep::meta_release");
3435 
3436  // Don't delete the "meta" package.
3437  if (this != cdm.meta ().get_rep ())
3438  cdm.unregister_package (wrap ());
3439 }
3440 
3441 //----------------------------------------------------------------------------
3442 
3443 cdef_manager::cdef_manager (octave::interpreter& interp)
3444  : m_interpreter (interp), m_all_classes (), m_all_packages (),
3445  m_meta_class (), m_meta_property (), m_meta_method (),
3446  m_meta_package (), m_meta ()
3447 {
3448  octave::type_info& ti = m_interpreter.get_type_info ();
3449 
3450  octave_classdef::register_type (ti);
3451 
3452  // bootstrap
3453  cdef_class tmp_handle = make_class ("handle");
3454 
3455  m_meta_class = make_meta_class ("meta.class", tmp_handle);
3456 
3457  tmp_handle.set_class (m_meta_class);
3458  m_meta_class.set_class (m_meta_class);
3459 
3460  // meta classes
3461  m_meta_property = make_meta_class ("meta.property", tmp_handle);
3462 
3463  m_meta_method = make_meta_class ("meta.method", tmp_handle);
3464 
3465  m_meta_package = make_meta_class ("meta.package", tmp_handle);
3466 
3467  cdef_class tmp_meta_event
3468  = make_meta_class ("meta.event", tmp_handle);
3469 
3470  cdef_class tmp_meta_dynproperty
3471  = make_meta_class ("meta.dynamicproperty", tmp_handle);
3472 
3473  // meta.class properties
3474  m_meta_class.install_property
3475  (make_attribute (m_meta_class, "Abstract"));
3476 
3477  m_meta_class.install_property
3478  (make_attribute (m_meta_class, "ConstructOnLoad"));
3479 
3480  m_meta_class.install_property
3481  (make_property (m_meta_class, "ContainingPackage"));
3482 
3483  m_meta_class.install_property
3484  (make_property (m_meta_class, "Description"));
3485 
3486  m_meta_class.install_property
3487  (make_property (m_meta_class, "DetailedDescription"));
3488 
3489  m_meta_class.install_property
3490  (make_property (m_meta_class, "Events"));
3491 
3492  m_meta_class.install_property
3493  (make_attribute (m_meta_class, "HandleCompatible"));
3494 
3495  m_meta_class.install_property
3496  (make_attribute (m_meta_class, "Hidden"));
3497 
3498  m_meta_class.install_property
3499  (make_property (m_meta_class, "InferiorClasses",
3500  make_fcn_handle (class_get_inferiorclasses,
3501  "meta.class>get.InferiorClasses"),
3502  "public", Matrix (), "private"));
3503 
3504  m_meta_class.install_property
3505  (make_property (m_meta_class, "Methods",
3506  make_fcn_handle (class_get_methods,
3507  "meta.class>get.Methods"),
3508  "public", Matrix (), "private"));
3509 
3510  m_meta_class.install_property
3511  (make_property (m_meta_class, "MethodList",
3512  make_fcn_handle (class_get_methods,
3513  "meta.class>get.MethodList"),
3514  "public", Matrix (), "private"));
3515 
3516  m_meta_class.install_property (make_attribute (m_meta_class, "Name"));
3517 
3518  m_meta_class.install_property
3519  (make_property (m_meta_class, "Properties",
3520  make_fcn_handle (class_get_properties,
3521  "meta.class>get.Properties"),
3522  "public", Matrix (), "private"));
3523 
3524  m_meta_class.install_property
3525  (make_property (m_meta_class, "PropertyList",
3526  make_fcn_handle (class_get_properties,
3527  "meta.class>get.PropertyList"),
3528  "public", Matrix (), "private"));
3529 
3530  m_meta_class.install_property (make_attribute (m_meta_class, "Sealed"));
3531 
3532  m_meta_class.install_property
3533  (make_property (m_meta_class, "SuperClasses",
3534  make_fcn_handle (class_get_superclasses,
3535  "meta.class>get.SuperClasses"),
3536  "public", Matrix (), "private"));
3537 
3538  m_meta_class.install_property
3539  (make_property (m_meta_class, "SuperClassList",
3540  make_fcn_handle (class_get_superclasses,
3541  "meta.class>get.SuperClassList"),
3542  "public", Matrix (), "private"));
3543 
3544  // meta.class methods
3545  m_meta_class.install_method
3546  (make_method (m_meta_class, "fromName", class_fromName, "public", true));
3547 
3548  m_meta_class.install_method
3549  (make_method (m_meta_class, "fevalStatic", class_fevalStatic, "public",
3550  false));
3551 
3552  m_meta_class.install_method
3553  (make_method (m_meta_class, "getConstant", class_getConstant, "public",
3554  false));
3555 
3556  m_meta_class.install_method (make_method (m_meta_class, "eq", class_eq));
3557  m_meta_class.install_method (make_method (m_meta_class, "ne", class_ne));
3558  m_meta_class.install_method (make_method (m_meta_class, "lt", class_lt));
3559  m_meta_class.install_method (make_method (m_meta_class, "le", class_le));
3560  m_meta_class.install_method (make_method (m_meta_class, "gt", class_gt));
3561  m_meta_class.install_method (make_method (m_meta_class, "ge", class_ge));
3562 
3563  // meta.method properties
3564  m_meta_method.install_property
3565  (make_attribute (m_meta_method, "Abstract"));
3566 
3567  m_meta_method.install_property
3568  (make_attribute (m_meta_method, "Access"));
3569 
3570  m_meta_method.install_property
3571  (make_attribute (m_meta_method, "DefiningClass"));
3572 
3573  m_meta_method.install_property
3574  (make_attribute (m_meta_method, "Description"));
3575 
3576  m_meta_method.install_property
3577  (make_attribute (m_meta_method, "DetailedDescription"));
3578 
3579  m_meta_method.install_property
3580  (make_attribute (m_meta_method, "Hidden"));
3581 
3582  m_meta_method.install_property
3583  (make_attribute (m_meta_method, "Name"));
3584 
3585  m_meta_method.install_property
3586  (make_attribute (m_meta_method, "Sealed"));
3587 
3588  m_meta_method.install_property
3589  (make_attribute (m_meta_method, "Static"));
3590 
3591  // meta.property properties
3592  m_meta_property.install_property
3593  (make_attribute (m_meta_property, "Name"));
3594 
3595  m_meta_property.install_property
3596  (make_attribute (m_meta_property, "Description"));
3597 
3598  m_meta_property.install_property
3599  (make_attribute (m_meta_property, "DetailedDescription"));
3600 
3601  m_meta_property.install_property
3602  (make_attribute (m_meta_property, "Abstract"));
3603 
3604  m_meta_property.install_property
3605  (make_attribute (m_meta_property, "Constant"));
3606 
3607  m_meta_property.install_property
3608  (make_attribute (m_meta_property, "GetAccess"));
3609 
3610  m_meta_property.install_property
3611  (make_attribute (m_meta_property, "SetAccess"));
3612 
3613  m_meta_property.install_property
3614  (make_attribute (m_meta_property, "Dependent"));
3615 
3616  m_meta_property.install_property
3617  (make_attribute (m_meta_property, "Transient"));
3618 
3619  m_meta_property.install_property
3620  (make_attribute (m_meta_property, "Hidden"));
3621 
3622  m_meta_property.install_property
3623  (make_attribute (m_meta_property, "GetObservable"));
3624 
3625  m_meta_property.install_property
3626  (make_attribute (m_meta_property, "SetObservable"));
3627 
3628  m_meta_property.install_property
3629  (make_attribute (m_meta_property, "GetMethod"));
3630 
3631  m_meta_property.install_property
3632  (make_attribute (m_meta_property, "SetMethod"));
3633 
3634  m_meta_property.install_property
3635  (make_attribute (m_meta_property, "DefiningClass"));
3636 
3637  m_meta_property.install_property
3638  (make_property (m_meta_property, "DefaultValue",
3639  make_fcn_handle (property_get_defaultvalue,
3640  "meta.property>get.DefaultValue"),
3641  "public", Matrix (), "private"));
3642 
3643  m_meta_property.install_property
3644  (make_attribute (m_meta_property, "HasDefault"));
3645 
3646  // meta.property events
3647  // FIXME: add events
3648 
3649  // handle methods
3650 
3651  tmp_handle.install_method
3652  (make_method (tmp_handle, "delete", handle_delete));
3653 
3654  // meta.package properties
3655 
3656  m_meta_package.install_property
3657  (make_attribute (m_meta_package, "Name"));
3658 
3659  m_meta_package.install_property
3660  (make_property (m_meta_package, "ContainingPackage"));
3661 
3662  m_meta_package.install_property
3663  (make_property (m_meta_package, "ClassList",
3664  make_fcn_handle (package_get_classes,
3665  "meta.package>get.ClassList"),
3666  "public", Matrix (), "private"));
3667 
3668  m_meta_package.install_property
3669  (make_property (m_meta_package, "Classes",
3670  make_fcn_handle (package_get_classes,
3671  "meta.package>get.Classes"),
3672  "public", Matrix (), "private"));
3673 
3674  m_meta_package.install_property
3675  (make_property (m_meta_package, "FunctionList",
3676  make_fcn_handle (package_get_functions,
3677  "meta.package>get.FunctionList"),
3678  "public", Matrix (), "private"));
3679 
3680  m_meta_package.install_property
3681  (make_property (m_meta_package, "Functions",
3682  make_fcn_handle (package_get_functions,
3683  "meta.package>get.Functions"),
3684  "public", Matrix (), "private"));
3685 
3686  m_meta_package.install_property
3687  (make_property (m_meta_package, "PackageList",
3688  make_fcn_handle (package_get_packages,
3689  "meta.package>get.PackageList"),
3690  "public", Matrix (), "private"));
3691 
3692  m_meta_package.install_property
3693  (make_property (m_meta_package, "Packages",
3694  make_fcn_handle (package_get_packages,
3695  "meta.package>get.Packages"),
3696  "public", Matrix (), "private"));
3697 
3698  m_meta_package.install_method
3699  (make_method (m_meta_package, "fromName", package_fromName,
3700  "public", true));
3701 
3702  m_meta_package.install_method
3703  (make_method (m_meta_package, "getAllPackages", package_getAllPackages,
3704  "public", true));
3705 
3706  // create "meta" package
3707  cdef_package package_meta
3708  = m_meta
3709  = make_package ("meta");
3710 
3711  package_meta.install_class (m_meta_class, "class");
3712  package_meta.install_class (m_meta_property, "property");
3713  package_meta.install_class (m_meta_method, "method");
3714  package_meta.install_class (m_meta_package, "package");
3715  package_meta.install_class (tmp_meta_event, "event");
3716  package_meta.install_class (tmp_meta_dynproperty, "dynproperty");
3717 
3718  octave::symbol_table& symtab = m_interpreter.get_symbol_table ();
3719 
3720  // install built-in classes into the symbol table
3721  symtab.install_built_in_function
3722  ("meta.class",
3723  octave_value (m_meta_class.get_constructor_function ()));
3724 
3725  symtab.install_built_in_function
3726  ("meta.method",
3727  octave_value (m_meta_method.get_constructor_function ()));
3728 
3729  symtab.install_built_in_function
3730  ("meta.property",
3731  octave_value (m_meta_property.get_constructor_function ()));
3732 
3733  symtab.install_built_in_function
3734  ("meta.package",
3735  octave_value (m_meta_package.get_constructor_function ()));
3736 
3737 // FIXME: meta.event and meta.dynproperty are not implemented
3738 // and should not be installed into symbol table.
3739 
3740 // symtab.install_built_in_function
3741 // ("meta.event",
3742 // octave_value (tmp_meta_event.get_constructor_function ()));
3743 
3744 // symtab.install_built_in_function
3745 // ("meta.dynproperty",
3746 // octave_value (tmp_meta_dynproperty.get_constructor_function ()));
3747 }
3748 
3749 cdef_class
3750 cdef_manager::find_class (const std::string& name, bool error_if_not_found,
3751  bool load_if_not_found)
3752 {
3753  std::map<std::string, cdef_class>::iterator it = m_all_classes.find (name);
3754 
3755  if (it == m_all_classes.end ())
3756  {
3757  if (load_if_not_found)
3758  {
3759  octave_value ov_cls;
3760 
3761  size_t pos = name.rfind ('.');
3762 
3763  if (pos == std::string::npos)
3764  {
3765  octave::symbol_table& symtab
3766  = octave::__get_symbol_table__ ("cdef_manager::find_class");
3767 
3768  ov_cls = symtab.find (name);
3769  }
3770  else
3771  {
3772  std::string pack_name = name.substr (0, pos);
3773 
3774  cdef_package pack = find_package (pack_name, false, true);
3775 
3776  if (pack.ok ())
3777  ov_cls = pack.find (name.substr (pos+1));
3778  }
3779 
3780  if (ov_cls.is_defined ())
3781  it = m_all_classes.find (name);
3782  }
3783  }
3784 
3785  if (it == m_all_classes.end ())
3786  {
3787  if (error_if_not_found)
3788  error ("class not found: %s", name.c_str ());
3789  }
3790  else
3791  {
3792  cdef_class cls = it->second;
3793 
3794  if (! cls.is_builtin ())
3795  cls = lookup_class (cls);
3796 
3797  if (cls.ok ())
3798  return cls;
3799  else
3800  m_all_classes.erase (it);
3801  }
3802 
3803  return cdef_class ();
3804 }
3805 
3806 octave_function *
3807 cdef_manager::find_method_symbol (const std::string& method_name,
3808  const std::string& class_name)
3809 {
3810  octave_function *retval = nullptr;
3811 
3812  cdef_class cls = find_class (class_name, false, false);
3813 
3814  if (cls.ok ())
3815  {
3816  cdef_method meth = cls.find_method (method_name);
3817 
3818  if (meth.ok ())
3819  retval = new octave_classdef_meta (meth);
3820  }
3821 
3822  return retval;
3823 }
3824 
3825 cdef_package
3826 cdef_manager::find_package (const std::string& name, bool error_if_not_found,
3827  bool load_if_not_found)
3828 {
3829  cdef_package retval;
3830 
3831  std::map<std::string, cdef_package>::const_iterator it
3832  = m_all_packages.find (name);
3833 
3834  if (it != m_all_packages.end ())
3835  {
3836  retval = it->second;
3837 
3838  if (! retval.ok ())
3839  error ("invalid package `%s'", name.c_str ());
3840  }
3841  else
3842  {
3843  octave::load_path& lp
3844  = octave::__get_load_path__ ("cdef_manager::find_package");
3845 
3846  if (load_if_not_found && lp.find_package (name))
3847  {
3848  size_t pos = name.find ('.');
3849 
3850  if (pos == std::string::npos)
3851  retval = make_package (name, "");
3852  else
3853  {
3854  std::string parent_name = name.substr (0, pos);
3855 
3856  retval = make_package (name, parent_name);
3857  }
3858  }
3859  else if (error_if_not_found)
3860  error ("unknown package `%s'", name.c_str ());
3861  }
3862 
3863  return retval;
3864 }
3865 
3866 octave_function *
3867 cdef_manager::find_package_symbol (const std::string& pack_name)
3868 {
3869  octave_function *retval = nullptr;
3870 
3871  cdef_package pack = find_package (pack_name, false);
3872 
3873  if (pack.ok ())
3874  retval = new octave_classdef_meta (pack);
3875 
3876  return retval;
3877 }
3878 
3879 //----------------------------------------------------------------------------
3880 
3881 DEFUN (__meta_get_package__, args, ,
3882  doc: /* -*- texinfo -*-
3883 @deftypefn {} {} __meta_get_package__ ()
3884 Undocumented internal function.
3885 @end deftypefn */)
3886 {
3887  if (args.length () != 1)
3888  print_usage ();
3889 
3890  std::string cname = args(0).xstring_value ("PACKAGE_NAME must be a string");
3891 
3892  return to_ov (lookup_package (cname));
3893 }
3894 
3895 DEFUN (__superclass_reference__, args, ,
3896  doc: /* -*- texinfo -*-
3897 @deftypefn {} {} __superclass_reference__ ()
3898 Undocumented internal function.
3899 @end deftypefn */)
3900 {
3901  return ovl (new octave_classdef_superclass_ref (args));
3902 }
3903 
3904 DEFUN (__meta_class_query__, args, ,
3905  doc: /* -*- texinfo -*-
3906 @deftypefn {} {} __meta_class_query__ ()
3907 Undocumented internal function.
3908 @end deftypefn */)
3909 {
3910 #if DEBUG_TRACE
3911  std::cerr << "__meta_class_query__ ("
3912  << args(0).string_value () << ')'
3913  << std::endl;
3914 #endif
3915 
3916  if (args.length () != 1)
3917  print_usage ();
3918 
3919  std::string cls = args(0).xstring_value ("CLASS_NAME must be a string");
3920 
3921  return to_ov (lookup_class (cls));
3922 }
3923 
3924 DEFUN (metaclass, args, ,
3925  doc: /* -*- texinfo -*-
3926 @deftypefn {} {} metaclass (obj)
3927 Returns the meta.class object corresponding to the class of @var{obj}.
3928 @end deftypefn */)
3929 {
3930  if (args.length () != 1)
3931  print_usage ();
3932 
3933  cdef_object obj = to_cdef (args(0));
3934 
3935  return to_ov (obj.get_class ());
3936 }
3937 
3938 /*
3939 ;;; Local Variables: ***
3940 ;;; mode: C++ ***
3941 ;;; End: ***
3942 */
bool called_from_builtin(void)
Definition: ov-base.cc:1464
void print_raw(std::ostream &os, bool pr_as_read_syntax=false) const
virtual bool is_user_function(void) const
Definition: ov-base.h:473
Definition: Cell.h:37
is already an absolute the name is checked against the file system instead of Octave s loadpath In this if otherwise an empty string is returned If the first argument is a cell array of search each directory of the loadpath for element of the cell array and return the first that matches If the second optional argument return a cell array containing the list of all files that have the same name in the path If no files are found
Definition: utils.cc:305
cdef_property make_attribute(const cdef_class &cls, const std::string &name)
Definition: ov-classdef.cc:757
const cdef_class & meta_method(void) const
Definition: ov-classdef.h:1648
Cell get_properties(int mode=property_normal)
Definition: ov-classdef.h:860
bool is_direct_superclass(const cdef_class &clsa, const cdef_class &clsb)
Definition: ov-classdef.cc:238
octave_value subsref(const std::string &type, const std::list< octave_value_list > &idx)
Definition: ov.h:418
static bool check_access(const cdef_class &cls, const octave_value &acc, const std::string &meth_name="", const std::string &prop_name="", bool is_prop_set=false)
Definition: ov-classdef.cc:300
std::string string_value(bool force=false) const
Definition: ov.h:955
bool isempty(void) const
Definition: ov.h:529
cdef_class make_meta_class(const std::string &name, const cdef_class &super)
Definition: ov-classdef.cc:707
for fields that display a single number
Definition: time.cc:441
virtual void assign(const std::string &, const octave_value &)
Definition: ov-base.h:300
std::string get_name(void) const
Definition: ov-classdef.h:1204
bool empty(void) const
Definition: ovl.h:98
static bool in_class_method(const cdef_class &cls)
Definition: ov-classdef.cc:292
octave_value_list(* fcn)(const octave_value_list &, int)
Definition: ov-builtin.h:60
void error(const char *fmt,...)
Definition: error.cc:578
octave_value_list splice(octave_idx_type offset, octave_idx_type len, const octave_value_list &lst=octave_value_list()) const
Definition: ovl.cc:124
octave::tree_statement_list * body(void)
Definition: ov-usr-fcn.h:388
static octave_value_list class_get_inferiorclasses(const octave_value_list &args, int)
Definition: ov-classdef.cc:503
#define META_CLASS_CMP(OP, CLSA, CLSB, FUN)
Definition: ov-classdef.cc:584
static std::list< cdef_class > lookup_classes(const Cell &cls_list)
Definition: ov-classdef.cc:183
static octave_value_list class_getConstant(const octave_value_list &args, int)
Definition: ov-classdef.cc:557
static octave_value_list class_get_properties(const octave_value_list &args, int)
Definition: ov-classdef.cc:242
void register_class(const cdef_class &cls)
Definition: ov-classdef.h:1626
bool is_defined(void) const
Definition: ov.h:523
static void make_function_of_class(const std::string &class_name, const octave_value &fcn)
Definition: ov-classdef.cc:101
const cdef_class & meta_package(void) const
Definition: ov-classdef.h:1649
OCTAVE_EXPORT octave_value_list return the number of command line arguments passed to Octave If called with the optional argument the function t
Definition: ov-usr-fcn.cc:997
cdef_manager & __get_cdef_manager__(const std::string &who)
static std::string get_base_name(const std::string &nm)
Definition: ov-classdef.cc:90
void register_package(const cdef_package &pkg)
Definition: ov-classdef.h:1636
nd example oindent opens the file binary numeric values will be read assuming they are stored in IEEE format with the least significant bit and then converted to the native representation Opening a file that is already open simply opens it again and returns a separate file id It is not an error to open a file several though writing to the same file through several different file ids may produce unexpected results The possible values of text mode reading and writing automatically converts linefeeds to the appropriate line end character for the you may append a you must also open the file in binary mode The parameter conversions are currently only supported for and permissions will be set to and then everything is written in a single operation This is very efficient and improves performance c
Definition: file-io.cc:587
s
Definition: file-io.cc:2729
static octave_value_list package_getAllPackages(octave::interpreter &interp, const octave_value_list &, int)
OCTAVE_EXPORT octave_value_list or class The return code an ordinary file in Octave s or(after appending @samp{.m}) a function file in Octave 's ode
Definition: variables.cc:593
virtual bool is_classdef_constructor(const std::string &="") const
Definition: ov-fcn.h:102
static octave_value_list class_get_methods(const octave_value_list &args, int)
Definition: ov-classdef.cc:470
static octave_value_list handle_delete(const octave_value_list &, int)
Definition: ov-classdef.cc:634
octave_function * fcn
Definition: ov-class.cc:1754
cdef_class make_class(const std::string &name, const std::list< cdef_class > &super_list=std::list< cdef_class >())
Definition: ov-classdef.cc:644
static cdef_package lookup_package(const std::string &name, bool error_if_not_found=true, bool load_if_not_found=true)
bool is_defined(void) const
Definition: ov-fcn.h:68
calling an anonymous function involves an overhead quite comparable to the overhead of an m file function Passing a handle to a built in function is because the interpreter is not involved in the internal loop For a
Definition: cellfun.cc:400
octave::call_stack & cs
Definition: ov-class.cc:1752
octave::tree_parameter_list * parameter_list(void)
Definition: ov-usr-fcn.h:384
virtual octave_value undef_subsasgn(const std::string &type, const std::list< octave_value_list > &idx, const octave_value &rhs)
Definition: ov-base.cc:304
then the function must return scalars which will be concatenated into the return array(s). If code
Definition: cellfun.cc:400
size_t size(void) const
Definition: base-list.h:49
nd deftypefn *std::string name
Definition: sysdep.cc:647
static octave_value_list class_fromName(const octave_value_list &args, int)
Definition: ov-classdef.cc:521
OCTAVE_EXPORT octave_value_list isdir nd deftypefn *std::string nm
Definition: utils.cc:975
octave_value_list property_get_defaultvalue(const octave_value_list &args, int)
Definition: ov-classdef.cc:614
virtual octave_user_function * user_function_value(bool silent=false)
Definition: ov-base.cc:880
OCTAVE_EXPORT octave_value_list return the number of command line arguments passed to Octave If called with the optional argument the function xample nargout(@histc)
Definition: ov-usr-fcn.cc:997
static octave_value to_ov(const std::list< cdef_class > &class_list)
Definition: ov-classdef.cc:198
cdef_method find_method(const std::string &nm, bool local=false)
Definition: ov-classdef.h:1296
std::string dispatch_class(void) const
Definition: ov-fcn.h:122
octave_idx_type numel(const octave_value_list &idx)
Definition: ov.h:412
static bool is_dummy_method(const octave_value &fcn)
Definition: ov-classdef.cc:397
octave_value get(const std::string &pname) const
Definition: ov-classdef.h:269
void error_with_id(const char *id, const char *fmt,...)
Definition: error.cc:623
void mark_as_external(const std::string &dtype)
Definition: ov-classdef.h:1219
nd example The result of the integration is returned in the value of it is recommended to verify this value for difficult integrands and then a warning is issued and as such
Definition: quadcc.cc:1567
void put(const std::string &pname, const octave_value &val)
Definition: ov-classdef.h:266
bool iscell(void) const
Definition: ov.h:536
bool is_strict_superclass(const cdef_class &clsa, const cdef_class &clsb)
Definition: ov-classdef.cc:234
octave_value_list execute(const octave_value_list &args, int nargout, bool do_check_access=true, const std::string &who="")
Definition: ov-classdef.h:1190
virtual bool is_class_method(const std::string &="") const
Definition: ov-fcn.h:105
void mark_as_class_method(void)
Definition: ov-usr-fcn.h:372
octave_value retval
Definition: data.cc:6246
#define panic_impossible()
Definition: error.h:40
octave_value find(const std::string &nm)
octave_value_list(* meth)(octave::interpreter &, const octave_value_list &, int)
Definition: ov-builtin.h:57
virtual octave_idx_type numel(void) const
Definition: ov-base.h:333
octave_function * function_value(bool silent=false) const
idx type
Definition: ov.cc:3114
static void register_type(void)
Definition: ov-base.cc:97
Definition: dMatrix.h:36
void mark_as_meta_class(void)
Definition: ov-classdef.h:935
virtual bool is_anonymous_function_of_class(const std::string &="") const
Definition: ov-fcn.h:141
static bool is_superclass(const cdef_class &clsa, const cdef_class &clsb, bool allow_equal=true, int max_depth=-1)
Definition: ov-classdef.cc:210
cdef_property find_property(const std::string &nm)
Definition: ov-classdef.h:1300
cdef_class find_class(const std::string &name, bool error_if_not_found=true, bool load_if_not_found=true)
cdef_package find_package(const std::string &name, bool error_if_not_found=true, bool load_if_not_found=true)
void indent(std::ostream &os) const
Definition: ov-base.cc:1309
friend class octave_value
Definition: ov-base.h:228
octave::tree_parameter_list * return_list(void)
Definition: ov-usr-fcn.h:386
octave_function * current(void) const
Definition: call-stack.h:97
bool ok(void) const
Definition: ov-classdef.h:300
bool is_static(void) const
Definition: ov-classdef.h:1206
return octave_value(v1.char_array_value() . concat(v2.char_array_value(), ra_idx),((a1.is_sq_string()||a2.is_sq_string()) ? '\'' :'"'))
static int t_id
Definition: ov-classdef.h:1557
void mark_as_classdef_constructor(void)
Definition: ov-usr-fcn.h:358
octave_value undef_subsasgn(const std::string &type, const std::list< octave_value_list > &idx, const octave_value &rhs)
Definition: ov-classdef.cc:943
defaults to zero A value of zero computes the digamma a value the trigamma and so on The digamma function is defined
Definition: psi.cc:68
octave_value make_idx_args(const std::string &type, const std::list< octave_value_list > &idx, const std::string &who)
Definition: ov-base.cc:1401
int register_type(const std::string &, const std::string &, const octave_value &, bool abort_on_duplicate=false)
Definition: ov-typeinfo.cc:85
static octave_value_list class_fevalStatic(const octave_value_list &args, int nargout)
Definition: ov-classdef.cc:536
bool is_constant(void) const
Definition: ov-classdef.h:1078
cdef_object to_cdef(const octave_value &val)
Definition: ov-classdef.h:1576
static OCTAVE_NORETURN void err_method_access(const std::string &from, const cdef_method &meth)
Definition: ov-classdef.cc:54
std::string get_name(void) const
Definition: ov-classdef.h:879
void mark_as_handle_class(void)
Definition: ov-classdef.h:929
static const std::string t_name
Definition: ov-classdef.h:1559
void set_class(const cdef_class &cls)
Definition: ov-classdef.h:237
cdef_method make_method(const cdef_class &cls, const std::string &name, const octave_value &fcn, const std::string &m_access="public", bool is_static=false)
Definition: ov-classdef.cc:763
p
Definition: lu.cc:138
call_stack & __get_call_stack__(const std::string &who)
static octave_value make_fcn_handle(octave_builtin::fcn ff, const std::string &nm)
Definition: ov-classdef.cc:129
bool is_constructed_object(const std::string nm)
std::string method
Definition: urlwrite.cc:123
bool is(const cdef_object &obj) const
Definition: ov-classdef.h:318
octave_idx_type length(void) const
Definition: ovl.h:96
defaults to zero A value of zero computes the digamma a value of
Definition: psi.cc:68
elt_type & front(void)
Definition: base-list.h:97
static octave_value_list class_get_superclasses(const octave_value_list &args, int)
Definition: ov-classdef.cc:485
std::string get_name(void) const
Definition: ov-classdef.h:1076
const cdef_class & meta_property(void) const
Definition: ov-classdef.h:1647
cdef_package make_package(const std::string &nm, const std::string &parent="")
Definition: ov-classdef.cc:812
octave::refcount< octave_idx_type > count
Definition: ov-base.h:862
octave_value evaluate(tree_expression *expr, int nargout=1)
Definition: pt-eval.h:294
for i
Definition: data.cc:5264
static bool is_method_executing(const octave_value &ov, const cdef_object &obj)
Definition: ov-classdef.cc:418
const cdef_class & meta_class(void) const
Definition: ov-classdef.h:1646
bool is_string(void) const
Definition: ov.h:577
octave_value_list subsref(const std::string &type, const std::list< octave_value_list > &idx, int nargout)
Definition: ov-classdef.cc:843
static OCTAVE_NORETURN void err_property_access(const std::string &from, const cdef_property &prop, bool is_set=false)
Definition: ov-classdef.cc:70
static cdef_class lookup_class(const std::string &name, bool error_if_not_found=true, bool load_if_not_found=true)
Definition: ov-classdef.cc:150
bool is_classdef_constructor(const std::string &cname="") const
Definition: ov-usr-fcn.h:366
octave_value get_value(const cdef_object &obj, bool do_check_access=true, const std::string &who="")
Definition: ov-classdef.h:1057
Cell get_methods(void)
Definition: ov-classdef.h:853
virtual octave_function * function_value(bool silent=false)
Definition: ov-base.cc:871
octave_value_list call(octave::tree_evaluator &, int nargout, const octave_value_list &idx)
is a function handle
Definition: bsxfun.cc:337
octave_idx_type numel(void) const
Number of elements in the array.
Definition: Array.h:366
octave_idx_type length(void) const
cdef_property make_property(const cdef_class &cls, const std::string &name, const octave_value &get_method=Matrix(), const std::string &get_access="public", const octave_value &set_method=Matrix(), const std::string &set_access="public")
Definition: ov-classdef.cc:719
write the output to stdout if nargout is
Definition: load-save.cc:1612
bool is_private_function(void) const
Definition: ov-fcn.h:135
std::string name(void) const
Definition: ov-fcn.h:182
std::string type_name(void) const
Definition: ov.h:1289
If this string is the system will ring the terminal sometimes it is useful to be able to print the original representation of the string
Definition: utils.cc:888
tree_evaluator & __get_evaluator__(const std::string &who)
static cdef_class get_class_context(std::string &name, bool &in_constructor)
Definition: ov-classdef.cc:257
void print(std::ostream &os, bool pr_as_read_syntax=false)
Definition: ov-classdef.cc:996
With real arguments
Definition: data.cc:3260
octave_value next_subsref(const std::string &type, const std::list< octave_value_list > &idx, size_t skip=1)
octave::stream os
Definition: file-io.cc:627
Cell cell_value(void) const
cdef_class get_class(void) const
Definition: ov-classdef.h:1241
void mark_as_class_constructor(void)
Definition: ov-usr-fcn.h:356
void set_function(const octave_value &fcn)
Definition: ov-classdef.h:1208
octave_value subsasgn(const std::string &type, const std::list< octave_value_list > &idx, const octave_value &rhs)
Definition: ov-classdef.cc:903
T::properties & properties(graphics_object obj)