Mercurial > octave
diff libinterp/corefcn/symrec.h @ 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 | f494b87d2a93 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libinterp/corefcn/symrec.h Thu Nov 16 16:06:31 2017 -0500 @@ -0,0 +1,783 @@ +/* + +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_symrec_h) +#define octave_symrec_h 1 + +#include "octave-config.h" + +#include <deque> +#include <list> +#include <string> + +#include "oct-refcount.h" + +class octave_user_function; + +#include "ov.h" +#include "ovl.h" + +namespace octave +{ + class fcn_info; + class scope; + + class symbol_record + { + public: + + typedef size_t context_id; + + // generic variable + static const unsigned int local = 1; + + // varargin, argn, .nargin., .nargout. + // (FIXME: is this really used now?) + static const unsigned int automatic = 2; + + // formal parameter + static const unsigned int formal = 4; + + // not listed or cleared (.nargin., .nargout.) + static const unsigned int hidden = 8; + + // inherited from parent scope; not cleared at function exit + static const unsigned int inherited = 16; + + // global (redirects to global scope) + static const unsigned int global = 32; + + // not cleared at function exit + static const unsigned int persistent = 64; + + // this symbol may NOT become a variable. + // (symbol added to a static workspace) + static const unsigned int added_static = 128; + + private: + + class symbol_record_rep + { + public: + + symbol_record_rep (scope *s, const std::string& nm, + const octave_value& v, unsigned int sc) + : m_decl_scope (s), curr_fcn (nullptr), name (nm), + m_fwd_rep (nullptr), value_stack (), + storage_class (sc), /* finfo (), */ valid (true), count (1) + { + value_stack.push_back (v); + } + + // No copying! + + symbol_record_rep (const symbol_record_rep& ov) = delete; + + symbol_record_rep& operator = (const symbol_record_rep&) = delete; + + ~symbol_record_rep (void) = default; + + void assign (const octave_value& value) + { + if (m_fwd_rep) + { + m_fwd_rep->assign (value); + return; + } + + varref () = value; + } + + void assign (octave_value::assign_op op, + const std::string& type, + const std::list<octave_value_list>& idx, + const octave_value& value) + { + if (m_fwd_rep) + { + m_fwd_rep->assign (op, type, idx, value); + return; + } + + varref().assign (op, type, idx, value); + } + + void assign (octave_value::assign_op op, const octave_value& value) + { + if (m_fwd_rep) + { + m_fwd_rep->assign (op, value); + return; + } + + varref().assign (op, value); + } + + void do_non_const_unary_op (octave_value::unary_op op) + { + if (m_fwd_rep) + { + m_fwd_rep->do_non_const_unary_op (op); + return; + } + + varref().do_non_const_unary_op (op); + } + + void do_non_const_unary_op (octave_value::unary_op op, + const std::string& type, + const std::list<octave_value_list>& idx) + { + if (m_fwd_rep) + { + m_fwd_rep->do_non_const_unary_op (op, type, idx); + return; + } + + varref().do_non_const_unary_op (op, type, idx); + } + + context_id get_decl_scope_context (void) const; + + octave_value& varref (void) + { + if (m_fwd_rep) + return m_fwd_rep->varref (); + + context_id context = m_decl_scope ? get_decl_scope_context () : 0; + + if (is_global ()) + return xglobal_varref (); + else if (is_persistent ()) + return xpersistent_varref (); + else + { + context_id n = value_stack.size (); + while (n++ <= context) + value_stack.push_back (octave_value ()); + + return value_stack[context]; + } + } + + octave_value varval (void) const + { + if (m_fwd_rep) + return m_fwd_rep->varval (); + + context_id context = m_decl_scope ? get_decl_scope_context () : 0; + + if (is_global ()) + return xglobal_varval (); + else if (is_persistent ()) + return xpersistent_varval (); + else + { + if (context < value_stack.size ()) + return value_stack[context]; + else + return octave_value (); + } + } + + void push_context (scope *sid) + { + if (m_fwd_rep) + { + m_fwd_rep->push_context (sid); + return; + } + + if (! (is_persistent () || is_global ()) + && sid == decl_scope ()) + value_stack.push_back (octave_value ()); + } + + // If pop_context returns 0, we are out of values and this element + // of the symbol table should be deleted. This can happen for + // functions like + // + // function foo (n) + // if (n > 0) + // foo (n-1); + // else + // eval ("x = 1"); + // endif + // endfunction + // + // Here, X should only exist in the final stack frame. + + size_t pop_context (scope *sid) + { + if (m_fwd_rep) + return m_fwd_rep->pop_context (sid); + + size_t retval = 1; + + if (! (is_persistent () || is_global ()) + && sid == decl_scope ()) + { + value_stack.pop_back (); + retval = value_stack.size (); + } + + return retval; + } + + void clear (void) + { + if (m_fwd_rep) + { + m_fwd_rep->clear (); + return; + } + + clear (decl_scope ()); + } + + void clear (scope *sid); + + bool is_defined (void) const + { + if (m_fwd_rep) + return m_fwd_rep->is_defined (); + + return varval ().is_defined (); + } + + bool is_valid (void) const + { + if (m_fwd_rep) + return m_fwd_rep->is_valid (); + + return valid; + } + + bool is_variable (void) const + { + if (m_fwd_rep) + return m_fwd_rep->is_variable (); + + return (! is_local () || is_defined ()); + } + + bool is_local (void) const + { + if (m_fwd_rep) + return m_fwd_rep->is_local (); + + return storage_class & local; + } + + bool is_automatic (void) const + { + if (m_fwd_rep) + return m_fwd_rep->is_automatic (); + + return storage_class & automatic; + } + + bool is_formal (void) const + { + if (m_fwd_rep) + return m_fwd_rep->is_formal (); + + return storage_class & formal; + } + + bool is_hidden (void) const + { + if (m_fwd_rep) + return m_fwd_rep->is_hidden (); + + return storage_class & hidden; + } + + bool is_inherited (void) const + { + if (m_fwd_rep) + return m_fwd_rep->is_inherited (); + + return storage_class & inherited; + } + + bool is_global (void) const + { + if (m_fwd_rep) + return m_fwd_rep->is_global (); + + return storage_class & global; + } + + bool is_persistent (void) const + { + if (m_fwd_rep) + return m_fwd_rep->is_persistent (); + + return storage_class & persistent; + } + + bool is_added_static (void) const + { + if (m_fwd_rep) + return m_fwd_rep->is_added_static (); + + return storage_class & added_static; + } + + void mark_local (void) + { + if (m_fwd_rep) + { + m_fwd_rep->mark_local (); + return; + } + + storage_class |= local; + } + + void mark_automatic (void) + { + if (m_fwd_rep) + { + m_fwd_rep->mark_automatic (); + return; + } + + storage_class |= automatic; + } + + void mark_formal (void) + { + if (m_fwd_rep) + { + m_fwd_rep->mark_formal (); + return; + } + + storage_class |= formal; + } + + void mark_hidden (void) + { + if (m_fwd_rep) + { + m_fwd_rep->mark_hidden (); + return; + } + + storage_class |= hidden; + } + + void mark_inherited (void) + { + if (m_fwd_rep) + { + m_fwd_rep->mark_inherited (); + return; + } + + storage_class |= inherited; + } + + void mark_global (void) + { + if (m_fwd_rep) + { + m_fwd_rep->mark_global (); + return; + } + + if (is_persistent ()) + error ("can't make persistent variable %s global", name.c_str ()); + + storage_class |= global; + } + + void mark_persistent (void) + { + if (m_fwd_rep) + { + m_fwd_rep->mark_persistent (); + return; + } + + if (is_global ()) + error ("can't make global variable %s persistent", name.c_str ()); + + storage_class |= persistent; + } + + void mark_added_static (void) + { + if (m_fwd_rep) + { + m_fwd_rep->mark_added_static (); + return; + } + + storage_class |= added_static; + } + + void unmark_local (void) + { + if (m_fwd_rep) + { + m_fwd_rep->unmark_local (); + return; + } + + storage_class &= ~local; + } + + void unmark_automatic (void) + { + if (m_fwd_rep) + { + m_fwd_rep->unmark_automatic (); + return; + } + + storage_class &= ~automatic; + } + + void unmark_formal (void) + { + if (m_fwd_rep) + { + m_fwd_rep->unmark_formal (); + return; + } + + storage_class &= ~formal; + } + + void unmark_hidden (void) + { + if (m_fwd_rep) + { + m_fwd_rep->unmark_hidden (); + return; + } + + storage_class &= ~hidden; + } + + void unmark_inherited (void) + { + if (m_fwd_rep) + { + m_fwd_rep->unmark_inherited (); + return; + } + + storage_class &= ~inherited; + } + + void unmark_global (void) + { + if (m_fwd_rep) + { + m_fwd_rep->unmark_global (); + return; + } + + storage_class &= ~global; + } + + void unmark_persistent (void) + { + if (m_fwd_rep) + { + m_fwd_rep->unmark_persistent (); + return; + } + + storage_class &= ~persistent; + } + + void unmark_added_static (void) + { + if (m_fwd_rep) + { + m_fwd_rep->unmark_added_static (); + return; + } + + storage_class &= ~added_static; + } + + void init_persistent (void); + + void invalidate (void) + { + if (m_fwd_rep) + { + m_fwd_rep->invalidate (); + return; + } + + valid = false; + } + + void erase_persistent (void); + + scope *decl_scope (void) + { + if (m_fwd_rep) + return m_fwd_rep->decl_scope (); + + return m_decl_scope; + } + + void set_curr_fcn (octave_user_function *fcn) + { + if (m_fwd_rep) + { + m_fwd_rep->set_curr_fcn (fcn); + return; + } + + curr_fcn = fcn; + } + + // We don't forward more than once, so no need to forward the + // next two. + + void bind_fwd_rep (symbol_record_rep *fwd_rep) { m_fwd_rep = fwd_rep; } + + void unbind_fwd_rep (void) { m_fwd_rep = nullptr; } + + symbol_record_rep * dup (scope *new_scope) const; + + octave_value dump (void) const; + + scope *m_decl_scope; + + octave_user_function *curr_fcn; + + std::string name; + + symbol_record_rep *m_fwd_rep; + + std::deque<octave_value> value_stack; + + unsigned int storage_class; + + // fcn_info *finfo; + + bool valid; + + refcount<size_t> count; + + private: + + octave_value& xglobal_varref (void); + + octave_value& xpersistent_varref (void); + + octave_value xglobal_varval (void) const; + + octave_value xpersistent_varval (void) const; + }; + + public: + + symbol_record (void); + + symbol_record (scope *s, const std::string& nm = "", + const octave_value& v = octave_value (), + unsigned int sc = local) + : rep (new symbol_record_rep (s, nm, v, sc)) { } + + symbol_record (const symbol_record& sr) + : rep (sr.rep) + { + rep->count++; + } + + symbol_record& operator = (const symbol_record& sr) + { + if (this != &sr) + { + if (--rep->count == 0) + delete rep; + + rep = sr.rep; + rep->count++; + } + + return *this; + } + + ~symbol_record (void) + { + if (--rep->count == 0) + delete rep; + } + + symbol_record dup (scope *sid) const + { + return symbol_record (rep->dup (sid)); + } + + const std::string& name (void) const { return rep->name; } + + void rename (const std::string& new_name) { rep->name = new_name; } + + octave_value + find (const octave_value_list& args = octave_value_list ()) const; + + void assign (const octave_value& value) + { + rep->assign (value); + } + + void assign (octave_value::assign_op op, + const std::string& type, + const std::list<octave_value_list>& idx, + const octave_value& value) + { + rep->assign (op, type, idx, value); + } + + void assign (octave_value::assign_op op, const octave_value& value) + { + rep->assign (op, value); + } + + void do_non_const_unary_op (octave_value::unary_op op) + { + rep->do_non_const_unary_op (op); + } + + void do_non_const_unary_op (octave_value::unary_op op, + const std::string& type, + const std::list<octave_value_list>& idx) + { + rep->do_non_const_unary_op (op, type, idx); + } + + // Delete when deprecated varref functions are removed. + octave_value& varref (void) + { + return rep->varref (); + } + + octave_value varval (void) const + { + return rep->varval (); + } + + void push_context (scope *sid) { rep->push_context (sid); } + + size_t pop_context (scope *sid) { return rep->pop_context (sid); } + + void clear (void) { rep->clear (); } + + void clear (scope *sid) { rep->clear (sid); } + + bool is_defined (void) const + { + return rep->is_defined (); + } + + bool is_undefined (void) const + { + return ! rep->is_defined (); + } + + bool is_valid (void) const + { + return rep->is_valid (); + } + + bool is_variable (void) const + { + return rep->is_variable (); + } + + bool is_local (void) const { return rep->is_local (); } + bool is_automatic (void) const { return rep->is_automatic (); } + bool is_formal (void) const { return rep->is_formal (); } + bool is_global (void) const { return rep->is_global (); } + bool is_hidden (void) const { return rep->is_hidden (); } + bool is_inherited (void) const { return rep->is_inherited (); } + bool is_persistent (void) const { return rep->is_persistent (); } + bool is_added_static (void) const { return rep->is_added_static (); } + + void mark_local (void) { rep->mark_local (); } + void mark_automatic (void) { rep->mark_automatic (); } + void mark_formal (void) { rep->mark_formal (); } + void mark_hidden (void) { rep->mark_hidden (); } + void mark_inherited (void) { rep->mark_inherited (); } + void mark_global (void) { rep->mark_global (); } + void mark_persistent (void) { rep->mark_persistent (); } + void mark_added_static (void) { rep->mark_added_static (); } + + void unmark_local (void) { rep->unmark_local (); } + void unmark_automatic (void) { rep->unmark_automatic (); } + void unmark_formal (void) { rep->unmark_formal (); } + void unmark_hidden (void) { rep->unmark_hidden (); } + void unmark_inherited (void) { rep->unmark_inherited (); } + void unmark_global (void) { rep->unmark_global (); } + void unmark_persistent (void) { rep->unmark_persistent (); } + void unmark_added_static (void) { rep->unmark_added_static (); } + + void init_persistent (void) { rep->init_persistent (); } + + void erase_persistent (void) { rep->erase_persistent (); } + + void invalidate (void) { rep->invalidate (); } + + scope *decl_scope (void) { return rep->decl_scope (); } + + unsigned int xstorage_class (void) const { return rep->storage_class; } + + void set_curr_fcn (octave_user_function *fcn) + { + rep->set_curr_fcn (fcn); + } + + void bind_fwd_rep (const symbol_record& sr) + { + rep->bind_fwd_rep (sr.rep); + } + + void unbind_fwd_rep (void) { rep->unbind_fwd_rep (); } + + octave_value dump (void) const { return rep->dump (); } + + const symbol_record_rep *xrep (void) const { return rep; } + + private: + + static octave_value dummy_octave_value; + + symbol_record_rep *rep; + + symbol_record (symbol_record_rep *new_rep) : rep (new_rep) { } + }; +} + +#endif