# HG changeset patch # User John W. Eaton # Date 1585965606 14400 # Node ID 71c34141cc2d9924855e84426fe53f3eab804bc7 # Parent 0ffae065ca03cd27a60339cc9409c0ec3c643495 refactor handling of parent functions and localfunctions * help.cc (Flocalfunctions): Simply call symbol_scope::localfunctions for the current user function. * symscope.h, symscope.cc (symbol_scope_rep::m_fcn_name, symbol_scope_rep::m_parent_fcn_names, symbol_scope_rep::m_is_primary_fcn_scope): New data members. (symbol_scope_rep::localfunctions, symbol_scope_rep::fcn_name, symbol_scope_rep::cache_fcn_name, symbol_scope_rep::parent_fcn_names, symbol_scope_rep::cache_parent_fcn_names, symbol_scope_rep::mark_primary_fcn_scope, symbol_scope_rep::is_primary_fcn_scope, symbol_scope::localfunctions, symbol_scope::fcn_name, symbol_scope::cache_fcn_name, symbol_scope::parent_fcn_names, symbol_scope::cache_parent_fcn_names, symbol_scope::mark_primary_fcn_scope, symbol_scope::is_primary_fcn_scope): New functions. (symbol_scope_rep): Also cache parent function names. * oct-parse.yy (base_parser::push_fcn_symtab): Mark primary_fcn_scope as primary. (base_parser::finish_function): If parsing subfunction, set primary parent scope in subfunction scope. Cache parent function names in current scope. * ov-fcn.h (octave_function::parent_fcn_names): New virtual function. * ov-usr-fcn.h (octave_user_function::parent_fcn_names): New function. diff -r 0ffae065ca03 -r 71c34141cc2d libinterp/corefcn/help.cc --- a/libinterp/corefcn/help.cc Fri Apr 03 21:59:15 2020 -0400 +++ b/libinterp/corefcn/help.cc Fri Apr 03 22:00:06 2020 -0400 @@ -814,30 +814,14 @@ // Find the main function we are in. octave::tree_evaluator& tw = interp.get_evaluator (); - octave_user_code *parent_fcn = tw.debug_user_code (); + octave_user_code *caller = tw.debug_user_code (); - if (! parent_fcn) + if (! caller) return ovl (retval); - // Find the subfunctions of this function. - // 1) subfunction_names contains only valid subfunctions - // 2) subfunctions contains both nested functions and subfunctions - const std::list names = parent_fcn->subfunction_names (); - const std::map h = parent_fcn->subfunctions (); - - size_t sz = names.size (); - retval.resize (dim_vector (sz, 1)); + octave::symbol_scope scope = caller->scope (); - // loop over them. - size_t i = 0; - for (const auto& nm : names) - { - std::map::const_iterator nm_fcn = h.find (nm); - if (nm_fcn != h.end ()) - retval(i++) = octave_value (new octave_fcn_handle (nm_fcn->second, nm)); - } - - return ovl (retval); + return ovl (Cell (scope.localfunctions ())); } /* diff -r 0ffae065ca03 -r 71c34141cc2d libinterp/corefcn/symscope.cc --- a/libinterp/corefcn/symscope.cc Fri Apr 03 21:59:15 2020 -0400 +++ b/libinterp/corefcn/symscope.cc Fri Apr 03 22:00:06 2020 -0400 @@ -92,6 +92,43 @@ return p->second; } + std::list symbol_scope_rep::localfunctions (void) const + { + std::list retval; + + // Find the subfunctions of this function (which should be the + // primary parent function for this scope). + + // 1) m_subfunction_names contains only valid subfunctions + // 2) m_subfunctions contains both nested functions and subfunctions + + // loop over them. + + for (const auto& nm : m_subfunction_names) + { + auto nm_fcn_iter = m_subfunctions.find (nm); + + if (nm_fcn_iter != m_subfunctions.end ()) + { + octave_value ov_fcn = nm_fcn_iter->second; + octave_user_code *fcn = ov_fcn.user_code_value (); + + if (! fcn) + continue; + + octave::symbol_scope scope = fcn->scope (); + + std::list plst = scope.parent_fcn_names (); + + octave_fcn_handle *fh = new octave_fcn_handle (ov_fcn, nm, plst); + + retval.push_back (octave_value (fh)); + } + } + + return retval; + } + octave_value symbol_scope_rep::dump (void) const { @@ -243,8 +280,14 @@ m_is_static = true; } + std::list plst = parent_fcn_names (); + plst.push_front (m_fcn_name); + for (auto& scope_obj : m_children) - scope_obj.update_nest (); + { + scope_obj.cache_parent_fcn_names (plst); + scope_obj.update_nest (); + } } bool symbol_scope_rep::look_nonlocal (const std::string& name, @@ -280,4 +323,21 @@ return false; } + + std::list symbol_scope::localfunctions (void) const + { + if (! m_rep) + return std::list (); + + if (is_primary_fcn_scope ()) + return m_rep->localfunctions (); + + std::shared_ptr ppsr + = m_rep->primary_parent_scope_rep (); + + if (! ppsr) + return std::list (); + + return ppsr->localfunctions (); + } } diff -r 0ffae065ca03 -r 71c34141cc2d libinterp/corefcn/symscope.h --- a/libinterp/corefcn/symscope.h Fri Apr 03 21:59:15 2020 -0400 +++ b/libinterp/corefcn/symscope.h Fri Apr 03 22:00:06 2020 -0400 @@ -66,10 +66,11 @@ subfunctions_iterator; symbol_scope_rep (const std::string& name = "") - : m_name (name), m_symbols (), m_subfunctions (), - m_persistent_values (), m_code (nullptr), m_fcn_file_name (), - m_dir_name (), m_parent (), m_primary_parent (), m_children (), - m_nesting_depth (0), m_is_static (false) + : m_name (name), m_symbols (), m_subfunctions (), m_persistent_values (), + m_code (nullptr), m_fcn_name (), m_parent_fcn_names (), + m_fcn_file_name (), m_dir_name (), m_parent (), m_primary_parent (), + m_children (), m_nesting_depth (0), m_is_static (false), + m_is_primary_fcn_scope (false) { // All scopes have ans as the first symbol, initially undefined. @@ -126,6 +127,8 @@ new_sid->m_persistent_values = m_persistent_values; new_sid->m_subfunction_names = m_subfunction_names; new_sid->m_code = m_code; + new_sid->m_fcn_name = m_fcn_name; + new_sid->m_parent_fcn_names = m_parent_fcn_names; new_sid->m_fcn_file_name = m_fcn_file_name; new_sid->m_dir_name = m_dir_name; new_sid->m_parent = m_parent; @@ -133,6 +136,7 @@ new_sid->m_children = m_children; new_sid->m_nesting_depth = m_nesting_depth; new_sid->m_is_static = m_is_static; + new_sid->m_is_primary_fcn_scope = m_is_primary_fcn_scope; return new_sid; } @@ -213,6 +217,7 @@ nm_sf.second.unlock (); } + // Pairs of name, function objects. std::map subfunctions (void) const { return m_subfunctions; @@ -240,12 +245,28 @@ return m_subfunction_names; } + std::list localfunctions (void) const; + octave_value dump (void) const; std::string name (void) const { return m_name; } void cache_name (const std::string& name) { m_name = name; } + std::string fcn_name (void) const { return m_fcn_name; } + + void cache_fcn_name (const std::string& name) { m_fcn_name = name; } + + std::list parent_fcn_names (void) const + { + return m_parent_fcn_names; + } + + void cache_parent_fcn_names (const std::list& names) + { + m_parent_fcn_names = names; + } + octave_user_code *user_code (void) const { return m_code; } void set_user_code (octave_user_code *code) { m_code = code; } @@ -259,11 +280,15 @@ m_fcn_file_name = name; } + std::string fcn_file_name (void) const { return m_fcn_file_name; } + void cache_dir_name (const std::string& name); - std::string fcn_file_name (void) const { return m_fcn_file_name; } + std::string dir_name (void) const { return m_dir_name; } - std::string dir_name (void) const { return m_dir_name; } + void mark_primary_fcn_scope (void) { m_is_primary_fcn_scope = true; } + + bool is_primary_fcn_scope (void) const { return m_is_primary_fcn_scope; } bool is_relative (const std::shared_ptr& scope) const; @@ -313,6 +338,14 @@ octave_user_code *m_code; + //! Simple name of the function corresponding to this scope. + + std::string m_fcn_name; + + //! List Simple names of the parent functions corresponding to this scope. + + std::list m_parent_fcn_names; + //! The file name associated with m_code. std::string m_fcn_file_name; @@ -341,6 +374,9 @@ //! If true then no variables can be added. bool m_is_static; + + //! If true, this is the scope of a primary function. + bool m_is_primary_fcn_scope; }; class symbol_scope @@ -532,6 +568,9 @@ return m_rep ? m_rep->subfunction_names () : std::list (); } + // List of function handle objects. + std::list localfunctions (void) const; + octave_value dump (void) const { return m_rep ? m_rep->dump () : octave_value (); @@ -548,6 +587,28 @@ m_rep->cache_name (name); } + std::string fcn_name (void) const + { + return m_rep ? m_rep->fcn_name () : ""; + } + + void cache_fcn_name (const std::string& name) + { + if (m_rep) + m_rep->cache_fcn_name (name); + } + + std::list parent_fcn_names (void) const + { + return m_rep ? m_rep->parent_fcn_names () : std::list (); + } + + void cache_parent_fcn_names (const std::list& names) + { + if (m_rep) + m_rep->cache_parent_fcn_names (names); + } + octave_user_code * user_code (void) const { return m_rep ? m_rep->user_code () : nullptr; @@ -593,6 +654,17 @@ return m_rep ? m_rep->dir_name () : ""; } + void mark_primary_fcn_scope (void) + { + if (m_rep) + m_rep->mark_primary_fcn_scope (); + } + + bool is_primary_fcn_scope (void) const + { + return m_rep ? m_rep->is_primary_fcn_scope () : false; + } + bool is_relative (const symbol_scope& scope) const { return m_rep ? m_rep->is_relative (scope.get_rep ()) : false; diff -r 0ffae065ca03 -r 71c34141cc2d libinterp/octave-value/ov-class.cc --- a/libinterp/octave-value/ov-class.cc Fri Apr 03 21:59:15 2020 -0400 +++ b/libinterp/octave-value/ov-class.cc Fri Apr 03 22:00:06 2020 -0400 @@ -2141,7 +2141,6 @@ Internal function. Implements final construction for inline objects. -@seealso{inline} @end deftypefn */) { // Input validation has already been done in input.m. diff -r 0ffae065ca03 -r 71c34141cc2d libinterp/octave-value/ov-fcn-handle.cc --- a/libinterp/octave-value/ov-fcn-handle.cc Fri Apr 03 21:59:15 2020 -0400 +++ b/libinterp/octave-value/ov-fcn-handle.cc Fri Apr 03 22:00:06 2020 -0400 @@ -2016,7 +2016,7 @@ Previous versions of Octave accepted an optional second argument, @qcode{"global"}, that caused str2func to ignore locally visible functions. This option is no longer supported. -@seealso{func2str, inline, functions} +@seealso{func2str, functions} @end deftypefn */) { int nargin = args.length (); diff -r 0ffae065ca03 -r 71c34141cc2d libinterp/octave-value/ov-fcn.h --- a/libinterp/octave-value/ov-fcn.h Fri Apr 03 21:59:15 2020 -0400 +++ b/libinterp/octave-value/ov-fcn.h Fri Apr 03 22:00:06 2020 -0400 @@ -87,6 +87,11 @@ virtual octave::symbol_scope parent_fcn_scope (void) const { return octave::symbol_scope (); } + virtual std::list parent_fcn_names (void) const + { + return std::list (); + } + virtual void mark_fcn_file_up_to_date (const octave::sys::time&) { } virtual octave::symbol_scope scope (void) { return octave::symbol_scope (); } diff -r 0ffae065ca03 -r 71c34141cc2d libinterp/octave-value/ov-usr-fcn.h --- a/libinterp/octave-value/ov-usr-fcn.h Fri Apr 03 21:59:15 2020 -0400 +++ b/libinterp/octave-value/ov-usr-fcn.h Fri Apr 03 22:00:06 2020 -0400 @@ -273,6 +273,11 @@ return m_scope.parent_scope (); } + std::list parent_fcn_names (void) const + { + return m_scope.parent_fcn_names (); + } + void mark_as_system_fcn_file (void); bool is_system_fcn_file (void) const { return system_fcn_file; } diff -r 0ffae065ca03 -r 71c34141cc2d libinterp/parse-tree/oct-parse.yy --- a/libinterp/parse-tree/oct-parse.yy Fri Apr 03 21:59:15 2020 -0400 +++ b/libinterp/parse-tree/oct-parse.yy Fri Apr 03 22:00:06 2020 -0400 @@ -2489,7 +2489,10 @@ if (! m_lexer.m_reading_script_file && m_curr_fcn_depth == 0 && ! m_parsing_subfunctions) - m_primary_fcn_scope = m_lexer.m_symtab_context.curr_scope (); + { + m_primary_fcn_scope = m_lexer.m_symtab_context.curr_scope (); + m_primary_fcn_scope.mark_primary_fcn_scope (); + } if (m_lexer.m_reading_script_file && m_curr_fcn_depth > 0) { @@ -3681,15 +3684,16 @@ if (fcn) { - std::string nm = fcn->name (); + std::string fcn_nm = fcn->name (); std::string file = fcn->fcn_file_name (); - std::string tmp = nm; + std::string tmp = fcn_nm; if (! file.empty ()) tmp += ": " + file; symbol_scope fcn_scope = fcn->scope (); fcn_scope.cache_name (tmp); + fcn_scope.cache_fcn_name (fcn_nm); fcn_scope.cache_fcn_file_name (file); fcn_scope.cache_dir_name (m_lexer.m_dir_name); @@ -3713,14 +3717,27 @@ symbol_scope pscope = m_function_scopes.parent_scope (); fcn_scope.set_parent (pscope); fcn_scope.set_primary_parent (m_primary_fcn_scope); - pscope.install_nestfunction (nm, ov_fcn, fcn_scope); + pscope.install_nestfunction (fcn_nm, ov_fcn, fcn_scope); + + // For nested functions, the list of parent functions is + // set in symbol_scope::update_nest. } else { fcn->mark_as_subfunction (); - m_subfunction_names.push_back (nm); + m_subfunction_names.push_back (fcn_nm); fcn_scope.set_parent (m_primary_fcn_scope); - m_primary_fcn_scope.install_subfunction (nm, ov_fcn); + if (m_parsing_subfunctions) + fcn_scope.set_primary_parent (m_primary_fcn_scope); + m_primary_fcn_scope.install_subfunction (fcn_nm, ov_fcn); + + // Prepend name of primary fucntion to list of parent + // functions (if any) for subfunction. + + std::list plst + = fcn_scope.parent_fcn_names (); + plst.push_front (m_primary_fcn_scope.fcn_name ()); + fcn_scope.cache_parent_fcn_names (plst); } }