Mercurial > hg > octave-nkf
diff libinterp/octave-value/ov-classdef.cc @ 16676:7368654f302f classdef
Initial support for (classdef) packages.
* libinterp/interpfcn/load-path.h (class load_path::loader): New class.
(load_path::default_loader, load_path::loader_map): New members.
(load_path::load_path): Initialize them.
(load_path::fcn_map, load_path::private_fcn_map,
load_path::method_map): Move to class load_path::loader.
(load_path::add_to_fcn_map, load_path::add_to_private_fcn_map,
load_path::add_to_method_map, load_path::move_fcn_map,
load_path::move_method_map, load_path::remove_fcn_map,
load_path::remove_private_fcn_map, load_path::remove_method_map):
Move to class load_path::loader.
(load_path::move): Change signature.
(load_path::do_move, load_path::remove, load_path::add,
load_path::get_loader): New methods.
(load_path::find_package, load_path::do_find_package): Likewise.
(load_path::dir_info::package_dir_map): New member.
(load_path::dir_info::dir_info, load_path::dir_info::operator=):
Initialize/assign it.
(load_path::dir_info::get_package_dir): New method.
(load_path::do_find_fcn, load_path::do_find_private_fcn): Remove
methods.
(load_path::find_fcn, load_path::find_private_fcn,
load_path::find_fcn_file, load_path::find_oct_file,
load_path::find_mex_file): Rewrite using class load_path::loader.
New argument for package name.
*libinterp/interpfcn/load-path.cc (load_path::dir_info::initialize):
Clear package_map_dir.
(load_path::dir_info::get_package_dir): New method.
(load_path::dir_info::get_files_list): Use it.
(load_path::add_to_fcn_map, load_path::add_to_private_fcn_map,
load_path::add_to_method_map, load_path::move_fcn_map,
load_path::move_method_map, load_path::remove_fcn_map,
load_path::remove_private_fcn_map, load_path::remove_method_map):
Move to class load_path::loader.
(load_path::move): Move implementation to do_move, rewrite using
class load_path::loader. Signature change.
(load_path::do_move, load_path::add, load_path::remove): New methods.
(load_path::do_clear): Rewrite using class load_path::loader.
(load_path::do_add): Use "do_move" and "add" methods.
(load_path::do_remove): Rewrite using "remove" method.
(load_path::do_update): Rewitre using class load_path::loader and
"add" method.
(load_path::do_find_method, load_path::do_methods,
load_path::do_overloads, load_path::do_fcn_names, load_path::do_display):
Move Implementation to class load_path::loader, without "do_" prefix.
Rewrite original to redirect to appropriate loaders.
(F__dump_load_path__): New debug function.
* libinterp/interpfcn/symtab.h (symbol_table::package_name): New member.
(symbol_table::symbol_table): Initialize it.
(symbol_table::find): New scope argument.
(symbol_table::alloc_package_scope): New method.
(symbol_table::fcn_info::find, symbol_table::fcn_info::find_function,
symbol_table::fcn_info::find_user_function,
symbol_table::fcn_info::fcn_info_rep::xfind,
symbol_table::fcn_info::fcn_info_rep::load_class_constructor,
symbol_table::fcn_info::fcn_info_rep::find,
symbol_table::fcn_info::fcn_info_rep::find_user_function): New
argument for package name.
(symbol_table::fcn_info::fcn_info_rep::package): New member.
(symbol_table::fcn_info::fcn_info_rep::find_package,
symbol_table::fcn_info::fcn_info_rep::clear_package): New methods.
(symbol_table::fcn_info::fcn_info_rep::clear): Clear package.
* libinterp/interpfcn/symtab.cc
(symbol_table::fcn_info::fcn_info_rep::load_class_constructor,
symbol_table::fcn_info::fcn_info_rep::find,
symbol_table::fcn_info::fcn_info_rep::xfind,
symbol_table::fcn_info::fcn_info_rep::find_user_function):
New argument for package name.
(symbol_table::fcn_info::fcn_info_rep::find_package): New method.
(symbol_table::find): New scope argument.
(symbol_table::do_find): Use package_name member.
* libinterp/octave-value/ov-classdef.h
(cdef_package::cdef_package_rep::scope): New member.
(cdef_package::cdef_package_rep::~cdef_package_rep): New destructor.
(cdef_package::cdef_package_rep::meta_subsref,
cdef_package::cdef_package_rep::meta_release,
cdef_package::cdef_package_rep::meta_is_postfix_index_handled,
cdef_package::cdef_package_rep::find,
cdef_package::cdef_package_rep::wrap): New methods.
(cdef_package::find): New method.
(cdef_manager::find_package, cdef_manager::do_find_package): New
argument "load_if_not_found".
(cdef_manager::find_package_symbol,
cdef_manager::do_find_package_symbol): New methods.
* libinterp/octave-value/ov-classdef.cc
(cdef_manager::do_find_package_symbol): New method.
(cdef_manager::do_find_package): New argument. Create package object if
it is not loaded yet and the package exists in load_path.
(cdef_manager::do_find_class): Handle class names with package.
(cdef_package::cdef_package_rep::meta_subsref,
cdef_package::cdef_package_rep::meta_release,
cdef_package::cdef_package_rep::find): New methods.
(cdef_class::make_meta_class): Handle package-scoped classes.
(make_package): Assign correct name to the package object.
* libinterp/parse-tree/pt-classdef.h (tree_classdef::pack_name): New
member.
(tree_classdef::tree_classdef): New argument. Initialize it.
(tree_classdef::package_name): New accessor.
* libinterp/parse-tree/parse.h (octave_base_parser::curr_package_name):
New member.
(octave_base_parser::octave_base_parser): Initialize it.
(load_fcn_from_file): New argument for package name.
* libinterp/parse-tree/oct-parse.in.yy (load_fcn_from_file): New
argument for package name. Change callers.
(parse_fcn_from_file): New argument for package name. Change callers.
(octave_base_parser::make_classdef): Use curr_package_name to create
the tree_classdef object.
* libinterp/octave-value/ov-fcn-handle.cc (octave_fcn_handle::set_fcn):
Adapt to new load_fcn_from_file signature.
* libinterp/interp-core/ls-mat5.cc (read_mat5_binary_element): Adapt
to new load_fcn_from_file signature.
author | Michael Goffioul <michael.goffioul@gmail.com> |
---|---|
date | Fri, 17 May 2013 23:17:25 -0400 |
parents | 10142aad4b9f |
children | edbb123cbe3a |
line wrap: on
line diff
--- a/libinterp/octave-value/ov-classdef.cc +++ b/libinterp/octave-value/ov-classdef.cc @@ -27,6 +27,7 @@ #include <algorithm> #include "defun.h" +#include "load-path.h" #include "ov-builtin.h" #include "ov-classdef.h" #include "ov-fcn-handle.h" @@ -723,10 +724,9 @@ make_package (const std::string& nm, const std::string& parent = std::string ()) { - cdef_package pack ("meta.package"); + cdef_package pack (nm); pack.set_class (cdef_class::meta_package ()); - pack.put ("Name", nm); if (parent.empty ()) pack.put ("ContainingPackage", Matrix ()); else @@ -779,6 +779,8 @@ const std::list<octave_value_list>& idx, const octave_value& rhs) { + // FIXME: should check "subsasgn" method first + return object.subsasgn (type, idx, rhs); } @@ -950,7 +952,7 @@ { // I see 2 possible implementations here: // 1) use cdef_object::subsref with a different class - // context; this avoids duplicating codem but + // context; this avoids duplicating code, but // assumes the object is always the first argument // 2) lookup the method manually and call // cdef_method::execute; this duplicates part of @@ -2190,12 +2192,14 @@ cdef_class::make_meta_class (tree_classdef* t) { cdef_class retval; - std::string class_name; + std::string class_name, full_class_name; // Class creation - class_name = t->ident ()->name (); - gnulib::printf ("class: %s\n", class_name.c_str ()); + class_name = full_class_name = t->ident ()->name (); + if (! t->package_name ().empty ()) + full_class_name = t->package_name () + "." + full_class_name; + gnulib::printf ("class: %s\n", full_class_name.c_str ()); std::list<cdef_class> slist; @@ -2219,7 +2223,7 @@ else { ::error ("`%s' cannot inherit from `%s', because it is sealed", - class_name.c_str (), sclass_name.c_str ()); + full_class_name.c_str (), sclass_name.c_str ()); return retval; } } @@ -2229,11 +2233,21 @@ } } - retval = ::make_class (class_name, slist); + retval = ::make_class (full_class_name, slist); if (error_state) return cdef_class (); + // Package owning this class + + if (! t->package_name ().empty ()) + { + cdef_package pack = cdef_manager::find_package (t->package_name ()); + + if (! error_state && pack.ok ()) + retval.put ("ContainingPackage", to_ov (pack)); + } + // Class attributes if (t->attribute_list ()) @@ -2770,6 +2784,89 @@ cdef_package::cdef_package_rep::get_packages (void) const { return map2Cell (package_map); } +octave_value +cdef_package::cdef_package_rep::find (const std::string& nm) +{ + if (scope == -1) + scope = symbol_table::alloc_package_scope (get_name ()); + + return symbol_table::find (nm, octave_value_list (), true, false, scope); +} + +octave_value_list +cdef_package::cdef_package_rep::meta_subsref + (const std::string& type, const std::list<octave_value_list>& idx, + int nargout) +{ + octave_value_list retval; + + switch (type[0]) + { + case '.': + if (idx.front ().length () == 1) + { + std::string nm = idx.front ()(0).string_value (); + + if (! error_state) + { + gnulib::printf ("meta.package query: %s\n", nm.c_str ()); + + octave_value o = find (nm); + + if (o.is_defined ()) + { + if (o.is_function ()) + { + octave_function* fcn = o.function_value (); + + if (! error_state) + { + if (type.size () == 1 || + ! fcn->is_postfix_index_handled (type[1])) + { + octave_value_list tmp_args; + + retval = o.do_multi_index_op (nargout, + tmp_args); + } + else + retval(0) = o; + + if (type.size () > 1 && idx.size () > 1) + retval = retval(0).next_subsref (nargout, type, + idx, 1); + } + } + else if (type.size () > 1 && idx.size () > 1) + retval = o.next_subsref (nargout, type, idx, 1); + else + retval(0) = o; + } + else + error ("member `%s' in package `%s' does not exist", + nm.c_str (), get_name ().c_str ()); + } + else + error ("invalid meta.package indexing, expected a symbol name"); + } + else + error ("invalid meta.package indexing"); + break; + + default: + error ("invalid meta.package indexing"); + break; + } + + return retval; +} + +void +cdef_package::cdef_package_rep::meta_release (void) +{ + cdef_manager::unregister_package (wrap ()); +} + cdef_class cdef_class::_meta_class = cdef_class (); cdef_class cdef_class::_meta_property = cdef_class (); cdef_class cdef_class::_meta_method = cdef_class (); @@ -2948,11 +3045,23 @@ 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); + octave_value ov_cls; + + size_t pos = name.rfind ('.'); + + if (pos == std::string::npos) + ov_cls = symbol_table::find (name); + else + { + std::string pack_name = name.substr (0, pos); + + cdef_package pack = do_find_package (pack_name, false, true); + + if (pack.ok ()) + ov_cls = pack.find (name.substr (pos+1)); + } if (ov_cls.is_defined ()) it = all_classes.find (name); @@ -3001,7 +3110,8 @@ cdef_package cdef_manager::do_find_package (const std::string& name, - bool error_if_not_found) + bool error_if_not_found, + bool load_if_not_found) { cdef_package retval; @@ -3015,8 +3125,37 @@ if (! retval.ok ()) error ("invalid package `%s'", name.c_str ()); } - else if (error_if_not_found) - error ("unknown package `%s'", name.c_str ()); + else + { + if (load_if_not_found && load_path::find_package (name)) + { + size_t pos = name.find ('.'); + + if (pos == std::string::npos) + retval = make_package (name, std::string ()); + else + { + std::string parent_name = name.substr (0, pos); + + retval = make_package (name, parent_name); + } + } + else if (error_if_not_found) + error ("unknown package `%s'", name.c_str ()); + } + + return retval; +} + +octave_function* +cdef_manager::do_find_package_symbol (const std::string& pack_name) +{ + octave_function* retval = 0; + + cdef_package pack = find_package (pack_name, false); + + if (pack.ok ()) + retval = new octave_classdef_meta (pack); return retval; }