comparison src/ov-classdef.cc @ 15036:aa1f9e479c6e classdef

octave_value classdef objects * ov-classdef.h, ov-classdef.cc: New files. * octave.cc: Include ov-classdef.h. (octave_main): Call install_classdef. * src/Makefile.am (OV_SRC): Add ov-classdef.cc to the list. (OV_INCLUDES): Add ov-classdef.h to the list.
author Michael Goffioul <michael.goffioul@gmail.com>
date Fri, 27 Jul 2012 16:02:01 -0400
parents
children 56b8eb7c9c04
comparison
equal deleted inserted replaced
15035:a820a990968e 15036:aa1f9e479c6e
1 /*
2
3 Copyright (C) 2012 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 <map>
28
29 #include "defun.h"
30 #include "ov-builtin.h"
31 #include "ov-classdef.h"
32 #include "ov-fcn-handle.h"
33 #include "ov-typeinfo.h"
34
35 static std::map<std::string, cdef_class> all_classes;
36 static std::map<std::string, cdef_package> all_packages;
37
38 static void
39 gripe_method_access (const std::string& from, const cdef_method& meth)
40 {
41 error ("%s: method `%s' has %s access and cannot be run in this context",
42 from.c_str (), meth.get_name ().c_str (),
43 meth.get_access ().c_str ());
44 }
45
46 static void
47 gripe_property_access (const std::string& from, const cdef_property& prop,
48 bool is_set = false)
49 {
50 if (is_set)
51 error ("%s: property `%s' has %s access and cannot be set in this context",
52 from.c_str (), prop.get_name ().c_str (),
53 prop.get_set_access ().c_str ());
54 else
55 error ("%s: property `%s' has %s access and cannot be obtained in this context",
56 from.c_str (), prop.get_name ().c_str (),
57 prop.get_get_access ().c_str ());
58 }
59
60 static octave_value
61 make_fcn_handle (octave_builtin::fcn ff, const std::string& nm)
62 {
63 octave_value fcn (new octave_builtin (ff, nm));
64
65 octave_value fcn_handle (new octave_fcn_handle (fcn, nm));
66
67 return fcn_handle;
68 }
69
70 inline octave_value_list
71 execute_ov (octave_value val, const octave_value_list& args, int nargout)
72 {
73 std::list<octave_value_list> idx (1, args);
74
75 std::string type ("(");
76
77 return val.subsref (type, idx, nargout);
78 }
79
80 static bool
81 check_access (const std::string& req, const std::string& acc)
82 {
83 if (req == "private")
84 return true;
85 else if (req == "protected")
86 return (acc != "private");
87 else
88 return (acc == "public");
89 }
90
91 static std::string
92 get_base_name (const std::string& nm)
93 {
94 std::string::size_type pos = nm.find_last_of ('.');
95
96 if (pos != std::string::npos)
97 return nm.substr (pos + 1);
98
99 return nm;
100 }
101
102 static std::string
103 superclass_access (const std::string& acc)
104 {
105 if (acc == "public")
106 return acc;
107 else
108 return "protected";
109 }
110
111 static cdef_class
112 lookup_class (const std::string& name, bool error_if_not_found = true)
113 {
114 std::map<std::string, cdef_class>::iterator it = all_classes.find (name);
115
116 if (it == all_classes.end ())
117 {
118 // FIXME: should look into load-path
119 if (error_if_not_found)
120 error ("class not found: %s", name.c_str ());
121 }
122 else
123 {
124 cdef_class& cls = it->second;
125
126 if (! cls.is_builtin ())
127 {
128 // FIXME: check whether a class reload is needed
129 }
130
131 if (cls.ok ())
132 return cls;
133 else
134 all_classes.erase (it);
135 }
136
137 return cdef_class ();
138 }
139
140 static Cell
141 lookup_classes (const Cell& cls_names)
142 {
143 Cell cls (cls_names.numel (), 1);
144
145 for (int i = 0; i < cls_names.numel (); i++)
146 {
147 cdef_class c = lookup_class (cls_names(i).string_value ());
148
149 if (! error_state)
150 cls(i) = to_ov (c);
151 else
152 return Cell ();
153 }
154
155 return cls;
156 }
157
158 static bool
159 is_superclass (const cdef_class& clsa, const cdef_class& clsb,
160 bool allow_equal = true)
161 {
162 if (allow_equal && clsa == clsb)
163 return true;
164 else
165 {
166 Cell c = clsb.get ("SuperClasses").cell_value ();
167
168 bool retval = false;
169
170 for (int i = 0; ! retval && i < c.numel (); i++)
171 {
172 cdef_class cls = lookup_class (c(i).string_value ());
173
174 if (! error_state)
175 retval = is_superclass (clsa, cls, true);
176 }
177
178 return retval;
179 }
180 }
181
182 inline bool
183 is_strict_superclass (const cdef_class& clsa, const cdef_class& clsb)
184 { return is_superclass (clsa, clsb, false); }
185
186 static octave_value_list
187 class_get_properties (const octave_value_list& args, int /* nargout */)
188 {
189 octave_value_list retval;
190
191 if (args.length () == 1 && args(0).type_name () == "object")
192 {
193 cdef_class cls (to_cdef (args(0)));
194
195 retval(0) = cls.get_properties ();
196 }
197
198 return retval;
199 }
200
201 static octave_value_list
202 class_get_methods (const octave_value_list& args, int /* nargout */)
203 {
204 octave_value_list retval;
205
206 if (args.length () == 1 && args(0).type_name () == "object")
207 {
208 cdef_class cls (to_cdef (args(0)));
209
210 retval(0) = cls.get_methods ();
211 }
212
213 return retval;
214 }
215
216 static octave_value_list
217 class_get_superclasses (const octave_value_list& args, int /* nargout */)
218 {
219 octave_value_list retval;
220
221 if (args.length () == 1 && args(0).type_name () == "object"
222 && args(0).class_name () == "meta.class")
223 {
224 cdef_class cls (to_cdef (args(0)));
225
226 Cell classes = cls.get ("SuperClasses").cell_value ();
227
228 retval(0) = lookup_classes (classes);
229 }
230
231 return retval;
232 }
233
234 static octave_value_list
235 class_get_inferiorclasses (const octave_value_list& args, int /* nargout */)
236 {
237 octave_value_list retval;
238
239 if (args.length () == 1 && args(0).type_name () == "object"
240 && args(0).class_name () == "meta.class")
241 {
242 cdef_class cls (to_cdef (args(0)));
243
244 Cell classes = cls.get ("InferiorClasses").cell_value ();
245
246 retval(0) = lookup_classes (classes);
247 }
248
249 return retval;
250 }
251
252 static octave_value_list
253 class_fromName (const octave_value_list& args, int /* nargout */)
254 {
255 octave_value_list retval;
256
257 if (args.length () == 1)
258 {
259 std::string name = args(0).string_value ();
260
261 if (! error_state)
262 retval(0) = to_ov (lookup_class (name));
263 else
264 error ("fromName: invalid class name, expected a string value");
265 }
266 else
267 error ("fromName: invalid number of parameters");
268
269 return retval;
270 }
271
272 static octave_value_list
273 class_fevalStatic (const octave_value_list& args, int nargout)
274 {
275 octave_value_list retval;
276
277 if (args.length () > 1 && args(0).type_name () == "object")
278 {
279 cdef_class cls (to_cdef (args(0)));
280
281 if (! error_state)
282 {
283 std::string meth_name = args(1).string_value ();
284
285 if (! error_state)
286 {
287 cdef_method meth = cls.find_method (meth_name);
288
289 if (meth.ok ())
290 {
291 // FIXME: can the context be something else?
292 if (meth.check_access ("public"))
293 {
294 if (meth.is_static ())
295 retval = meth.execute (args.splice (0, 2), nargout);
296 else
297 error ("fevalStatic: method `%s' is not static",
298 meth_name.c_str ());
299 }
300 else
301 gripe_method_access ("fevalStatic", meth);
302 }
303 else
304 error ("fevalStatic: method not found: %s",
305 meth_name.c_str ());
306 }
307 else
308 error ("fevalStatic: invalid method name, expected a string value");
309 }
310 error ("fevalStatic: invalid object, expected a meta.class object");
311 }
312 else
313 error ("fevalStatic: invalid arguments");
314
315 return retval;
316 }
317
318 static octave_value_list
319 class_getConstant (const octave_value_list& args, int /* nargout */)
320 {
321 octave_value_list retval;
322
323 if (args.length () == 2 && args(0).type_name () == "object"
324 && args(0).class_name () == "meta.class")
325 {
326 cdef_class cls = to_cdef (args(0));
327
328 if (! error_state)
329 {
330 std::string prop_name = args(1).string_value ();
331
332 if (! error_state)
333 {
334 cdef_property prop = cls.find_property (prop_name);
335
336 if (prop.ok ())
337 {
338 // FIXME: can the context be something else?
339 if (prop.check_get_access ("public"))
340 {
341 if (prop.is_constant ())
342 retval(0) = prop.get_value ();
343 else
344 error ("getConstant: property `%s' is not constant",
345 prop_name.c_str ());
346 }
347 else
348 gripe_property_access ("getConstant", prop);
349 }
350 else
351 error ("getConstant: property not found: %s",
352 prop_name.c_str ());
353 }
354 else
355 error ("getConstant: invalid property name, expected a string value");
356 }
357 else
358 error ("getConstant: invalid object, expected a meta.class object");
359 }
360 else
361 error ("getConstant: invalid arguments");
362
363 return retval;
364 }
365
366 #define META_CLASS_CMP(OP, CLSA, CLSB, FUN) \
367 static octave_value_list \
368 class_ ## OP (const octave_value_list& args, int /* nargout */) \
369 { \
370 octave_value_list retval; \
371 \
372 if (args.length () == 2 \
373 && args(0).type_name () == "object" && args(1).type_name () == "object" \
374 && args(0).class_name () == "meta.class" && args(1).class_name () == "meta.class") \
375 { \
376 cdef_class clsa = to_cdef (args(0)); \
377 \
378 cdef_class clsb = to_cdef (args(1)); \
379 \
380 if (! error_state) \
381 retval(0) = FUN (CLSA, CLSB); \
382 else \
383 error (#OP ": invalid objects, expected meta.class objects"); \
384 } \
385 else \
386 error (#OP ": invalid arguments"); \
387 \
388 return retval; \
389 }
390
391 META_CLASS_CMP (lt, clsb, clsa, is_strict_superclass)
392 META_CLASS_CMP (le, clsb, clsa, is_superclass)
393 META_CLASS_CMP (gt, clsa, clsb, is_strict_superclass)
394 META_CLASS_CMP (ge, clsa, clsb, is_superclass)
395 META_CLASS_CMP (eq, clsa, clsb, operator==)
396 META_CLASS_CMP (ne, clsa, clsb, operator!=)
397
398 static octave_value_list
399 handle_delete (const octave_value_list& /* args */, int /* nargout */)
400 {
401 octave_value_list retval;
402
403 // FIXME: implement this
404
405 return retval;
406 }
407
408 static cdef_class
409 make_class (const std::string& name, const std::string& super = std::string())
410 {
411 cdef_class cls ("meta.class");
412
413 all_classes[name] = cls;
414 cls.put ("ConstructOnLoad", false);
415 cls.put ("ContainingPackage", Matrix ());
416 cls.put ("Description", std::string ());
417 cls.put ("DetailedDescription", std::string ());
418 cls.put ("Events", Cell ());
419 cls.put ("Hidden", false);
420 cls.put ("InferiorClasses", Cell ());
421 cls.put ("Methods", Cell ());
422 cls.put ("Name", name);
423 cls.put ("Properties", Cell ());
424 cls.put ("Sealed", true);
425 if (super.empty ())
426 cls.put ("SuperClasses", Cell ());
427 else
428 cls.put ("SuperClasses", Cell (octave_value (super)));
429
430 return cls;
431 }
432
433 static cdef_property
434 make_property (const cdef_object& cls, const std::string& name,
435 const octave_value& get_method = Matrix (),
436 const std::string& get_access = "public",
437 const octave_value& set_method = Matrix (),
438 const std::string& set_access = "public")
439 {
440 // FIXME: what about default value?
441
442 cdef_property prop ("meta.property");
443
444 prop.put ("Name", name);
445 prop.put ("Description", std::string ());
446 prop.put ("DetailedDescription", std::string ());
447 prop.put ("Abstract", false);
448 prop.put ("Constant", false);
449 prop.put ("GetAccess", get_access);
450 prop.put ("SetAccess", set_access);
451 prop.put ("Dependent", false);
452 prop.put ("Transient", false);
453 prop.put ("Hidden", false);
454 prop.put ("GetObservable", false);
455 prop.put ("SetObservable", false);
456 prop.put ("GetMethod", get_method);
457 prop.put ("SetMethod", set_method);
458 prop.put ("DefiningClass", to_ov (cls));
459
460 return prop;
461 }
462
463 inline cdef_property
464 make_attribute (const cdef_object& cls, const std::string& name)
465 {
466 return make_property (cls, name, Matrix (), "public", Matrix (), "private");
467 }
468
469 static cdef_method
470 make_method (const cdef_object& cls, const std::string& name, const octave_value& fcn,
471 const std::string& m_access = "public", bool is_static = false)
472 {
473 cdef_method meth ("meta.method");
474
475 meth.put ("Abstract", false);
476 meth.put ("Access", m_access);
477 meth.put ("DefiningClass", to_ov (cls));
478 meth.put ("Description", std::string ());
479 meth.put ("DetailedDescription", std::string ());
480 meth.put ("Hidden", false);
481 meth.put ("Name", name);
482 meth.put ("Sealed", true);
483 meth.put ("Static", is_static);
484
485 meth.set_function (fcn);
486
487 return meth;
488 }
489
490 inline cdef_method
491 make_method (const cdef_object& cls, const std::string& name, octave_builtin::fcn ff,
492 const std::string& m_access = "public", bool is_static = false)
493 {
494 octave_value fcn (new octave_builtin (ff, name));
495
496 octave_value fcn_handle (new octave_fcn_handle (fcn, name));
497
498 return make_method (cls, name, fcn_handle, m_access, is_static);
499 }
500
501 static cdef_package
502 make_package (const std::string& nm,
503 const std::string& parent = std::string ())
504 {
505 cdef_package pack ("meta.package");
506
507 all_packages[nm] = pack;
508 pack.put ("Name", nm);
509 pack.put ("ContainingPackage", to_ov (all_packages[parent]));
510
511 return pack;
512 }
513
514 DEFINE_OCTAVE_ALLOCATOR (octave_classdef);
515
516 int octave_classdef::t_id (-1);
517
518 const std::string octave_classdef::t_name ("object");
519
520 void
521 octave_classdef::register_type (void)
522 {
523 t_id = octave_value_typeinfo::register_type
524 (octave_classdef::t_name, "<unknown>", octave_value (new octave_classdef ()));
525 }
526
527 cdef_class
528 cdef_object_rep::get_class (void) const
529 {
530 cdef_class cls = lookup_class (class_name ());
531
532 return cls;
533 }
534
535 string_vector
536 cdef_object_rep::map_keys (void) const
537 {
538 cdef_class cls = get_class ();
539
540 if (cls.ok ())
541 return cls.get_names ();
542
543 return string_vector ();
544 }
545
546 octave_value_list
547 handle_cdef_object::subsref (const std::string& type,
548 const std::list<octave_value_list>& idx,
549 int nargout, int& skip)
550 {
551 skip = 0;
552
553 cdef_class cls = get_class ();
554
555 octave_value_list retval;
556
557 if (! cls.ok ())
558 return retval;
559
560 switch (type[0])
561 {
562 case '.':
563 {
564 std::string name = (idx.front ())(0).string_value ();
565
566 // FIXME: get the right context; context should also
567 // be linked to the current executing class (if any)
568 // such that protected/private methods found in inherited
569 // classes are correctly resolved.
570 std::string context = "public";
571
572 cdef_method meth = cls.find_method (name);
573
574 if (meth.ok ())
575 {
576 if (meth.check_access (context))
577 {
578 int _nargout = (type.length () > 2 ? 1 : nargout);
579
580 octave_value_list args;
581
582 skip = 1;
583
584 if (type.length () > 1 && type[1] == '(')
585 {
586 std::list<octave_value_list>::const_iterator it = idx.begin ();
587
588 args = *++it;
589
590 skip++;
591 }
592
593 if (meth.is_static ())
594 retval = meth.execute (args, _nargout);
595 else
596 {
597 refcount++;
598 retval = meth.execute (cdef_object (this), args, _nargout);
599 }
600 }
601 else
602 gripe_method_access ("subsref", meth);
603 }
604
605 if (skip == 0 && ! error_state)
606 {
607 cdef_property prop = cls.find_property (name);
608
609 if (prop.ok ())
610 {
611 if (prop.check_get_access (context))
612 {
613 refcount++;
614 retval(0) = prop.get_value (cdef_object (this));
615
616 skip = 1;
617 }
618 else
619 gripe_property_access ("subsref", prop);
620 }
621 else
622 error ("subsref: unknown method or property: %s", name.c_str ());
623 }
624 break;
625 }
626 default:
627 error ("object cannot be indexed with `%c'", type[0]);
628 break;
629 }
630
631 return retval;
632 }
633
634 cdef_method
635 cdef_class::cdef_class_rep::find_method (const std::string& nm)
636 {
637 method_iterator it = method_map.find (nm);
638
639 if (it == method_map.end ())
640 {
641 // FIXME: look into class directory
642 }
643 else
644 {
645 cdef_method& meth = it->second;
646
647 // FIXME: check if method reload needed
648
649 if (meth.ok ())
650 return meth;
651 }
652
653 // Look into superclasses
654
655 Cell super_classes = get ("SuperClasses").cell_value ();
656
657 for (int i = 0; i < super_classes.numel (); i++)
658 {
659 cdef_class cls = lookup_class (super_classes(i).string_value ());
660
661 if (! error_state)
662 {
663 cdef_method meth = cls.find_method (nm);
664
665 if (meth.ok ())
666 return meth;
667 }
668 }
669
670 return cdef_method ();
671 }
672
673 void
674 cdef_class::cdef_class_rep::install_method (const cdef_method& meth)
675 {
676 method_map[meth.get_name ()] = meth;
677 }
678
679 void
680 cdef_class::cdef_class_rep::load_all_methods (void)
681 {
682 // FIXME: re-scan class directory
683 }
684
685 Cell
686 cdef_class::cdef_class_rep::get_methods (void)
687 {
688 std::map<std::string,cdef_method> meths;
689
690 std::map<std::string,int> count;
691
692 count["public"] = count["protected"] = count["private"] = 0;
693
694 find_methods (meths, count);
695
696 if (! error_state)
697 {
698 Cell c (count["public"] + count["protected"], 1);
699
700 int idx = 0;
701
702 for (std::map<std::string,cdef_method>::const_iterator it = meths.begin ();
703 it != meths.end (); ++it)
704 if (::check_access ("protected", it->second.get_access ()))
705 c (idx++, 0) = to_ov (it->second);
706
707 return c;
708 }
709
710 return Cell ();
711 }
712
713 void
714 cdef_class::cdef_class_rep::find_methods (std::map<std::string,cdef_method>& meths,
715 std::map<std::string,int>& count)
716 {
717 load_all_methods ();
718
719 method_const_iterator it;
720
721 for (it = method_map.begin (); it != method_map.end (); ++it)
722 {
723 std::string nm = it->second.get_name ();
724
725 if (meths.find (nm) == meths.end ())
726 {
727 std::string acc = it->second.get_access ();
728
729 meths[nm] = it->second;
730 count[acc]++;
731 }
732 }
733
734 // Look into superclasses
735
736 Cell super_classes = get ("SuperClasses").cell_value ();
737
738 for (int i = 0; i < super_classes.numel (); i++)
739 {
740 cdef_class cls = lookup_class (super_classes(i).string_value ());
741
742 if (! error_state)
743 cls.get_rep ()->find_methods (meths, count);
744 else
745 break;
746 }
747 }
748
749 cdef_property
750 cdef_class::cdef_class_rep::find_property (const std::string& nm)
751 {
752 property_iterator it = property_map.find (nm);
753
754 if (it != property_map.end ())
755 {
756 cdef_property& prop = it->second;
757
758 if (prop.ok ())
759 return prop;
760 }
761
762 // Look into superclasses
763
764 Cell super_classes = get ("SuperClasses").cell_value ();
765
766 for (int i = 0; i < super_classes.numel (); i++)
767 {
768 cdef_class cls = lookup_class (super_classes(i).string_value ());
769
770 if (! error_state)
771 {
772 cdef_property prop = cls.find_property (nm);
773
774 if (prop.ok ())
775 return prop;
776 }
777 }
778
779 return cdef_property ();
780 }
781
782 void
783 cdef_class::cdef_class_rep::install_property (const cdef_property& prop)
784 {
785 property_map[prop.get_name ()] = prop;
786 }
787
788 Cell
789 cdef_class::cdef_class_rep::get_properties (void)
790 {
791 std::map<std::string,cdef_property> props;
792
793 std::map<std::string,int> count;
794
795 count["public"] = count["protected"] = count["private"] = 0;
796
797 find_properties (props, count);
798
799 if (! error_state)
800 {
801 Cell c (count["public"] + count["protected"], 1);
802
803 int idx = 0;
804
805 for (std::map<std::string,cdef_property>::const_iterator it = props.begin ();
806 it != props.end (); ++it)
807 if (::check_access ("protected", it->second.get_get_access ()))
808 c (idx++, 0) = to_ov (it->second);
809
810 return c;
811 }
812
813 return Cell ();
814 }
815
816 void
817 cdef_class::cdef_class_rep::find_properties (std::map<std::string,cdef_property>& props,
818 std::map<std::string,int>& count)
819 {
820 property_const_iterator it;
821
822 for (it = property_map.begin (); it != property_map.end (); ++it)
823 {
824 std::string nm = it->second.get_name ();
825
826 if (props.find (nm) == props.end ())
827 {
828 std::string acc = it->second.get_get_access ();
829
830 props[nm] = it->second;
831 count[acc]++;
832 }
833 }
834
835 // Look into superclasses
836
837 Cell super_classes = get ("SuperClasses").cell_value ();
838
839 for (int i = 0; i < super_classes.numel (); i++)
840 {
841 cdef_class cls = lookup_class (super_classes(i).string_value ());
842
843 if (! error_state)
844 cls.get_rep ()->find_properties (props, count);
845 else
846 break;
847 }
848 }
849
850 void
851 cdef_class::cdef_class_rep::find_names (std::map<std::string,std::string>& names,
852 std::map<std::string,int>& count)
853 {
854 load_all_methods ();
855
856 for (method_const_iterator it = method_map.begin ();
857 it != method_map.end(); ++it)
858 {
859 std::string nm = it->second.get_name ();
860
861 if (names.find (nm) == names.end ())
862 {
863 std::string acc = it->second.get_access ();
864
865 names[nm] = acc;
866 count[acc]++;
867 }
868 }
869
870 for (property_const_iterator it = property_map.begin ();
871 it != property_map.end (); ++it)
872 {
873 std::string nm = it->second.get_name ();
874
875 if (names.find (nm) == names.end ())
876 {
877 std::string acc = it->second.get_get_access ();
878
879 names[nm] = acc;
880 count[acc]++;
881 }
882 }
883
884 // Look into superclasses
885
886 Cell super_classes = get ("SuperClasses").cell_value ();
887
888 for (int i = 0; i < super_classes.numel (); i++)
889 {
890 cdef_class cls = lookup_class (super_classes(i).string_value ());
891
892 if (! error_state)
893 cls.get_rep ()->find_names (names, count);
894 else
895 break;
896 }
897 }
898
899 string_vector
900 cdef_class::cdef_class_rep::get_names (void)
901 {
902 std::map<std::string,std::string> names;
903
904 std::map<std::string,int> count;
905
906 count["public"] = count["protected"] = count["private"] = 0;
907
908 find_names (names, count);
909
910 if (! error_state)
911 {
912 string_vector v (count["public"]);
913
914 int idx = 0;
915 for (std::map<std::string,std::string>::const_iterator it = names.begin ();
916 it != names.end (); ++it)
917 {
918 if (it->second == "public")
919 v[idx++] = it->first;
920 }
921
922 return v.sort (true);
923 }
924
925 return string_vector ();
926 }
927
928 void
929 cdef_class::cdef_class_rep::delete_object (cdef_object obj)
930 {
931 method_iterator it = method_map.find ("delete");
932
933 if (it != method_map.end ())
934 {
935 std::string cls_name = obj.class_name ();
936
937 obj.set_class_name (get ("Name").string_value ());
938
939 it->second.execute (obj, octave_value_list (), 0);
940
941 obj.set_class_name (cls_name);
942 }
943
944 // FIXME: should we destroy corresponding properties here?
945
946 // Call "delete" in super classes
947
948 Cell super_classes = get ("SuperClasses").cell_value ();
949
950 for (int i = 0; i < super_classes.numel (); i++)
951 {
952 cdef_class cls = lookup_class (super_classes(i).string_value ());
953
954 if (!error_state)
955 cls.delete_object (obj);
956 }
957 }
958
959 octave_value
960 cdef_property::cdef_property_rep::get_value (const cdef_object& obj)
961 {
962 // FIXME: should check whether we're already in get accessor method
963
964 octave_value retval;
965
966 octave_value get_fcn = get ("GetMethod");
967
968 std::string get_access = get ("GetAccess").string_value ();
969
970 if (get_access != "public")
971 {
972 // FIXME: should check the current call stack
973 }
974
975 if (get_fcn.is_empty ())
976 retval = obj.get (get ("Name").string_value ());
977 else
978 {
979 octave_value_list args;
980
981 args(0) = to_ov (obj);
982
983 args = execute_ov (get_fcn, args, 1);
984
985 if (! error_state)
986 retval = args(0);
987 }
988
989 return retval;
990 }
991
992 bool
993 cdef_property::check_get_access (const std::string& req) const
994 {
995 return ::check_access (req, get_get_access ());
996 }
997
998 bool
999 cdef_property::check_set_access (const std::string& req) const
1000 {
1001 return ::check_access (req, get_set_access ());
1002 }
1003
1004 void
1005 cdef_method::cdef_method_rep::check_method (void)
1006 {
1007 // FIXME: check whether re-load is needed
1008 }
1009
1010 octave_value_list
1011 cdef_method::cdef_method_rep::execute (const octave_value_list& args,
1012 int nargout)
1013 {
1014 octave_value_list retval;
1015
1016 if (! get ("Abstract").bool_value ())
1017 {
1018 check_method ();
1019
1020 if (function.is_defined ())
1021 {
1022 retval = execute_ov (function, args, nargout);
1023 }
1024 }
1025 else
1026 error ("%s: cannot execute abstract method",
1027 get ("Name").string_value ().c_str ());
1028
1029 return retval;
1030 }
1031
1032 octave_value_list
1033 cdef_method::cdef_method_rep::execute (const cdef_object& obj,
1034 const octave_value_list& args,
1035 int nargout)
1036 {
1037 octave_value_list retval;
1038
1039 if (! get ("Abstract").bool_value ())
1040 {
1041 check_method ();
1042
1043 octave_value_list new_args;
1044
1045 if (function.is_defined ())
1046 {
1047 new_args.resize (args.length () + 1);
1048
1049 new_args(0) = to_ov (obj);
1050 for (int i = 0; i < args.length (); i++)
1051 new_args(i+1) = args(i);
1052
1053 retval = execute_ov (function, new_args, nargout);
1054 }
1055 }
1056 else
1057 error ("%s: cannot execute abstract method",
1058 get ("Name").string_value ().c_str ());
1059
1060 return retval;
1061 }
1062
1063 bool
1064 cdef_method::check_access (const std::string& req) const
1065 {
1066 return ::check_access (req, get_access ());
1067 }
1068
1069 static cdef_package
1070 lookup_package (const std::string& name)
1071 {
1072 std::map<std::string, cdef_package>::const_iterator it = all_packages.find (name);
1073
1074 if (it != all_packages.end ())
1075 {
1076 cdef_package pack = it->second;
1077
1078 if (pack.ok ())
1079 return pack;
1080 else
1081 error ("invalid package: %s", name.c_str ());
1082 }
1083 else
1084 error ("package not found: %s", name.c_str ());
1085
1086 return cdef_package ();
1087 }
1088
1089 static octave_value_list
1090 package_fromName (const octave_value_list& args, int /* nargout */)
1091 {
1092 octave_value_list retval;
1093
1094 if (args.length () == 1)
1095 {
1096 std::string name = args(0).string_value ();
1097
1098 if (! error_state)
1099 retval(0) = to_ov (lookup_package (name));
1100 else
1101 error ("fromName: invalid package name, expected a string value");
1102 }
1103 else
1104 error ("fromName: invalid number of parameters");
1105
1106 return retval;
1107 }
1108
1109 static octave_value_list
1110 package_get_classes (const octave_value_list& args, int /* nargout */)
1111 {
1112 octave_value_list retval (1, Matrix ());
1113
1114 if (args.length () == 1 && args(0).type_name () == "object"
1115 && args(0).class_name () == "meta.package")
1116 {
1117 cdef_package pack (to_cdef (args(0)));
1118
1119 retval(0) = pack.get_classes ();
1120 }
1121
1122 return retval;
1123 }
1124
1125 static octave_value_list
1126 package_get_functions (const octave_value_list& args, int /* nargout */)
1127 {
1128 octave_value_list retval (1, Matrix ());
1129
1130 if (args.length () == 0 && args(0).type_name () == "object"
1131 && args(0).class_name () == "meta.package")
1132 {
1133 cdef_package pack (to_cdef (args(0)));
1134
1135 retval(0) = pack.get_functions ();
1136 }
1137
1138 return retval;
1139 }
1140
1141 static octave_value_list
1142 package_get_packages (const octave_value_list& args, int /* nargout */)
1143 {
1144 octave_value_list retval (1, Matrix ());
1145
1146 if (args.length () == 0 && args(0).type_name () == "object"
1147 && args(0).class_name () == "meta.package")
1148 {
1149 cdef_package pack (to_cdef (args(0)));
1150
1151 retval(0) = pack.get_packages ();
1152 }
1153
1154 return retval;
1155 }
1156
1157 void
1158 cdef_package::cdef_package_rep::install_class (const cdef_class& cls,
1159 const std::string& nm)
1160 {
1161 class_map[nm] = cls;
1162 }
1163
1164 void
1165 cdef_package::cdef_package_rep::install_function (const octave_value& fcn,
1166 const std::string& nm)
1167 {
1168 function_map[nm] = fcn;
1169 }
1170
1171 void
1172 cdef_package::cdef_package_rep::install_package (const cdef_package& pack,
1173 const std::string& nm)
1174 {
1175 package_map[nm] = pack;
1176 }
1177
1178 octave_value_list
1179 cdef_package::cdef_package_rep::subsref (const std::string& type,
1180 const std::list<octave_value_list>& idx,
1181 int nargout, int& skip)
1182 {
1183 return handle_cdef_object::subsref (type, idx, nargout, skip);
1184 }
1185
1186 template<class T1, class T2>
1187 Cell
1188 map2Cell (const std::map<T1, T2>& m)
1189 {
1190 Cell retval (1, m.size ());
1191 int i = 0;
1192
1193 for (typename std::map<T1, T2>::const_iterator it = m.begin ();
1194 it != m.end (); ++it, ++i)
1195 {
1196 retval(i) = to_ov (it->second);
1197 }
1198
1199 return retval;
1200 }
1201
1202 Cell
1203 cdef_package::cdef_package_rep::get_classes (void) const
1204 { return map2Cell (class_map); }
1205
1206 Cell
1207 cdef_package::cdef_package_rep::get_functions (void) const
1208 { return map2Cell (function_map); }
1209
1210 Cell
1211 cdef_package::cdef_package_rep::get_packages (void) const
1212 { return map2Cell (package_map); }
1213
1214 octave_value_list
1215 octave_classdef::subsref (const std::string& type,
1216 const std::list<octave_value_list>& idx,
1217 int nargout)
1218 {
1219 int skip = 0;
1220 octave_value_list retval;
1221
1222 // FIXME: should check "subsref" method first
1223
1224 retval = object.subsref (type, idx, nargout, skip);
1225
1226 if (! error_state)
1227 {
1228 if (type.length () > skip && idx.size () > skip)
1229 retval = retval(0).next_subsref (nargout, type, idx, skip);
1230 }
1231
1232 return retval;
1233 }
1234
1235 void
1236 install_classdef (void)
1237 {
1238 octave_classdef::register_type ();
1239
1240 /* meta classes */
1241 cdef_class handle = make_class ("handle");
1242 cdef_class meta_class = make_class ("meta.class", "handle");
1243 cdef_class meta_property = make_class ("meta.property", "handle");
1244 cdef_class meta_method = make_class ("meta.method", "handle");
1245 cdef_class meta_event = make_class ("meta.event", "handle");
1246 cdef_class meta_package = make_class ("meta.package", "handle");
1247 cdef_class meta_dynproperty = make_class ("meta.dynamicproperty", "handle");
1248
1249 /* meta.class properties */
1250 meta_class.install_property (make_attribute (meta_class, "ConstructOnLoad"));
1251 meta_class.install_property (make_property (meta_class, "ContainingPackage"));
1252 meta_class.install_property (make_property (meta_class, "Description"));
1253 meta_class.install_property (make_property (meta_class, "DetailedDescription"));
1254 meta_class.install_property (make_property (meta_class, "Events"));
1255 meta_class.install_property (make_attribute (meta_class, "Hidden"));
1256 meta_class.install_property
1257 (make_property (meta_class, "InferiorClasses",
1258 make_fcn_handle (class_get_inferiorclasses, "meta.class>get.InferiorClasses"),
1259 "public", Matrix (), "private"));
1260 meta_class.install_property
1261 (make_property (meta_class, "Methods",
1262 make_fcn_handle (class_get_methods, "meta.class>get.Methods"),
1263 "public", Matrix (), "private"));
1264 meta_class.install_property
1265 (make_property (meta_class, "MethodList",
1266 make_fcn_handle (class_get_methods, "meta.class>get.MethodList"),
1267 "public", Matrix (), "private"));
1268 meta_class.install_property (make_attribute (meta_class, "Name"));
1269 meta_class.install_property
1270 (make_property (meta_class, "Properties",
1271 make_fcn_handle (class_get_properties, "meta.class>get.Properties"),
1272 "public", Matrix (), "private"));
1273 meta_class.install_property
1274 (make_property (meta_class, "PropertyList",
1275 make_fcn_handle (class_get_properties, "meta.class>get.PropertyList"),
1276 "public", Matrix (), "private"));
1277 meta_class.install_property (make_attribute (meta_class, "Sealed"));
1278 meta_class.install_property
1279 (make_property (meta_class, "SuperClasses",
1280 make_fcn_handle (class_get_superclasses, "meta.class>get.SuperClasses"),
1281 "public", Matrix (), "private"));
1282 meta_class.install_property
1283 (make_property (meta_class, "SuperClassList",
1284 make_fcn_handle (class_get_superclasses, "meta.class>get.SuperClassList"),
1285 "public", Matrix (), "private"));
1286 /* meta.class methods */
1287 meta_class.install_method (make_method (meta_class, "fromName", class_fromName,
1288 "public", true));
1289 meta_class.install_method (make_method (meta_class, "fevalStatic", class_fevalStatic,
1290 "public", false));
1291 meta_class.install_method (make_method (meta_class, "getConstant", class_getConstant,
1292 "public", false));
1293 meta_class.install_method (make_method (meta_class, "eq", class_eq));
1294 meta_class.install_method (make_method (meta_class, "ne", class_ne));
1295 meta_class.install_method (make_method (meta_class, "lt", class_lt));
1296 meta_class.install_method (make_method (meta_class, "le", class_le));
1297 meta_class.install_method (make_method (meta_class, "gt", class_gt));
1298 meta_class.install_method (make_method (meta_class, "ge", class_ge));
1299
1300 /* meta.method properties */
1301 meta_method.install_property (make_attribute (meta_method, "Abstract"));
1302 meta_method.install_property (make_attribute (meta_method, "Access"));
1303 meta_method.install_property (make_attribute (meta_method, "DefiningClass"));
1304 meta_method.install_property (make_attribute (meta_method, "Description"));
1305 meta_method.install_property (make_attribute (meta_method, "DetailedDescription"));
1306 meta_method.install_property (make_attribute (meta_method, "Hidden"));
1307 meta_method.install_property (make_attribute (meta_method, "Name"));
1308 meta_method.install_property (make_attribute (meta_method, "Sealed"));
1309 meta_method.install_property (make_attribute (meta_method, "Static"));
1310
1311 /* meta.property properties */
1312 meta_property.install_property (make_attribute (meta_property, "Name"));
1313 meta_property.install_property (make_attribute (meta_property, "Description"));
1314 meta_property.install_property (make_attribute (meta_property, "DetailedDescription"));
1315 meta_property.install_property (make_attribute (meta_property, "Abstract"));
1316 meta_property.install_property (make_attribute (meta_property, "Constant"));
1317 meta_property.install_property (make_attribute (meta_property, "GetAccess"));
1318 meta_property.install_property (make_attribute (meta_property, "SetAccess"));
1319 meta_property.install_property (make_attribute (meta_property, "Dependent"));
1320 meta_property.install_property (make_attribute (meta_property, "Transient"));
1321 meta_property.install_property (make_attribute (meta_property, "Hidden"));
1322 meta_property.install_property (make_attribute (meta_property, "GetObservable"));
1323 meta_property.install_property (make_attribute (meta_property, "SetObservable"));
1324 meta_property.install_property (make_attribute (meta_property, "GetMethod"));
1325 meta_property.install_property (make_attribute (meta_property, "SetMethod"));
1326 meta_property.install_property (make_attribute (meta_property, "DefiningClass"));
1327 /* meta.property events */
1328 // FIXME: add events
1329
1330 /* handle methods */
1331 handle.install_method (make_method (handle, "delete", handle_delete));
1332
1333 /* meta.package properties */
1334 meta_package.install_property (make_attribute (meta_package, "Name"));
1335 meta_package.install_property (make_property (meta_package, "ContainingPackage"));
1336 meta_package.install_property
1337 (make_property (meta_package, "ClassList",
1338 make_fcn_handle (package_get_classes, "meta.package>get.ClassList"),
1339 "public", Matrix (), "private"));
1340 meta_package.install_property
1341 (make_property (meta_package, "Classes",
1342 make_fcn_handle (package_get_classes, "meta.package>get.Classes"),
1343 "public", Matrix (), "private"));
1344 meta_package.install_property
1345 (make_property (meta_package, "FunctionList",
1346 make_fcn_handle (package_get_functions, "meta.package>get.FunctionList"),
1347 "public", Matrix (), "private"));
1348 meta_package.install_property
1349 (make_property (meta_package, "Functions",
1350 make_fcn_handle (package_get_functions, "meta.package>get.Functions"),
1351 "public", Matrix (), "private"));
1352 meta_package.install_property
1353 (make_property (meta_package, "PackageList",
1354 make_fcn_handle (package_get_packages, "meta.package>get.PackageList"),
1355 "public", Matrix (), "private"));
1356 meta_package.install_property
1357 (make_property (meta_package, "Packages",
1358 make_fcn_handle (package_get_packages, "meta.package>get.Packages"),
1359 "public", Matrix (), "private"));
1360 meta_package.install_method (make_method (meta_package, "fromName", package_fromName,
1361 "public", true));
1362
1363 /* create "meta" package */
1364 cdef_package package_meta = make_package ("meta");
1365 package_meta.install_class (meta_class, "class");
1366 package_meta.install_class (meta_property, "property");
1367 package_meta.install_class (meta_method, "method");
1368 package_meta.install_class (meta_package, "package");
1369 package_meta.install_class (meta_event, "event");
1370 package_meta.install_class (meta_dynproperty, "dynproperty");
1371 }
1372
1373 DEFUN (__meta_get_class__, args, , "")
1374 {
1375 octave_value retval;
1376
1377 if (args.length () == 1)
1378 {
1379 std::string cname = args(0).string_value ();
1380
1381 if (! error_state)
1382 retval = to_ov (lookup_class (cname));
1383 else
1384 error ("invalid class name, expected a string value");
1385 }
1386 else
1387 print_usage ();
1388
1389 return retval;
1390 }
1391
1392 DEFUN (__meta_get_package__, args, , "")
1393 {
1394 octave_value retval;
1395
1396 if (args.length () == 1)
1397 {
1398 std::string cname = args(0).string_value ();
1399
1400 if (! error_state)
1401 retval = to_ov (lookup_package (cname));
1402 else
1403 error ("invalid package name, expected a string value");
1404 }
1405 else
1406 print_usage ();
1407
1408 return retval;
1409 }
1410
1411 /*
1412 ;;; Local Variables: ***
1413 ;;; mode: C++ ***
1414 ;;; End: ***
1415 */