Mercurial > jwe > octave
changeset 24037:21915520ac7b
use more direct method for non-local symbol access (bug #38236)
* pt-id.h, pd-id.cc (tree_evaluator::get_current_scope): New function.
* symtab.h, symtab.cc (symbol_table::symbol_reference): Delete class.
(symbol_table::dummy_symbol_record): Delete static data member.
* oct-lvalue.h, oct-lvalue.cc (octave_lvalue::sym): Use symbol_record,
not symbol_reference. Change all uses.
(octave_lvalue::black_hole): New data member.
(octave_lvalue:is_black_hole): Use it.
(octave_lvalue::mark_black_hole): New function.
* pt-eval.cc (tree_identifier::sym): Use symbol_record, not
symbol_reference. Change all uses.
(tree_black_hole::lvalue): Explicitly mark retval as black_hole.
(tree_evaluator::visit_tree_identifier): Adapt to
tree_identifier::symbol returning symbol_record, not symbol_reference.
* oct-parse.in.yy (push_script_symtab, begin_file): New non-terminals.
(file): Use begin_file to start script and classdef files.
Use separate symbol table scope when parsing scripts.
* ov-usr-fcn.h, ov-usr-fcn.cc (octave_user_code::m_scope): Move here
from octave_user_fcn.
(octave_user_code::scope): Likewise.
(octave_user_script::octave_user_script): New argument scope.
(octave_user_script::call): Add
symbol_table::scope::unbind_script_symbols to unwind_protect frame.
Call scope::bind_script_symbols to access evaluation scope.
(octave_user_function::octave_user_function): Pass scope argument to
octave_user_code base class.
* symtab.h, symtab.cc (symbol_record_rep::m_fwd_rep): New data
member. Change member functions to forward to secondary rep if it is
defined.
(symbol_record::bind_fwd_rep, symbol_record_rep::bind_fwd_rep,
symbol_record::unbind_fwd_rep, symbol_record_rep::unbind_fwd_rep):
New functions.
(scope::bind_script_symbols, scope::unbind_script_symbols): New functions.
(scope::varval, scope::global_varval, scope::top_level_varval):
Now const.
(scope::update_nest): Set forwarding rep for nonlocal symbol.
(scope::look_nonlocal): Likewise.
author | John W. Eaton <jwe@octave.org> |
---|---|
date | Wed, 13 Sep 2017 17:10:51 -0400 |
parents | 2932a325930c |
children | bb5c1e767039 |
files | libinterp/corefcn/oct-lvalue.cc libinterp/corefcn/oct-lvalue.h libinterp/corefcn/symtab.cc libinterp/corefcn/symtab.h libinterp/octave-value/ov-usr-fcn.cc libinterp/octave-value/ov-usr-fcn.h libinterp/parse-tree/oct-parse.in.yy libinterp/parse-tree/pt-eval.cc libinterp/parse-tree/pt-eval.h libinterp/parse-tree/pt-id.cc libinterp/parse-tree/pt-id.h |
diffstat | 11 files changed, 499 insertions(+), 191 deletions(-) [+] |
line wrap: on
line diff
--- a/libinterp/corefcn/oct-lvalue.cc Wed Sep 13 16:42:14 2017 -0700 +++ b/libinterp/corefcn/oct-lvalue.cc Wed Sep 13 17:10:51 2017 -0400 @@ -35,9 +35,9 @@ if (! is_black_hole ()) { if (idx.empty ()) - sym->assign (op, rhs); + sym.assign (op, rhs); else - sym->assign (op, type, idx, rhs); + sym.assign (op, type, idx, rhs); } } @@ -73,9 +73,9 @@ if (! is_black_hole ()) { if (idx.empty ()) - sym->do_non_const_unary_op (op); + sym.do_non_const_unary_op (op); else - sym->do_non_const_unary_op (op, type, idx); + sym.do_non_const_unary_op (op, type, idx); } } @@ -86,7 +86,7 @@ if (! is_black_hole ()) { - octave_value val = sym->varval (); + octave_value val = sym.varval (); if (idx.empty ()) retval = val;
--- a/libinterp/corefcn/oct-lvalue.h Wed Sep 13 16:42:14 2017 -0700 +++ b/libinterp/corefcn/oct-lvalue.h Wed Sep 13 17:10:51 2017 -0400 @@ -38,13 +38,13 @@ { public: - octave_lvalue (const octave::symbol_table::symbol_reference& s - = octave::symbol_table::symbol_reference ()) - : sym (s), type (), idx (), nel (1) + octave_lvalue (const octave::symbol_table::symbol_record& s + = octave::symbol_table::symbol_record ()) + : sym (s), black_hole (false), type (), idx (), nel (1) { } octave_lvalue (const octave_lvalue& vr) - : sym (vr.sym), type (vr.type), idx (vr.idx), nel (vr.nel) + : sym (vr.sym), black_hole (vr.black_hole), type (vr.type), idx (vr.idx), nel (vr.nel) { } octave_lvalue& operator = (const octave_lvalue& vr) @@ -52,6 +52,7 @@ if (this != &vr) { sym = vr.sym; + black_hole = vr.black_hole; type = vr.type; idx = vr.idx; nel = vr.nel; @@ -62,21 +63,23 @@ ~octave_lvalue (void) = default; - bool is_black_hole (void) const { return sym.is_black_hole (); } + bool is_black_hole (void) const { return black_hole; } + + void mark_black_hole (void) { black_hole = true; } bool is_defined (void) const { - return ! is_black_hole () && sym->is_defined (); + return ! is_black_hole () && sym.is_defined (); } bool is_undefined (void) const { - return is_black_hole () || sym->is_undefined (); + return is_black_hole () || sym.is_undefined (); } bool isstruct (void) const { return value().isstruct (); } - void define (const octave_value& v) { sym->assign (v); } + void define (const octave_value& v) { sym.assign (v); } void assign (octave_value::assign_op, const octave_value&); @@ -98,7 +101,9 @@ private: - octave::symbol_table::symbol_reference sym; + octave::symbol_table::symbol_record sym; + + bool black_hole; std::string type;
--- a/libinterp/corefcn/symtab.cc Wed Sep 13 16:42:14 2017 -0700 +++ b/libinterp/corefcn/symtab.cc Wed Sep 13 17:10:51 2017 -0400 @@ -60,6 +60,12 @@ void symbol_table::symbol_record::symbol_record_rep::clear (scope *sid) { + if (m_fwd_rep) + { + m_fwd_rep->clear (sid); + return; + } + if (! (is_hidden () || is_inherited ()) && sid == decl_scope ()) { @@ -80,6 +86,12 @@ void symbol_table::symbol_record::symbol_record_rep::init_persistent (void) { + if (m_fwd_rep) + { + m_fwd_rep->init_persistent (); + return; + } + symbol_table::scope *scope = __require_current_scope__ ("symbol_table::symbol_record::symbol_record_rep::init_persistent"); @@ -97,6 +109,12 @@ void symbol_table::symbol_record::symbol_record_rep::erase_persistent (void) { + if (m_fwd_rep) + { + m_fwd_rep->erase_persistent (); + return; + } + unmark_persistent (); symbol_table::scope *scope @@ -108,12 +126,19 @@ symbol_table::symbol_record::symbol_record_rep * symbol_table::symbol_record::symbol_record_rep::dup (scope *new_scope) const { + // FIXME: is this the right thing do to? + if (m_fwd_rep) + return m_fwd_rep->dup (new_scope); + return new symbol_record_rep (new_scope, name, varval (), storage_class); } octave_value symbol_table::symbol_record::symbol_record_rep::dump (void) const { + if (m_fwd_rep) + return m_fwd_rep->dump (); + std::map<std::string, octave_value> m = {{ "name", name }, { "local", is_local () }, @@ -135,6 +160,9 @@ octave_value& symbol_table::symbol_record::symbol_record_rep::xglobal_varref (void) { + if (m_fwd_rep) + return m_fwd_rep->xglobal_varref (); + symbol_table& symtab = __get_symbol_table__ ("symbol_table::symbol_record::symbol_record_rep::xglobal_varref"); @@ -148,6 +176,9 @@ octave_value& symbol_table::symbol_record::symbol_record_rep::xpersistent_varref (void) { + if (m_fwd_rep) + return m_fwd_rep->xpersistent_varref (); + symbol_table::scope *scope = __get_current_scope__ ("symbol_table::symbol_record::symbol_record_rep::xpersistent_varref"); @@ -157,6 +188,9 @@ octave_value symbol_table::symbol_record::symbol_record_rep::xglobal_varval (void) const { + if (m_fwd_rep) + return m_fwd_rep->xglobal_varval (); + symbol_table& symtab = __get_symbol_table__ ("symbol_table::symbol_record::symbol_record_rep::xglobal_varval"); @@ -166,6 +200,9 @@ octave_value symbol_table::symbol_record::symbol_record_rep::xpersistent_varval (void) const { + if (m_fwd_rep) + return m_fwd_rep->xpersistent_varval (); + symbol_table::scope *scope = __get_current_scope__ ("symbol_table::symbol_record::symbol_record_rep::xpersistent_varval"); @@ -216,30 +253,6 @@ return retval; } - - symbol_table::symbol_record - symbol_table::dummy_symbol_record (static_cast<symbol_table::scope*> (nullptr)); - - symbol_table::symbol_reference::symbol_reference (const symbol_record& record) - : m_scope (nullptr), m_context (0), m_sym (record) - { - m_scope = __get_current_scope__ ("symbol_reference"); - } - - void - symbol_table::symbol_reference::update (void) const - { - symbol_table::scope *curr_scope - = __get_current_scope__ ("symbol_reference::update"); - - if (curr_scope && (m_scope != curr_scope || ! m_sym.is_valid ())) - { - m_scope = curr_scope; - m_sym = m_scope->insert (m_sym.name ()); // ??? - } - - m_context = m_scope ? m_scope->current_context () : 0; - } } static void @@ -1828,19 +1841,12 @@ for (auto& nm_sr : m_symbols) { symbol_record& ours = nm_sr.second; - symbol_record parents; if (! ours.is_formal () - && m_is_nested && m_parent->look_nonlocal (nm_sr.first, parents)) + && 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"); - - if (! ours.is_formal ()) - { - ours.invalidate (); - nm_sr.second = parents; - } } else ours.set_curr_fcn (m_fcn); @@ -1874,12 +1880,26 @@ } else if (! p->second.is_automatic ()) { - result = p->second; + result.bind_fwd_rep (p->second); return true; } return false; } + + void + symbol_table::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 + symbol_table::scope::unbind_script_symbols (void) + { + for (auto& nm_sr : m_symbols) + nm_sr.second.unbind_fwd_rep (); + } } DEFUN (ignore_function_time_stamp, args, nargout,
--- a/libinterp/corefcn/symtab.h Wed Sep 13 16:42:14 2017 -0700 +++ b/libinterp/corefcn/symtab.h Wed Sep 13 17:10:51 2017 -0400 @@ -96,7 +96,8 @@ 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), value_stack (), + : 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); @@ -112,6 +113,12 @@ void assign (const octave_value& value) { + if (m_fwd_rep) + { + m_fwd_rep->assign (value); + return; + } + varref () = value; } @@ -120,16 +127,34 @@ 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); } @@ -137,11 +162,20 @@ 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); } octave_value& varref (void) { + if (m_fwd_rep) + return m_fwd_rep->varref (); + context_id context = m_decl_scope ? m_decl_scope->current_context () : 0; @@ -161,6 +195,9 @@ octave_value varval (void) const { + if (m_fwd_rep) + return m_fwd_rep->varval (); + context_id context = m_decl_scope ? m_decl_scope->current_context () : 0; @@ -179,6 +216,12 @@ 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 ()); @@ -200,6 +243,9 @@ 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 ()) @@ -212,80 +258,330 @@ return retval; } - void clear (void) { clear (decl_scope ()); } + 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 { return storage_class & local; } - bool is_automatic (void) const { return storage_class & automatic; } - bool is_formal (void) const { return storage_class & formal; } - bool is_hidden (void) const { return storage_class & hidden; } - bool is_inherited (void) const { return storage_class & inherited; } - bool is_global (void) const { return storage_class & global; } - bool is_persistent (void) const { return storage_class & persistent; } - bool is_added_static (void) const {return storage_class & added_static; } - - void mark_local (void) { storage_class |= local; } - void mark_automatic (void) { storage_class |= automatic; } - void mark_formal (void) { storage_class |= formal; } - void mark_hidden (void) { storage_class |= hidden; } - void mark_inherited (void) { storage_class |= inherited; } + 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) { storage_class |= added_static; } - - void unmark_local (void) { storage_class &= ~local; } - void unmark_automatic (void) { storage_class &= ~automatic; } - void unmark_formal (void) { storage_class &= ~formal; } - void unmark_hidden (void) { storage_class &= ~hidden; } - void unmark_inherited (void) { storage_class &= ~inherited; } - void unmark_global (void) { storage_class &= ~global; } - void unmark_persistent (void) { storage_class &= ~persistent; } - void unmark_added_static (void) { storage_class &= ~added_static; } + + 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) { return m_decl_scope; } + 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 *rep) { m_fwd_rep = rep; } + + void unbind_fwd_rep (void) { m_fwd_rep = nullptr; } + symbol_record_rep * dup (scope *new_scope) const; octave_value dump (void) const; @@ -296,6 +592,8 @@ std::string name; + symbol_record_rep *m_fwd_rep; + std::deque<octave_value> value_stack; unsigned int storage_class; @@ -470,7 +768,17 @@ unsigned int xstorage_class (void) const { return rep->storage_class; } - void set_curr_fcn (octave_user_function *fcn) { rep->set_curr_fcn (fcn); } + 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 (); } @@ -483,76 +791,6 @@ symbol_record (symbol_record_rep *new_rep) : rep (new_rep) { } }; - static symbol_record dummy_symbol_record; - - // Always access a symbol from the current scope. - // Useful for scripts, as they may be executed in more than one scope. - class - symbol_reference - { - public: - - symbol_reference (void) : m_scope (nullptr), m_context (0) { } - - symbol_reference (const symbol_record& record); - - symbol_reference (const symbol_record& record, scope *curr_scope, - context_id context) - : m_scope (curr_scope), m_context (context), m_sym (record) - { } - - symbol_reference (const symbol_reference& ref) = default; - - symbol_reference& operator = (const symbol_reference& ref) = default; - - bool is_black_hole (void) const { return ! m_scope; } - - symbol_table::scope * scope (void) const - { - update (); - return m_scope; - } - - context_id context (void) const - { - update (); - return m_context; - } - - // The name is the same regardless of scope. - const std::string& name (void) const { return m_sym.name (); } - - symbol_record *operator-> (void) - { - update (); - return &m_sym; - } - - symbol_record *operator-> (void) const - { - update (); - return &m_sym; - } - - // can be used to place symbol_reference in maps, we don't overload < as - // it doesn't make any sense for symbol_reference - struct comparator - { - bool operator ()(const symbol_reference& lhs, - const symbol_reference& rhs) const - { - return lhs.name () < rhs.name (); - } - }; - private: - - void update (void) const; - - mutable symbol_table::scope *m_scope; - mutable context_id m_context; - mutable symbol_record m_sym; - }; - class fcn_info { public: @@ -969,7 +1207,7 @@ m_current_scope->assign (name, value); } - octave_value varval (const std::string& name) + octave_value varval (const std::string& name) const { return (m_current_scope ? m_current_scope->varval (name) : octave_value ()); @@ -987,8 +1225,7 @@ p->second = value; } - octave_value - global_varval (const std::string& name) + octave_value global_varval (const std::string& name) const { global_symbols_const_iterator p = m_global_symbols.find (name); @@ -1002,8 +1239,7 @@ m_top_scope->assign (name, value); } - octave_value - top_level_varval (const std::string& name) + octave_value top_level_varval (const std::string& name) const { return m_top_scope->varval (name); } @@ -1765,7 +2001,7 @@ ? m_persistent_symbols[name] : p->second); } - octave_value persistent_varval (const std::string& name) + octave_value persistent_varval (const std::string& name) const { m_persistent_symbols_const_iterator p = m_persistent_symbols.find (name); @@ -2043,6 +2279,10 @@ bool look_nonlocal (const std::string& name, symbol_table::symbol_record& result); + void bind_script_symbols (scope *curr_scope); + + void unbind_script_symbols (void); + private: // Name for this scope (usually the corresponding filename of the
--- a/libinterp/octave-value/ov-usr-fcn.cc Wed Sep 13 16:42:14 2017 -0700 +++ b/libinterp/octave-value/ov-usr-fcn.cc Wed Sep 13 17:10:51 2017 -0400 @@ -64,6 +64,7 @@ octave_user_code::~octave_user_code (void) { + delete m_scope; delete m_file_info; } @@ -131,11 +132,11 @@ call_depth (-1) { } -octave_user_script::octave_user_script (const std::string& fnm, - const std::string& nm, - octave::tree_statement_list *cmds, - const std::string& ds) - : octave_user_code (nm, ds), cmd_list (cmds), file_name (fnm), +octave_user_script::octave_user_script + (const std::string& fnm, const std::string& nm, + octave::symbol_table::scope *scope, octave::tree_statement_list *cmds, + const std::string& ds) + : octave_user_code (nm, scope, ds), cmd_list (cmds), file_name (fnm), t_parsed (static_cast<time_t> (0)), t_checked (static_cast<time_t> (0)), call_depth (-1) @@ -144,10 +145,10 @@ cmd_list->mark_as_script_body (); } -octave_user_script::octave_user_script (const std::string& fnm, - const std::string& nm, - const std::string& ds) - : octave_user_code (nm, ds), cmd_list (nullptr), file_name (fnm), +octave_user_script::octave_user_script + (const std::string& fnm, const std::string& nm, + octave::symbol_table::scope *scope, const std::string& ds) + : octave_user_code (nm, scope, ds), cmd_list (nullptr), file_name (fnm), t_parsed (static_cast<time_t> (0)), t_checked (static_cast<time_t> (0)), call_depth (-1) @@ -204,6 +205,10 @@ octave::profiler::enter<octave_user_script> block (profiler, *this); + frame.add_method (m_scope, + &octave::symbol_table::scope::unbind_script_symbols); + m_scope->bind_script_symbols (tw.get_current_scope ()); + if (tw.echo ()) tw.push_echo_state (frame, octave::tree_evaluator::ECHO_SCRIPTS, file_name); @@ -238,7 +243,7 @@ octave_user_function::octave_user_function (octave::symbol_table::scope *scope, octave::tree_parameter_list *pl, octave::tree_parameter_list *rl, octave::tree_statement_list *cl) - : octave_user_code ("", ""), m_scope (scope), + : octave_user_code ("", scope, ""), param_list (pl), ret_list (rl), cmd_list (cl), lead_comm (), trail_comm (), file_name (), location_line (0), location_column (0), @@ -267,8 +272,6 @@ if (cmd_list) cmd_list->remove_all_breakpoints (file_name); - delete m_scope; - delete param_list; delete ret_list; delete cmd_list;
--- a/libinterp/octave-value/ov-usr-fcn.h Wed Sep 13 16:42:14 2017 -0700 +++ b/libinterp/octave-value/ov-usr-fcn.h Wed Sep 13 17:10:51 2017 -0400 @@ -61,15 +61,18 @@ protected: octave_user_code (const std::string& nm, + octave::symbol_table::scope *scope = nullptr, const std::string& ds = "") - : octave_function (nm, ds), curr_unwind_protect_frame (nullptr), - m_file_info (nullptr) + : octave_function (nm, ds), m_scope (scope), m_file_info (nullptr), + curr_unwind_protect_frame (nullptr) { } public: octave_user_code (void) - : octave_function () { } + : octave_function (), m_scope (nullptr), m_file_info (nullptr), + curr_unwind_protect_frame (nullptr) + { } // No copying! @@ -94,6 +97,8 @@ void cache_function_text (const std::string& text, const octave::sys::time& timestamp); + octave::symbol_table::scope *scope (void) { return m_scope; } + virtual std::map<std::string, octave_value> subfunctions (void) const; virtual octave::tree_statement_list * body (void) = 0; @@ -102,12 +107,15 @@ void get_file_info (void); - // pointer to the current unwind_protect frame of this function. - octave::unwind_protect *curr_unwind_protect_frame; + // Our symbol table scope. + octave::symbol_table::scope *m_scope; // Cached text of function or script code with line offsets // calculated. octave::file_info *m_file_info; + + // pointer to the current unwind_protect frame of this function. + octave::unwind_protect *curr_unwind_protect_frame; }; // Scripts. @@ -120,10 +128,12 @@ octave_user_script (void); octave_user_script (const std::string& fnm, const std::string& nm, - octave::tree_statement_list *cmds, + octave::symbol_table::scope *scope = nullptr, + octave::tree_statement_list *cmds = nullptr, const std::string& ds = ""); octave_user_script (const std::string& fnm, const std::string& nm, + octave::symbol_table::scope *scope = nullptr, const std::string& ds = ""); // No copying! @@ -273,8 +283,6 @@ octave::symbol_table::scope * parent_fcn_scope (void) const { return parent_scope; } - octave::symbol_table::scope *scope (void) { return m_scope; } - octave::sys::time time_parsed (void) const { return t_parsed; } octave::sys::time time_checked (void) const { return t_checked; } @@ -411,9 +419,6 @@ std::string ctor_type_str (void) const; - // Our symbol table scope. - octave::symbol_table::scope *m_scope; - // List of arguments for this function. These are local variables. octave::tree_parameter_list *param_list;
--- a/libinterp/parse-tree/oct-parse.in.yy Wed Sep 13 16:42:14 2017 -0700 +++ b/libinterp/parse-tree/oct-parse.in.yy Wed Sep 13 17:10:51 2017 -0400 @@ -230,7 +230,8 @@ %token<dummy_type> '(' ')' '[' ']' '{' '}' '.' ',' ';' '@' '\n' // Nonterminals we construct. -%type <dummy_type> indirect_ref_op decl_param_init push_fcn_symtab +%type <dummy_type> indirect_ref_op decl_param_init +%type <dummy_type> push_fcn_symtab push_script_symtab begin_file %type <dummy_type> param_list_beg param_list_end stmt_begin parse_error %type <dummy_type> parsing_local_fcns %type <comment_type> stash_comment @@ -1438,7 +1439,19 @@ { parser.m_parsing_local_functions = true; } ; -file : INPUT_FILE opt_nl opt_list END_OF_INPUT +push_script_symtab : // empty + { + $$ = 0; + + lexer.symtab_context.push (new octave::symbol_table::scope ()); + } + ; + +begin_file : push_script_symtab INPUT_FILE + { $$ = 0; } + ; + +file : begin_file opt_nl opt_list END_OF_INPUT { YYUSE ($2); @@ -1450,6 +1463,9 @@ // been stored in the symbol table or in // base_parser::m_primary_fcn_ptr. + // Unused symbol table context. + lexer.symtab_context.pop (); + delete $3; } else @@ -1464,12 +1480,15 @@ $$ = nullptr; } - | INPUT_FILE opt_nl classdef parsing_local_fcns opt_sep opt_fcn_list END_OF_INPUT + | begin_file opt_nl classdef parsing_local_fcns opt_sep opt_fcn_list END_OF_INPUT { YYUSE ($2); YYUSE ($5); YYUSE ($6); + // Unused symbol table context. + lexer.symtab_context.pop (); + if (lexer.reading_classdef_file) parser.m_classdef_object = $3; @@ -3216,8 +3235,10 @@ octave_user_script *script = new octave_user_script (m_lexer.fcn_file_full_name, m_lexer.fcn_file_name, + m_lexer.symtab_context.curr_scope (), cmds, m_lexer.help_text); + m_lexer.symtab_context.pop (); m_lexer.help_text = ""; sys::time now;
--- a/libinterp/parse-tree/pt-eval.cc Wed Sep 13 16:42:14 2017 -0700 +++ b/libinterp/parse-tree/pt-eval.cc Wed Sep 13 17:10:51 2017 -0400 @@ -618,6 +618,14 @@ return false; } + symbol_table::scope * + tree_evaluator::get_current_scope (void) + { + symbol_table& symtab = m_interpreter.get_symbol_table (); + + return symtab.current_scope (); + } + void tree_evaluator::visit_decl_command (tree_decl_command& cmd) { @@ -972,9 +980,9 @@ { octave_value_list retval; - symbol_table::symbol_reference sym = expr.symbol (); - - octave_value val = sym->find (); + symbol_table::symbol_record sym = expr.symbol (); + + octave_value val = sym.find (); if (val.is_defined ()) { @@ -1014,7 +1022,7 @@ retval = val; } } - else if (sym->is_added_static ()) + else if (sym.is_added_static ()) expr.static_workspace_error (); else expr.eval_undefined_error ();
--- a/libinterp/parse-tree/pt-eval.h Wed Sep 13 16:42:14 2017 -0700 +++ b/libinterp/parse-tree/pt-eval.h Wed Sep 13 17:10:51 2017 -0400 @@ -35,6 +35,7 @@ #include "profiler.h" #include "pt-exp.h" #include "pt-walk.h" +#include "symtab.h" namespace octave { @@ -307,6 +308,8 @@ profiler& get_profiler (void) { return m_profiler; } + symbol_table::scope *get_current_scope (void); + int max_recursion_depth (void) const { return m_max_recursion_depth; } int max_recursion_depth (int n)
--- a/libinterp/parse-tree/pt-id.cc Wed Sep 13 16:42:14 2017 -0700 +++ b/libinterp/parse-tree/pt-id.cc Wed Sep 13 17:10:51 2017 -0400 @@ -60,7 +60,7 @@ octave_lvalue tree_identifier::lvalue (tree_evaluator *) { - if (sym->is_added_static ()) + if (sym.is_added_static ()) static_workspace_error (); return octave_lvalue (sym);
--- a/libinterp/parse-tree/pt-id.h Wed Sep 13 16:42:14 2017 -0700 +++ b/libinterp/parse-tree/pt-id.h Wed Sep 13 17:10:51 2017 -0400 @@ -73,9 +73,9 @@ // accessing it through sym so that this function may remain const. std::string name (void) const { return sym.name (); } - bool is_defined (void) { return sym->is_defined (); } + bool is_defined (void) { return sym.is_defined (); } - virtual bool is_variable (void) const { return sym->is_variable (); } + virtual bool is_variable (void) const { return sym.is_variable (); } virtual bool is_black_hole (void) { return false; } @@ -97,14 +97,14 @@ octave_value do_lookup (const octave_value_list& args = octave_value_list ()) { - return sym->find (args); + return sym.find (args); } - void mark_global (void) { sym->mark_global (); } + void mark_global (void) { sym.mark_global (); } - void mark_persistent (void) { sym->init_persistent (); } + void mark_persistent (void) { sym.init_persistent (); } - void mark_as_formal_parameter (void) { sym->mark_formal (); } + void mark_as_formal_parameter (void) { sym.mark_formal (); } // We really need to know whether this symbol referst to a variable // or a function, but we may not know that yet. @@ -128,14 +128,15 @@ tw.visit_identifier (*this); } - symbol_table::symbol_reference symbol (void) const + symbol_table::symbol_record symbol (void) const { return sym; } + private: // The symbol record that this identifier references. - symbol_table::symbol_reference sym; + symbol_table::symbol_record sym; }; class tree_black_hole : public tree_identifier @@ -158,7 +159,9 @@ octave_lvalue lvalue (tree_evaluator *) { - return octave_lvalue (); // black hole lvalue + octave_lvalue retval; + retval.mark_black_hole (); + return retval; } }; }