Mercurial > octave
diff src/symtab.cc @ 7761:5adeea5de26c
symbol table reporting functions
author | John W. Eaton <jwe@octave.org> |
---|---|
date | Tue, 06 May 2008 05:51:17 -0400 |
parents | 40c428ea3408 |
children | 71f068b22fcc |
line wrap: on
line diff
--- a/src/symtab.cc Tue May 06 03:23:12 2008 -0400 +++ b/src/symtab.cc Tue May 06 05:51:17 2008 -0400 @@ -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?