comparison libinterp/octave-value/ov-classdef.cc @ 15841:5861c4bde387 classdef

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