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)