Mercurial > hg > octave-lyh
changeset 7761:5adeea5de26c
symbol table reporting functions
author | John W. Eaton <jwe@octave.org> |
---|---|
date | Tue, 06 May 2008 05:51:17 -0400 |
parents | f5268d7045d7 |
children | 9c24ca8761f7 |
files | src/ChangeLog src/ls-mat5.cc src/ov-base.cc src/ov-base.h src/ov-builtin.h src/ov-fcn-handle.cc src/ov-fcn-handle.h src/ov-fcn.h src/ov-mex-fcn.h src/ov-usr-fcn.cc src/ov-usr-fcn.h src/ov.cc src/ov.h src/parse.y src/pt-id.cc src/symtab.cc src/symtab.h src/variables.cc |
diffstat | 18 files changed, 778 insertions(+), 157 deletions(-) [+] |
line wrap: on
line diff
--- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,5 +1,74 @@ 2008-05-06 John W. Eaton <jwe@octave.org> + * symtab.h (symbol_table::scope_id_cache): New class. Use it to + replace scope_ids_in_use and scope_ids_free_list. + (symbol_table::erase_scope): Call free_scope. + (symbol_table::free_scope): Call scope_id_cache::free. + + * ov-fcn.h (octave_function::lock_subfunctions, + octave_function::unlock_subfunctions): New virtual functions. + (octave_function::lock_subfunctions): Call lock_subfunctions here. + (octave_function::unlock_subfunctions): Call unlock_subfunctions here. + * ov-usr-fcn.h (octave_user_function::lock_subfunctions, + octave_user_function::unlock_subfunctions): New functions. + + * symtab.h (symbol_table::lock_subfunctions, + symbol_table::lock_subfunctions, + symbol_table::fcn_info::lock_subfunction, + symbol_table::fcn_info::unlock_subfunction, + symbol_table::fcn_info::fcn_info_rep::lock_subfunction, + symbol_table::fcn_info::fcn_info_rep::unlock_subfunction): + New functions. + + * symtab.h (symbol_table::set_scope, symbol_table::get_instance): + Don't set instance unless allocation succeeds. + (symbol_table::print_scope, symbol_table::do_print_scope): Delete. + (symbol_table::free_scope): Avoid using invalid iterator. + (symbol_table::erase_scope): Call free_scope here. + + * ov-fcn-handle.cc (octave_fcn_handle::load_ascii, + octave_fcn_handle::load_binary, octave_fcn_handle::load_hdf5): + Cache anonymous name here. + (octave_fcn_handle::octave_fcn_handle): Move here from + ov-fcn-handle.h. Cache name if function is user-defined. + + * pt-id.cc (tree_identifier::dup): Avoid shadow warning. + + * symtab.h (symbol_table::cache_name, symbol_table::do_cache_name): + New functions. + (symbol_table::get_instance): Cache top-level name here. + * parse.y (finish_function): Call symbol_table::cache_name here. + + * symtab.cc (F__dump_symtab_info__): New function. + + * symtab.cc (symbol_table::dump, symbol_table::dump_global, + symbol_table::dump_functions, symbol_table::do_dump, + symbol_table::symbol_record::symbol_record_rep::dump, + symobl_table::fcn_info::fcn_info_rep::dump): New functions. + * symtab.h: Provide decls. + (symtab::scopes, symbol_table::symbol_record::dump, + symbol_table::fcn_info::dump): New functions. + (symtab::get_instance): New arg, create; if false throw error if + instance for given scope is not found. + + * ov-base.cc (octave_base_value::dump): New virtual function. + * ov-base.h: Proivde decl. + * ov.h (octave_value::dump): New function. + + * ov.h, ov.c (octave_value::function_value): New const version. + * ov-base.h, ov-base.cc (octave_base_value::function_value): Likewise. + * ov-builtin.h (octave_builtin::function_value): Likewise. + * ov-fcn-handle.h (octave_fcn_handle::function_value): Likewise. + * ov-mex-fcn.h (octave_mex_function::function_value): Likewise. + * ov-usr-fcn.h (octave_user_script::function_value, + octave_user_function): Likewise. + + * symtab.h, symtab.cc: Use consistent naming scheme for iterator + typedefs. Change all uses. + + * variables.cc (F__print_symtab_info__, F__print_symbol_info__): + Delete. + * ov-cell.cc (Fstruct2cell): Handle structure arrays properly. 2008-05-05 David Bateman <dbateman@free.fr>
--- a/src/ls-mat5.cc +++ b/src/ls-mat5.cc @@ -892,8 +892,9 @@ { octave_fcn_handle *fh = anon_fcn_handle.fcn_handle_value (); + if (fh) - tc = new octave_fcn_handle (fh->fcn_val(), "@<anonymous>"); + tc = new octave_fcn_handle (fh->fcn_val (), "@<anonymous>"); else { error ("load: failed to load anonymous function handle");
--- a/src/ov-base.cc +++ b/src/ov-base.cc @@ -771,6 +771,17 @@ return retval; } +const octave_function * +octave_base_value::function_value (bool silent) const +{ + const octave_function *retval = 0; + + if (! silent) + gripe_wrong_type_arg ("octave_base_value::function_value()", + type_name ()); + return retval; +} + octave_user_function * octave_base_value::user_function_value (bool silent) { @@ -1011,6 +1022,16 @@ gripe_wrong_type_arg ("octave_base_value::unlock ()", type_name ()); } +void +octave_base_value::dump (std::ostream& os) const +{ + dim_vector dv = this->dims (); + + os << "class: " << this->class_name () + << " type: " << this->type_name () + << " dims: " << dv.str (); +} + static void gripe_indexed_assignment (const std::string& tn1, const std::string& tn2) {
--- a/src/ov-base.h +++ b/src/ov-base.h @@ -401,6 +401,8 @@ virtual octave_function *function_value (bool silent = false); + virtual const octave_function *function_value (bool silent = false) const; + virtual octave_user_function *user_function_value (bool silent = false); virtual octave_user_script *user_script_value (bool silent = false); @@ -480,6 +482,8 @@ virtual bool islocked (void) const { return false; } + virtual void dump (std::ostream& os) const; + virtual octave_value abs (void) const; virtual octave_value acos (void) const; virtual octave_value acosh (void) const;
--- a/src/ov-builtin.h +++ b/src/ov-builtin.h @@ -63,6 +63,8 @@ octave_function *function_value (bool = false) { return this; } + const octave_function *function_value (bool = false) const { return this; } + bool is_builtin_function (void) const { return true; } octave_value_list
--- a/src/ov-fcn-handle.cc +++ b/src/ov-fcn-handle.cc @@ -65,6 +65,16 @@ "function handle", "function_handle"); +octave_fcn_handle::octave_fcn_handle (const octave_value& f, + const std::string& n) + : warn_reload (true), fcn (f), nm (n) +{ + octave_user_function *uf = fcn.user_function_value (true); + + if (uf) + symbol_table::cache_name (uf->scope (), nm); +} + octave_value_list octave_fcn_handle::subsref (const std::string& type, const std::list<octave_value_list>& idx, @@ -358,8 +368,16 @@ { octave_fcn_handle *fh = anon_fcn_handle.fcn_handle_value (); + if (fh) - fcn = fh->fcn; + { + fcn = fh->fcn; + + octave_user_function *uf = fcn.user_function_value (true); + + if (uf) + symbol_table::cache_name (uf->scope (), nm); + } else success = false; } @@ -519,8 +537,16 @@ if (parse_status == 0) { octave_fcn_handle *fh = anon_fcn_handle.fcn_handle_value (); + if (fh) - fcn = fh->fcn; + { + fcn = fh->fcn; + + octave_user_function *uf = fcn.user_function_value (true); + + if (uf) + symbol_table::cache_name (uf->scope (), nm); + } else success = false; } @@ -968,8 +994,16 @@ if (parse_status == 0) { octave_fcn_handle *fh = anon_fcn_handle.fcn_handle_value (); + if (fh) - fcn = fh->fcn; + { + fcn = fh->fcn; + + octave_user_function *uf = fcn.user_function_value (true); + + if (uf) + symbol_table::cache_name (uf->scope (), nm); + } else success = false; }
--- a/src/ov-fcn-handle.h +++ b/src/ov-fcn-handle.h @@ -45,8 +45,7 @@ octave_fcn_handle (const std::string& n) : warn_reload (true), fcn (), nm (n) { } - octave_fcn_handle (const octave_value& f, const std::string& n) - : warn_reload (true), fcn (f), nm (n) { } + octave_fcn_handle (const octave_value& f, const std::string& n); octave_fcn_handle (const octave_fcn_handle& fh) : octave_base_value (fh), warn_reload (fh.warn_reload), @@ -77,6 +76,9 @@ octave_function *function_value (bool = false) { return fcn.function_value (); } + const octave_function *function_value (bool = false) const + { return fcn.function_value (); } + octave_user_function *user_function_value (bool = false) { return fcn.user_function_value (); }
--- a/src/ov-fcn.h +++ b/src/ov-fcn.h @@ -88,12 +88,24 @@ void stash_dir_name (const std::string& dir) { my_dir_name = dir; } - void lock (void) { locked = true; } + void lock (void) + { + this->lock_subfunctions (); + locked = true; + } - void unlock (void) { locked = false; } + void unlock (void) + { + this->unlock_subfunctions (); + locked = false; + } bool islocked (void) const { return locked; } + virtual void lock_subfunctions (void) { } + + virtual void unlock_subfunctions (void) { } + void mark_relative (void) { relative = true; } bool is_relative (void) const { return relative; }
--- a/src/ov-mex-fcn.h +++ b/src/ov-mex-fcn.h @@ -63,6 +63,8 @@ octave_function *function_value (bool = false) { return this; } + const octave_function *function_value (bool = false) const { return this; } + void mark_fcn_file_up_to_date (const octave_time& t) { t_checked = t; } std::string fcn_file_name (void) const;
--- a/src/ov-usr-fcn.cc +++ b/src/ov-usr-fcn.cc @@ -272,6 +272,18 @@ return (ret_list && ret_list->takes_varargs ()); } +void +octave_user_function::lock_subfunctions (void) +{ + symbol_table::lock_subfunctions (local_scope); +} + +void +octave_user_function::unlock_subfunctions (void) +{ + symbol_table::unlock_subfunctions (local_scope); +} + octave_value_list octave_user_function::octave_all_va_args (void) {
--- a/src/ov-usr-fcn.h +++ b/src/ov-usr-fcn.h @@ -91,6 +91,8 @@ octave_function *function_value (bool = false) { return this; } + const octave_function *function_value (bool = false) const { return this; } + octave_user_script *user_script_value (bool = false) { return this; } octave_user_code *user_code_value (bool = false) { return this; } @@ -181,6 +183,8 @@ octave_function *function_value (bool = false) { return this; } + const octave_function *function_value (bool = false) const { return this; } + octave_user_function *user_function_value (bool = false) { return this; } octave_user_code *user_code_value (bool = false) { return this; } @@ -225,6 +229,10 @@ bool takes_var_return (void) const; + void lock_subfunctions (void); + + void unlock_subfunctions (void); + octave_value_list octave_all_va_args (void); void stash_function_name (const std::string& s) { my_name = s; }
--- a/src/ov.cc +++ b/src/ov.cc @@ -1145,6 +1145,12 @@ return rep->function_value (silent); } +const octave_function * +octave_value::function_value (bool silent) const +{ + return rep->function_value (silent); +} + octave_user_function * octave_value::user_function_value (bool silent) {
--- a/src/ov.h +++ b/src/ov.h @@ -740,6 +740,8 @@ octave_function *function_value (bool silent = false); + const octave_function *function_value (bool silent = false) const; + octave_user_function *user_function_value (bool silent = false); octave_user_script *user_script_value (bool silent = false); @@ -890,6 +892,8 @@ bool islocked (void) const { return rep->islocked (); } + void dump (std::ostream& os) const { rep->dump (os); } + #define MAPPER_FORWARD(F) \ octave_value F (void) const { return rep->F (); }
--- a/src/parse.y +++ b/src/parse.y @@ -2548,6 +2548,15 @@ if (fcn) { + std::string nm = fcn->name (); + std::string file = fcn->fcn_file_name (); + + std::string tmp = nm; + if (! file.empty ()) + tmp += ": " + file; + + symbol_table::cache_name (fcn->scope (), tmp); + if (lc) fcn->stash_leading_comment (lc); @@ -2555,8 +2564,6 @@ if (lexer_flags.parsing_nested_function) { - std::string nm = fcn->name (); - fcn->mark_as_nested_function (); symbol_table::install_subfunction (nm, octave_value (fcn));
--- a/src/pt-id.cc +++ b/src/pt-id.cc @@ -123,14 +123,14 @@ } tree_identifier * -tree_identifier::dup (symbol_table::scope_id scope) +tree_identifier::dup (symbol_table::scope_id sc) { // The new tree_identifier object contains a symbol_record // entry from the duplicated scope. // FIXME -- is this the best way? symbol_table::symbol_record new_sym - = symbol_table::find_symbol (xsym().name (), scope); + = symbol_table::find_symbol (xsym().name (), sc); tree_identifier *new_id = new tree_identifier (new_sym, line (), column ());
--- a/src/symtab.cc +++ b/src/symtab.cc @@ -45,6 +45,8 @@ symbol_table *symbol_table::instance = 0; +symbol_table::scope_id_cache *symbol_table::scope_id_cache::instance = 0; + std::map<symbol_table::scope_id, symbol_table*> symbol_table::all_instances; std::map<std::string, octave_value> symbol_table::global_table; @@ -61,16 +63,37 @@ std::deque<symbol_table::scope_id> symbol_table::scope_stack; -symbol_table::scope_id symbol_table::next_available_scope = 2; -std::set<symbol_table::scope_id> symbol_table::scope_ids_in_use; -std::set<symbol_table::scope_id> symbol_table::scope_ids_free_list; - symbol_table::context_id symbol_table::xcurrent_context = 0; // Should Octave always check to see if function files have changed // since they were last compiled? static int Vignore_function_time_stamp = 1; +void +symbol_table::symbol_record::symbol_record_rep::dump + (std::ostream& os, const std::string& prefix) const +{ + octave_value val = varval (); + + os << prefix << name; + + if (val.is_defined ()) + { + os << " [" + << (is_local () ? "l" : "") + << (is_automatic () ? "a" : "") + << (is_formal () ? "f" : "") + << (is_hidden () ? "h" : "") + << (is_inherited () ? "i" : "") + << (is_global () ? "g" : "") + << (is_persistent () ? "p" : "") + << "] "; + val.dump (os); + } + + os << "\n"; +} + octave_value symbol_table::symbol_record::find (tree_argument_list *args, const string_vector& arg_names, @@ -309,7 +332,7 @@ { os << "Overloaded function " << name << ":\n\n"; - for (const_dispatch_map_iterator p = dispatch_map.begin (); + for (dispatch_map_const_iterator p = dispatch_map.begin (); p != dispatch_map.end (); p++) os << " " << name << " (" << p->first << ", ...) -> " << p->second << " (" << p->first << ", ...)\n"; @@ -327,7 +350,7 @@ { retval = "Overloaded function:\n\n"; - for (const_dispatch_map_iterator p = dispatch_map.begin (); + for (dispatch_map_const_iterator p = dispatch_map.begin (); p != dispatch_map.end (); p++) retval += " " + p->second + " (" + p->first + ", ...)\n\n"; } @@ -671,6 +694,75 @@ return function_on_path; } +static std::string +fcn_file_name (const octave_value& fcn) +{ + const octave_function *f = fcn.function_value (); + + return f ? f->fcn_file_name () : std::string (); +} + +void +symbol_table::fcn_info::fcn_info_rep::dump + (std::ostream& os, const std::string& prefix) const +{ + os << prefix << name + << " [" + << (cmdline_function.is_defined () ? "c" : "") + << (built_in_function.is_defined () ? "b" : "") + << "]\n"; + + std::string tprefix = prefix + " "; + + if (autoload_function.is_defined ()) + os << tprefix << "autoload: " + << fcn_file_name (autoload_function) << "\n"; + + if (function_on_path.is_defined ()) + os << tprefix << "function from path: " + << fcn_file_name (function_on_path) << "\n"; + + if (! subfunctions.empty ()) + { + for (scope_val_const_iterator p = subfunctions.begin (); + p != subfunctions.end (); p++) + os << tprefix << "subfunction: " << fcn_file_name (p->second) + << " [" << p->first << "]\n"; + } + + if (! private_functions.empty ()) + { + for (str_val_const_iterator p = private_functions.begin (); + p != private_functions.end (); p++) + os << tprefix << "private: " << fcn_file_name (p->second) + << " [" << p->first << "]\n"; + } + + if (! class_constructors.empty ()) + { + for (str_val_const_iterator p = class_constructors.begin (); + p != class_constructors.end (); p++) + os << tprefix << "constructor: " << fcn_file_name (p->second) + << " [" << p->first << "]\n"; + } + + if (! class_methods.empty ()) + { + for (str_val_const_iterator p = class_methods.begin (); + p != class_methods.end (); p++) + os << tprefix << "method: " << fcn_file_name (p->second) + << " [" << p->first << "]\n"; + } + + if (! dispatch_map.empty ()) + { + for (dispatch_map_const_iterator p = dispatch_map.begin (); + p != dispatch_map.end (); p++) + os << tprefix << "dispatch: " << fcn_file_name (p->second) + << " [" << p->first << "]\n"; + } +} + octave_value symbol_table::fcn_info::find (tree_argument_list *args, const string_vector& arg_names, @@ -703,6 +795,76 @@ return find (name, args, arg_names, evaluated_args, args_evaluated, true); } +void +symbol_table::dump (std::ostream& os, scope_id scope) +{ + if (scope == xglobal_scope) + dump_global (os); + else + { + symbol_table *inst = get_instance (scope, false); + + if (inst) + { + os << "*** dumping symbol table scope " << scope + << " (" << inst->table_name << ")\n\n"; + + std::map<std::string, octave_value> sfuns + = symbol_table::subfunctions_defined_in_scope (scope); + + if (! sfuns.empty ()) + { + os << " subfunctions defined in this scope:\n"; + + for (std::map<std::string, octave_value>::const_iterator p = sfuns.begin (); + p != sfuns.end (); p++) + os << " " << p->first << "\n"; + + os << "\n"; + } + + + inst->do_dump (os); + } + } +} + +void +symbol_table::dump_global (std::ostream& os) +{ + if (! global_table.empty ()) + { + os << "*** dumping global symbol table\n\n"; + + for (global_table_const_iterator p = global_table.begin (); + p != global_table.end (); p++) + { + std::string nm = p->first; + octave_value val = p->second; + + os << " " << nm << " "; + val.dump (os); + os << "\n"; + } + } +} + +void +symbol_table::dump_functions (std::ostream& os) +{ + if (! fcn_table.empty ()) + { + os << "*** dumping globally visible functions from symbol table\n" + << " (c=commandline, b=built-in)\n\n"; + + for (fcn_table_const_iterator p = fcn_table.begin (); + p != fcn_table.end (); p++) + p->second.dump (os, " "); + + os << "\n"; + } +} + octave_value symbol_table::do_find (const std::string& name, tree_argument_list *args, const string_vector& arg_names, @@ -719,7 +881,7 @@ if (p != table.end ()) { - symbol_record& sr = p->second; + symbol_record sr = p->second; // FIXME -- should we be using something other than varref here? @@ -760,6 +922,39 @@ return retval; } +void +symbol_table::do_dump (std::ostream& os) +{ + if (! persistent_table.empty ()) + { + os << " persistent variables in this scope:\n\n"; + + for (persistent_table_const_iterator p = persistent_table.begin (); + p != persistent_table.end (); p++) + { + std::string nm = p->first; + octave_value val = p->second; + + os << " " << nm << " "; + val.dump (os); + os << "\n"; + } + + os << "\n"; + } + + if (! table.empty ()) + { + os << " other symbols in this scope (l=local; a=auto; f=formal\n" + << " h=hidden; i=inherited; g=global; p=persistent)\n\n"; + + for (table_const_iterator p = table.begin (); p != table.end (); p++) + p->second.dump (os, " "); + + os << "\n"; + } +} + DEFUN (ignore_function_time_stamp, args, nargout, "-*- texinfo -*-\n\ @deftypefn {Built-in Function} {@var{val} =} ignore_function_time_stamp ()\n\ @@ -823,6 +1018,90 @@ return retval; } +DEFUN (__current_scope__, , , + "-*- texinfo -*-\n\ +@deftypefn {Built-in Function} {[@var{scope}, @var{context}]} __dump_symtab_info__ ()\n\ +Undocumented internal function.\n\ +@end deftypefn") +{ + octave_value_list retval; + + retval(1) = symbol_table::current_context (); + retval(0) = symbol_table::current_scope (); + + return retval; +} + +DEFUN (__dump_symtab_info__, args, , + "-*- texinfo -*-\n\ +@deftypefn {Built-in Function} {} __dump_symtab_info__ ()\n\ +@deftypefnx {Built-in Function} {} __dump_symtab_info__ (@var{scope})\n\ +@deftypefnx {Built-in Function} {} __dump_symtab_info__ (\"scopes\")\n\ +@deftypefnx {Built-in Function} {} __dump_symtab_info__ (\"functions\")\n\ +Undocumented internal function.\n\ +@end deftypefn") +{ + octave_value retval; + + int nargin = args.length (); + + if (nargin == 0) + { + symbol_table::dump_functions (octave_stdout); + + symbol_table::dump_global (octave_stdout); + + std::list<symbol_table::scope_id> lst = symbol_table::scopes (); + + for (std::list<symbol_table::scope_id>::const_iterator p = lst.begin (); + p != lst.end (); p++) + symbol_table::dump (octave_stdout, *p); + } + else if (nargin == 1) + { + octave_value arg = args(0); + + if (arg.is_string ()) + { + std::string s_arg = arg.string_value (); + + if (s_arg == "scopes") + { + std::list<symbol_table::scope_id> lst = symbol_table::scopes (); + + RowVector v (lst.size ()); + + octave_idx_type k = 0; + + for (std::list<symbol_table::scope_id>::const_iterator p = lst.begin (); + p != lst.end (); p++) + v.xelem (k++) = *p; + + retval = v; + } + else if (s_arg == "functions") + { + symbol_table::dump_functions (octave_stdout); + } + else + error ("__dump_symtab_info__: expecting \"functions\" or \"scopes\""); + } + else + { + int s = arg.int_value (); + + if (! error_state) + symbol_table::dump (octave_stdout, s); + else + error ("__dump_symtab_info__: expecting string or scope id"); + } + } + else + print_usage (); + + return retval; +} + #if 0 // FIXME -- should we have functions like this in Octave?
--- a/src/symtab.h +++ b/src/symtab.h @@ -47,6 +47,114 @@ typedef size_t context_id; class + scope_id_cache + { + protected: + + typedef std::set<scope_id>::iterator set_iterator; + typedef std::set<scope_id>::const_iterator set_const_iterator; + + // We start with 2 because we allocate 0 for the global symbols + // and 1 for the top-level workspace. + + scope_id_cache (void) : next_available (2), in_use (), free_list () { } + + public: + + ~scope_id_cache (void) { } + + static scope_id alloc (void) + { + return instance_ok () ? instance->do_alloc () : -1; + } + + static void free (scope_id scope) + { + if (instance_ok ()) + return instance->do_free (scope); + } + + static std::list<scope_id> scopes (void) + { + return instance_ok () ? instance->do_scopes () : std::list<scope_id> (); + } + + static bool instance_ok (void) + { + bool retval = true; + + if (! instance) + instance = new scope_id_cache (); + + if (! instance) + { + ::error ("unable to create scope_id_cache object!"); + + retval = false; + } + + return retval; + } + + private: + + static scope_id_cache *instance; + + // The next available scope not in the free list. + scope_id next_available; + + // The set of scope IDs that are currently allocated. + std::set<scope_id> in_use; + + // The set of scope IDs that are currently available. + std::set<scope_id> free_list; + + scope_id do_alloc (void) + { + scope_id retval; + + set_iterator p = free_list.begin (); + + if (p != free_list.end ()) + { + retval = *p; + free_list.erase (p); + } + else + retval = next_available++; + + in_use.insert (retval); + + return retval; + } + + void do_free (scope_id scope) + { + set_iterator p = in_use.find (scope); + + if (p != in_use.end ()) + { + in_use.erase (p); + free_list.insert (scope); + } + else + error ("free_scope: scope %d not found!", scope); + } + + std::list<scope_id> do_scopes (void) const + { + std::list<scope_id> retval; + + for (set_const_iterator p = in_use.begin (); p != in_use.end (); p++) + retval.push_back (*p); + + retval.sort (); + + return retval; + } + }; + + class symbol_record { public: @@ -235,6 +343,8 @@ return new symbol_record_rep (name, varval (), storage_class); } + void dump (std::ostream& os, const std::string& prefix) const; + std::string name; std::deque<octave_value> value_stack; @@ -333,6 +443,12 @@ unsigned int xstorage_class (void) const { return rep->storage_class; } + void + dump (std::ostream& os, const std::string& prefix = std::string ()) const + { + rep->dump (os, prefix); + } + private: symbol_record_rep *rep; @@ -347,13 +463,13 @@ typedef std::map<std::string, std::string> dispatch_map_type; - typedef std::map<scope_id, octave_value>::const_iterator const_scope_val_iterator; + typedef std::map<scope_id, octave_value>::const_iterator scope_val_const_iterator; typedef std::map<scope_id, octave_value>::iterator scope_val_iterator; - typedef std::map<std::string, octave_value>::const_iterator const_str_val_iterator; + typedef std::map<std::string, octave_value>::const_iterator str_val_const_iterator; typedef std::map<std::string, octave_value>::iterator str_val_iterator; - typedef dispatch_map_type::const_iterator const_dispatch_map_iterator; + typedef dispatch_map_type::const_iterator dispatch_map_const_iterator; typedef dispatch_map_type::iterator dispatch_map_iterator; private: @@ -406,6 +522,32 @@ return find (0, arg_names, evaluated_args, args_evaluated); } + void lock_subfunction (scope_id scope) + { + scope_val_iterator p = subfunctions.find (scope); + + if (p != subfunctions.end ()) + p->second.lock (); + } + + void unlock_subfunction (scope_id scope) + { + scope_val_iterator p = subfunctions.find (scope); + + if (p != subfunctions.end ()) + p->second.unlock (); + } + + std::pair<std::string, octave_value> + subfunction_defined_in_scope (scope_id scope) const + { + scope_val_const_iterator p = subfunctions.find (scope); + + return p == subfunctions.end () + ? std::pair<std::string, octave_value> () + : std::pair<std::string, octave_value> (name, p->second); + } + void install_cmdline_function (const octave_value& f) { cmdline_function = f; @@ -497,6 +639,8 @@ dispatch_map_type get_dispatch (void) const { return dispatch_map; } + void dump (std::ostream& os, const std::string& prefix) const; + std::string name; // Scope id to function object. @@ -599,6 +743,22 @@ return rep->find_function (args); } + void lock_subfunction (scope_id scope) + { + rep->lock_subfunction (scope); + } + + void unlock_subfunction (scope_id scope) + { + rep->unlock_subfunction (scope); + } + + std::pair<std::string, octave_value> + subfunction_defined_in_scope (scope_id scope = xcurrent_scope) const + { + return rep->subfunction_defined_in_scope (scope); + } + void install_cmdline_function (const octave_value& f) { rep->install_cmdline_function (f); @@ -647,6 +807,12 @@ return rep->get_dispatch (); } + void + dump (std::ostream& os, const std::string& prefix = std::string ()) const + { + rep->dump (os, prefix); + } + private: fcn_info_rep *rep; @@ -663,24 +829,7 @@ // We use parent_scope to handle parsing subfunctions. static scope_id parent_scope (void) { return xparent_scope; } - static scope_id alloc_scope (void) - { - scope_id retval; - - scope_ids_free_list_iterator p = scope_ids_free_list.begin (); - - if (p != scope_ids_free_list.end ()) - { - retval = *p; - scope_ids_free_list.erase (p); - } - else - retval = next_available_scope++; - - scope_ids_in_use.insert (retval); - - return retval; - } + static scope_id alloc_scope (void) { return scope_id_cache::alloc (); } static void set_scope (scope_id scope) { @@ -692,9 +841,10 @@ if (p == all_instances.end ()) { - instance = new symbol_table (); - - all_instances[scope] = instance; + symbol_table *inst = new symbol_table (); + + if (inst) + all_instances[scope] = instance = inst; } else instance = p->second; @@ -780,9 +930,13 @@ all_instances_iterator p = all_instances.find (scope); if (p != all_instances.end ()) - all_instances.erase (p); - - // free_scope (scope); + { + delete p->second; + + all_instances.erase (p); + + free_scope (scope); + } } static scope_id dup_scope (scope_id scope) @@ -810,30 +964,10 @@ return retval; } -#if 0 - static void print_scope (const std::string& tag) - { - symbol_table *inst = get_instance (xcurrent_scope); - - if (inst) - inst->do_print_scope (std::cerr); - } - - void do_print_scope (std::ostream& os) const + static std::list<scope_id> scopes (void) { - for (const_table_iterator p = table.begin (); p != table.end (); p++) - { - symbol_record sr = p->second; - - octave_value val = sr.varval (); - - if (val.is_defined ()) - sr.varval ().print_with_name (os, sr.name ()); - else - os << sr.name () << " is not defined" << std::endl; - } + return scope_id_cache::scopes (); } -#endif static symbol_record find_symbol (const std::string& name, scope_id scope = xcurrent_scope) @@ -899,7 +1033,7 @@ static octave_value global_varval (const std::string& name) { - const_global_table_iterator p = global_table.find (name); + global_table_const_iterator p = global_table.find (name); return (p != global_table.end ()) ? p->second : octave_value (); } @@ -946,7 +1080,7 @@ static octave_value find_method (const std::string& name, const std::string& dispatch_type) { - const_fcn_table_iterator p = fcn_table.find (name); + fcn_table_const_iterator p = fcn_table.find (name); if (p != fcn_table.end ()) return p->second.find_method (dispatch_type); @@ -966,7 +1100,7 @@ static octave_value find_built_in_function (const std::string& name) { - const_fcn_table_iterator p = fcn_table.find (name); + fcn_table_const_iterator p = fcn_table.find (name); return (p != fcn_table.end ()) ? p->second.find_built_in_function () : octave_value (); @@ -1383,7 +1517,7 @@ glob_match pat (pattern); - for (const_global_table_iterator p = global_table.begin (); + for (global_table_const_iterator p = global_table.begin (); p != global_table.end (); p++) { // We generate a list of symbol_record objects so that @@ -1435,7 +1569,7 @@ { std::list<std::string> retval; - for (const_global_table_iterator p = global_table.begin (); + for (global_table_const_iterator p = global_table.begin (); p != global_table.end (); p++) retval.push_back (p->first); @@ -1462,7 +1596,7 @@ { std::list<std::string> retval; - for (const_fcn_table_iterator p = fcn_table.begin (); + for (fcn_table_const_iterator p = fcn_table.begin (); p != fcn_table.end (); p++) { octave_value fcn = p->second.find_built_in_function (); @@ -1501,28 +1635,62 @@ } } + static void dump (std::ostream& os, scope_id scope = xcurrent_scope); + + static void dump_global (std::ostream& os); + + static void dump_functions (std::ostream& os); + + static void cache_name (scope_id scope, const std::string& name) + { + symbol_table *inst = get_instance (scope, false); + + if (inst) + inst->do_cache_name (name); + } + + static void lock_subfunctions (scope_id scope = xcurrent_scope) + { + for (fcn_table_iterator p = fcn_table.begin (); + p != fcn_table.end (); p++) + p->second.lock_subfunction (scope); + } + + static void unlock_subfunctions (scope_id scope = xcurrent_scope) + { + for (fcn_table_iterator p = fcn_table.begin (); + p != fcn_table.end (); p++) + p->second.unlock_subfunction (scope); + } + + static void free_scope (scope_id scope) + { + if (scope == xglobal_scope || scope == xtop_scope) + error ("can't free global or top-level scopes!"); + else + symbol_table::scope_id_cache::free (scope); + } + private: - typedef std::map<std::string, symbol_record>::const_iterator const_table_iterator; + typedef std::map<std::string, symbol_record>::const_iterator table_const_iterator; typedef std::map<std::string, symbol_record>::iterator table_iterator; - typedef std::map<std::string, octave_value>::const_iterator const_global_table_iterator; + typedef std::map<std::string, octave_value>::const_iterator global_table_const_iterator; typedef std::map<std::string, octave_value>::iterator global_table_iterator; - typedef std::map<std::string, octave_value>::const_iterator const_persistent_table_iterator; + typedef std::map<std::string, octave_value>::const_iterator persistent_table_const_iterator; typedef std::map<std::string, octave_value>::iterator persistent_table_iterator; typedef std::map<scope_id, symbol_table*>::const_iterator all_instances_const_iterator; typedef std::map<scope_id, symbol_table*>::iterator all_instances_iterator; - typedef std::map<std::string, fcn_info>::const_iterator const_fcn_table_iterator; + typedef std::map<std::string, fcn_info>::const_iterator fcn_table_const_iterator; typedef std::map<std::string, fcn_info>::iterator fcn_table_iterator; - typedef std::set<scope_id>::const_iterator scope_ids_free_list_const_iterator; - typedef std::set<scope_id>::iterator scope_ids_free_list_iterator; - - typedef std::set<scope_id>::const_iterator scope_ids_in_use_const_iterator; - typedef std::set<scope_id>::iterator scope_ids_in_use_iterator; + // Name for this table (usually the file name of the function + // corresponding to the scope); + std::string table_name; // Map from symbol names to symbol info. std::map<std::string, symbol_record> table; @@ -1558,54 +1726,36 @@ static std::deque<scope_id> scope_stack; - // The next available scope ID. - static scope_id next_available_scope; - - // The set of scope IDs that are currently allocated. - static std::set<scope_id> scope_ids_in_use; - - // The set of scope IDs that are currently available. - static std::set<scope_id> scope_ids_free_list; - - symbol_table (void) : table (), xcurrent_context_this_table () { } + symbol_table (void) + : table_name (), table (), xcurrent_context_this_table () { } ~symbol_table (void) { } - static void free_scope (scope_id scope) - { - if (scope == xglobal_scope || scope == xtop_scope) - error ("can't free global or top-level scopes!"); - else - { - scope_ids_in_use_iterator p = scope_ids_in_use.find (scope); - - if (p != scope_ids_in_use.end ()) - { - scope_ids_in_use.erase (p); - scope_ids_free_list.insert (*p); - } - else - error ("scope id = %ld not found!", scope); - } - } - - static symbol_table *get_instance (scope_id scope) + static symbol_table *get_instance (scope_id scope, bool create = true) { symbol_table *retval = 0; + bool ok = true; + if (scope != xglobal_scope) { if (scope == xcurrent_scope) { - if (! instance) + if (! instance && create) { - instance = new symbol_table (); - - all_instances[scope] = instance; + symbol_table *inst = new symbol_table (); + + if (inst) + { + all_instances[scope] = instance = inst; + + if (scope == xtop_scope) + instance->do_cache_name ("top-level"); + } } if (! instance) - error ("unable to create symbol_table object!"); + ok = false; retval = instance; } @@ -1615,15 +1765,27 @@ if (p == all_instances.end ()) { - retval = new symbol_table (); - - all_instances[scope] = retval; + if (create) + { + retval = new symbol_table (); + + if (retval) + all_instances[scope] = retval; + else + ok = false; + } + else + ok = false; } else retval = p->second; } } + if (! ok) + error ("unable to %s symbol_table object for scope %d!", + create ? "create" : "find", scope); + return retval; } @@ -1635,7 +1797,7 @@ void do_dup_scope (symbol_table& new_symbol_table) const { - for (const_table_iterator p = table.begin (); p != table.end (); p++) + for (table_const_iterator p = table.begin (); p != table.end (); p++) new_symbol_table.insert_symbol_record (p->second.dup ()); } @@ -1701,7 +1863,7 @@ octave_value do_varval (const std::string& name) const { - const_table_iterator p = table.find (name); + table_const_iterator p = table.find (name); return (p != table.end ()) ? p->second.varval () : octave_value (); } @@ -1716,7 +1878,7 @@ octave_value do_persistent_varval (const std::string& name) { - const_persistent_table_iterator p = persistent_table.find (name); + persistent_table_const_iterator p = persistent_table.find (name); return (p != persistent_table.end ()) ? p->second : octave_value (); } @@ -1733,7 +1895,7 @@ { bool retval = false; - const_table_iterator p = table.find (name); + table_const_iterator p = table.find (name); if (p != table.end ()) { @@ -1859,7 +2021,7 @@ { std::list<symbol_record> retval; - for (const_table_iterator p = table.begin (); p != table.end (); p++) + for (table_const_iterator p = table.begin (); p != table.end (); p++) { const symbol_record& sr = p->second; @@ -1879,7 +2041,7 @@ glob_match pat (pattern); - for (const_table_iterator p = table.begin (); p != table.end (); p++) + for (table_const_iterator p = table.begin (); p != table.end (); p++) { if (pat.match (p->first)) { @@ -1899,7 +2061,7 @@ { std::list<std::string> retval; - for (const_table_iterator p = table.begin (); p != table.end (); p++) + for (table_const_iterator p = table.begin (); p != table.end (); p++) retval.push_back (p->first); retval.sort (); @@ -1907,9 +2069,29 @@ return retval; } + static std::map<std::string, octave_value> + subfunctions_defined_in_scope (scope_id scope = xcurrent_scope) + { + std::map<std::string, octave_value> retval; + + for (fcn_table_const_iterator p = fcn_table.begin (); + p != fcn_table.end (); p++) + { + std::pair<std::string, octave_value> tmp + = p->second.subfunction_defined_in_scope (scope); + + std::string nm = tmp.first; + + if (! nm.empty ()) + retval[nm] = tmp.second; + } + + return retval; + } + bool do_is_local_variable (const std::string& name) const { - const_table_iterator p = table.find (name); + table_const_iterator p = table.find (name); return (p != table.end () && ! p->second.is_global () @@ -1918,10 +2100,14 @@ bool do_is_global (const std::string& name) const { - const_table_iterator p = table.find (name); + table_const_iterator p = table.find (name); return p != table.end () && p->second.is_global (); } + + void do_dump (std::ostream& os); + + void do_cache_name (const std::string& name) { table_name = name; } }; extern bool out_of_date_check (octave_value& function);
--- a/src/variables.cc +++ b/src/variables.cc @@ -2375,34 +2375,6 @@ return retval; } -DEFUN (__print_symtab_info__, args, , - "-*- texinfo -*-\n\ -@deftypefn {Built-in Function} {} __print_symtab_info__ ()\n\ -Undocumented internal function.\n\ -@end deftypefn") -{ - octave_value_list retval; - - // FIXME -- what should this function do now? Print a summary for - // each scope? Print the entire symbol table? Accept a scope - // argument? - - return retval; -} - -DEFUN (__print_symbol_info__, args, , - "-*- texinfo -*-\n\ -@deftypefn {Built-in Function} {} __dump_symbol_info__ (@var{name})\n\ -Undocumented internal function.\n\ -@end deftypefn") -{ - octave_value_list retval; - - // FIXME -- what should this function do now? - - return retval; -} - DEFUN (whos_line_format, args, nargout, "-*- texinfo -*-\n\ @deftypefn {Built-in Function} {@var{val} =} whos_line_format ()\n\