Mercurial > octave-nkf
comparison libinterp/octave-value/ov-classdef.cc @ 16048:10142aad4b9f classdef
Implement indirect method call: fun(obj, ...).
* libinterp/octave-value/ov-classdef.h (class cdef_manager): New class.
(cdef_method::cdef_method_rep::meta_subsref,
cdef_method::cdef_method_rep::meta_is_postfix_index_handled): New
methods.
* libinterp/octave-value/ov-classdef.cc (all_packages, all_classes):
Move static variables to class cdef_manager.
(lookup_class (std::string, bool, bool)): Move implementation to
method cdef_manager::do_find_class().
(lookup_package): Move implementation to method
cdef_manager::do_find_package().
(make_class): Use cdef_manager::register_class.
(make_package): Use cdef_manager::register_package and
cdef_manager::find_package.
(cdef_class::cdef_class_rep::meta_release): Use
cdef_manager::unregister_class.
(cdef_method::cdef_method_rep::meta_subsref): New method.
(class cdef_manager): New class.
* libinterp/interpfcn/symtab.cc
(symbol_table::fcn_info::fcn_info_rep::load_class_constructor):
Look for classdef constructor in normal m-files. Call
find_user_function() and check whether the result is a classdef
constructor. If it is, stash it as a constructor and restore the
previous value of function_on_path.
(symbol_table::fcn_info::fcn_info_rep::load_class_method): Look for
method in classdef system, using cdef_manager::find_method_symbol().
author | Michael Goffioul <michael.goffioul@gmail.com> |
---|---|
date | Mon, 11 Feb 2013 15:20:00 -0500 |
parents | 14aa0b5a980c |
children | 7368654f302f |
comparison
equal
deleted
inserted
replaced
15986:14aa0b5a980c | 16048:10142aad4b9f |
---|---|
23 #ifdef HAVE_CONFIG_H | 23 #ifdef HAVE_CONFIG_H |
24 #include <config.h> | 24 #include <config.h> |
25 #endif | 25 #endif |
26 | 26 |
27 #include <algorithm> | 27 #include <algorithm> |
28 #include <map> | |
29 | 28 |
30 #include "defun.h" | 29 #include "defun.h" |
31 #include "ov-builtin.h" | 30 #include "ov-builtin.h" |
32 #include "ov-classdef.h" | 31 #include "ov-classdef.h" |
33 #include "ov-fcn-handle.h" | 32 #include "ov-fcn-handle.h" |
36 #include "pt-classdef.h" | 35 #include "pt-classdef.h" |
37 #include "pt-funcall.h" | 36 #include "pt-funcall.h" |
38 #include "pt-misc.h" | 37 #include "pt-misc.h" |
39 #include "pt-stmt.h" | 38 #include "pt-stmt.h" |
40 #include "pt-walk.h" | 39 #include "pt-walk.h" |
40 #include "singleton-cleanup.h" | |
41 #include "symtab.h" | 41 #include "symtab.h" |
42 #include "toplev.h" | 42 #include "toplev.h" |
43 | 43 |
44 #include "Array.cc" | 44 #include "Array.cc" |
45 | |
46 static std::map<std::string, cdef_class> all_classes; | |
47 static std::map<std::string, cdef_package> all_packages; | |
48 | 45 |
49 static void | 46 static void |
50 gripe_method_access (const std::string& from, const cdef_method& meth) | 47 gripe_method_access (const std::string& from, const cdef_method& meth) |
51 { | 48 { |
52 octave_value acc = meth.get ("Access"); | 49 octave_value acc = meth.get ("Access"); |
142 | 139 |
143 return val.subsref (type, idx, nargout); | 140 return val.subsref (type, idx, nargout); |
144 } | 141 } |
145 | 142 |
146 static cdef_class | 143 static cdef_class |
147 lookup_class (const std::string& name, bool error_if_not_found = true) | 144 lookup_class (const std::string& name, bool error_if_not_found = true, |
148 { | 145 bool load_if_not_found = true) |
149 std::map<std::string, cdef_class>::iterator it = all_classes.find (name); | 146 { |
150 | 147 return cdef_manager::find_class (name, error_if_not_found, |
151 if (it == all_classes.end ()) | 148 load_if_not_found); |
152 { | |
153 // FIXME: implement this properly | |
154 | |
155 octave_value ov_cls = symbol_table::find (name); | |
156 | |
157 if (ov_cls.is_defined ()) | |
158 it = all_classes.find (name); | |
159 } | |
160 | |
161 if (it == all_classes.end ()) | |
162 { | |
163 if (error_if_not_found) | |
164 error ("class not found: %s", name.c_str ()); | |
165 } | |
166 else | |
167 { | |
168 cdef_class& cls = it->second; | |
169 | |
170 if (! cls.is_builtin ()) | |
171 { | |
172 // FIXME: check whether a class reload is needed | |
173 } | |
174 | |
175 if (cls.ok ()) | |
176 return cls; | |
177 else | |
178 all_classes.erase (it); | |
179 } | |
180 | |
181 return cdef_class (); | |
182 } | 149 } |
183 | 150 |
184 static cdef_class | 151 static cdef_class |
185 lookup_class (const cdef_class& cls) | 152 lookup_class (const cdef_class& cls) |
186 { | 153 { |
650 | 617 |
651 if (error_state) | 618 if (error_state) |
652 return cdef_class (); | 619 return cdef_class (); |
653 | 620 |
654 if (! name.empty ()) | 621 if (! name.empty ()) |
655 all_classes[name] = cls; | 622 cdef_manager::register_class (cls); |
656 | 623 |
657 return cls; | 624 return cls; |
658 } | 625 } |
659 | 626 |
660 static cdef_class | 627 static cdef_class |
758 { | 725 { |
759 cdef_package pack ("meta.package"); | 726 cdef_package pack ("meta.package"); |
760 | 727 |
761 pack.set_class (cdef_class::meta_package ()); | 728 pack.set_class (cdef_class::meta_package ()); |
762 pack.put ("Name", nm); | 729 pack.put ("Name", nm); |
763 pack.put ("ContainingPackage", to_ov (all_packages[parent])); | 730 if (parent.empty ()) |
731 pack.put ("ContainingPackage", Matrix ()); | |
732 else | |
733 pack.put ("ContainingPackage", to_ov (cdef_manager::find_package (parent))); | |
764 | 734 |
765 if (! nm.empty ()) | 735 if (! nm.empty ()) |
766 all_packages[nm] = pack; | 736 cdef_manager::register_package (pack); |
767 | 737 |
768 return pack; | 738 return pack; |
769 } | 739 } |
770 | 740 |
771 //---------------------------------------------------------------------------- | 741 //---------------------------------------------------------------------------- |
1999 } | 1969 } |
2000 | 1970 |
2001 void | 1971 void |
2002 cdef_class::cdef_class_rep::meta_release (void) | 1972 cdef_class::cdef_class_rep::meta_release (void) |
2003 { | 1973 { |
2004 all_classes.erase (get_name ()); | 1974 cdef_manager::unregister_class (wrap ()); |
2005 } | 1975 } |
2006 | 1976 |
2007 void | 1977 void |
2008 cdef_class::cdef_class_rep::initialize_object (cdef_object& obj) | 1978 cdef_class::cdef_class_rep::initialize_object (cdef_object& obj) |
2009 { | 1979 { |
2644 return ::check_access (cls, get ("Access")); | 2614 return ::check_access (cls, get ("Access")); |
2645 | 2615 |
2646 return false; | 2616 return false; |
2647 } | 2617 } |
2648 | 2618 |
2619 octave_value_list | |
2620 cdef_method::cdef_method_rep::meta_subsref | |
2621 (const std::string& type, const std::list<octave_value_list>& idx, | |
2622 int nargout) | |
2623 { | |
2624 octave_value_list retval; | |
2625 | |
2626 switch (type[0]) | |
2627 { | |
2628 case '(': | |
2629 retval = execute (idx.front (), type.length () > 1 ? 1 : nargout, true); | |
2630 break; | |
2631 | |
2632 default: | |
2633 error ("invalid meta.method indexing"); | |
2634 break; | |
2635 } | |
2636 | |
2637 if (! error_state) | |
2638 { | |
2639 if (type.length () > 1 && idx.size () > 1 && ! retval.empty ()) | |
2640 retval = retval(0).next_subsref (nargout, type, idx, 1); | |
2641 } | |
2642 | |
2643 return retval; | |
2644 } | |
2645 | |
2649 static cdef_package | 2646 static cdef_package |
2650 lookup_package (const std::string& name) | 2647 lookup_package (const std::string& name) |
2651 { | 2648 { |
2652 std::map<std::string, cdef_package>::const_iterator it = all_packages.find (name); | 2649 return cdef_manager::find_package (name); |
2653 | |
2654 if (it != all_packages.end ()) | |
2655 { | |
2656 cdef_package pack = it->second; | |
2657 | |
2658 if (pack.ok ()) | |
2659 return pack; | |
2660 else | |
2661 error ("invalid package: %s", name.c_str ()); | |
2662 } | |
2663 else | |
2664 error ("package not found: %s", name.c_str ()); | |
2665 | |
2666 return cdef_package (); | |
2667 } | 2650 } |
2668 | 2651 |
2669 static octave_value_list | 2652 static octave_value_list |
2670 package_fromName (const octave_value_list& args, int /* nargout */) | 2653 package_fromName (const octave_value_list& args, int /* nargout */) |
2671 { | 2654 { |
2942 package_meta.install_class (meta_package, "package"); | 2925 package_meta.install_class (meta_package, "package"); |
2943 package_meta.install_class (meta_event, "event"); | 2926 package_meta.install_class (meta_event, "event"); |
2944 package_meta.install_class (meta_dynproperty, "dynproperty"); | 2927 package_meta.install_class (meta_dynproperty, "dynproperty"); |
2945 } | 2928 } |
2946 | 2929 |
2930 //---------------------------------------------------------------------------- | |
2931 | |
2932 cdef_manager* cdef_manager::instance = 0; | |
2933 | |
2934 void | |
2935 cdef_manager::create_instance (void) | |
2936 { | |
2937 instance = new cdef_manager (); | |
2938 | |
2939 if (instance) | |
2940 singleton_cleanup_list::add (cleanup_instance); | |
2941 } | |
2942 | |
2943 cdef_class | |
2944 cdef_manager::do_find_class (const std::string& name, | |
2945 bool error_if_not_found, bool load_if_not_found) | |
2946 { | |
2947 std::map<std::string, cdef_class>::iterator it = all_classes.find (name); | |
2948 | |
2949 if (it == all_classes.end ()) | |
2950 { | |
2951 // FIXME: implement this properly, take package prefix into account | |
2952 | |
2953 if (load_if_not_found) | |
2954 { | |
2955 octave_value ov_cls = symbol_table::find (name); | |
2956 | |
2957 if (ov_cls.is_defined ()) | |
2958 it = all_classes.find (name); | |
2959 } | |
2960 } | |
2961 | |
2962 if (it == all_classes.end ()) | |
2963 { | |
2964 if (error_if_not_found) | |
2965 error ("class not found: %s", name.c_str ()); | |
2966 } | |
2967 else | |
2968 { | |
2969 cdef_class cls = it->second; | |
2970 | |
2971 if (! cls.is_builtin ()) | |
2972 cls = lookup_class (cls); | |
2973 | |
2974 if (cls.ok ()) | |
2975 return cls; | |
2976 else | |
2977 all_classes.erase (it); | |
2978 } | |
2979 | |
2980 return cdef_class (); | |
2981 } | |
2982 | |
2983 octave_function* | |
2984 cdef_manager::do_find_method_symbol (const std::string& method_name, | |
2985 const std::string& class_name) | |
2986 { | |
2987 octave_function *retval = 0; | |
2988 | |
2989 cdef_class cls = find_class (class_name, false, false); | |
2990 | |
2991 if (cls.ok ()) | |
2992 { | |
2993 cdef_method meth = cls.find_method (method_name); | |
2994 | |
2995 if (meth.ok ()) | |
2996 retval = new octave_classdef_meta (meth); | |
2997 } | |
2998 | |
2999 return retval; | |
3000 } | |
3001 | |
3002 cdef_package | |
3003 cdef_manager::do_find_package (const std::string& name, | |
3004 bool error_if_not_found) | |
3005 { | |
3006 cdef_package retval; | |
3007 | |
3008 std::map<std::string, cdef_package>::const_iterator it | |
3009 = all_packages.find (name); | |
3010 | |
3011 if (it != all_packages.end ()) | |
3012 { | |
3013 retval = it->second; | |
3014 | |
3015 if (! retval.ok ()) | |
3016 error ("invalid package `%s'", name.c_str ()); | |
3017 } | |
3018 else if (error_if_not_found) | |
3019 error ("unknown package `%s'", name.c_str ()); | |
3020 | |
3021 return retval; | |
3022 } | |
3023 | |
3024 //---------------------------------------------------------------------------- | |
3025 | |
2947 DEFUN (__meta_get_package__, args, , "") | 3026 DEFUN (__meta_get_package__, args, , "") |
2948 { | 3027 { |
2949 octave_value retval; | 3028 octave_value retval; |
2950 | 3029 |
2951 if (args.length () == 1) | 3030 if (args.length () == 1) |