Mercurial > octave
view libinterp/corefcn/scope.cc @ 24263:3b302b2890d7
disentangle symbol_record, scope, and fcn_info from symbol_table class
* fcn-info.cc, fcn-info.h, scope.cc, scope.h, symrec.cc, symrec.h:
New files extracted from symtab.h and symtab.cc.
* libinterp/corefcn/module.mk: Update.
* symrec.cc (symbol_record::symbol_record_rep::xglobal_varref):
Don't access private symbol_table internals directly.
* scope.h, scope.cc (scope::find, scope::builtin_find,
scope::clear_global, scope::clear_global_pattern):
Don't access private symbol_table internals directly.
* symtab.h, symtab.cc (symbol_table::builtin_find): Don't forward to
current scope. Look directly in fcn_info table.
(symbol_table::global_varref, symbol_table::fcn_table_find,
symbol_table::erase_global, symbol_table::erase_global_pattern):
New functions.
* scope.h (scope::context_id): New typedef.
* symrec.h (symbol_record::context_id): New typedef.
* symtab.h (symbol_table::context_id): Update.
* symtab.h, symtab.cc (symbol_table::dummy_octave_value):
Delete static data member.
* symtab.h (symbol_table::context_id): Delete typedef.
(symbol_table::symbol_record, symbol_table::scope,
symbol_table::fcn_info): New typedefs.
author | John W. Eaton <jwe@octave.org> |
---|---|
date | Thu, 16 Nov 2017 16:06:31 -0500 |
parents | |
children |
line wrap: on
line source
/* 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 "scope.h" #include "symrec.h" #include "symtab.h" #include "utils.h" namespace octave { octave_value scope::find (const std::string& name, const octave_value_list& args, bool skip_variables, bool local_funcs) { // Variable. symbol_table& symtab = __get_symbol_table__ ("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& 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 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__ ("scope::clear_global"); symtab.erase_global (name); } void 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__ ("scope::clear_global_pattern"); symtab.erase_global_pattern (pattern); } std::list<workspace_element> 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 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 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 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 (); 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 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 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 scope::set_parent (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 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 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 scope::bind_script_symbols (scope *curr_scope) { for (auto& nm_sr : m_symbols) nm_sr.second.bind_fwd_rep (curr_scope->find_symbol (nm_sr.first)); } void scope::unbind_script_symbols (void) { for (auto& nm_sr : m_symbols) nm_sr.second.unbind_fwd_rep (); } }