changeset 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 94c4ebecca6e
children bc3819b7cca1
files libinterp/corefcn/fcn-info.cc libinterp/corefcn/module.mk libinterp/corefcn/scope.cc libinterp/corefcn/scope.h libinterp/corefcn/symrec.cc libinterp/corefcn/symrec.h libinterp/corefcn/symscope.cc libinterp/corefcn/symscope.h libinterp/corefcn/symtab.cc libinterp/corefcn/symtab.h
diffstat 10 files changed, 1002 insertions(+), 1002 deletions(-) [+]
line wrap: on
line diff
--- a/libinterp/corefcn/fcn-info.cc	Fri Nov 17 16:53:42 2017 +0000
+++ b/libinterp/corefcn/fcn-info.cc	Thu Nov 16 19:39:00 2017 -0500
@@ -34,8 +34,8 @@
 #include "ov-fcn.h"
 #include "ov-usr-fcn.h"
 #include "parse.h"
-#include "scope.h"
 #include "symrec.h"
+#include "symscope.h"
 #include "symtab.h"
 
 namespace octave
@@ -374,7 +374,7 @@
   {
     if (local_funcs)
       {
-        scope *curr_scope
+        symbol_scope *curr_scope
           = __get_current_scope__ ("fcn_info::fcn_info_rep::xfind");
 
         octave_user_function *current_fcn
@@ -592,7 +592,7 @@
 
     // Private function.
 
-    scope *curr_scope
+    symbol_scope *curr_scope
       = __get_current_scope__ ("fcn_info::fcn_info_rep::x_builtin_find");
 
     octave_user_function *current_fcn = curr_scope ? curr_scope->function () : nullptr;
--- a/libinterp/corefcn/module.mk	Fri Nov 17 16:53:42 2017 +0000
+++ b/libinterp/corefcn/module.mk	Thu Nov 16 19:39:00 2017 -0500
@@ -79,11 +79,11 @@
   %reldir%/pager.h \
   %reldir%/pr-output.h \
   %reldir%/procstream.h \
-  %reldir%/scope.h \
   %reldir%/sighandlers.h \
   %reldir%/sparse-xdiv.h \
   %reldir%/sparse-xpow.h \
   %reldir%/symrec.h \
+  %reldir%/symscope.h \
   %reldir%/symtab.h \
   %reldir%/sysdep.h \
   %reldir%/text-renderer.h \
@@ -225,7 +225,6 @@
   %reldir%/rcond.cc \
   %reldir%/regexp.cc \
   %reldir%/schur.cc \
-  %reldir%/scope.cc \
   %reldir%/sighandlers.cc \
   %reldir%/sparse-xdiv.cc \
   %reldir%/sparse-xpow.cc \
@@ -239,6 +238,7 @@
   %reldir%/svd.cc \
   %reldir%/sylvester.cc \
   %reldir%/symrec.cc \
+  %reldir%/symscope.cc \
   %reldir%/symtab.cc \
   %reldir%/syscalls.cc \
   %reldir%/sysdep.cc \
--- a/libinterp/corefcn/scope.cc	Fri Nov 17 16:53:42 2017 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,368 +0,0 @@
-/*
-
-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 ();
-  }
-}
--- a/libinterp/corefcn/scope.h	Fri Nov 17 16:53:42 2017 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,587 +0,0 @@
-/*
-
-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_scope_h)
-#define octave_scope_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 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;
-
-    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!
-
-    scope (const scope&) = delete;
-
-    scope& operator = (const scope&) = delete;
-
-    ~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; }
-
-    scope * parent_scope (void) const { return m_parent; }
-    octave_value parent_fcn (void) const { return m_parent_fcn; }
-
-    scope * dup (void) const
-    {
-      scope *new_sid = new 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 (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 (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 (scope *p);
-
-    void update_nest (void);
-
-    bool look_nonlocal (const std::string& name, 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
-    // 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).
-    scope *m_parent;
-    octave_value m_parent_fcn;
-
-    // Child nested functions.
-    std::vector<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
--- a/libinterp/corefcn/symrec.cc	Fri Nov 17 16:53:42 2017 +0000
+++ b/libinterp/corefcn/symrec.cc	Thu Nov 16 19:39:00 2017 -0500
@@ -35,8 +35,8 @@
 #include "fcn-info.h"
 #include "interpreter-private.h"
 #include "interpreter.h"
-#include "scope.h"
 #include "symrec.h"
+#include "symscope.h"
 #include "symtab.h"
 
 namespace octave
@@ -48,7 +48,7 @@
   }
 
   void
-  symbol_record::symbol_record_rep::clear (scope *sid)
+  symbol_record::symbol_record_rep::clear (symbol_scope *sid)
   {
     if (m_fwd_rep)
       {
@@ -82,7 +82,7 @@
         return;
       }
 
-    scope *curr_scope
+    symbol_scope *curr_scope
       = __require_current_scope__ ("symbol_record::symbol_record_rep::init_persistent");
 
     if (! is_defined ())
@@ -107,14 +107,14 @@
 
     unmark_persistent ();
 
-    scope *curr_scope
+    symbol_scope *curr_scope
       = __require_current_scope__ ("symbol_record::symbol_record_rep::erase_persistent");
 
     curr_scope->erase_persistent (name);
   }
 
   symbol_record::symbol_record_rep *
-  symbol_record::symbol_record_rep::dup (scope *new_scope) const
+  symbol_record::symbol_record_rep::dup (symbol_scope *new_scope) const
   {
     // FIXME: is this the right thing do to?
     if (m_fwd_rep)
@@ -165,7 +165,7 @@
     if (m_fwd_rep)
       return m_fwd_rep->xpersistent_varref ();
 
-    scope *curr_scope
+    symbol_scope *curr_scope
       = __get_current_scope__ ("symbol_record::symbol_record_rep::xpersistent_varref");
 
     return (curr_scope
@@ -190,7 +190,7 @@
     if (m_fwd_rep)
       return m_fwd_rep->xpersistent_varval ();
 
-    scope *curr_scope
+    symbol_scope *curr_scope
       = __get_current_scope__ ("symbol_record::symbol_record_rep::xpersistent_varval");
 
     return curr_scope ? curr_scope->persistent_varval (name) : octave_value ();
--- a/libinterp/corefcn/symrec.h	Fri Nov 17 16:53:42 2017 +0000
+++ b/libinterp/corefcn/symrec.h	Thu Nov 16 19:39:00 2017 -0500
@@ -40,7 +40,7 @@
 namespace octave
 {
   class fcn_info;
-  class scope;
+  class symbol_scope;
 
   class symbol_record
   {
@@ -80,7 +80,7 @@
     {
     public:
 
-      symbol_record_rep (scope *s, const std::string& nm,
+      symbol_record_rep (symbol_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 (),
@@ -200,7 +200,7 @@
           }
       }
 
-      void push_context (scope *sid)
+      void push_context (symbol_scope *sid)
       {
         if (m_fwd_rep)
           {
@@ -227,7 +227,7 @@
       //
       // Here, X should only exist in the final stack frame.
 
-      size_t pop_context (scope *sid)
+      size_t pop_context (symbol_scope *sid)
       {
         if (m_fwd_rep)
           return m_fwd_rep->pop_context (sid);
@@ -255,7 +255,7 @@
         clear (decl_scope ());
       }
 
-      void clear (scope *sid);
+      void clear (symbol_scope *sid);
 
       bool is_defined (void) const
       {
@@ -542,7 +542,7 @@
 
       void erase_persistent (void);
 
-      scope *decl_scope (void)
+      symbol_scope *decl_scope (void)
       {
         if (m_fwd_rep)
           return m_fwd_rep->decl_scope ();
@@ -568,11 +568,11 @@
 
       void unbind_fwd_rep (void) { m_fwd_rep = nullptr; }
 
-      symbol_record_rep * dup (scope *new_scope) const;
+      symbol_record_rep * dup (symbol_scope *new_scope) const;
 
       octave_value dump (void) const;
 
-      scope *m_decl_scope;
+      symbol_scope *m_decl_scope;
 
       octave_user_function *curr_fcn;
 
@@ -605,7 +605,7 @@
 
     symbol_record (void);
 
-    symbol_record (scope *s, const std::string& nm = "",
+    symbol_record (symbol_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)) { }
@@ -636,7 +636,7 @@
         delete rep;
     }
 
-    symbol_record dup (scope *sid) const
+    symbol_record dup (symbol_scope *sid) const
     {
       return symbol_record (rep->dup (sid));
     }
@@ -689,13 +689,13 @@
       return rep->varval ();
     }
 
-    void push_context (scope *sid) { rep->push_context (sid); }
+    void push_context (symbol_scope *sid) { rep->push_context (sid); }
 
-    size_t pop_context (scope *sid) { return rep->pop_context (sid); }
+    size_t pop_context (symbol_scope *sid) { return rep->pop_context (sid); }
 
     void clear (void) { rep->clear (); }
 
-    void clear (scope *sid) { rep->clear (sid); }
+    void clear (symbol_scope *sid) { rep->clear (sid); }
 
     bool is_defined (void) const
     {
@@ -750,7 +750,7 @@
 
     void invalidate (void) { rep->invalidate (); }
 
-    scope *decl_scope (void) { return rep->decl_scope (); }
+    symbol_scope *decl_scope (void) { return rep->decl_scope (); }
 
     unsigned int xstorage_class (void) const { return rep->storage_class; }
 
--- /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 ();
+  }
+}
--- /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
--- a/libinterp/corefcn/symtab.cc	Fri Nov 17 16:53:42 2017 +0000
+++ b/libinterp/corefcn/symtab.cc	Thu Nov 16 19:39:00 2017 -0500
@@ -46,8 +46,8 @@
 #include "pager.h"
 #include "parse.h"
 #include "pt-pr-code.h"
-#include "scope.h"
 #include "symrec.h"
+#include "symscope.h"
 #include "symtab.h"
 #include "unwind-prot.h"
 #include "utils.h"
@@ -443,7 +443,7 @@
         else
           {
             std::string fcn_scope = name.substr (0, pos);
-            scope *stored_scope = m_current_scope;
+            symbol_scope *stored_scope = m_current_scope;
             m_current_scope = m_top_scope;
             octave_value parent = find_function (name.substr (0, pos),
                                                  octave_value_list (), false);
@@ -482,7 +482,7 @@
     if (pos != std::string::npos)
       {
         std::string fcn_scope = full_name.substr (0, pos);
-        scope *stored_scope = m_current_scope;
+        symbol_scope *stored_scope = m_current_scope;
         m_current_scope = m_top_scope;
         octave_value parent = find_function (full_name.substr (0, pos),
                                              octave_value_list (), false);
@@ -658,7 +658,7 @@
 {
   octave::symbol_table& symtab = interp.get_symbol_table ();
 
-  octave::scope *scope = symtab.current_scope ();
+  octave::symbol_scope *scope = symtab.current_scope ();
 
   std::string nm = scope ? scope->name () : "<unknown>";
 
--- a/libinterp/corefcn/symtab.h	Fri Nov 17 16:53:42 2017 +0000
+++ b/libinterp/corefcn/symtab.h	Thu Nov 16 19:39:00 2017 -0500
@@ -43,8 +43,8 @@
 #include "fcn-info.h"
 #include "ov.h"
 #include "ovl.h"
-#include "scope.h"
 #include "symrec.h"
+#include "symscope.h"
 #include "workspace-element.h"
 
 namespace octave
@@ -54,16 +54,16 @@
   public:
 
     typedef octave::symbol_record symbol_record;
-    typedef octave::scope scope;
+    typedef octave::symbol_scope scope;
     typedef octave::fcn_info fcn_info;
 
     typedef scope::context_id context_id;
 
     symbol_table (void)
       : m_global_symbols (), m_fcn_table (), m_class_precedence_table (),
-      m_parent_map (), m_global_scope (new scope ("global scope")),
-      m_top_scope (new scope ("top scope")),
-      m_current_scope (m_top_scope)
+        m_parent_map (), m_global_scope (new scope ("global scope")),
+        m_top_scope (new symbol_scope ("top scope")),
+        m_current_scope (m_top_scope)
       { }
 
     // No copying!
@@ -78,12 +78,12 @@
         delete m_global_scope;
       }
 
-    scope *global_scope (void) { return m_global_scope; }
-    scope *top_scope (void) { return m_top_scope; }
+    symbol_scope *global_scope (void) { return m_global_scope; }
+    symbol_scope *top_scope (void) { return m_top_scope; }
 
-    scope *current_scope (void) { return m_current_scope; }
+    symbol_scope *current_scope (void) { return m_current_scope; }
 
-    scope *require_current_scope (const std::string& who)
+    symbol_scope *require_current_scope (const std::string& who)
     {
       if (! m_current_scope)
         error ("%s: missing scope", who.c_str ());
@@ -96,12 +96,12 @@
       return m_current_scope ? m_current_scope->current_context () : 0;
     }
 
-    void set_scope (scope *sid)
+    void set_scope (symbol_scope *sid)
     {
       set_scope_and_context (sid, 0);
     }
 
-    void set_scope_and_context (scope *sid, context_id context)
+    void set_scope_and_context (symbol_scope *sid, context_id context)
     {
       if (sid == m_global_scope)
         error ("can't set scope to global");
@@ -112,7 +112,7 @@
         m_current_scope->set_context (context);
     }
 
-    symbol_record find_symbol (const std::string& name, scope *sid)
+    symbol_record find_symbol (const std::string& name, symbol_scope *sid)
     {
       return sid ? sid->find_symbol (name) : symbol_record ();
     }
@@ -122,13 +122,13 @@
       return find_symbol (name, m_current_scope);
     }
 
-    void inherit (scope *recipient_scope, scope *donor_scope)
+    void inherit (symbol_scope *recipient_scope, symbol_scope *donor_scope)
     {
       if (recipient_scope)
         recipient_scope->inherit (donor_scope);
     }
 
-    void inherit (scope *recipient_scope)
+    void inherit (symbol_scope *recipient_scope)
     {
       inherit (recipient_scope, m_current_scope);
     }
@@ -788,10 +788,10 @@
     typedef std::map<std::string, std::list<std::string>>::iterator
       parent_map_iterator;
 
-    scope *m_global_scope;
-    scope *m_top_scope;
+    symbol_scope *m_global_scope;
+    symbol_scope *m_top_scope;
 
-    scope *m_current_scope;
+    symbol_scope *m_current_scope;
 
     octave_value dump_fcn_table_map (void) const;
   };