Mercurial > octave
diff libinterp/corefcn/symscope.h @ 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.h@3b302b2890d7 |
children | dd810f9d26e7 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libinterp/corefcn/symscope.h Thu Nov 16 19:39:00 2017 -0500 @@ -0,0 +1,587 @@ +/* + +Copyright (C) 1993-2017 John W. Eaton +Copyright (C) 2009 VZLU Prague + +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 (octave_symscope_h) +#define octave_symscope_h 1 + +#include "octave-config.h" + +#include <deque> +#include <limits> +#include <list> +#include <map> +#include <set> +#include <string> + +#include "glob-match.h" +#include "lo-regexp.h" +#include "oct-refcount.h" + +class tree_argument_list; +class octave_user_function; + +#include "ov.h" +#include "ovl.h" +#include "symrec.h" +#include "workspace-element.h" + +namespace octave +{ + class symbol_scope + { + public: + + typedef symbol_record::context_id context_id; + + 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 + m_persistent_symbols_const_iterator; + typedef std::map<std::string, octave_value>::iterator + m_persistent_symbols_iterator; + + typedef std::map<std::string, octave_value>::const_iterator + subfunctions_const_iterator; + typedef std::map<std::string, octave_value>::iterator + subfunctions_iterator; + + symbol_scope (const std::string& name = "") + : m_name (name), m_symbols (), m_persistent_symbols (), m_subfunctions (), + m_fcn (nullptr), m_parent (nullptr), m_parent_fcn (), m_children (), m_is_nested (false), + m_is_static (false), m_context (0) + { } + + // No copying! + + symbol_scope (const symbol_scope&) = delete; + + symbol_scope& operator = (const symbol_scope&) = delete; + + ~symbol_scope (void) = default; + + void insert_symbol_record (const symbol_record& sr) + { + m_symbols[sr.name ()] = sr; + } + + bool is_nested (void) const { return m_is_nested; } + + void mark_nested (void) { m_is_nested = true; } + + bool is_static (void) const { return m_is_static; } + + void mark_static (void) { m_is_static = true; } + + symbol_scope * parent_scope (void) const { return m_parent; } + octave_value parent_fcn (void) const { return m_parent_fcn; } + + symbol_scope * dup (void) const + { + symbol_scope *new_sid = new symbol_scope (); + + for (const auto& nm_sr : m_symbols) + new_sid->insert_symbol_record (nm_sr.second.dup (new_sid)); + + new_sid->m_parent = m_parent; + new_sid->m_parent_fcn = m_parent_fcn; + + return new_sid; + } + + void set_context (context_id context) { m_context = context; } + + context_id current_context (void) const { return m_context; } + + symbol_record find_symbol (const std::string& name) + { + table_iterator p = m_symbols.find (name); + + if (p == m_symbols.end ()) + return insert (name); + else + return p->second; + } + + void inherit_internal (symbol_scope& donor_scope) + { + for (auto& nm_sr : m_symbols) + { + symbol_record& sr = nm_sr.second; + + if (! (sr.is_automatic () || sr.is_formal ())) + { + std::string nm = sr.name (); + + if (nm != "__retval__") + { + octave_value val = donor_scope.varval (nm); + + if (val.is_defined ()) + { + sr.assign (val); + + sr.mark_inherited (); + } + } + } + } + } + + void inherit (symbol_scope *donor_scope) + { + while (donor_scope) + { + inherit_internal (*donor_scope); + + if (donor_scope->is_nested ()) + donor_scope = donor_scope->parent_scope (); + else + break; + } + } + + + octave_value + find (const std::string& name, const octave_value_list& args, + bool skip_variables, bool local_funcs); + + symbol_record& + insert (const std::string& name, bool force_add = false); + + void rename (const std::string& old_name, const std::string& new_name) + { + table_iterator p = m_symbols.find (old_name); + + if (p != m_symbols.end ()) + { + symbol_record sr = p->second; + + sr.rename (new_name); + + m_symbols.erase (p); + + m_symbols[new_name] = sr; + } + } + + void assign (const std::string& name, const octave_value& value, + bool force_add) + { + table_iterator p = m_symbols.find (name); + + if (p == m_symbols.end ()) + { + symbol_record& sr = insert (name, force_add); + + sr.assign (value); + } + else + p->second.assign (value); + } + + void assign (const std::string& name, + const octave_value& value = octave_value ()) + { + assign (name, value, false); + } + + void force_assign (const std::string& name, const octave_value& value) + { + table_iterator p = m_symbols.find (name); + + if (p == m_symbols.end ()) + { + symbol_record& sr = insert (name, true); + + sr.assign (value); + } + else + p->second.assign (value); + } + + // Use assign (name, value, force_add) instead. + // Delete when deprecated varref functions are removed. + octave_value& varref (const std::string& name, bool force_add) + { + table_iterator p = m_symbols.find (name); + + if (p == m_symbols.end ()) + { + symbol_record& sr = insert (name, force_add); + + return sr.varref (); + } + else + return p->second.varref (); + } + + octave_value varval (const std::string& name) const + { + table_const_iterator p = m_symbols.find (name); + + return (p != m_symbols.end () + ? p->second.varval () : octave_value ()); + } + + void persistent_assign (const std::string& name, const octave_value& value) + { + m_persistent_symbols_iterator p = m_persistent_symbols.find (name); + + if (p == m_persistent_symbols.end ()) + m_persistent_symbols[name] = value; + else + p->second = value; + } + + // Use persistent_assign (name, value) instead. + // Delete when deprecated varref functions are removed. + octave_value& persistent_varref (const std::string& name) + { + m_persistent_symbols_iterator p = m_persistent_symbols.find (name); + + return (p == m_persistent_symbols.end () + ? m_persistent_symbols[name] : p->second); + } + + octave_value persistent_varval (const std::string& name) const + { + m_persistent_symbols_const_iterator p = m_persistent_symbols.find (name); + + return (p != m_persistent_symbols.end ()) ? p->second : octave_value (); + } + + void erase_persistent (const std::string& name) + { + m_persistent_symbols_iterator p = m_persistent_symbols.find (name); + + if (p != m_persistent_symbols.end ()) + m_persistent_symbols.erase (p); + } + + bool is_variable (const std::string& name) const + { + bool retval = false; + + table_const_iterator p = m_symbols.find (name); + + if (p != m_symbols.end ()) + { + const symbol_record& sr = p->second; + + retval = sr.is_variable (); + } + + return retval; + } + + void push_context (void) + { + for (auto& nm_sr : m_symbols) + nm_sr.second.push_context (this); + } + + void pop_context (void) + { + table_iterator tbl_it = m_symbols.begin (); + + while (tbl_it != m_symbols.end ()) + { + if (tbl_it->second.pop_context (this) == 0) + m_symbols.erase (tbl_it++); + else + tbl_it++; + } + } + + void clear_variables (void) + { + for (auto& nm_sr : m_symbols) + nm_sr.second.clear (this); + } + + void clear_objects (void) + { + for (auto& nm_sr : m_symbols) + { + symbol_record& sr = nm_sr.second; + octave_value val = sr.varval (); + if (val.isobject ()) + nm_sr.second.clear (this); + } + } + + void clear_global (const std::string& name); + + void clear_variable (const std::string& name) + { + table_iterator p = m_symbols.find (name); + + if (p != m_symbols.end ()) + p->second.clear (this); + } + + void clear_global_pattern (const std::string& pat); + + void clear_variable_pattern (const std::string& pat) + { + glob_match pattern (pat); + + for (auto& nm_sr : m_symbols) + { + symbol_record& sr = nm_sr.second; + + if (sr.is_defined () || sr.is_global ()) + { + if (pattern.match (sr.name ())) + sr.clear (this); + } + } + } + + void clear_variable_regexp (const std::string& pat) + { + octave::regexp pattern (pat); + + for (auto& nm_sr : m_symbols) + { + symbol_record& sr = nm_sr.second; + + if (sr.is_defined () || sr.is_global ()) + { + if (pattern.is_match (sr.name ())) + sr.clear (this); + } + } + } + + void mark_automatic (const std::string& name) + { + insert (name).mark_automatic (); + } + + void mark_hidden (const std::string& name) + { + insert (name).mark_hidden (); + } + + void mark_global (const std::string& name) + { + insert (name).mark_global (); + } + + std::list<symbol_record> + all_variables (bool defined_only = true, + unsigned int exclude = symbol_record::hidden) const + { + std::list<symbol_record> retval; + + for (const auto& nm_sr : m_symbols) + { + const symbol_record& sr = nm_sr.second; + + if ((defined_only && ! sr.is_defined ()) + || (sr.xstorage_class () & exclude)) + continue; + + retval.push_back (sr); + } + + return retval; + } + + std::list<symbol_record> + glob (const std::string& pattern, bool vars_only = false) const + { + std::list<symbol_record> retval; + + glob_match pat (pattern); + + for (const auto& nm_sr : m_symbols) + { + if (pat.match (nm_sr.first)) + { + const symbol_record& sr = nm_sr.second; + + if (vars_only && ! sr.is_variable ()) + continue; + + retval.push_back (sr); + } + } + + return retval; + } + + std::list<symbol_record> + regexp (const std::string& pattern, bool vars_only = false) const + { + std::list<symbol_record> retval; + + octave::regexp pat (pattern); + + for (const auto& nm_sr : m_symbols) + { + if (pat.is_match (nm_sr.first)) + { + const symbol_record& sr = nm_sr.second; + + if (vars_only && ! sr.is_variable ()) + continue; + + retval.push_back (sr); + } + } + + return retval; + } + + std::list<std::string> variable_names (void) + { + std::list<std::string> retval; + + for (const auto& nm_sr : m_symbols) + { + if (nm_sr.second.is_variable ()) + retval.push_back (nm_sr.first); + } + + retval.sort (); + + return retval; + } + + bool is_local_variable (const std::string& name) const + { + table_const_iterator p = m_symbols.find (name); + + return (p != m_symbols.end () + && ! p->second.is_global () + && p->second.is_defined ()); + } + + bool is_global (const std::string& name) const + { + table_const_iterator p = m_symbols.find (name); + + return p != m_symbols.end () && p->second.is_global (); + } + + void install_subfunction (const std::string& name, + const octave_value& fval, + bool is_nested = false); + + void install_nestfunction (const std::string& name, + const octave_value& fval) + { + install_subfunction (name, fval, true); + } + + octave_value find_subfunction (const std::string& name) const; + + void lock_subfunctions (void) + { + for (auto& nm_sf : m_subfunctions) + nm_sf.second.lock (); + } + + void unlock_subfunctions (void) + { + for (auto& nm_sf : m_subfunctions) + nm_sf.second.unlock (); + } + + std::map<std::string, octave_value> subfunctions (void) + { + return m_subfunctions; + } + + void erase_subfunctions (void) + { + m_subfunctions.clear (); + } + + void mark_subfunctions_in_scope_as_private (const std::string& class_name); + + std::list<workspace_element> workspace_info (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; } + + octave_user_function *function (void) { return m_fcn; } + + void set_function (octave_user_function *fcn) { m_fcn = fcn; } + + void set_parent (symbol_scope *p); + + void update_nest (void); + + bool look_nonlocal (const std::string& name, symbol_record& result); + + void bind_script_symbols (symbol_scope *curr_scope); + + void unbind_script_symbols (void); + + private: + + // Name for this scope (usually the corresponding filename of the + // function corresponding to the scope). + std::string m_name; + + // Map from symbol names to symbol info. + std::map<std::string, symbol_record> m_symbols; + + // Map from names of persistent variables to values. + std::map<std::string, octave_value> m_persistent_symbols; + + // Map from symbol names to subfunctions. + std::map<std::string, octave_value> m_subfunctions; + + // The associated user code (may be null). + octave_user_function *m_fcn; + + // Parent of nested function (may be null). + symbol_scope *m_parent; + octave_value m_parent_fcn; + + // Child nested functions. + std::vector<symbol_scope*> m_children; + + // If true, then this scope belongs to a nested function. + bool m_is_nested; + + // If true then no variables can be added. + bool m_is_static; + + context_id m_context; + + octave_value dump_symbols_map (void) const; + }; +} + +#endif