Mercurial > octave
diff libinterp/corefcn/symscope.cc @ 24269:f494b87d2a93
rename scope to symbol_scope
* symscope.h, symscope.cc: Rename from scope.h and scope.cc.
(class symbol_scope): Rename from scope. Change all uses.
author | John W. Eaton <jwe@octave.org> |
---|---|
date | Thu, 16 Nov 2017 19:39:00 -0500 |
parents | libinterp/corefcn/scope.cc@3b302b2890d7 |
children | bc65aa8a5ff1 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libinterp/corefcn/symscope.cc Thu Nov 16 19:39:00 2017 -0500 @@ -0,0 +1,368 @@ +/* + +Copyright (C) 1993-2017 John W. Eaton +Copyright (C) 2009 VZLU Prague, a.s. + +This file is part of Octave. + +Octave is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 3 of the License, or +(at your option) any later version. + +Octave is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Octave; see the file COPYING. If not, see +<http://www.gnu.org/licenses/>. + +*/ + +#if defined (HAVE_CONFIG_H) +# include "config.h" +#endif + +#include <sstream> + +#include "fcn-info.h" +#include "interpreter-private.h" +#include "interpreter.h" +#include "ov-fcn.h" +#include "ov-usr-fcn.h" +#include "symrec.h" +#include "symscope.h" +#include "symtab.h" +#include "utils.h" + +namespace octave +{ + octave_value + symbol_scope::find (const std::string& name, const octave_value_list& args, + bool skip_variables, bool local_funcs) + { + // Variable. + + symbol_table& symtab + = __get_symbol_table__ ("symbol_scope::find"); + + if (! skip_variables) + { + table_iterator p = m_symbols.find (name); + + if (p != m_symbols.end ()) + { + symbol_record sr = p->second; + + if (sr.is_global ()) + return symtab.global_varval (name); + else + { + octave_value val = sr.varval (); + + if (val.is_defined ()) + return val; + } + } + } + + if (local_funcs) + { + // Subfunction. I think it only makes sense to check for + // subfunctions if we are currently executing a function defined + // from a .m file. + + octave_value fcn = find_subfunction (name); + + if (fcn.is_defined ()) + return fcn; + } + + return symtab.fcn_table_find (name, args, local_funcs); + } + + symbol_record& + symbol_scope::insert (const std::string& name, bool force_add) + { + table_iterator p = m_symbols.find (name); + + if (p == m_symbols.end ()) + { + symbol_record ret (this, name); + + if (m_is_nested && m_parent && m_parent->look_nonlocal (name, ret)) + return m_symbols[name] = ret; + else + { + if (m_is_static && ! force_add) + ret.mark_added_static (); + + return m_symbols[name] = ret; + } + } + else + return p->second; + } + + void + symbol_scope::clear_global (const std::string& name) + { + table_iterator p = m_symbols.find (name); + + if (p != m_symbols.end ()) + { + symbol_record& sr = p->second; + + if (sr.is_global ()) + sr.unmark_global (); + } + + symbol_table& symtab + = __get_symbol_table__ ("symbol_scope::clear_global"); + + symtab.erase_global (name); + } + + void + symbol_scope::clear_global_pattern (const std::string& pat) + { + glob_match pattern (pat); + + for (auto& nm_sr : m_symbols) + { + symbol_record& sr = nm_sr.second; + + if (sr.is_global () && pattern.match (sr.name ())) + sr.unmark_global (); + } + + symbol_table& symtab + = __get_symbol_table__ ("symbol_scope::clear_global_pattern"); + + symtab.erase_global_pattern (pattern); + } + + std::list<workspace_element> + symbol_scope::workspace_info (void) const + { + std::list<workspace_element> retval; + + for (const auto& nm_sr : m_symbols) + { + std::string nm = nm_sr.first; + symbol_record sr = nm_sr.second; + + if (! sr.is_hidden ()) + { + octave_value val = sr.varval (); + + if (val.is_defined ()) + { + // FIXME: fix size for objects, see kluge in variables.cc + //dim_vector dv = val.dims (); + octave_value tmp = val; + Matrix sz = tmp.size (); + dim_vector dv = dim_vector::alloc (sz.numel ()); + for (octave_idx_type i = 0; i < dv.ndims (); i++) + dv(i) = sz(i); + + char storage = ' '; + if (sr.is_global ()) + storage = 'g'; + else if (sr.is_persistent ()) + storage = 'p'; + else if (sr.is_automatic ()) + storage = 'a'; + else if (sr.is_formal ()) + storage = 'f'; + else if (sr.is_hidden ()) + storage = 'h'; + else if (sr.is_inherited ()) + storage = 'i'; + + std::ostringstream buf; + val.short_disp (buf); + std::string short_disp_str = buf.str (); + + workspace_element elt (storage, nm, val.class_name (), + short_disp_str, dv.str (), + val.iscomplex ()); + + retval.push_back (elt); + } + } + } + + return retval; + } + + octave_value + symbol_scope::dump (void) const + { + std::map<std::string, octave_value> m + = {{ "name", m_name }, + { "symbols", dump_symbols_map () }, + { "persistent_variables", m_persistent_symbols }, + { "subfunctions", dump_function_map (m_subfunctions) }}; + + return octave_value (m); + } + + octave_value + symbol_scope::dump_symbols_map (void) const + { + std::map<std::string, octave_value> info_map; + + for (const auto& nm_sr : m_symbols) + { + std::string nm = nm_sr.first; + const symbol_record& sr = nm_sr.second; + info_map[nm] = sr.dump (); + } + + return octave_value (info_map); + } + + void + symbol_scope::install_subfunction (const std::string& name, + const octave_value& fval, bool is_nested) + { + m_subfunctions[name] = fval; + + // This can be simpler once the scope object is stored in the function + // object... + octave_user_function *fcn = fval.user_function_value (); + + symbol_scope *fcn_scope = fcn->scope (); + + fcn_scope->set_parent (this); + + if (is_nested) + { + m_children.push_back (fcn_scope); + + fcn->mark_as_nested_function (); + + fcn_scope->m_is_nested = true; + } + + } + + octave_value + symbol_scope::find_subfunction (const std::string& name) const + { + subfunctions_const_iterator p = m_subfunctions.find (name); + + if (p != m_subfunctions.end ()) + return p->second; + + if (m_parent) + return m_parent->find_subfunction (name); + + return octave_value (); + } + + void + symbol_scope::mark_subfunctions_in_scope_as_private (const std::string& class_name) + { + for (auto& nm_sf : m_subfunctions) + { + octave_function *fcn = nm_sf.second.function_value (); + + if (fcn) + fcn->mark_as_private_function (class_name); + } + } + + void + symbol_scope::set_parent (symbol_scope *p) + { + m_parent = p; + + if (m_parent) + { + // If m_parent is the top-level scope, there will be no parent + // function. + + octave_function *current_fcn = function (); + + if (current_fcn && current_fcn->is_anonymous_function ()) + { + octave_function *parent_fcn = m_parent->function (); + + if (parent_fcn) + m_parent_fcn = octave_value (parent_fcn, true); + } + } + } + + void + symbol_scope::update_nest (void) + { + if (m_parent) + { + // fix bad symbol_records + for (auto& nm_sr : m_symbols) + { + symbol_record& ours = nm_sr.second; + + if (! ours.is_formal () + && m_is_nested && m_parent->look_nonlocal (nm_sr.first, ours)) + { + if (ours.is_global () || ours.is_persistent ()) + error ("global and persistent may only be used in the topmost level in which a nested variable is used"); + } + else + ours.set_curr_fcn (m_fcn); + } + + // The scopes of nested functions are static. + m_is_static = true; + } + else if (m_children.size ()) + { + // Parents of nested functions have static scopes. + m_is_static = true; + + for (auto& nm_sr : m_symbols) + nm_sr.second.set_curr_fcn (m_fcn); + } + + for (auto& symtab_p : m_children) + symtab_p->update_nest (); + } + + bool + symbol_scope::look_nonlocal (const std::string& name, symbol_record& result) + { + table_iterator p = m_symbols.find (name); + if (p == m_symbols.end ()) + { + if (m_is_nested && m_parent) + return m_parent->look_nonlocal (name, result); + } + else if (! p->second.is_automatic ()) + { + result.bind_fwd_rep (p->second); + return true; + } + + return false; + } + + void + symbol_scope::bind_script_symbols (symbol_scope *curr_scope) + { + for (auto& nm_sr : m_symbols) + nm_sr.second.bind_fwd_rep (curr_scope->find_symbol (nm_sr.first)); + } + + void + symbol_scope::unbind_script_symbols (void) + { + for (auto& nm_sr : m_symbols) + nm_sr.second.unbind_fwd_rep (); + } +}