diff libinterp/corefcn/symtab.h @ 24263:3b302b2890d7

disentangle symbol_record, scope, and fcn_info from symbol_table class * fcn-info.cc, fcn-info.h, scope.cc, scope.h, symrec.cc, symrec.h: New files extracted from symtab.h and symtab.cc. * libinterp/corefcn/module.mk: Update. * symrec.cc (symbol_record::symbol_record_rep::xglobal_varref): Don't access private symbol_table internals directly. * scope.h, scope.cc (scope::find, scope::builtin_find, scope::clear_global, scope::clear_global_pattern): Don't access private symbol_table internals directly. * symtab.h, symtab.cc (symbol_table::builtin_find): Don't forward to current scope. Look directly in fcn_info table. (symbol_table::global_varref, symbol_table::fcn_table_find, symbol_table::erase_global, symbol_table::erase_global_pattern): New functions. * scope.h (scope::context_id): New typedef. * symrec.h (symbol_record::context_id): New typedef. * symtab.h (symbol_table::context_id): Update. * symtab.h, symtab.cc (symbol_table::dummy_octave_value): Delete static data member. * symtab.h (symbol_table::context_id): Delete typedef. (symbol_table::symbol_record, symbol_table::scope, symbol_table::fcn_info): New typedefs.
author John W. Eaton <jwe@octave.org>
date Thu, 16 Nov 2017 16:06:31 -0500
parents e15ad9af158f
children f494b87d2a93
line wrap: on
line diff
--- a/libinterp/corefcn/symtab.h	Thu Nov 16 16:12:12 2017 -0500
+++ b/libinterp/corefcn/symtab.h	Thu Nov 16 16:06:31 2017 -0500
@@ -40,8 +40,11 @@
 class tree_argument_list;
 class octave_user_function;
 
+#include "fcn-info.h"
 #include "ov.h"
 #include "ovl.h"
+#include "scope.h"
+#include "symrec.h"
 #include "workspace-element.h"
 
 namespace octave
@@ -50,1064 +53,11 @@
   {
   public:
 
-    static octave_value dummy_octave_value;
-
-    typedef size_t context_id;
-
-    class scope;
-
-    class fcn_info;
-
-    class symbol_record
-    {
-    public:
-
-      // generic variable
-      static const unsigned int local = 1;
-
-      // varargin, argn, .nargin., .nargout.
-      // (FIXME: is this really used now?)
-      static const unsigned int automatic = 2;
-
-      // formal parameter
-      static const unsigned int formal = 4;
-
-      // not listed or cleared (.nargin., .nargout.)
-      static const unsigned int hidden = 8;
-
-      // inherited from parent scope; not cleared at function exit
-      static const unsigned int inherited = 16;
-
-      // global (redirects to global scope)
-      static const unsigned int global = 32;
-
-      // not cleared at function exit
-      static const unsigned int persistent = 64;
-
-      // this symbol may NOT become a variable.
-      // (symbol added to a static workspace)
-      static const unsigned int added_static = 128;
-
-    private:
-
-      class symbol_record_rep
-      {
-      public:
-
-        symbol_record_rep (scope *s, const std::string& nm,
-                           const octave_value& v, unsigned int sc)
-          : m_decl_scope (s), curr_fcn (nullptr), name (nm),
-            m_fwd_rep (nullptr), value_stack (),
-            storage_class (sc), /* finfo (), */ valid (true), count (1)
-        {
-          value_stack.push_back (v);
-        }
-
-        // No copying!
-
-        symbol_record_rep (const symbol_record_rep& ov) = delete;
-
-        symbol_record_rep& operator = (const symbol_record_rep&) = delete;
-
-        ~symbol_record_rep (void) = default;
-
-        void assign (const octave_value& value)
-        {
-          if (m_fwd_rep)
-            {
-              m_fwd_rep->assign (value);
-              return;
-            }
-
-          varref () = value;
-        }
-
-        void assign (octave_value::assign_op op,
-                     const std::string& type,
-                     const std::list<octave_value_list>& idx,
-                     const octave_value& value)
-        {
-          if (m_fwd_rep)
-            {
-              m_fwd_rep->assign (op, type, idx, value);
-              return;
-            }
-
-          varref().assign (op, type, idx, value);
-        }
-
-        void assign (octave_value::assign_op op, const octave_value& value)
-        {
-          if (m_fwd_rep)
-            {
-              m_fwd_rep->assign (op, value);
-              return;
-            }
-
-          varref().assign (op, value);
-        }
-
-        void do_non_const_unary_op (octave_value::unary_op op)
-        {
-          if (m_fwd_rep)
-            {
-              m_fwd_rep->do_non_const_unary_op (op);
-              return;
-            }
-
-          varref().do_non_const_unary_op (op);
-        }
-
-        void do_non_const_unary_op (octave_value::unary_op op,
-                                    const std::string& type,
-                                    const std::list<octave_value_list>& idx)
-        {
-          if (m_fwd_rep)
-            {
-              m_fwd_rep->do_non_const_unary_op (op, type, idx);
-              return;
-            }
-
-          varref().do_non_const_unary_op (op, type, idx);
-        }
-
-        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;
-
-          if (is_global ())
-            return xglobal_varref ();
-          else if (is_persistent ())
-            return xpersistent_varref ();
-          else
-            {
-              context_id n = value_stack.size ();
-              while (n++ <= context)
-                value_stack.push_back (octave_value ());
-
-              return value_stack[context];
-            }
-        }
-
-        octave_value varval (void) const
-        {
-          if (m_fwd_rep)
-            return m_fwd_rep->varval ();
-
-          context_id context
-            = m_decl_scope ? m_decl_scope->current_context () : 0;
-
-          if (is_global ())
-            return xglobal_varval ();
-          else if (is_persistent ())
-            return xpersistent_varval ();
-          else
-            {
-              if (context < value_stack.size ())
-                return value_stack[context];
-              else
-                return octave_value ();
-            }
-        }
-
-        void push_context (scope *sid)
-        {
-          if (m_fwd_rep)
-            {
-              m_fwd_rep->push_context (sid);
-              return;
-            }
-
-          if (! (is_persistent () || is_global ())
-              && sid == decl_scope ())
-            value_stack.push_back (octave_value ());
-        }
-
-        // If pop_context returns 0, we are out of values and this element
-        // of the symbol table should be deleted.  This can happen for
-        // functions like
-        //
-        //   function foo (n)
-        //     if (n > 0)
-        //       foo (n-1);
-        //     else
-        //       eval ("x = 1");
-        //     endif
-        //   endfunction
-        //
-        // Here, X should only exist in the final stack frame.
-
-        size_t pop_context (scope *sid)
-        {
-          if (m_fwd_rep)
-            return m_fwd_rep->pop_context (sid);
-
-          size_t retval = 1;
-
-          if (! (is_persistent () || is_global ())
-              && sid == decl_scope ())
-            {
-              value_stack.pop_back ();
-              retval = value_stack.size ();
-            }
-
-          return retval;
-        }
-
-        void clear (void)
-        {
-          if (m_fwd_rep)
-            {
-              m_fwd_rep->clear ();
-              return;
-            }
-
-          clear (decl_scope ());
-        }
-
-        void clear (scope *sid);
-
-        bool is_defined (void) const
-        {
-          if (m_fwd_rep)
-            return m_fwd_rep->is_defined ();
-
-          return varval ().is_defined ();
-        }
-
-        bool is_valid (void) const
-        {
-          if (m_fwd_rep)
-            return m_fwd_rep->is_valid ();
-
-          return valid;
-        }
-
-        bool is_variable (void) const
-        {
-          if (m_fwd_rep)
-            return m_fwd_rep->is_variable ();
-
-          return (! is_local () || is_defined ());
-        }
-
-        bool is_local (void) const
-        {
-          if (m_fwd_rep)
-            return m_fwd_rep->is_local ();
-
-          return storage_class & local;
-        }
-
-        bool is_automatic (void) const
-        {
-          if (m_fwd_rep)
-            return m_fwd_rep->is_automatic ();
-
-          return storage_class & automatic;
-        }
-
-        bool is_formal (void) const
-        {
-          if (m_fwd_rep)
-            return m_fwd_rep->is_formal ();
-
-          return storage_class & formal;
-        }
-
-        bool is_hidden (void) const
-        {
-          if (m_fwd_rep)
-            return m_fwd_rep->is_hidden ();
-
-          return storage_class & hidden;
-        }
-
-        bool is_inherited (void) const
-        {
-          if (m_fwd_rep)
-            return m_fwd_rep->is_inherited ();
-
-          return storage_class & inherited;
-        }
-
-        bool is_global (void) const
-        {
-          if (m_fwd_rep)
-            return m_fwd_rep->is_global ();
-
-          return storage_class & global;
-        }
-
-        bool is_persistent (void) const
-        {
-          if (m_fwd_rep)
-            return m_fwd_rep->is_persistent ();
-
-          return storage_class & persistent;
-        }
-
-        bool is_added_static (void) const
-        {
-          if (m_fwd_rep)
-            return m_fwd_rep->is_added_static ();
-
-          return storage_class & added_static;
-        }
-
-        void mark_local (void)
-        {
-          if (m_fwd_rep)
-            {
-              m_fwd_rep->mark_local ();
-              return;
-            }
-
-          storage_class |= local;
-        }
-
-        void mark_automatic (void)
-        {
-          if (m_fwd_rep)
-            {
-              m_fwd_rep->mark_automatic ();
-              return;
-            }
-
-          storage_class |= automatic;
-        }
-
-        void mark_formal (void)
-        {
-          if (m_fwd_rep)
-            {
-              m_fwd_rep->mark_formal ();
-              return;
-            }
-
-          storage_class |= formal;
-        }
-
-        void mark_hidden (void)
-        {
-          if (m_fwd_rep)
-            {
-              m_fwd_rep->mark_hidden ();
-              return;
-            }
-
-          storage_class |= hidden;
-        }
-
-        void mark_inherited (void)
-        {
-          if (m_fwd_rep)
-            {
-              m_fwd_rep->mark_inherited ();
-              return;
-            }
-
-          storage_class |= inherited;
-        }
-
-        void mark_global (void)
-        {
-          if (m_fwd_rep)
-            {
-              m_fwd_rep->mark_global ();
-              return;
-            }
-
-          if (is_persistent ())
-            error ("can't make persistent variable %s global", name.c_str ());
-
-          storage_class |= global;
-        }
-
-        void mark_persistent (void)
-        {
-          if (m_fwd_rep)
-            {
-              m_fwd_rep->mark_persistent ();
-              return;
-            }
-
-          if (is_global ())
-            error ("can't make global variable %s persistent", name.c_str ());
-
-          storage_class |= persistent;
-        }
-
-        void mark_added_static (void)
-        {
-          if (m_fwd_rep)
-            {
-              m_fwd_rep->mark_added_static ();
-              return;
-            }
-
-          storage_class |= added_static;
-        }
-
-        void unmark_local (void)
-        {
-          if (m_fwd_rep)
-            {
-              m_fwd_rep->unmark_local ();
-              return;
-            }
-
-          storage_class &= ~local;
-        }
-
-        void unmark_automatic (void)
-        {
-          if (m_fwd_rep)
-            {
-              m_fwd_rep->unmark_automatic ();
-              return;
-            }
-
-          storage_class &= ~automatic;
-        }
-
-        void unmark_formal (void)
-        {
-          if (m_fwd_rep)
-            {
-              m_fwd_rep->unmark_formal ();
-              return;
-            }
-
-          storage_class &= ~formal;
-        }
-
-        void unmark_hidden (void)
-        {
-          if (m_fwd_rep)
-            {
-              m_fwd_rep->unmark_hidden ();
-              return;
-            }
-
-          storage_class &= ~hidden;
-        }
-
-        void unmark_inherited (void)
-        {
-          if (m_fwd_rep)
-            {
-              m_fwd_rep->unmark_inherited ();
-              return;
-            }
-
-          storage_class &= ~inherited;
-        }
-
-        void unmark_global (void)
-        {
-          if (m_fwd_rep)
-            {
-              m_fwd_rep->unmark_global ();
-              return;
-            }
-
-          storage_class &= ~global;
-        }
-
-        void unmark_persistent (void)
-        {
-          if (m_fwd_rep)
-            {
-              m_fwd_rep->unmark_persistent ();
-              return;
-            }
-
-          storage_class &= ~persistent;
-        }
-
-        void unmark_added_static (void)
-        {
-          if (m_fwd_rep)
-            {
-              m_fwd_rep->unmark_added_static ();
-              return;
-            }
-
-          storage_class &= ~added_static;
-        }
-
-        void init_persistent (void);
-
-        void invalidate (void)
-        {
-          if (m_fwd_rep)
-            {
-              m_fwd_rep->invalidate ();
-              return;
-            }
-
-          valid = false;
-        }
-
-        void erase_persistent (void);
-
-        scope *decl_scope (void)
-        {
-          if (m_fwd_rep)
-            return m_fwd_rep->decl_scope ();
-
-          return m_decl_scope;
-        }
-
-        void set_curr_fcn (octave_user_function *fcn)
-        {
-          if (m_fwd_rep)
-            {
-              m_fwd_rep->set_curr_fcn (fcn);
-              return;
-            }
-
-          curr_fcn = fcn;
-        }
-
-        // We don't forward more than once, so no need to forward the
-        // next two.
+    typedef octave::symbol_record symbol_record;
+    typedef octave::scope scope;
+    typedef octave::fcn_info fcn_info;
 
-        void bind_fwd_rep (symbol_record_rep *fwd_rep) { m_fwd_rep = fwd_rep; }
-
-        void unbind_fwd_rep (void) { m_fwd_rep = nullptr; }
-
-        symbol_record_rep * dup (scope *new_scope) const;
-
-        octave_value dump (void) const;
-
-        scope *m_decl_scope;
-
-        octave_user_function *curr_fcn;
-
-        std::string name;
-
-        symbol_record_rep *m_fwd_rep;
-
-        std::deque<octave_value> value_stack;
-
-        unsigned int storage_class;
-
-        //      fcn_info *finfo;
-
-        bool valid;
-
-        refcount<size_t> count;
-
-      private:
-
-        octave_value& xglobal_varref (void);
-
-        octave_value& xpersistent_varref (void);
-
-        octave_value xglobal_varval (void) const;
-
-        octave_value xpersistent_varval (void) const;
-      };
-
-    public:
-
-      symbol_record (void);
-
-      symbol_record (scope *s, const std::string& nm = "",
-                     const octave_value& v = octave_value (),
-                     unsigned int sc = local)
-        : rep (new symbol_record_rep (s, nm, v, sc)) { }
-
-      symbol_record (const symbol_record& sr)
-        : rep (sr.rep)
-      {
-        rep->count++;
-      }
-
-      symbol_record& operator = (const symbol_record& sr)
-      {
-        if (this != &sr)
-          {
-            if (--rep->count == 0)
-              delete rep;
-
-            rep = sr.rep;
-            rep->count++;
-          }
-
-        return *this;
-      }
-
-      ~symbol_record (void)
-      {
-        if (--rep->count == 0)
-          delete rep;
-      }
-
-      symbol_record dup (scope *sid) const
-      {
-        return symbol_record (rep->dup (sid));
-      }
-
-      const std::string& name (void) const { return rep->name; }
-
-      void rename (const std::string& new_name) { rep->name = new_name; }
-
-      octave_value
-      find (const octave_value_list& args = octave_value_list ()) const;
-
-      void assign (const octave_value& value)
-      {
-        rep->assign (value);
-      }
-
-      void assign (octave_value::assign_op op,
-                   const std::string& type,
-                   const std::list<octave_value_list>& idx,
-                   const octave_value& value)
-      {
-        rep->assign (op, type, idx, value);
-      }
-
-      void assign (octave_value::assign_op op, const octave_value& value)
-      {
-        rep->assign (op, value);
-      }
-
-      void do_non_const_unary_op (octave_value::unary_op op)
-      {
-        rep->do_non_const_unary_op (op);
-      }
-
-      void do_non_const_unary_op (octave_value::unary_op op,
-                                  const std::string& type,
-                                  const std::list<octave_value_list>& idx)
-      {
-        rep->do_non_const_unary_op (op, type, idx);
-      }
-
-      // Delete when deprecated varref functions are removed.
-      octave_value& varref (void)
-      {
-        return rep->varref ();
-      }
-
-      octave_value varval (void) const
-      {
-        return rep->varval ();
-      }
-
-      void push_context (scope *sid) { rep->push_context (sid); }
-
-      size_t pop_context (scope *sid) { return rep->pop_context (sid); }
-
-      void clear (void) { rep->clear (); }
-
-      void clear (scope *sid) { rep->clear (sid); }
-
-      bool is_defined (void) const
-      {
-        return rep->is_defined ();
-      }
-
-      bool is_undefined (void) const
-      {
-        return ! rep->is_defined ();
-      }
-
-      bool is_valid (void) const
-      {
-        return rep->is_valid ();
-      }
-
-      bool is_variable (void) const
-      {
-        return rep->is_variable ();
-      }
-
-      bool is_local (void) const { return rep->is_local (); }
-      bool is_automatic (void) const { return rep->is_automatic (); }
-      bool is_formal (void) const { return rep->is_formal (); }
-      bool is_global (void) const { return rep->is_global (); }
-      bool is_hidden (void) const { return rep->is_hidden (); }
-      bool is_inherited (void) const { return rep->is_inherited (); }
-      bool is_persistent (void) const { return rep->is_persistent (); }
-      bool is_added_static (void) const { return rep->is_added_static (); }
-
-      void mark_local (void) { rep->mark_local (); }
-      void mark_automatic (void) { rep->mark_automatic (); }
-      void mark_formal (void) { rep->mark_formal (); }
-      void mark_hidden (void) { rep->mark_hidden (); }
-      void mark_inherited (void) { rep->mark_inherited (); }
-      void mark_global (void) { rep->mark_global (); }
-      void mark_persistent (void) { rep->mark_persistent (); }
-      void mark_added_static (void) { rep->mark_added_static (); }
-
-      void unmark_local (void) { rep->unmark_local (); }
-      void unmark_automatic (void) { rep->unmark_automatic (); }
-      void unmark_formal (void) { rep->unmark_formal (); }
-      void unmark_hidden (void) { rep->unmark_hidden (); }
-      void unmark_inherited (void) { rep->unmark_inherited (); }
-      void unmark_global (void) { rep->unmark_global (); }
-      void unmark_persistent (void) { rep->unmark_persistent (); }
-      void unmark_added_static (void) { rep->unmark_added_static (); }
-
-      void init_persistent (void) { rep->init_persistent (); }
-
-      void erase_persistent (void) { rep->erase_persistent (); }
-
-      void invalidate (void) { rep->invalidate (); }
-
-      scope *decl_scope (void) { return rep->decl_scope (); }
-
-      unsigned int xstorage_class (void) const { return rep->storage_class; }
-
-      void set_curr_fcn (octave_user_function *fcn)
-      {
-        rep->set_curr_fcn (fcn);
-      }
-
-      void bind_fwd_rep (const symbol_record& sr)
-      {
-        rep->bind_fwd_rep (sr.rep);
-      }
-
-      void unbind_fwd_rep (void) { rep->unbind_fwd_rep (); }
-
-      octave_value dump (void) const { return rep->dump (); }
-
-      const symbol_record_rep *xrep (void) const { return rep; }
-
-    private:
-
-      symbol_record_rep *rep;
-
-      symbol_record (symbol_record_rep *new_rep) : rep (new_rep) { }
-    };
-
-    class fcn_info
-    {
-    public:
-
-      typedef std::map<std::string, octave_value>::const_iterator
-      str_val_const_iterator;
-      typedef std::map<std::string, octave_value>::iterator str_val_iterator;
-
-    private:
-
-      class fcn_info_rep
-      {
-      public:
-
-        fcn_info_rep (const std::string& nm)
-          : name (nm), package_name (), local_functions (),
-            private_functions (), class_constructors (), class_methods (),
-            cmdline_function (), autoload_function (), function_on_path (),
-            built_in_function (), count (1)
-        {
-          size_t pos = name.rfind ('.');
-
-          if (pos != std::string::npos)
-            {
-              package_name = name.substr (0, pos);
-              name = name.substr (pos+1);
-            }
-        }
-
-        // No copying!
-
-        fcn_info_rep (const fcn_info_rep&) = delete;
-
-        fcn_info_rep& operator = (const fcn_info_rep&) = delete;
-
-        ~fcn_info_rep (void) = default;
-
-        octave_value install_local_function (const std::string& file_name);
-
-        octave_value load_private_function (const std::string& dir_name);
-
-        octave_value load_class_constructor (void);
-
-        octave_value load_class_method (const std::string& dispatch_type);
-
-        octave_value find (const octave_value_list& args, bool local_funcs);
-
-        octave_value builtin_find (void);
-
-        octave_value find_method (const std::string& dispatch_type);
-
-        octave_value find_autoload (void);
-
-        octave_value find_package (void);
-
-        octave_value find_user_function (void);
-
-        bool is_user_function_defined (void) const
-        {
-          return function_on_path.is_defined ();
-        }
-
-        octave_value find_function (const octave_value_list& args,
-                                    bool local_funcs)
-        {
-          return find (args, local_funcs);
-        }
-
-        void install_cmdline_function (const octave_value& f)
-        {
-          cmdline_function = f;
-        }
-
-        void install_local_function (const octave_value& f,
-                                     const std::string& file_name)
-        {
-          local_functions[file_name] = f;
-        }
-
-        void install_user_function (const octave_value& f)
-        {
-          function_on_path = f;
-        }
-
-        void install_built_in_function (const octave_value& f)
-        {
-          built_in_function = f;
-        }
-
-        void install_built_in_dispatch (const std::string& klass);
-
-        template <typename T>
-        void
-        clear_map (std::map<T, octave_value>& map, bool force = false)
-        {
-          typename std::map<T, octave_value>::iterator p = map.begin ();
-
-          while (p != map.end ())
-            {
-              if (force || ! p->second.islocked ())
-                map.erase (p++);
-              else
-                p++;
-            }
-        }
-
-        void clear_autoload_function (bool force = false)
-        {
-          if (force || ! autoload_function.islocked ())
-            autoload_function = octave_value ();
-        }
-
-        // We also clear command line functions here, as these are both
-        // "user defined"
-        void clear_user_function (bool force = false)
-        {
-          clear_autoload_function (force);
-
-          if (force || ! function_on_path.islocked ())
-            function_on_path = octave_value ();
-
-          if (force || ! cmdline_function.islocked ())
-            cmdline_function = octave_value ();
-        }
-
-        void clear_mex_function (void)
-        {
-          if (function_on_path.is_mex_function ())
-            clear_user_function ();
-        }
-
-        void clear_package (void)
-        {
-          package = octave_value ();
-        }
-
-        void clear (bool force = false)
-        {
-          clear_map (local_functions, force);
-          clear_map (private_functions, force);
-          clear_map (class_constructors, force);
-          clear_map (class_methods, force);
-
-          clear_autoload_function (force);
-          clear_user_function (force);
-          clear_package ();
-        }
-
-        octave_value dump (void) const;
-
-        std::string full_name (void) const
-        {
-          if (package_name.empty ())
-            return name;
-          else
-            return package_name + '.' + name;
-        }
-
-        std::string name;
-
-        std::string package_name;
-
-        // File name to function object.
-        std::map<std::string, octave_value> local_functions;
-
-        // Directory name to function object.
-        std::map<std::string, octave_value> private_functions;
-
-        // Class name to function object.
-        std::map<std::string, octave_value> class_constructors;
-
-        // Dispatch type to function object.
-        std::map<std::string, octave_value> class_methods;
-
-        octave_value cmdline_function;
-
-        octave_value autoload_function;
-
-        octave_value function_on_path;
-
-        octave_value package;
-
-        octave_value built_in_function;
-
-        refcount<size_t> count;
-
-      private:
-
-        octave_value xfind (const octave_value_list& args, bool local_funcs);
-
-        octave_value x_builtin_find (void);
-      };
-
-    public:
-
-      fcn_info (const std::string& nm = "")
-        : rep (new fcn_info_rep (nm)) { }
-
-      fcn_info (const fcn_info& fi) : rep (fi.rep)
-      {
-        rep->count++;
-      }
-
-      fcn_info& operator = (const fcn_info& fi)
-      {
-        if (this != &fi)
-          {
-            if (--rep->count == 0)
-              delete rep;
-
-            rep = fi.rep;
-            rep->count++;
-          }
-
-        return *this;
-      }
-
-      ~fcn_info (void)
-      {
-        if (--rep->count == 0)
-          delete rep;
-      }
-
-      octave_value find (const octave_value_list& args = octave_value_list (),
-                         bool local_funcs = true)
-      {
-        return rep->find (args, local_funcs);
-      }
-
-      octave_value builtin_find (void)
-      {
-        return rep->builtin_find ();
-      }
-
-      octave_value find_method (const std::string& dispatch_type) const
-      {
-        return rep->find_method (dispatch_type);
-      }
-
-      octave_value find_built_in_function (void) const
-      {
-        return rep->built_in_function;
-      }
-
-      octave_value find_cmdline_function (void) const
-      {
-        return rep->cmdline_function;
-      }
-
-      octave_value find_autoload (void)
-      {
-        return rep->find_autoload ();
-      }
-
-      octave_value find_user_function (void)
-      {
-        return rep->find_user_function ();
-      }
-
-      bool is_user_function_defined (void) const
-      {
-        return rep->is_user_function_defined ();
-      }
-
-      octave_value find_function (const octave_value_list& args
-                                  = octave_value_list (),
-                                  bool local_funcs = true)
-      {
-        return rep->find_function (args, local_funcs);
-      }
-
-      void install_cmdline_function (const octave_value& f)
-      {
-        rep->install_cmdline_function (f);
-      }
-
-      void install_local_function (const octave_value& f,
-                                   const std::string& file_name)
-      {
-        rep->install_local_function (f, file_name);
-      }
-
-      void install_user_function (const octave_value& f)
-      {
-        rep->install_user_function (f);
-      }
-
-      void install_built_in_function (const octave_value& f)
-      {
-        rep->install_built_in_function (f);
-      }
-
-      void install_built_in_dispatch (const std::string& klass)
-      {
-        rep->install_built_in_dispatch (klass);
-      }
-
-      void clear (bool force = false) { rep->clear (force); }
-
-      void clear_user_function (bool force = false)
-      {
-        rep->clear_user_function (force);
-      }
-
-      void clear_autoload_function (bool force = false)
-      {
-        rep->clear_autoload_function (force);
-      }
-
-      void clear_mex_function (void) { rep->clear_mex_function (); }
-
-      octave_value dump (void) const { return rep->dump (); }
-
-    private:
-
-      fcn_info_rep *rep;
-    };
+    typedef scope::context_id context_id;
 
     symbol_table (void)
       : m_global_symbols (), m_fcn_table (), m_class_precedence_table (),
@@ -1192,8 +142,6 @@
             bool skip_variables = false,
             bool local_funcs = true);
 
-    octave_value builtin_find (const std::string& name);
-
     void assign (const std::string& name, const octave_value& value, bool force_add)
     {
       if (m_current_scope)
@@ -1225,6 +173,14 @@
         p->second = value;
     }
 
+    octave_value& global_varref (const std::string& name)
+    {
+      global_symbols_iterator p = m_global_symbols.find (name);
+
+      return (p == m_global_symbols.end ()
+              ? m_global_symbols[name] : p->second);
+    }
+
     octave_value global_varval (const std::string& name) const
     {
       global_symbols_const_iterator p = m_global_symbols.find (name);
@@ -1303,6 +259,13 @@
               ? p->second.find_autoload () : octave_value ());
     }
 
+    octave_value builtin_find (const std::string& name);
+
+    octave_value
+    fcn_table_find (const std::string& name,
+                    const octave_value_list& args = octave_value_list (),
+                    bool local_funcs = true);
+
     octave_value
       find_function (const std::string& name,
                      const octave_value_list& args = octave_value_list (),
@@ -1512,6 +475,10 @@
         (p++)->second.clear_mex_function ();
     }
 
+    void erase_global (const std::string& name);
+
+    void erase_global_pattern (const glob_match& pattern);
+
     bool set_class_relationship (const std::string& sup_class,
                                  const std::string& inf_class);
 
@@ -1783,542 +750,6 @@
       return p != m_fcn_table.end () ? &p->second : nullptr;
     }
 
-    class scope
-    {
-    public:
-
-      typedef std::map<std::string, symbol_table::symbol_record>::const_iterator
-      table_const_iterator;
-      typedef std::map<std::string, symbol_table::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_table::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_table::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_table::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);
-
-      octave_value builtin_find (const std::string& name);
-
-      symbol_table::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_table::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_table::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_table::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_table::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_table::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_table::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_table::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_table::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_table::symbol_record>
-      all_variables (bool defined_only = true,
-                     unsigned int exclude = symbol_table::symbol_record::hidden) const
-      {
-        std::list<symbol_table::symbol_record> retval;
-
-        for (const auto& nm_sr : m_symbols)
-          {
-            const symbol_table::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_table::symbol_record>
-      glob (const std::string& pattern, bool vars_only = false) const
-      {
-        std::list<symbol_table::symbol_record> retval;
-
-        glob_match pat (pattern);
-
-        for (const auto& nm_sr : m_symbols)
-          {
-            if (pat.match (nm_sr.first))
-              {
-                const symbol_table::symbol_record& sr = nm_sr.second;
-
-                if (vars_only && ! sr.is_variable ())
-                  continue;
-
-                retval.push_back (sr);
-              }
-          }
-
-        return retval;
-      }
-
-      std::list<symbol_table::symbol_record>
-      regexp (const std::string& pattern, bool vars_only = false) const
-      {
-        std::list<symbol_table::symbol_record> retval;
-
-        octave::regexp pat (pattern);
-
-        for (const auto& nm_sr : m_symbols)
-          {
-            if (pat.is_match (nm_sr.first))
-              {
-                const symbol_table::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_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
-      // function corresponding to the scope).
-      std::string m_name;
-
-      // Map from symbol names to symbol info.
-      std::map<std::string, symbol_table::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;
-    };
-
   private:
 
     typedef std::map<std::string, octave_value>::const_iterator