Mercurial > octave-nkf
diff 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 |
line wrap: on
line diff
--- a/libinterp/octave-value/ov-classdef.cc Mon Jan 28 21:56:01 2013 -0500 +++ b/libinterp/octave-value/ov-classdef.cc Mon Feb 11 15:20:00 2013 -0500 @@ -25,7 +25,6 @@ #endif #include <algorithm> -#include <map> #include "defun.h" #include "ov-builtin.h" @@ -38,14 +37,12 @@ #include "pt-misc.h" #include "pt-stmt.h" #include "pt-walk.h" +#include "singleton-cleanup.h" #include "symtab.h" #include "toplev.h" #include "Array.cc" -static std::map<std::string, cdef_class> all_classes; -static std::map<std::string, cdef_package> all_packages; - static void gripe_method_access (const std::string& from, const cdef_method& meth) { @@ -144,41 +141,11 @@ } static cdef_class -lookup_class (const std::string& name, bool error_if_not_found = true) +lookup_class (const std::string& name, bool error_if_not_found = true, + bool load_if_not_found = true) { - std::map<std::string, cdef_class>::iterator it = all_classes.find (name); - - if (it == all_classes.end ()) - { - // FIXME: implement this properly - - octave_value ov_cls = symbol_table::find (name); - - if (ov_cls.is_defined ()) - it = all_classes.find (name); - } - - if (it == all_classes.end ()) - { - if (error_if_not_found) - error ("class not found: %s", name.c_str ()); - } - else - { - cdef_class& cls = it->second; - - if (! cls.is_builtin ()) - { - // FIXME: check whether a class reload is needed - } - - if (cls.ok ()) - return cls; - else - all_classes.erase (it); - } - - return cdef_class (); + return cdef_manager::find_class (name, error_if_not_found, + load_if_not_found); } static cdef_class @@ -652,7 +619,7 @@ return cdef_class (); if (! name.empty ()) - all_classes[name] = cls; + cdef_manager::register_class (cls); return cls; } @@ -760,10 +727,13 @@ pack.set_class (cdef_class::meta_package ()); pack.put ("Name", nm); - pack.put ("ContainingPackage", to_ov (all_packages[parent])); + if (parent.empty ()) + pack.put ("ContainingPackage", Matrix ()); + else + pack.put ("ContainingPackage", to_ov (cdef_manager::find_package (parent))); if (! nm.empty ()) - all_packages[nm] = pack; + cdef_manager::register_package (pack); return pack; } @@ -2001,7 +1971,7 @@ void cdef_class::cdef_class_rep::meta_release (void) { - all_classes.erase (get_name ()); + cdef_manager::unregister_class (wrap ()); } void @@ -2646,24 +2616,37 @@ return false; } +octave_value_list +cdef_method::cdef_method_rep::meta_subsref + (const std::string& type, const std::list<octave_value_list>& idx, + int nargout) +{ + octave_value_list retval; + + switch (type[0]) + { + case '(': + retval = execute (idx.front (), type.length () > 1 ? 1 : nargout, true); + break; + + default: + error ("invalid meta.method indexing"); + break; + } + + if (! error_state) + { + if (type.length () > 1 && idx.size () > 1 && ! retval.empty ()) + retval = retval(0).next_subsref (nargout, type, idx, 1); + } + + return retval; +} + static cdef_package lookup_package (const std::string& name) { - std::map<std::string, cdef_package>::const_iterator it = all_packages.find (name); - - if (it != all_packages.end ()) - { - cdef_package pack = it->second; - - if (pack.ok ()) - return pack; - else - error ("invalid package: %s", name.c_str ()); - } - else - error ("package not found: %s", name.c_str ()); - - return cdef_package (); + return cdef_manager::find_package (name); } static octave_value_list @@ -2944,6 +2927,102 @@ package_meta.install_class (meta_dynproperty, "dynproperty"); } +//---------------------------------------------------------------------------- + +cdef_manager* cdef_manager::instance = 0; + +void +cdef_manager::create_instance (void) +{ + instance = new cdef_manager (); + + if (instance) + singleton_cleanup_list::add (cleanup_instance); +} + +cdef_class +cdef_manager::do_find_class (const std::string& name, + bool error_if_not_found, bool load_if_not_found) +{ + std::map<std::string, cdef_class>::iterator it = all_classes.find (name); + + if (it == all_classes.end ()) + { + // FIXME: implement this properly, take package prefix into account + + if (load_if_not_found) + { + octave_value ov_cls = symbol_table::find (name); + + if (ov_cls.is_defined ()) + it = all_classes.find (name); + } + } + + if (it == all_classes.end ()) + { + if (error_if_not_found) + error ("class not found: %s", name.c_str ()); + } + else + { + cdef_class cls = it->second; + + if (! cls.is_builtin ()) + cls = lookup_class (cls); + + if (cls.ok ()) + return cls; + else + all_classes.erase (it); + } + + return cdef_class (); +} + +octave_function* +cdef_manager::do_find_method_symbol (const std::string& method_name, + const std::string& class_name) +{ + octave_function *retval = 0; + + cdef_class cls = find_class (class_name, false, false); + + if (cls.ok ()) + { + cdef_method meth = cls.find_method (method_name); + + if (meth.ok ()) + retval = new octave_classdef_meta (meth); + } + + return retval; +} + +cdef_package +cdef_manager::do_find_package (const std::string& name, + bool error_if_not_found) +{ + cdef_package retval; + + std::map<std::string, cdef_package>::const_iterator it + = all_packages.find (name); + + if (it != all_packages.end ()) + { + retval = it->second; + + if (! retval.ok ()) + error ("invalid package `%s'", name.c_str ()); + } + else if (error_if_not_found) + error ("unknown package `%s'", name.c_str ()); + + return retval; +} + +//---------------------------------------------------------------------------- + DEFUN (__meta_get_package__, args, , "") { octave_value retval;