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