# HG changeset patch # User Michael Goffioul # Date 1368847045 14400 # Node ID 7368654f302fb5662e90924a162615210baefaae # Parent 450c03932d6c5d9c65bfe268f80a3df7443e41d8 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. diff -r 450c03932d6c -r 7368654f302f libinterp/interp-core/ls-mat5.cc --- a/libinterp/interp-core/ls-mat5.cc Sun May 12 21:47:57 2013 -0400 +++ b/libinterp/interp-core/ls-mat5.cc Fri May 17 23:17:25 2013 -0400 @@ -906,7 +906,7 @@ std::string dir_name = str.substr (0, xpos); octave_function *fcn - = load_fcn_from_file (str, dir_name, "", fname); + = load_fcn_from_file (str, dir_name, "", "", fname); if (fcn) { @@ -934,7 +934,7 @@ std::string dir_name = str.substr (0, xpos); octave_function *fcn - = load_fcn_from_file (str, dir_name, "", fname); + = load_fcn_from_file (str, dir_name, "", "", fname); if (fcn) { @@ -958,7 +958,7 @@ std::string dir_name = fpath.substr (0, xpos); octave_function *fcn - = load_fcn_from_file (fpath, dir_name, "", fname); + = load_fcn_from_file (fpath, dir_name, "", "", fname); if (fcn) { diff -r 450c03932d6c -r 7368654f302f libinterp/interpfcn/load-path.cc --- a/libinterp/interpfcn/load-path.cc Sun May 12 21:47:57 2013 -0400 +++ b/libinterp/interpfcn/load-path.cc Fri May 17 23:17:25 2013 -0400 @@ -119,6 +119,7 @@ if (fs) { method_file_map.clear (); + package_dir_map.clear (); dir_mtime = fs.mtime (); dir_time_last_checked = octave_time (); @@ -180,6 +181,8 @@ get_private_file_map (full_name); else if (fname[0] == '@') get_method_file_map (full_name, fname.substr (1)); + else if (fname[0] == '+') + get_package_dir (full_name, fname.substr (1)); } else { @@ -285,6 +288,13 @@ method_file_map[class_name].private_file_map = get_fcn_files (pd); } +void +load_path::dir_info::get_package_dir (const std::string& d, + const std::string& package_name) +{ + package_dir_map[package_name] = dir_info (d); +} + bool load_path::instance_ok (void) { @@ -373,8 +383,8 @@ } void -load_path::move_fcn_map (const std::string& dir_name, - const string_vector& fcn_files, bool at_end) +load_path::loader::move_fcn_map (const std::string& dir_name, + const string_vector& fcn_files, bool at_end) { octave_idx_type len = fcn_files.length (); @@ -422,7 +432,7 @@ } void -load_path::move_method_map (const std::string& dir_name, bool at_end) +load_path::loader::move_method_map (const std::string& dir_name, bool at_end) { for (method_map_iterator i = method_map.begin (); i != method_map.end (); @@ -467,7 +477,7 @@ } void -load_path::move (dir_info_list_iterator i, bool at_end) +load_path::do_move (dir_info_list_iterator i, bool at_end) { if (dir_info_list.size () > 1) { @@ -480,16 +490,56 @@ else dir_info_list.push_front (di); - std::string dir_name = di.dir_name; - - move_fcn_map (dir_name, di.fcn_files, at_end); - - // No need to move elements of private function map. - - move_method_map (dir_name, at_end); + move (di, at_end); + } +} + +void +load_path::move (const dir_info& di, bool at_end, const std::string& pname) +{ + loader& l = get_loader (pname); + + l.move (di, at_end); + + dir_info::package_dir_map_type package_dir_map = di.package_dir_map; + + for (dir_info::const_package_dir_map_iterator p = package_dir_map.begin (); + p != package_dir_map.end (); ++p) + { + std::string full_name = p->first; + + if (! pname.empty ()) + full_name = pname + "." + full_name; + + move (p->second, at_end, full_name); } } +void +load_path::loader::move (const dir_info& di, bool at_end) +{ + std::string dir_name = di.dir_name; + + std::list::iterator s = + std::find (dir_list.begin (), dir_list.end (), dir_name); + + if (s != dir_list.end ()) + { + dir_list.erase (s); + + if (at_end) + dir_list.push_back (dir_name); + else + dir_list.push_front (dir_name); + } + + move_fcn_map (dir_name, di.fcn_files, at_end); + + // No need to move elements of private function map. + + move_method_map (dir_name, at_end); +} + static void maybe_add_path_elts (std::string& path, const std::string& dir) { @@ -545,9 +595,10 @@ load_path::do_clear (void) { dir_info_list.clear (); - fcn_map.clear (); - private_fcn_map.clear (); - method_map.clear (); + + default_loader.clear (); + + loader_map.clear (); } static std::list @@ -684,7 +735,7 @@ dir_info_list_iterator i = find_dir_info (dir); if (i != dir_info_list.end ()) - move (i, at_end); + do_move (i, at_end); else { file_stat fs (dir); @@ -702,11 +753,7 @@ else dir_info_list.push_front (di); - add_to_fcn_map (di, at_end); - - add_to_private_fcn_map (di); - - add_to_method_map (di, at_end); + add (di, at_end); if (add_hook) add_hook (dir); @@ -727,12 +774,12 @@ i = find_dir_info ("."); if (i != dir_info_list.end ()) - move (i, false); + do_move (i, false); } void -load_path::remove_fcn_map (const std::string& dir, - const string_vector& fcn_files) +load_path::loader::remove_fcn_map (const std::string& dir, + const string_vector& fcn_files) { octave_idx_type len = fcn_files.length (); @@ -771,7 +818,7 @@ } void -load_path::remove_private_fcn_map (const std::string& dir) +load_path::loader::remove_private_fcn_map (const std::string& dir) { private_fcn_map_iterator p = private_fcn_map.find (dir); @@ -780,7 +827,7 @@ } void -load_path::remove_method_map (const std::string& dir) +load_path::loader::remove_method_map (const std::string& dir) { for (method_map_iterator i = method_map.begin (); i != method_map.end (); @@ -849,15 +896,11 @@ if (remove_hook) remove_hook (dir); - string_vector fcn_files = i->fcn_files; + dir_info& di = *i; dir_info_list.erase (i); - remove_fcn_map (dir, fcn_files); - - remove_private_fcn_map (dir); - - remove_method_map (dir); + remove (di); } } } @@ -866,17 +909,52 @@ } void +load_path::remove (const dir_info& di, const std::string& pname) +{ + loader& l = get_loader (pname); + + l.remove (di); + + dir_info::package_dir_map_type package_dir_map = di.package_dir_map; + + for (dir_info::const_package_dir_map_iterator p = package_dir_map.begin (); + p != package_dir_map.end (); ++p) + { + std::string full_name = p->first; + + if (! pname.empty ()) + full_name = pname + "." + full_name; + + remove (p->second, full_name); + } +} + +void +load_path::loader::remove (const dir_info& di) +{ + std::string dir = di.dir_name; + + string_vector fcn_files = di.fcn_files; + + dir_list.remove (dir); + + remove_fcn_map (dir, fcn_files); + + remove_private_fcn_map (dir); + + remove_method_map (dir); +} + +void load_path::do_update (void) const { // I don't see a better way to do this because we need to // preserve the correct directory ordering for new files that // have appeared. - fcn_map.clear (); - - private_fcn_map.clear (); - - method_map.clear (); + default_loader.clear (); + + loader_map.clear (); for (dir_info_list_iterator p = dir_info_list.begin (); p != dir_info_list.end (); @@ -886,11 +964,7 @@ di.update (); - add_to_fcn_map (di, true); - - add_to_private_fcn_map (di); - - add_to_method_map (di, true); + add (di, true); } } @@ -989,8 +1063,8 @@ } std::string -load_path::do_find_fcn (const std::string& fcn, std::string& dir_name, - int type) const +load_path::loader::find_fcn (const std::string& fcn, std::string& dir_name, + int type) const { std::string retval; @@ -1005,7 +1079,7 @@ std::string class_name = fcn.substr (1, pos-1); std::string meth = fcn.substr (pos+1); - retval = do_find_method (class_name, meth, dir_name); + retval = find_method (class_name, meth, dir_name); } else retval = std::string (); @@ -1044,8 +1118,8 @@ } std::string -load_path::do_find_private_fcn (const std::string& dir, - const std::string& fcn, int type) const +load_path::loader::find_private_fcn (const std::string& dir, + const std::string& fcn, int type) const { std::string retval; @@ -1076,7 +1150,26 @@ std::string load_path::do_find_method (const std::string& class_name, const std::string& meth, - std::string& dir_name, int type) const + std::string& dir_name) const +{ + size_t pos = class_name.rfind ('.'); + + if (pos == std::string::npos) + return default_loader.find_method (class_name, meth, dir_name); + else + { + std::string pname = class_name.substr (0, pos); + + std::string cname = class_name.substr (pos+1); + + return get_loader(pname).find_method (cname, meth, dir_name); + } +} + +std::string +load_path::loader::find_method (const std::string& class_name, + const std::string& meth, + std::string& dir_name, int type) const { std::string retval; @@ -1124,6 +1217,23 @@ std::list load_path::do_methods (const std::string& class_name) const { + size_t pos = class_name.rfind ('.'); + + if (pos == std::string::npos) + return default_loader.methods (class_name); + else + { + std::string pname = class_name.substr (0, pos); + + std::string cname = class_name.substr (pos+1); + + return get_loader (pname).methods (cname); + } +} + +std::list +load_path::loader::methods (const std::string& class_name) const +{ std::list retval; // update (); @@ -1151,16 +1261,34 @@ // update (); + default_loader.overloads (meth, retval); + + for (const_loader_map_iterator l = loader_map.begin (); + l != loader_map.end (); ++l) + l->second.overloads (meth, retval); + + return retval; +} + +void +load_path::loader::overloads (const std::string& meth, + std::list& l) const +{ for (const_method_map_iterator q = method_map.begin (); q != method_map.end (); q++) { const fcn_map_type& m = q->second; if (m.find (meth) != m.end ()) - retval.push_back (q->first); + { + std::string class_name = q->first; + + if (! prefix.empty ()) + class_name = prefix + "." + class_name; + + l.push_back (class_name); + } } - - return retval; } std::string @@ -1518,6 +1646,12 @@ string_vector load_path::do_fcn_names (void) const { + return default_loader.fcn_names (); +} + +string_vector +load_path::loader::fcn_names (void) const +{ size_t len = fcn_map.size (); string_vector retval (len); @@ -1661,69 +1795,11 @@ } } - for (const_private_fcn_map_iterator i = private_fcn_map.begin (); - i != private_fcn_map.end (); i++) - { - os << "\n*** private functions in " - << file_ops::concat (i->first, "private") << ":\n\n"; - - print_fcn_list (os, i->second); - } - -#if defined (DEBUG_LOAD_PATH) - - for (const_fcn_map_iterator i = fcn_map.begin (); - i != fcn_map.end (); - i++) - { - os << i->first << ":\n"; - - const file_info_list_type& file_info_list = i->second; - - for (const_file_info_list_iterator p = file_info_list.begin (); - p != file_info_list.end (); - p++) - { - os << " " << p->dir_name << " ("; - - print_types (os, p->types); - - os << ")\n"; - } - } - - for (const_method_map_iterator i = method_map.begin (); - i != method_map.end (); - i++) - { - os << "CLASS " << i->first << ":\n"; - - const fcn_map_type& fm = i->second; - - for (const_fcn_map_iterator q = fm.begin (); - q != fm.end (); - q++) - { - os << " " << q->first << ":\n"; - - const file_info_list_type& file_info_list = q->second; - - for (const_file_info_list_iterator p = file_info_list.begin (); - p != file_info_list.end (); - p++) - { - os << " " << p->dir_name << " ("; - - print_types (os, p->types); - - os << ")\n"; - } - } - } - - os << "\n"; - -#endif + default_loader.display (os); + + for (const_loader_map_iterator l = loader_map.begin (); + l != loader_map.end (); ++l) + l->second.display (os); } // True if a path is contained in a path list separated by path_sep_char @@ -1745,7 +1821,29 @@ } void -load_path::add_to_fcn_map (const dir_info& di, bool at_end) const +load_path::add (const dir_info& di, bool at_end, + const std::string& pname) const +{ + loader& l = get_loader (pname); + + l.add (di, at_end); + + dir_info::package_dir_map_type package_dir_map = di.package_dir_map; + + for (dir_info::const_package_dir_map_iterator p = package_dir_map.begin (); + p != package_dir_map.end (); ++p) + { + std::string full_name = p->first; + + if (! pname.empty ()) + full_name = pname + "." + full_name; + + add (p->second, at_end, full_name); + } +} + +void +load_path::loader::add_to_fcn_map (const dir_info& di, bool at_end) { std::string dir_name = di.dir_name; @@ -1841,7 +1939,7 @@ } void -load_path::add_to_private_fcn_map (const dir_info& di) const +load_path::loader::add_to_private_fcn_map (const dir_info& di) { dir_info::fcn_file_map_type private_file_map = di.private_file_map; @@ -1850,7 +1948,7 @@ } void -load_path::add_to_method_map (const dir_info& di, bool at_end) const +load_path::loader::add_to_method_map (const dir_info& di, bool at_end) { std::string dir_name = di.dir_name; @@ -1920,6 +2018,81 @@ } } +void +load_path::loader::display (std::ostream& os) const +{ + os << "*** loader: " << (prefix.empty () ? "" : prefix) << "\n\n"; + + for (std::list::const_iterator s = dir_list.begin (); + s != dir_list.end (); ++s) + os << *s << "\n"; + os << "\n"; + + for (const_private_fcn_map_iterator i = private_fcn_map.begin (); + i != private_fcn_map.end (); i++) + { + os << "\n*** private functions in " + << file_ops::concat (i->first, "private") << ":\n\n"; + + print_fcn_list (os, i->second); + } + +#if defined (DEBUG_LOAD_PATH) + + for (const_fcn_map_iterator i = fcn_map.begin (); + i != fcn_map.end (); + i++) + { + os << i->first << ":\n"; + + const file_info_list_type& file_info_list = i->second; + + for (const_file_info_list_iterator p = file_info_list.begin (); + p != file_info_list.end (); + p++) + { + os << " " << p->dir_name << " ("; + + print_types (os, p->types); + + os << ")\n"; + } + } + + for (const_method_map_iterator i = method_map.begin (); + i != method_map.end (); + i++) + { + os << "CLASS " << i->first << ":\n"; + + const fcn_map_type& fm = i->second; + + for (const_fcn_map_iterator q = fm.begin (); + q != fm.end (); + q++) + { + os << " " << q->first << ":\n"; + + const file_info_list_type& file_info_list = q->second; + + for (const_file_info_list_iterator p = file_info_list.begin (); + p != file_info_list.end (); + p++) + { + os << " " << p->dir_name << " ("; + + print_types (os, p->types); + + os << ")\n"; + } + } + } + + os << "\n"; + +#endif +} + std::string genpath (const std::string& dirname, const string_vector& skip) { @@ -2340,3 +2513,10 @@ return retval; } + +DEFUN (__dump_load_path__, , , "") +{ + load_path::display (octave_stdout); + + return octave_value_list (); +} diff -r 450c03932d6c -r 7368654f302f libinterp/interpfcn/load-path.h --- a/libinterp/interpfcn/load-path.h Sun May 12 21:47:57 2013 -0400 +++ b/libinterp/interpfcn/load-path.h Fri May 17 23:17:25 2013 -0400 @@ -39,8 +39,7 @@ protected: load_path (void) - : dir_info_list (), fcn_map (), private_fcn_map (), method_map (), - init_dirs () { } + : loader_map (), default_loader (), dir_info_list (), init_dirs () { } public: @@ -99,7 +98,8 @@ std::string& dir_name) { return instance_ok () - ? instance->do_find_method (class_name, meth, dir_name) : std::string (); + ? instance->do_find_method (class_name, meth, dir_name) + : std::string (); } static std::string find_method (const std::string& class_name, @@ -121,47 +121,64 @@ ? instance->do_overloads (meth) : std::list (); } - static std::string find_fcn (const std::string& fcn, std::string& dir_name) + static bool find_package (const std::string& package_name) + { + return instance_ok () + ? instance->do_find_package (package_name) : false; + } + + static std::string find_fcn (const std::string& fcn, std::string& dir_name, + const std::string& pack_name = std::string ()) { return instance_ok () - ? instance->do_find_fcn (fcn, dir_name) : std::string (); + ? instance->get_loader (pack_name).find_fcn (fcn, dir_name) + : std::string (); } - static std::string find_fcn (const std::string& fcn) + static std::string find_fcn (const std::string& fcn, + const std::string& pack_name = std::string ()) { std::string dir_name; - return find_fcn (fcn, dir_name); + return find_fcn (fcn, dir_name, pack_name); } static std::string find_private_fcn (const std::string& dir, - const std::string& fcn) + const std::string& fcn, + const std::string& pack_name = std::string ()) { return instance_ok () - ? instance->do_find_private_fcn (dir, fcn) : std::string (); + ? instance->get_loader (pack_name).find_private_fcn (dir, fcn) + : std::string (); } - static std::string find_fcn_file (const std::string& fcn) + static std::string find_fcn_file (const std::string& fcn, + const std::string& pack_name = std::string ()) { std::string dir_name; - return instance_ok () ? - instance->do_find_fcn (fcn, dir_name, M_FILE) : std::string (); + return instance_ok () + ? instance->get_loader (pack_name).find_fcn (fcn, dir_name, M_FILE) + : std::string (); } - static std::string find_oct_file (const std::string& fcn) + static std::string find_oct_file (const std::string& fcn, + const std::string& pack_name = std::string ()) { std::string dir_name; - return instance_ok () ? - instance->do_find_fcn (fcn, dir_name, OCT_FILE) : std::string (); + return instance_ok () + ? instance->get_loader (pack_name).find_fcn (fcn, dir_name, M_FILE) + : std::string (); } - static std::string find_mex_file (const std::string& fcn) + static std::string find_mex_file (const std::string& fcn, + const std::string& pack_name = std::string ()) { std::string dir_name; - return instance_ok () ? - instance->do_find_fcn (fcn, dir_name, MEX_FILE) : std::string (); + return instance_ok () + ? instance->get_loader (pack_name).find_fcn (fcn, dir_name, M_FILE) + : std::string (); } static std::string find_file (const std::string& file) @@ -295,19 +312,27 @@ typedef method_file_map_type::const_iterator const_method_file_map_iterator; typedef method_file_map_type::iterator method_file_map_iterator; + // + typedef std::map package_dir_map_type; + + typedef package_dir_map_type::const_iterator const_package_dir_map_iterator; + typedef package_dir_map_type::iterator package_dir_map_iterator; + // This default constructor is only provided so we can create a // std::map of dir_info objects. You should not use this // constructor for any other purpose. dir_info (void) : dir_name (), abs_dir_name (), is_relative (false), dir_mtime (), dir_time_last_checked (), - all_files (), fcn_files (), private_file_map (), method_file_map () + all_files (), fcn_files (), private_file_map (), method_file_map (), + package_dir_map () { } dir_info (const std::string& d) : dir_name (d), abs_dir_name (), is_relative (false), dir_mtime (), dir_time_last_checked (), - all_files (), fcn_files (), private_file_map (), method_file_map () + all_files (), fcn_files (), private_file_map (), method_file_map (), + package_dir_map () { initialize (); } @@ -319,7 +344,8 @@ dir_time_last_checked (di.dir_time_last_checked), all_files (di.all_files), fcn_files (di.fcn_files), private_file_map (di.private_file_map), - method_file_map (di.method_file_map) { } + method_file_map (di.method_file_map), + package_dir_map (di.package_dir_map) { } ~dir_info (void) { } @@ -336,6 +362,7 @@ fcn_files = di.fcn_files; private_file_map = di.private_file_map; method_file_map = di.method_file_map; + package_dir_map = di.package_dir_map; } return *this; @@ -352,6 +379,7 @@ string_vector fcn_files; fcn_file_map_type private_file_map; method_file_map_type method_file_map; + package_dir_map_type package_dir_map; private: @@ -364,6 +392,9 @@ void get_method_file_map (const std::string& d, const std::string& class_name); + void get_package_dir (const std::string& d, + const std::string& package_name); + friend fcn_file_map_type get_fcn_files (const std::string& d); }; @@ -439,13 +470,125 @@ typedef method_map_type::const_iterator const_method_map_iterator; typedef method_map_type::iterator method_map_iterator; - mutable dir_info_list_type dir_info_list; + class loader + { + public: + loader (const std::string& pfx = std::string ()) + : prefix (pfx), dir_list (), fcn_map (), private_fcn_map (), + method_map () { } + + loader (const loader& l) + : prefix (l.prefix), dir_list (l.dir_list), + private_fcn_map (l.private_fcn_map), method_map (l.method_map) { } + + ~loader (void) { } + + loader& operator = (const loader& l) + { + if (&l != this) + { + prefix = l.prefix; + dir_list = l.dir_list; + fcn_map = l.fcn_map; + private_fcn_map = l.private_fcn_map; + method_map = l.method_map; + } + + return *this; + } - mutable fcn_map_type fcn_map; + void add (const dir_info& di, bool at_end) + { + if (at_end) + dir_list.push_back (di.dir_name); + else + dir_list.push_front (di.dir_name); + + add_to_fcn_map (di, at_end); + + add_to_private_fcn_map (di); + + add_to_method_map (di, at_end); + } + + void move (const dir_info& di, bool at_end); + + void remove (const dir_info& di); + + void clear (void) + { + dir_list.clear (); + + fcn_map.clear (); + + private_fcn_map.clear (); + + method_map.clear (); + } + + void display (std::ostream& out) const; - mutable private_fcn_map_type private_fcn_map; + std::string find_fcn (const std::string& fcn, + std::string& dir_name, + int type = M_FILE | OCT_FILE | MEX_FILE) const; + + std::string find_private_fcn (const std::string& dir, + const std::string& fcn, + int type = M_FILE | OCT_FILE | MEX_FILE) const; + + std::string find_method (const std::string& class_name, + const std::string& meth, + std::string& dir_name, + int type = M_FILE | OCT_FILE | MEX_FILE) const; + + std::list methods (const std::string& class_name) const; + + void overloads (const std::string& meth, std::list& l) const; + + string_vector fcn_names (void) const; + + private: + void add_to_fcn_map (const dir_info& di, bool at_end); + + void add_to_private_fcn_map (const dir_info& di); + + void add_to_method_map (const dir_info& di, bool at_end); + + void move_fcn_map (const std::string& dir, + const string_vector& fcn_files, bool at_end); + + void move_method_map (const std::string& dir, bool at_end); - mutable method_map_type method_map; + void remove_fcn_map (const std::string& dir, + const string_vector& fcn_files); + + void remove_private_fcn_map (const std::string& dir); + + void remove_method_map (const std::string& dir); + + private: + std::string prefix; + + std::list dir_list; + + fcn_map_type fcn_map; + + private_fcn_map_type private_fcn_map; + + method_map_type method_map; + }; + + // + typedef std::map loader_map_type; + + typedef loader_map_type::const_iterator const_loader_map_iterator; + typedef loader_map_type::iterator loader_map_iterator; + + mutable loader_map_type loader_map; + + mutable loader default_loader; + + mutable dir_info_list_type dir_info_list; mutable std::set init_dirs; @@ -472,12 +615,13 @@ bool do_contains_canonical (const std::string& dir) const; - void move_fcn_map (const std::string& dir, - const string_vector& fcn_files, bool at_end); + void do_move (dir_info_list_iterator i, bool at_end); - void move_method_map (const std::string& dir, bool at_end); + void move (const dir_info& di, bool at_end, + const std::string& pname = std::string ()); - void move (std::list::iterator i, bool at_end); + void remove (const dir_info& di, + const std::string& pname = std::string ()); void do_initialize (bool set_initial_path); @@ -491,12 +635,6 @@ void do_add (const std::string& dir, bool at_end, bool warn); - void remove_fcn_map (const std::string& dir, const string_vector& fcn_files); - - void remove_private_fcn_map (const std::string& dir); - - void remove_method_map (const std::string& dir); - bool do_remove (const std::string& dir); void do_update (void) const; @@ -505,23 +643,35 @@ check_file_type (std::string& fname, int type, int possible_types, const std::string& fcn, const char *who); - std::string do_find_fcn (const std::string& fcn, - std::string& dir_name, - int type = M_FILE | OCT_FILE | MEX_FILE) const; + loader& get_loader (const std::string& name) const + { + if (! name.empty ()) + { + loader_map_iterator l = loader_map.find (name); - std::string do_find_private_fcn (const std::string& dir, - const std::string& fcn, - int type = M_FILE | OCT_FILE | MEX_FILE) const; + if (l == loader_map.end ()) + l = loader_map.insert (loader_map.end (), + loader_map_type::value_type (name, loader (name))); + + return l->second; + } + + return default_loader; + } std::string do_find_method (const std::string& class_name, const std::string& meth, - std::string& dir_name, - int type = M_FILE | OCT_FILE | MEX_FILE) const; + std::string& dir_name) const; std::list do_methods (const std::string& class_name) const; std::list do_overloads (const std::string& meth) const; + bool do_find_package (const std::string& package_name) const + { + return (loader_map.find (package_name) != loader_map.end ()); + } + std::string do_find_file (const std::string& file) const; std::string do_find_dir (const std::string& dir) const; @@ -555,11 +705,8 @@ std::string do_get_command_line_path (void) const { return command_line_path; } - void add_to_fcn_map (const dir_info& di, bool at_end) const; - - void add_to_private_fcn_map (const dir_info& di) const; - - void add_to_method_map (const dir_info& di, bool at_end) const; + void add (const dir_info& di, bool at_end, + const std::string& pname = std::string ()) const; friend dir_info::fcn_file_map_type get_fcn_files (const std::string& d); }; diff -r 450c03932d6c -r 7368654f302f libinterp/interpfcn/symtab.cc --- a/libinterp/interpfcn/symtab.cc Sun May 12 21:47:57 2013 -0400 +++ b/libinterp/interpfcn/symtab.cc Fri May 17 23:17:25 2013 -0400 @@ -374,17 +374,24 @@ } octave_value -symbol_table::fcn_info::fcn_info_rep::load_class_constructor (void) +symbol_table::fcn_info::fcn_info_rep::load_class_constructor + (const std::string& pname) { octave_value retval; std::string dir_name; - std::string file_name = load_path::find_method (name, name, dir_name); + std::string full_name = name; + + if (! pname.empty ()) + full_name = pname + "." + full_name; + + std::string file_name = load_path::find_method (full_name, name, dir_name); if (! file_name.empty ()) { - octave_function *fcn = load_fcn_from_file (file_name, dir_name, name); + octave_function *fcn = load_fcn_from_file (file_name, dir_name, name, + pname); if (fcn) { @@ -402,7 +409,7 @@ octave_value old_function_on_path = function_on_path; - octave_value maybe_cdef_ctor = find_user_function (); + octave_value maybe_cdef_ctor = find_user_function (pname); if (maybe_cdef_ctor.is_defined ()) { @@ -429,7 +436,17 @@ octave_value retval; if (name == dispatch_type) - retval = load_class_constructor (); + retval = load_class_constructor (std::string ()); + else if (dispatch_type.length () > name.length () + && dispatch_type.substr (dispatch_type.length () - name.length () + - 1) == ("." + name)) + { + std::string pname = + dispatch_type.substr (0, + dispatch_type.length () - name.length () - 1); + + retval = load_class_constructor (pname); + } else { octave_function *cm = cdef_manager::find_method_symbol (name, @@ -647,9 +664,10 @@ octave_value symbol_table::fcn_info::fcn_info_rep::find (const octave_value_list& args, - bool local_funcs) + bool local_funcs, + const std::string& pname) { - octave_value retval = xfind (args, local_funcs); + octave_value retval = xfind (args, local_funcs, pname); if (! (error_state || retval.is_defined ())) { @@ -659,7 +677,7 @@ load_path::update (); - retval = xfind (args, local_funcs); + retval = xfind (args, local_funcs, pname); } return retval; @@ -667,7 +685,8 @@ octave_value symbol_table::fcn_info::fcn_info_rep::xfind (const octave_value_list& args, - bool local_funcs) + bool local_funcs, + const std::string& pname) { if (local_funcs) { @@ -750,7 +769,7 @@ if (q == class_constructors.end ()) { - octave_value val = load_class_constructor (); + octave_value val = load_class_constructor (pname); if (val.is_defined ()) return val; @@ -766,7 +785,7 @@ return fval; else { - octave_value val = load_class_constructor (); + octave_value val = load_class_constructor (pname); if (val.is_defined ()) return val; @@ -812,7 +831,14 @@ // Function on the path. - fcn = find_user_function (); + fcn = find_user_function (pname); + + if (fcn.is_defined ()) + return fcn; + + // Package + + fcn = find_package (pname); if (fcn.is_defined ()) return fcn; @@ -869,7 +895,7 @@ // Function on the path. - octave_value fcn = find_user_function (); + octave_value fcn = find_user_function (std::string ()); if (fcn.is_defined ()) return fcn; @@ -1004,7 +1030,7 @@ std::string dir_name = file_name.substr (0, pos); - octave_function *fcn = load_fcn_from_file (file_name, dir_name, + octave_function *fcn = load_fcn_from_file (file_name, dir_name, "", "", name, true); if (fcn) @@ -1016,7 +1042,7 @@ } octave_value -symbol_table::fcn_info::fcn_info_rep::find_user_function (void) +symbol_table::fcn_info::fcn_info_rep::find_user_function (const std::string& pname) { // Function on the path. @@ -1027,11 +1053,12 @@ { std::string dir_name; - std::string file_name = load_path::find_fcn (name, dir_name); + std::string file_name = load_path::find_fcn (name, dir_name, pname); if (! file_name.empty ()) { - octave_function *fcn = load_fcn_from_file (file_name, dir_name); + octave_function *fcn = load_fcn_from_file (file_name, dir_name, "", + pname); if (fcn) function_on_path = octave_value (fcn); @@ -1041,6 +1068,29 @@ return function_on_path; } +octave_value +symbol_table::fcn_info::fcn_info_rep::find_package (const std::string& pname) +{ + // FIXME: implement correct way to check out of date package + //if (package.is_defined ()) + // out_of_date_check (package); + + if (! (error_state || package.is_defined ())) + { + std::string full_name = name; + + if (! pname.empty ()) + full_name = pname + "." + full_name; + + octave_function * fcn = cdef_manager::find_package_symbol (full_name); + + if (fcn) + package = octave_value (fcn); + } + + return package; +} + // Insert INF_CLASS in the set of class names that are considered // inferior to SUP_CLASS. Return FALSE if INF_CLASS is currently // marked as superior to SUP_CLASS. @@ -1176,9 +1226,10 @@ symbol_table::find (const std::string& name, const octave_value_list& args, bool skip_variables, - bool local_funcs) + bool local_funcs, + scope_id scope) { - symbol_table *inst = get_instance (xcurrent_scope); + symbol_table *inst = get_instance (scope); return inst ? inst->do_find (name, args, skip_variables, local_funcs) @@ -1376,12 +1427,12 @@ fcn_table_iterator p = fcn_table.find (name); if (p != fcn_table.end ()) - return p->second.find (args, local_funcs); + return p->second.find (args, local_funcs, package_name); else { fcn_info finfo (name); - octave_value fcn = finfo.find (args, local_funcs); + octave_value fcn = finfo.find (args, local_funcs, package_name); if (fcn.is_defined ()) fcn_table[name] = finfo; diff -r 450c03932d6c -r 7368654f302f libinterp/interpfcn/symtab.h --- a/libinterp/interpfcn/symtab.h Sun May 12 21:47:57 2013 -0400 +++ b/libinterp/interpfcn/symtab.h Fri May 17 23:17:25 2013 -0400 @@ -761,11 +761,12 @@ octave_value load_private_function (const std::string& dir_name); - octave_value load_class_constructor (void); + octave_value load_class_constructor (const std::string& pname); octave_value load_class_method (const std::string& dispatch_type); - octave_value find (const octave_value_list& args, bool local_funcs); + octave_value find (const octave_value_list& args, bool local_funcs, + const std::string& package_name); octave_value builtin_find (void); @@ -773,16 +774,19 @@ octave_value find_autoload (void); - octave_value find_user_function (void); + octave_value find_package (const std::string& package_name); + + octave_value find_user_function (const std::string& package_name); bool is_user_function_defined (void) const { return function_on_path.is_defined (); } - octave_value find_function (const octave_value_list& args, bool local_funcs) + octave_value find_function (const octave_value_list& args, bool local_funcs, + const std::string& package_name) { - return find (args, local_funcs); + return find (args, local_funcs, package_name); } void lock_subfunction (scope_id scope) @@ -880,6 +884,11 @@ clear_user_function (); } + void clear_package (void) + { + package = octave_value (); + } + void clear (bool force = false) { clear_map (subfunctions, force); @@ -889,6 +898,7 @@ clear_autoload_function (force); clear_user_function (force); + clear_package (); } void add_dispatch (const std::string& type, const std::string& fname) @@ -935,13 +945,16 @@ octave_value function_on_path; + octave_value package; + octave_value built_in_function; octave_refcount count; private: - octave_value xfind (const octave_value_list& args, bool local_funcs); + octave_value xfind (const octave_value_list& args, bool local_funcs, + const std::string& package_name); octave_value x_builtin_find (void); @@ -983,9 +996,10 @@ } octave_value find (const octave_value_list& args = octave_value_list (), - bool local_funcs = true) + bool local_funcs = true, + const std::string& package_name = std::string ()) { - return rep->find (args, local_funcs); + return rep->find (args, local_funcs, package_name); } octave_value builtin_find (void) @@ -1013,9 +1027,9 @@ return rep->find_autoload (); } - octave_value find_user_function (void) + octave_value find_user_function (const std::string& pname = std::string ()) { - return rep->find_user_function (); + return rep->find_user_function (pname); } bool is_user_function_defined (void) const @@ -1024,9 +1038,10 @@ } octave_value find_function (const octave_value_list& args = octave_value_list (), - bool local_funcs = true) + bool local_funcs = true, + const std::string& package_name = std::string ()) { - return rep->find_function (args, local_funcs); + return rep->find_function (args, local_funcs, package_name); } void lock_subfunction (scope_id scope) @@ -1132,6 +1147,21 @@ static scope_id alloc_scope (void) { return scope_id_cache::alloc (); } + static scope_id alloc_package_scope (const std::string& name) + { + scope_id retval = alloc_scope (); + + if (retval != -1) + { + symbol_table* inst = get_instance (retval, true); + + inst->do_cache_name (name); + inst->package_name = name; + } + + return retval; + } + static void set_scope (scope_id scope) { if (scope == xglobal_scope) @@ -1275,7 +1305,8 @@ find (const std::string& name, const octave_value_list& args = octave_value_list (), bool skip_variables = false, - bool local_funcs = true); + bool local_funcs = true, + scope_id scope = xcurrent_scope); static octave_value builtin_find (const std::string& name); @@ -2312,6 +2343,10 @@ // If true then no variables can be added. bool static_workspace; + // The name of the package context associated with this table. This is + // only used by classdef packages. + std::string package_name; + // Map from names of global variables to values. static std::map global_table; @@ -2352,7 +2387,7 @@ symbol_table (scope_id scope) : my_scope (scope), table_name (), table (), nest_children (), nest_parent (0), - curr_fcn (0), static_workspace (false), persistent_table () { } + curr_fcn (0), static_workspace (false), package_name (), persistent_table () { } ~symbol_table (void) { } diff -r 450c03932d6c -r 7368654f302f libinterp/octave-value/ov-classdef.cc --- a/libinterp/octave-value/ov-classdef.cc Sun May 12 21:47:57 2013 -0400 +++ b/libinterp/octave-value/ov-classdef.cc Fri May 17 23:17:25 2013 -0400 @@ -27,6 +27,7 @@ #include #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& 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 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& 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; } diff -r 450c03932d6c -r 7368654f302f libinterp/octave-value/ov-classdef.h --- a/libinterp/octave-value/ov-classdef.h Sun May 12 21:47:57 2013 -0400 +++ b/libinterp/octave-value/ov-classdef.h Fri May 17 23:17:25 2013 -0400 @@ -30,6 +30,7 @@ #include "oct-map.h" #include "oct-refcount.h" #include "ov-base.h" +#include "symtab.h" class cdef_object; class cdef_class; @@ -1210,7 +1211,14 @@ cdef_package_rep : public cdef_meta_object_rep { public: - cdef_package_rep (void) : cdef_meta_object_rep (), member_count (0) { } + cdef_package_rep (void) + : cdef_meta_object_rep (), member_count (0), scope (-1) { } + + ~cdef_package_rep (void) + { + if (scope != -1) + symbol_table::erase_scope (scope); + } cdef_object_rep* copy (void) const { return new cdef_package_rep (*this); } @@ -1249,7 +1257,19 @@ delete this; } + octave_value_list + meta_subsref (const std::string& type, + const std::list& idx, int nargout); + + void meta_release (void); + + bool meta_is_postfix_index_handled (char type) const + { return (type == '.'); } + + octave_value find (const std::string& nm); + private: + std::string full_name; std::map class_map; std::map function_map; std::map package_map; @@ -1265,11 +1285,21 @@ typedef std::map::iterator package_iterator; typedef std::map::const_iterator package_const_iterator; + // The symbol_table scope corresponding to this package. + symbol_table::scope_id scope; + private: cdef_package_rep (const cdef_package_rep& p) - : cdef_meta_object_rep (p), class_map (p.class_map), - function_map (p.function_map), package_map (p.package_map), - member_count (p.member_count) { } + : cdef_meta_object_rep (p), full_name (p.full_name), + class_map (p.class_map), function_map (p.function_map), + package_map (p.package_map), member_count (p.member_count) + { } + + cdef_package wrap (void) + { + refcount++; + return cdef_package (this); + } }; public: @@ -1318,6 +1348,8 @@ std::string get_name (void) const { return get_rep ()->get_name (); } + octave_value find (const std::string& nm) { return get_rep ()->find (nm); } + static const cdef_package& meta (void) { return _meta; } private: @@ -1494,14 +1526,24 @@ } static cdef_package find_package (const std::string& name, - bool error_if_not_found = true) + bool error_if_not_found = true, + bool load_if_not_found = true) { if (instance_ok ()) - return instance->do_find_package (name, error_if_not_found); + return instance->do_find_package (name, error_if_not_found, + load_if_not_found); return cdef_package (); } + static octave_function* find_package_symbol (const std::string& pack_name) + { + if (instance_ok ()) + return instance->do_find_package_symbol (pack_name); + + return 0; + } + static void register_class (const cdef_class& cls) { if (instance_ok ()) @@ -1569,7 +1611,10 @@ const std::string& class_name); cdef_package do_find_package (const std::string& name, - bool error_if_not_found); + bool error_if_not_found, + bool load_if_not_found); + + octave_function* do_find_package_symbol (const std::string& pack_name); void do_register_class (const cdef_class& cls) { all_classes[cls.get_name ()] = cls; } diff -r 450c03932d6c -r 7368654f302f libinterp/octave-value/ov-fcn-handle.cc --- a/libinterp/octave-value/ov-fcn-handle.cc Sun May 12 21:47:57 2013 -0400 +++ b/libinterp/octave-value/ov-fcn-handle.cc Fri May 17 23:17:25 2013 -0400 @@ -266,7 +266,7 @@ std::string dir_name = str.substr (0, xpos); octave_function *xfcn - = load_fcn_from_file (str, dir_name, "", nm); + = load_fcn_from_file (str, dir_name, "", "", nm); if (xfcn) { @@ -296,7 +296,7 @@ std::string dir_name = str.substr (0, xpos); - octave_function *xfcn = load_fcn_from_file (str, dir_name, "", nm); + octave_function *xfcn = load_fcn_from_file (str, dir_name, "", "", nm); if (xfcn) { @@ -319,7 +319,7 @@ std::string dir_name = fpath.substr (0, xpos); - octave_function *xfcn = load_fcn_from_file (fpath, dir_name, "", nm); + octave_function *xfcn = load_fcn_from_file (fpath, dir_name, "", "", nm); if (xfcn) { diff -r 450c03932d6c -r 7368654f302f libinterp/parse-tree/oct-parse.in.yy --- a/libinterp/parse-tree/oct-parse.in.yy Sun May 12 21:47:57 2013 -0400 +++ b/libinterp/parse-tree/oct-parse.in.yy Fri May 17 23:17:25 2013 -0400 @@ -1588,6 +1588,7 @@ curr_fcn_depth = 0; primary_fcn_scope = -1; curr_class_name = ""; + curr_package_name = ""; function_scopes.clear (); primary_fcn_ptr = 0; subfunction_names.clear (); @@ -2972,7 +2973,8 @@ int l = tok_val->line (); int c = tok_val->column (); - retval = new tree_classdef (a, id, sc, body, lc, tc, l, c); + retval = new tree_classdef (a, id, sc, body, lc, tc, curr_package_name, + l, c); } return retval; @@ -3529,6 +3531,7 @@ static octave_function * parse_fcn_file (const std::string& full_file, const std::string& file, const std::string& dispatch_type, + const std::string& package_name, bool require_file, bool force_script, bool autoload, bool relative_lookup, const std::string& warn_for) { @@ -3562,6 +3565,7 @@ octave_parser parser (ffile); parser.curr_class_name = dispatch_type; + parser.curr_package_name = package_name; parser.autoloading = autoload; parser.fcn_file_from_relative_lookup = relative_lookup; @@ -3644,7 +3648,8 @@ symbol_found = true; octave_function *fcn - = parse_fcn_file (full_file, file, "", true, false, false, false, ""); + = parse_fcn_file (full_file, file, "", "", true, false, false, false, + ""); if (fcn) { @@ -3708,6 +3713,7 @@ octave_function * load_fcn_from_file (const std::string& file_name, const std::string& dir_name, const std::string& dispatch_type, + const std::string& package_name, const std::string& fcn_name, bool autoload) { octave_function *retval = 0; @@ -3755,7 +3761,8 @@ // to get the help-string to use. octave_function *tmpfcn = parse_fcn_file (file.substr (0, len - 2), - nm, dispatch_type, false, + nm, dispatch_type, + package_name, false, autoload, autoload, relative_lookup, ""); @@ -3767,8 +3774,8 @@ } else if (len > 2) { - retval = parse_fcn_file (file, nm, dispatch_type, true, autoload, - autoload, relative_lookup, ""); + retval = parse_fcn_file (file, nm, dispatch_type, package_name, true, + autoload, autoload, relative_lookup, ""); } if (retval) @@ -3966,7 +3973,7 @@ if (! error_state) { octave_function *fcn = parse_fcn_file (file_full_name, file_name, - "", require_file, true, + "", "", require_file, true, false, false, warn_for); if (! error_state) diff -r 450c03932d6c -r 7368654f302f libinterp/parse-tree/parse.h --- a/libinterp/parse-tree/parse.h Sun May 12 21:47:57 2013 -0400 +++ b/libinterp/parse-tree/parse.h Fri May 17 23:17:25 2013 -0400 @@ -104,6 +104,7 @@ load_fcn_from_file (const std::string& file_name, const std::string& dir_name = std::string (), const std::string& dispatch_type = std::string (), + const std::string& package_name = std::string (), const std::string& fcn_name = std::string (), bool autoload = false); @@ -148,9 +149,9 @@ autoloading (false), fcn_file_from_relative_lookup (false), parsing_subfunctions (false), max_fcn_depth (0), curr_fcn_depth (0), primary_fcn_scope (-1), - curr_class_name (), function_scopes (), primary_fcn_ptr (0), - subfunction_names (), classdef_object (0), stmt_list (0), - lexer (lxr) + curr_class_name (), curr_package_name (), function_scopes (), + primary_fcn_ptr (0), subfunction_names (), classdef_object (0), + stmt_list (0), lexer (lxr) { init (); } @@ -424,6 +425,10 @@ // constructors. std::string curr_class_name; + // Name of the current package when we are parsing an element contained + // in a package directory (+-directory). + std::string curr_package_name; + // A stack holding the nested function scopes being parsed. // We don't use std::stack, because we want the clear method. Also, we // must access one from the top diff -r 450c03932d6c -r 7368654f302f libinterp/parse-tree/pt-classdef.h --- a/libinterp/parse-tree/pt-classdef.h Sun May 12 21:47:57 2013 -0400 +++ b/libinterp/parse-tree/pt-classdef.h Fri May 17 23:17:25 2013 -0400 @@ -598,9 +598,12 @@ tree_classdef (tree_classdef_attribute_list *a, tree_identifier *i, tree_classdef_superclass_list *sc, tree_classdef_body *b, octave_comment_list *lc, - octave_comment_list *tc, int l = -1, int c = -1) + octave_comment_list *tc, + const std::string& pn = std::string (), int l = -1, + int c = -1) : tree_command (l, c), attr_list (a), id (i), - supclass_list (sc), element_list (b), lead_comm (lc), trail_comm (tc) { } + supclass_list (sc), element_list (b), lead_comm (lc), trail_comm (tc), + pack_name (pn) { } ~tree_classdef (void) { @@ -623,6 +626,8 @@ octave_comment_list *leading_comment (void) { return lead_comm; } octave_comment_list *trailing_comment (void) { return trail_comm; } + const std::string& package_name (void) const { return pack_name; } + octave_function* make_meta_class (void); tree_classdef *dup (symbol_table::scope_id scope, @@ -643,6 +648,8 @@ octave_comment_list *lead_comm; octave_comment_list *trail_comm; + std::string pack_name; + // No copying! tree_classdef (const tree_classdef&);