changeset 23611:91c8f006ed8b

remove additional functions from symbol_table class Remove functions from symbol_table class that simply forward to the corresponding function in the symbol_table::scope class. Change all uses to access these functions using a scope object.
author John W. Eaton <jwe@octave.org>
date Thu, 15 Jun 2017 19:15:06 -0400
parents 2fe11412e785
children 702db65be195
files examples/code/make_int.cc libgui/src/main-window.cc libgui/src/workspace-view.cc libinterp/corefcn/defun.cc libinterp/corefcn/error.cc libinterp/corefcn/interpreter.cc libinterp/corefcn/load-path.cc libinterp/corefcn/load-save.cc libinterp/corefcn/mex.cc libinterp/corefcn/octave-link.cc libinterp/corefcn/symtab.cc libinterp/corefcn/symtab.h libinterp/corefcn/variables.cc libinterp/octave-value/ov-classdef.cc libinterp/octave-value/ov-fcn-handle.cc libinterp/octave-value/ov-usr-fcn.cc libinterp/parse-tree/lex.ll libinterp/parse-tree/oct-parse.in.yy libinterp/parse-tree/pt-eval.cc libinterp/parse-tree/pt-fcn-handle.cc libinterp/parse-tree/pt-jit.cc
diffstat 21 files changed, 327 insertions(+), 428 deletions(-) [+]
line wrap: on
line diff
--- a/examples/code/make_int.cc	Thu Jun 15 10:47:50 2017 -0400
+++ b/examples/code/make_int.cc	Thu Jun 15 19:15:06 2017 -0400
@@ -22,7 +22,6 @@
 #include <octave/ov-scalar.h>
 #include <octave/pager.h>
 #include <octave/pr-output.h>
-#include <octave/symtab.h>
 #include <octave/variables.h>
 
 class octave_value_list;
--- a/libgui/src/main-window.cc	Thu Jun 15 10:47:50 2017 -0400
+++ b/libgui/src/main-window.cc	Thu Jun 15 19:15:06 2017 -0400
@@ -2420,10 +2420,11 @@
 {
   Fload (ovl (file));
 
- symbol_table& symtab
-   = octave::__get_symbol_table__ ("main_window::load_workspace_callback");
-
-  octave_link::set_workspace (true, symtab.workspace_info ());
+  symbol_table::scope *scope
+   = octave::__get_current_scope__ ("main_window::load_workspace_callback");
+
+  if (scope)
+    octave_link::set_workspace (true, scope->workspace_info ());
 }
 
 void
@@ -2438,16 +2439,18 @@
 void
 main_window::rename_variable_callback (const main_window::name_pair& names)
 {
-  symbol_table& symtab
-    = octave::__get_symbol_table__ ("main_window::rename_variable_callback");
-
-  /* bool status = */ symtab.rename (names.first, names.second);
-
-  // if (status)
-  octave_link::set_workspace (true, symtab.workspace_info ());
-
-  //  else
-  //    ; // we need an octave_link action that runs a GUI error option.
+  symbol_table::scope *scope
+    = octave::__get_current_scope__ ("main_window::rename_variable_callback");
+
+  if (scope)
+    {
+      scope->rename (names.first, names.second);
+
+      octave_link::set_workspace (true, scope->workspace_info ());
+    }
+
+  // FIXME: if this action fails, do we need a way to display that info
+  // in the GUI?
 }
 
 void
--- a/libgui/src/workspace-view.cc	Thu Jun 15 10:47:50 2017 -0400
+++ b/libgui/src/workspace-view.cc	Thu Jun 15 19:15:06 2017 -0400
@@ -373,10 +373,10 @@
     {
       QString var_name = get_var_name (index);
 
-      symbol_table& symtab
-        = octave::__get_symbol_table__ ("workspace_view::handle_contextmenu_copy_value");
+      symbol_table::scope *scope
+        = octave::__get_current_scope__ ("workspace_view::handle_contextmenu_copy_value");
 
-      octave_value val = symtab.varval (var_name.toStdString ());
+      octave_value val = scope ? scope->varval (var_name.toStdString ()) : 0;
       std::ostringstream buf;
       val.print_raw (buf, true);
 
--- a/libinterp/corefcn/defun.cc	Thu Jun 15 10:47:50 2017 -0400
+++ b/libinterp/corefcn/defun.cc	Thu Jun 15 19:15:06 2017 -0400
@@ -91,7 +91,8 @@
 {
   octave_value fcn (new octave_builtin (f, name, file, doc));
 
-  symbol_table& symtab = octave::__get_symbol_table__ ("install_builtin_function");
+  symbol_table& symtab
+    = octave::__get_symbol_table__ ("install_builtin_function");
 
   symtab.install_built_in_function (name, fcn);
 }
@@ -103,7 +104,8 @@
 {
   octave_value fcn (new octave_builtin (m, name, file, doc));
 
-  symbol_table& symtab = octave::__get_symbol_table__ ("install_builtin_function");
+  symbol_table& symtab
+    = octave::__get_symbol_table__ ("install_builtin_function");
 
   symtab.install_built_in_function (name, fcn);
 }
@@ -120,7 +122,8 @@
 
   octave_value fval (fcn);
 
-  symbol_table& symtab = octave::__get_symbol_table__ ("install_dld_function");
+  symbol_table& symtab
+    = octave::__get_symbol_table__ ("install_dld_function");
 
   symtab.install_built_in_function (name, fval);
 }
@@ -137,7 +140,8 @@
 
   octave_value fval (fcn);
 
-  symbol_table& symtab = octave::__get_symbol_table__ ("install_dld_function");
+  symbol_table& symtab
+    = octave::__get_symbol_table__ ("install_dld_function");
 
   symtab.install_built_in_function (name, fval);
 }
@@ -153,7 +157,8 @@
 
   octave_value fval (fcn);
 
-  symbol_table& symtab = octave::__get_symbol_table__ ("install_mex_function");
+  symbol_table& symtab
+    = octave::__get_symbol_table__ ("install_mex_function");
 
   symtab.install_built_in_function (name, fval);
 }
@@ -169,7 +174,8 @@
 void
 install_builtin_dispatch (const std::string& name, const std::string& klass)
 {
-  symbol_table& symtab = octave::__get_symbol_table__ ("install_builtin_dispatch");
+  symbol_table& symtab
+    = octave::__get_symbol_table__ ("install_builtin_dispatch");
 
   symtab.install_built_in_dispatch (name, klass);
 }
--- a/libinterp/corefcn/error.cc	Thu Jun 15 10:47:50 2017 -0400
+++ b/libinterp/corefcn/error.cc	Thu Jun 15 19:15:06 2017 -0400
@@ -1513,6 +1513,9 @@
           if (nargin == 3 && argv[3] == "local"
               && ! symtab.at_top_level ())
             {
+              symbol_table::scope *scope
+                = symtab.require_current_scope ("warning");
+
               octave_scalar_map val = warning_query (arg2);
 
               octave_value curr_state = val.contents ("state");
@@ -1520,7 +1523,7 @@
               // FIXME: this might be better with a dictionary object.
 
               octave_value curr_warning_states
-                = symtab.varval (".saved_warning_states.");
+                = scope->varval (".saved_warning_states.");
 
               octave_map m;
 
@@ -1568,7 +1571,7 @@
               m.contents ("identifier") = ids;
               m.contents ("state") = states;
 
-              symtab.assign (".saved_warning_states.", m);
+              scope->assign (".saved_warning_states.", m);
 
               // Now ignore the "local" argument and continue to
               // handle the current setting.
--- a/libinterp/corefcn/interpreter.cc	Thu Jun 15 10:47:50 2017 -0400
+++ b/libinterp/corefcn/interpreter.cc	Thu Jun 15 19:15:06 2017 -0400
@@ -519,8 +519,14 @@
 
   void interpreter::intern_nargin (octave_idx_type nargs)
   {
-    m_symbol_table.assign (".nargin.", nargs);
-    m_symbol_table.mark_hidden (".nargin.");
+    // FIXME: should this explicitly be top_scope?
+    symbol_table::scope *scope = m_symbol_table.current_scope ();
+
+    if (scope)
+      {
+        scope->assign (".nargin.", nargs);
+        scope->mark_hidden (".nargin.");
+      }
   }
 
   // Read the history file unless a command-line option inhibits that.
--- a/libinterp/corefcn/load-path.cc	Thu Jun 15 10:47:50 2017 -0400
+++ b/libinterp/corefcn/load-path.cc	Thu Jun 15 19:15:06 2017 -0400
@@ -121,9 +121,9 @@
   // Look in private directory corresponding to current function (if
   // any).
 
-  symbol_table& symtab = octave::__get_symbol_table__ ("find_private_file");
-
-  octave_user_function *curr_fcn = symtab.get_curr_fcn ();
+  symbol_table::scope *scope = octave::__get_current_scope__ ("find_private_file");
+
+  octave_user_function *curr_fcn = scope ? scope->function () : 0;
 
   if (curr_fcn)
     {
--- a/libinterp/corefcn/load-save.cc	Thu Jun 15 10:47:50 2017 -0400
+++ b/libinterp/corefcn/load-save.cc	Thu Jun 15 19:15:06 2017 -0400
@@ -145,16 +145,20 @@
                          const octave_value& val,
                          bool global, const std::string& /*doc*/)
 {
-  symbol_table& symtab = octave::__get_symbol_table__ ("install_loaded_variable");
+  symbol_table& symtab
+    = octave::__get_symbol_table__ ("install_loaded_varaible");
+
+  symbol_table::scope *scope
+    = symtab.require_current_scope ("install_loaded_variable");
 
   if (global)
     {
-      symtab.clear (name);
-      symtab.mark_global (name);
+      scope->clear_variable (name);
+      scope->mark_global (name);
       symtab.global_assign (name, val);
     }
   else
-    symtab.assign (name, val);
+    scope->assign (name, val);
 }
 
 // Return TRUE if NAME matches one of the given globbing PATTERNS.
@@ -1272,12 +1276,17 @@
 
       std::string struct_name = argv[argv_idx];
 
-      symbol_table& symtab = octave::__get_symbol_table__ ("save_vars");
+      symbol_table::scope *scope = octave::__get_current_scope__ ("save_vars");
+
+      octave_value struct_var;
 
-      if (! symtab.is_variable (struct_name))
-        error ("save: no such variable: '%s'", struct_name.c_str ());
+      if (scope)
+        {
+          if (! scope->is_variable (struct_name))
+            error ("save: no such variable: '%s'", struct_name.c_str ());
 
-      octave_value struct_var = symtab.varval (struct_name);
+          struct_var = scope->varval (struct_name);
+        }
 
       if (! struct_var.isstruct () || struct_var.numel () != 1)
         error ("save: '%s' is not a scalar structure", struct_name.c_str ());
@@ -1321,8 +1330,9 @@
 
   symbol_table& symtab = octave::__get_symbol_table__ ("dump_octave_core");
 
-  std::list<symbol_table::symbol_record> vars
-    = symtab.all_variables (symtab.top_scope ());
+  symbol_table::scope *top_scope = symtab.top_scope ();
+
+  std::list<symbol_table::symbol_record> vars = top_scope->all_variables ();
 
   double save_mem_size = 0;
 
--- a/libinterp/corefcn/mex.cc	Thu Jun 15 10:47:50 2017 -0400
+++ b/libinterp/corefcn/mex.cc	Thu Jun 15 19:15:06 2017 -0400
@@ -3425,9 +3425,10 @@
               frame.add_method (cs, &octave::call_stack::pop);
             }
 
-          symbol_table& symtab = octave::__get_symbol_table__ ("mexGetVariable");
-
-          val = symtab.varval (name);
+          symbol_table::scope *scope
+            = octave::__require_current_scope__ ("mexGetVariable");
+
+          val = scope->varval (name);
         }
       else
         mexErrMsgTxt ("mexGetVariable: symbol table does not exist");
@@ -3490,9 +3491,10 @@
               frame.add_method (cs, &octave::call_stack::pop);
             }
 
-          symbol_table& symtab = octave::__get_symbol_table__ ("mexPutVariable");
-
-          symtab.assign (name, mxArray::as_octave_value (ptr));
+          symbol_table::scope *scope
+            = octave::__require_current_scope__ ("mexPutVariable");
+
+          scope->assign (name, mxArray::as_octave_value (ptr));
         }
       else
         mexErrMsgTxt ("mexPutVariable: symbol table does not exist");
--- a/libinterp/corefcn/octave-link.cc	Thu Jun 15 10:47:50 2017 -0400
+++ b/libinterp/corefcn/octave-link.cc	Thu Jun 15 19:15:06 2017 -0400
@@ -69,10 +69,13 @@
       symbol_table& symtab
         = octave::__get_symbol_table__ ("octave_link::set_workspace");
 
+      std::list<workspace_element> workspace_info;
+      symbol_table::scope *scope = symtab.current_scope ();
+      if (scope)
+        workspace_info = scope->workspace_info ();
 
       instance->do_set_workspace (symtab.at_top_level (),
-                                  instance->debugging,
-                                  symtab.workspace_info ());
+                                  instance->debugging, workspace_info);
     }
 }
 
--- a/libinterp/corefcn/symtab.cc	Thu Jun 15 10:47:50 2017 -0400
+++ b/libinterp/corefcn/symtab.cc	Thu Jun 15 19:15:06 2017 -0400
@@ -57,7 +57,7 @@
 static int Vignore_function_time_stamp = 1;
 
 void
-symbol_table::symbol_record::symbol_record_rep::clear (const scope *sid)
+symbol_table::symbol_record::symbol_record_rep::clear (scope *sid)
 {
   if (! (is_hidden () || is_inherited ())
       && sid == decl_scope ())
@@ -65,12 +65,9 @@
       if (is_global ())
         unmark_global ();
 
-      symbol_table& symtab
-        = octave::__get_symbol_table__ ("symbol_table::symbol_record::symbol_record_rep::clear");
-
       if (is_persistent ())
         {
-          symtab.persistent_assign (name, varval ());
+          sid->persistent_assign (name, varval ());
 
           unmark_persistent ();
         }
@@ -82,14 +79,14 @@
 void
 symbol_table::symbol_record::symbol_record_rep::init_persistent (void)
 {
-  symbol_table& symtab
-    = octave::__get_symbol_table__ ("symbol_table::symbol_record::symbol_record_rep::init_persistent");
+  symbol_table::scope *scope
+    = octave::__require_current_scope__ ("symbol_table::symbol_record::symbol_record_rep::init_persistent");
 
   if (! is_defined ())
     {
       mark_persistent ();
 
-      assign (symtab.persistent_varval (name));
+      assign (scope->persistent_varval (name));
     }
   // FIXME: this causes trouble with recursive calls.
   // else
@@ -101,11 +98,10 @@
 {
   unmark_persistent ();
 
-  symbol_table& symtab
-    = octave::__get_symbol_table__ ("symbol_table::symbol_record::symbol_record_rep::erase_persistent");
+  symbol_table::scope *scope
+    = octave::__require_current_scope__ ("symbol_table::symbol_record::symbol_record_rep::erase_persistent");
 
-
-  symtab.erase_persistent (name);
+  scope->erase_persistent (name);
 }
 
 symbol_table::symbol_record::symbol_record_rep *
@@ -155,12 +151,10 @@
 octave_value&
 symbol_table::symbol_record::symbol_record_rep::xpersistent_varref (void)
 {
-  symbol_table& symtab
-    = octave::__get_symbol_table__ ("symbol_table::symbol_record::symbol_record_rep::xpersistent_varref");
+  symbol_table::scope *scope
+    = octave::__get_current_scope__ ("symbol_table::symbol_record::symbol_record_rep::xpersistent_varref");
 
-  scope *s = symtab.current_scope ();
-
-  return s ? s->persistent_varref (name) : dummy_octave_value;
+  return scope ? scope->persistent_varref (name) : dummy_octave_value;
 }
 
 octave_value
@@ -175,10 +169,10 @@
 octave_value
 symbol_table::symbol_record::symbol_record_rep::xpersistent_varval (void) const
 {
-  symbol_table& symtab
-    = octave::__get_symbol_table__ ("symbol_table::symbol_record::symbol_record_rep::xpersistent_varval");
+  symbol_table::scope *scope
+    = octave::__get_current_scope__ ("symbol_table::symbol_record::symbol_record_rep::xpersistent_varval");
 
-  return symtab.persistent_varval (name);
+  return scope ? scope->persistent_varval (name) : octave_value ();
 }
 
 symbol_table::symbol_record::symbol_record (void)
@@ -232,9 +226,7 @@
 symbol_table::symbol_reference::symbol_reference (const symbol_record& record)
   : m_scope (0), m_context (0),m_sym (record)
 {
-  symbol_table& symtab = octave::__get_symbol_table__ ("symbol_reference");
-
-  m_scope = symtab.current_scope ();
+  m_scope = octave::__get_current_scope__ ("symbol_reference");
 }
 
 void
@@ -806,10 +798,10 @@
 {
   if (local_funcs)
     {
-      symbol_table& symtab
-        = octave::__get_symbol_table__ ("symbol_table::fcn_info::fcn_info_rep::xfind");
+      symbol_table::scope *scope
+        = octave::__get_current_scope__ ("symbol_table::fcn_info::fcn_info_rep::xfind");
 
-      octave_user_function *current_fcn = symtab.get_curr_fcn ();
+      octave_user_function *current_fcn = scope ? scope->function () : 0;
 
       // Local function.
 
@@ -1010,10 +1002,10 @@
 
   // Private function.
 
-  symbol_table& symtab
-    = octave::__get_symbol_table__ ("symbol_table::fcn_info::fcn_info_rep::x_builtin_find");
+  symbol_table::scope *scope
+    = octave::__get_current_scope__ ("symbol_table::fcn_info::fcn_info_rep::x_builtin_find");
 
-  octave_user_function *current_fcn = symtab.get_curr_fcn ();
+  octave_user_function *current_fcn = scope ? scope->function () : 0;
 
   if (current_fcn)
     {
--- a/libinterp/corefcn/symtab.h	Thu Jun 15 10:47:50 2017 -0400
+++ b/libinterp/corefcn/symtab.h	Thu Jun 15 19:15:06 2017 -0400
@@ -214,7 +214,7 @@
 
       void clear (void) { clear (decl_scope ()); }
 
-      void clear (const scope *sid);
+      void clear (scope *sid);
 
       bool is_defined (void) const
       {
@@ -279,7 +279,7 @@
 
       void erase_persistent (void);
 
-      const scope *decl_scope (void) const { return m_decl_scope; }
+      scope *decl_scope (void) { return m_decl_scope; }
 
       void set_curr_fcn (octave_user_function *fcn)
       {
@@ -411,7 +411,7 @@
 
     void clear (void) { rep->clear (); }
 
-    void clear (const scope *sid) { rep->clear (sid); }
+    void clear (scope *sid) { rep->clear (sid); }
 
     bool is_defined (void) const
     {
@@ -466,7 +466,7 @@
 
     void invalidate (void) { rep->invalidate (); }
 
-    const scope *decl_scope (void) const { return rep->decl_scope (); }
+    scope *decl_scope (void) { return rep->decl_scope (); }
 
     unsigned int xstorage_class (void) const { return rep->storage_class; }
 
@@ -905,6 +905,14 @@
 
   scope *current_scope (void) { return m_current_scope; }
 
+  scope *require_current_scope (const std::string& who)
+  {
+    if (! m_current_scope)
+      error ("%s: missing scope", who.c_str ());
+
+    return m_current_scope;
+  }
+
   context_id current_context (void) const
   {
     return m_current_scope ? m_current_scope->current_context () : 0;
@@ -939,22 +947,12 @@
   void inherit (scope *recipient_scope, scope *donor_scope)
   {
     if (recipient_scope)
-      {
-        while (donor_scope)
-          {
-            recipient_scope->inherit (*donor_scope);
-
-            if (donor_scope->is_nested ())
-              donor_scope = donor_scope->parent_scope ();
-            else
-              break;
-          }
-      }
+      recipient_scope->inherit (donor_scope);
   }
 
-  void inherit (scope *sid)
+  void inherit (scope *recipient_scope)
   {
-    inherit (sid, m_current_scope);
+    inherit (recipient_scope, m_current_scope);
   }
 
   bool at_top_level (void) { return m_current_scope == m_top_scope; }
@@ -968,39 +966,6 @@
 
   octave_value builtin_find (const std::string& name);
 
-  void rename (const std::string& old_name, const std::string& new_name)
-  {
-    if (m_current_scope)
-      m_current_scope->rename (old_name, new_name);
-  }
-
-  void assign (const std::string& name,
-               const octave_value& value = octave_value ())
-  {
-    m_current_scope->assign (name, value);
-  }
-
-  // Convenience function to simplify
-  // octave_user_function::bind_automatic_vars
-
-  void force_assign (const std::string& name, const octave_value& value,
-                     scope *sid)
-  {
-    if (sid)
-      sid->assign (name, value, true);
-  }
-
-  void force_assign (const std::string& name,
-                     const octave_value& value = octave_value ())
-  {
-    m_current_scope->assign (name, value);
-  }
-
-  octave_value varval (const std::string& name)
-  {
-    return m_current_scope->varval (name);
-  }
-
   void
   global_assign (const std::string& name,
                  const octave_value& value = octave_value ())
@@ -1035,31 +1000,6 @@
     return m_top_scope->varval (name);
   }
 
-  void
-    persistent_assign (const std::string& name,
-                       const octave_value& value = octave_value ())
-  {
-    if (m_current_scope)
-      m_current_scope->persistent_assign (name, value);
-  }
-
-  octave_value persistent_varval (const std::string& name)
-  {
-    return (m_current_scope
-            ? m_current_scope->persistent_varval (name) : octave_value ());
-  }
-
-  void erase_persistent (const std::string& name)
-  {
-    if (m_current_scope)
-      m_current_scope->erase_persistent (name);
-  }
-
-  bool is_variable (const std::string& name)
-  {
-    return m_current_scope ? m_current_scope->is_variable (name) : false;
-  }
-
   bool
     is_built_in_function_name (const std::string& name)
   {
@@ -1161,29 +1101,6 @@
       }
   }
 
-  // Install subfunction FCN named NAME.  SCOPE is the scope of the
-  // primary function corresponding to this subfunction.
-
-  void install_subfunction (const std::string& name, const octave_value& fcn,
-                            scope *parent_scope)
-  {
-    if (parent_scope)
-      parent_scope->install_subfunction (name, fcn);
-  }
-
-  void install_nestfunction (const std::string& name, const octave_value& fcn,
-                             scope *parent_scope)
-  {
-    if (parent_scope)
-      parent_scope->install_subfunction (name, fcn, true);
-  }
-
-  void update_nest (scope *sid)
-  {
-    if (sid)
-      sid->update_nest ();
-  }
-
   // Install local function FCN named NAME.  FILE_NAME is the name of
   // the file containing the local function.
 
@@ -1251,16 +1168,13 @@
       }
   }
 
-  void clear (const std::string& name)
-  {
-    clear_variable (name);
-  }
-
   void clear_all (bool force = false)
   {
-    clear_variables ();
-
-    clear_global_pattern ("*");
+    if (m_current_scope)
+      {
+        m_current_scope->clear_variables ();
+        m_current_scope->clear_global_pattern ("*");
+      }
 
     clear_functions (force);
   }
@@ -1269,23 +1183,6 @@
   // function with default values so that it will work properly with
   // unwind_protect.
 
-  void clear_variables (scope *sid)
-  {
-    if (sid)
-      sid->clear_variables ();
-  }
-
-  void clear_variables (void)
-  {
-    clear_variables (m_current_scope);
-  }
-
-  void clear_objects (void)
-  {
-    if (m_current_scope)
-      m_current_scope->clear_objects ();
-  }
-
   void clear_functions (bool force = false)
   {
     fcn_table_iterator p = m_fcn_table.begin ();
@@ -1299,23 +1196,13 @@
     clear_user_function (name);
   }
 
-  void clear_global (const std::string& name)
-  {
-    if (m_current_scope)
-      m_current_scope->clear_global (name);
-  }
-
-  void clear_variable (const std::string& name)
-  {
-    if (m_current_scope)
-      m_current_scope->clear_variable (name);
-  }
-
   void clear_symbol (const std::string& name)
   {
     // FIXME: are we supposed to do both here?
 
-    clear_variable (name);
+    if (m_current_scope)
+      m_current_scope->clear_variable (name);
+
     clear_function (name);
   }
 
@@ -1334,29 +1221,13 @@
       }
   }
 
-  void clear_global_pattern (const std::string& pat)
-  {
-    if (m_current_scope)
-      m_current_scope->clear_global_pattern (pat);
-  }
-
-  void clear_variable_pattern (const std::string& pat)
-  {
-    if (m_current_scope)
-      m_current_scope->clear_variable_pattern (pat);
-  }
-
-  void clear_variable_regexp (const std::string& pat)
-  {
-    if (m_current_scope)
-      m_current_scope->clear_variable_regexp (pat);
-  }
-
   void clear_symbol_pattern (const std::string& pat)
   {
     // FIXME: are we supposed to do both here?
 
-    clear_variable_pattern (pat);
+    if (m_current_scope)
+      m_current_scope->clear_variable_pattern (pat);
+
     clear_function_pattern (pat);
   }
 
@@ -1460,45 +1331,6 @@
 
   void pop_context (void *) { pop_context (); }
 
-  void mark_hidden (const std::string& name)
-  {
-    if (m_current_scope)
-      m_current_scope->mark_hidden (name);
-  }
-
-  void mark_global (const std::string& name)
-  {
-    if (m_current_scope)
-      m_current_scope->mark_global (name);
-  }
-
-  // exclude: Storage classes to exclude, you can OR them together
-  std::list<symbol_record>
-  all_variables (scope *sid, bool defined_only, unsigned int exclude)
-  {
-    return (sid
-            ? sid->all_variables (defined_only, exclude)
-            : std::list<symbol_record> ());
-  }
-
-  std::list<symbol_record>
-  all_variables (scope *sid, bool defined_only)
-  {
-    return all_variables (sid, defined_only, symbol_record::hidden);
-  }
-
-  std::list<symbol_record>
-  all_variables (scope *sid)
-  {
-    return all_variables (sid, true);
-  }
-
-  std::list<symbol_record>
-  all_variables (void)
-  {
-    return all_variables (m_current_scope);
-  }
-
   std::list<symbol_record> glob (const std::string& pattern)
   {
     return (m_current_scope
@@ -1655,47 +1487,12 @@
     return retval;
   }
 
-  bool is_local_variable (const std::string& name)
-  {
-    return m_current_scope ? m_current_scope->is_local_variable (name) : false;
-  }
-
-  bool is_global (const std::string& name)
-  {
-    return m_current_scope ? m_current_scope->is_global (name) : false;
-  }
-
-  std::list<workspace_element> workspace_info (void)
-  {
-    return (m_current_scope
-            ? m_current_scope->workspace_info ()
-            : std::list<workspace_element> ());
-  }
-
   void dump (std::ostream& os, scope *sid);
 
   void dump_global (std::ostream& os);
 
   void dump_functions (std::ostream& os);
 
-  void cache_name (scope *sid, const std::string& name)
-  {
-    if (sid)
-      sid->cache_name (name);
-  }
-  void stash_dir_name_for_subfunctions (scope *sid,
-                                        const std::string& dir_name)
-  {
-    if (sid)
-      sid->stash_dir_name_for_subfunctions (dir_name);
-  }
-
-  void set_parent (scope *child_scope, scope *parent_scope)
-  {
-    if (child_scope)
-      child_scope->set_parent (parent_scope);
-  }
-
   void add_to_parent_map (const std::string& classname,
                           const std::list<std::string>& parent_list)
   {
@@ -1803,7 +1600,7 @@
         return p->second;
     }
 
-    void inherit (scope& donor_scope)
+    void inherit_internal (scope& donor_scope)
     {
       for (auto& nm_sr : m_symbols)
         {
@@ -1828,6 +1625,20 @@
         }
     }
 
+    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);
@@ -2059,7 +1870,8 @@
     }
 
     std::list<symbol_table::symbol_record>
-    all_variables (bool defined_only, unsigned int exclude) const
+    all_variables (bool defined_only = true,
+                   unsigned int exclude = symbol_table::symbol_record::hidden) const
     {
       std::list<symbol_table::symbol_record> retval;
 
@@ -2158,6 +1970,12 @@
                               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)
--- a/libinterp/corefcn/variables.cc	Thu Jun 15 10:47:50 2017 -0400
+++ b/libinterp/corefcn/variables.cc	Thu Jun 15 19:15:06 2017 -0400
@@ -89,9 +89,11 @@
 void
 clear_variable (const std::string& nm)
 {
-  symbol_table& symtab = octave::__get_symbol_table__ ("clear_variable");
-
-  symtab.clear_variable (nm);
+  symbol_table::scope *scope
+    = octave::__get_current_scope__ ("clear_variable");
+
+  if (scope)
+    scope->clear_variable (nm);
 }
 
 void
@@ -235,9 +237,10 @@
 
   if (! name.empty ())
     {
-      symbol_table& symtab = octave::__get_symbol_table__ ("is_variable");
-
-      octave_value val = symtab.varval (name);
+      symbol_table::scope *scope
+        = octave::__get_current_scope__ ("is_variable");
+
+      octave_value val = scope ? scope->varval (name) : octave_value ();
 
       retval = val.is_defined ();
     }
@@ -356,11 +359,11 @@
   if (! args(0).is_string ())
     error ("isglobal: NAME must be a string");
 
-  symbol_table& symtab = octave::__get_symbol_table__ ("do_isglobal");
+  symbol_table::scope *scope = octave::__get_current_scope__ ("do_isglobal");
 
   std::string name = args(0).string_value ();
 
-  return symtab.is_global (name);
+  return scope && scope->is_global (name);
 }
 
 DEFUN (isglobal, args, ,
@@ -414,7 +417,9 @@
 
   if (search_any || search_var)
     {
-      octave_value val = symtab.varval (name);
+      symbol_table::scope *scope = symtab.current_scope ();
+
+      octave_value val = scope ? scope->varval (name) : octave_value ();
 
       if (val.is_constant () || val.isobject ()
           || val.is_function_handle ()
@@ -695,9 +700,10 @@
 octave_value
 lookup_function_handle (const std::string& nm)
 {
-  symbol_table& symtab = octave::__get_symbol_table__ ("lookup_function_handle");
-
-  octave_value val = symtab.varval (nm);
+  symbol_table::scope *scope
+    = octave::__get_current_scope__ ("lookup_function_handle");
+
+  octave_value val = scope ? scope->varval (nm) : octave_value ();
 
   return val.is_function_handle () ? val : octave_value ();
 }
@@ -1706,7 +1712,7 @@
           cs.push (&tmp_scope, 0);
           frame.add_method (cs, &octave::call_stack::pop);
 
-          frame.add_method (symtab, &symbol_table::clear_variables);
+          frame.add_method (tmp_scope, &symbol_table::scope::clear_variables);
 
           octave::feval ("load", octave_value (nm), 0);
 
@@ -1745,15 +1751,18 @@
   symbol_info_list symbol_stats;
   std::list<std::string> symbol_names;
 
+  symbol_table::scope *scope = symtab.current_scope ();
+
   for (int j = 0; j < npats; j++)
     {
       std::string pat = pats[j];
 
       if (have_regexp)
         {
-          std::list<symbol_table::symbol_record> tmp = global_only
-            ? symtab.regexp_global_variables (pat)
-            : symtab.regexp_variables (pat);
+          std::list<symbol_table::symbol_record> tmp
+            = (global_only
+               ? symtab.regexp_global_variables (pat)
+               : symtab.regexp_variables (pat));
 
           for (const auto& symrec : tmp)
             {
@@ -1783,7 +1792,7 @@
 
                   std::string base_name = pat.substr (0, pos);
 
-                  if (symtab.is_variable (base_name))
+                  if (scope && scope->is_variable (base_name))
                     {
                       symbol_table::symbol_record sr
                         = symtab.find_symbol (base_name);
@@ -1802,9 +1811,10 @@
             }
           else
             {
-              std::list<symbol_table::symbol_record> tmp = global_only
-                ? symtab.glob_global_variables (pat)
-                : symtab.glob_variables (pat);
+              std::list<symbol_table::symbol_record> tmp
+                = (global_only
+                   ? symtab.glob_global_variables (pat)
+                   : symtab.glob_variables (pat));
 
               for (const auto& symrec : tmp)
                 {
@@ -1990,9 +2000,11 @@
         }
       else
         {
-          symbol_table& symtab = octave::__get_symbol_table__ ("bind_ans");
-
-          symtab.force_assign (ans, val);
+          symbol_table::scope *scope
+            = octave::__get_current_scope__ ("bind_ans");
+
+          if (scope)
+            scope->force_assign (ans, val);
 
           if (print)
             {
@@ -2241,6 +2253,11 @@
 {
   symbol_table& symtab = octave::__get_symbol_table__ ("do_clear_globals");
 
+  symbol_table::scope *scope = symtab.current_scope ();
+
+  if (! scope)
+    return;
+
   if (idx == argc)
     {
       string_vector gvars = symtab.global_variable_names ();
@@ -2248,7 +2265,7 @@
       int gcount = gvars.numel ();
 
       for (int i = 0; i < gcount; i++)
-        symtab.clear_global (gvars[i]);
+        scope->clear_global (gvars[i]);
     }
   else
     {
@@ -2263,13 +2280,13 @@
               std::string nm = gvars[i];
 
               if (! name_matches_any_pattern (nm, argv, argc, idx))
-                symtab.clear_global (nm);
+                scope->clear_global (nm);
             }
         }
       else
         {
           while (idx < argc)
-            symtab.clear_global_pattern (argv[idx++]);
+            scope->clear_global_pattern (argv[idx++]);
         }
     }
 }
@@ -2278,15 +2295,19 @@
 do_clear_variables (const string_vector& argv, int argc, int idx,
                     bool exclusive = false, bool have_regexp = false)
 {
-  symbol_table& symtab = octave::__get_symbol_table__ ("do_clear_variables");
+  symbol_table::scope *scope
+    = octave::__get_current_scope__ ("do_clear_variables");
+
+  if (! scope)
+    return;
 
   if (idx == argc)
-    symtab.clear_variables ();
+    scope->clear_variables ();
   else
     {
       if (exclusive)
         {
-          string_vector lvars = symtab.variable_names ();
+          string_vector lvars = scope->variable_names ();
 
           int lcount = lvars.numel ();
 
@@ -2295,17 +2316,17 @@
               std::string nm = lvars[i];
 
               if (! name_matches_any_pattern (nm, argv, argc, idx, have_regexp))
-                symtab.clear_variable (nm);
+                scope->clear_variable (nm);
             }
         }
       else
         {
           if (have_regexp)
             while (idx < argc)
-              symtab.clear_variable_regexp (argv[idx++]);
+              scope->clear_variable_regexp (argv[idx++]);
           else
             while (idx < argc)
-              symtab.clear_variable_pattern (argv[idx++]);
+              scope->clear_variable_pattern (argv[idx++]);
         }
     }
 }
@@ -2317,7 +2338,12 @@
   symbol_table& symtab = octave::__get_symbol_table__ ("do_clear_symbols");
 
   if (idx == argc)
-    symtab.clear_variables ();
+    {
+      symbol_table::scope *scope = symtab.current_scope ();
+
+      if (scope)
+        scope->clear_variables ();
+    }
   else
     {
       if (exclusive)
@@ -2343,34 +2369,40 @@
 {
   // This is supposed to be mostly Matlab compatible.
 
-  symbol_table& symtab = octave::__get_symbol_table__ ("do_matlab_compatible_clear");
+  symbol_table& symtab
+    = octave::__get_symbol_table__ ("do_matlab_compatible_clear");
+
+  symbol_table::scope *scope = symtab.current_scope ();
+
+  if (! scope)
+    return;
 
   for (; idx < argc; idx++)
     {
       if (argv[idx] == "all"
-          && ! symtab.is_local_variable ("all"))
+          && ! scope->is_local_variable ("all"))
         {
           symtab.clear_all ();
         }
       else if (argv[idx] == "functions"
-               && ! symtab.is_local_variable ("functions"))
+               && ! scope->is_local_variable ("functions"))
         {
           do_clear_functions (argv, argc, ++idx);
         }
       else if (argv[idx] == "global"
-               && ! symtab.is_local_variable ("global"))
+               && ! scope->is_local_variable ("global"))
         {
           do_clear_globals (argv, argc, ++idx);
         }
       else if (argv[idx] == "variables"
-               && ! symtab.is_local_variable ("variables"))
+               && ! scope->is_local_variable ("variables"))
         {
-          symtab.clear_variables ();
+          scope->clear_variables ();
         }
       else if (argv[idx] == "classes"
-               && ! symtab.is_local_variable ("classes"))
+               && ! scope->is_local_variable ("classes"))
         {
-          symtab.clear_objects ();
+          scope->clear_objects ();
           octave_class::clear_exemplar_map ();
           symtab.clear_all ();
         }
@@ -2488,6 +2520,7 @@
       bool have_dash_option = false;
 
       symbol_table& symtab = interp.get_symbol_table ();
+      symbol_table::scope *scope = symtab.current_scope ();
 
       while (++idx < argc)
         {
@@ -2575,7 +2608,8 @@
                 }
               else if (clear_objects)
                 {
-                  symtab.clear_objects ();
+                  if (scope)
+                    scope->clear_objects ();
                   octave_class::clear_exemplar_map ();
                   symtab.clear_all ();
                 }
@@ -2726,9 +2760,9 @@
 
   std::string name = args(0).xstring_value ("__varval__: first argument must be a variable name");
 
-  symbol_table& symtab = interp.get_symbol_table ();
-
-  return symtab.varval (args(0).string_value ());
+  symbol_table::scope *scope = interp.get_current_scope ();
+
+  return scope ? scope->varval (args(0).string_value ()) : octave_value ();
 }
 
 static std::string Vmissing_component_hook;
--- a/libinterp/octave-value/ov-classdef.cc	Thu Jun 15 10:47:50 2017 -0400
+++ b/libinterp/octave-value/ov-classdef.cc	Thu Jun 15 19:15:06 2017 -0400
@@ -1095,10 +1095,10 @@
           error ("cannot call superclass constructor with variable `%s'",
                  mname.c_str ());
 
-        symbol_table& symtab
-          = octave::__get_symbol_table__ ("octave_classdef_superclass_ref::call");
-
-        octave_value sym = symtab.varval (mname);
+        symbol_table::scope *scope
+          = octave::__require_current_scope__ ("octave_classdef_superclass_ref::call");
+
+        octave_value sym = scope->varval (mname);
 
         cls.run_constructor (to_cdef_ref (sym), idx);
 
--- a/libinterp/octave-value/ov-fcn-handle.cc	Thu Jun 15 10:47:50 2017 -0400
+++ b/libinterp/octave-value/ov-fcn-handle.cc	Thu Jun 15 19:15:06 2017 -0400
@@ -86,9 +86,10 @@
 
   if (uf && nm != anonymous)
     {
-      symbol_table& symtab = octave::__get_symbol_table__ ("octave_fcn_handle");
+      symbol_table::scope *uf_scope = uf->scope ();
 
-      symtab.cache_name (uf->scope (), nm);
+      if (uf_scope)
+        uf_scope->cache_name (nm);
     }
 
   if (uf && uf->is_nested_function () && ! uf->is_subfunction ())
@@ -351,13 +352,12 @@
       if (fcn.is_undefined ())
         return false;
 
-      octave_user_function *f = fcn.user_function_value ();
+      std::list<symbol_table::symbol_record> vars;
 
-      symbol_table& symtab
-        = octave::__get_symbol_table__ ("octave_fcn_handle::save_ascii");
-
-      std::list<symbol_table::symbol_record> vars
-        = symtab.all_variables (f->scope ());
+      octave_user_function *f = fcn.user_function_value ();
+      symbol_table::scope *f_scope = f->scope ();
+      if (f_scope)
+        vars = f_scope->all_variables ();
 
       size_t varlen = vars.size ();
 
@@ -489,7 +489,12 @@
                   octave_user_function *uf = fcn.user_function_value (true);
 
                   if (uf)
-                    symtab.cache_name (uf->scope (), nm);
+                    {
+                      symbol_table::scope *uf_scope = uf->scope ();
+
+                      if (uf_scope)
+                        uf_scope->cache_name (nm);
+                    }
                 }
               else
                 success = false;
@@ -516,13 +521,12 @@
       if (fcn.is_undefined ())
         return false;
 
-      octave_user_function *f = fcn.user_function_value ();
+      std::list<symbol_table::symbol_record> vars;
 
-      symbol_table& symtab
-        = octave::__get_symbol_table__ ("octave_fcn_handle::save_binary");
-
-      std::list<symbol_table::symbol_record> vars
-        = symtab.all_variables (f->scope ());
+      octave_user_function *f = fcn.user_function_value ();
+      symbol_table::scope *f_scope = f->scope ();
+      if (f_scope)
+        vars = f_scope->all_variables ();
 
       size_t varlen = vars.size ();
 
@@ -671,7 +675,12 @@
                   octave_user_function *uf = fcn.user_function_value (true);
 
                   if (uf)
-                    symtab.cache_name (uf->scope (), nm);
+                    {
+                      symbol_table::scope *uf_scope = uf->scope ();
+
+                      if (uf_scope)
+                        uf_scope->cache_name (nm);
+                    }
                 }
               else
                 success = false;
@@ -794,13 +803,12 @@
 
       H5Dclose (data_hid);
 
-      octave_user_function *f = fcn.user_function_value ();
+      std::list<symbol_table::symbol_record> vars;
 
-      symbol_table& symtab
-        = octave::__get_symbol_table__ ("octave_fcn_handle::load_hdf5");
-
-      std::list<symbol_table::symbol_record> vars
-        = symtab.all_variables (f->scope ());
+      octave_user_function *f = fcn.user_function_value ();
+      symbol_table::scope *f_scope = f->scope ();
+      if (f_scope)
+        vars = f_scope->all_variables ();
 
       size_t varlen = vars.size ();
 
@@ -1202,7 +1210,12 @@
                   octave_user_function *uf = fcn.user_function_value (true);
 
                   if (uf)
-                    symtab.cache_name (uf->scope (), nm);
+                    {
+                      symbol_table::scope *uf_scope = uf->scope ();
+
+                      if (uf_scope)
+                        uf_scope->cache_name (nm);
+                    }
                 }
               else
                 success = false;
@@ -1695,8 +1708,8 @@
 %! endfor
 */
 
-DEFMETHOD (functions, interp, args, ,
-           doc: /* -*- texinfo -*-
+DEFUN (functions, args, ,
+       doc: /* -*- texinfo -*-
 @deftypefn {} {@var{s} =} functions (@var{fcn_handle})
 Return a structure containing information about the function handle
 @var{fcn_handle}.
@@ -1791,12 +1804,12 @@
     {
       m.setfield ("file", nm);
 
-      octave_user_function *fu = fh->user_function_value ();
+      std::list<symbol_table::symbol_record> vars;
 
-      symbol_table& symtab = interp.get_symbol_table ();
-
-      std::list<symbol_table::symbol_record> vars
-        = symtab.all_variables (fu->scope ());
+      octave_user_function *fu = fh->user_function_value ();
+      symbol_table::scope *fu_scope = fu->scope ();
+      if (fu_scope)
+        vars = fu_scope->all_variables ();
 
       size_t varlen = vars.size ();
 
--- a/libinterp/octave-value/ov-usr-fcn.cc	Thu Jun 15 10:47:50 2017 -0400
+++ b/libinterp/octave-value/ov-usr-fcn.cc	Thu Jun 15 19:15:06 2017 -0400
@@ -825,7 +825,8 @@
     }
   else
     {
-      retval = symtab.varval (".nargin.");
+      symbol_table::scope *scope = symtab.require_current_scope ("nargin");
+      retval = scope->varval (".nargin.");
 
       if (retval.is_undefined ())
         retval = 0;
@@ -950,7 +951,8 @@
       if (symtab.at_top_level ())
         error ("nargout: invalid call at top level");
 
-      retval = symtab.varval (".nargout.");
+      symbol_table::scope *scope = symtab.require_current_scope ("nargout");
+      retval = scope->varval (".nargout.");
 
       if (retval.is_undefined ())
         retval = 0;
@@ -1022,10 +1024,12 @@
   if (symtab.at_top_level ())
     error ("isargout: invalid call at top level");
 
-  int nargout1 = symtab.varval (".nargout.").int_value ();
+  symbol_table::scope *scope = symtab.require_current_scope ("isargout");
+
+  int nargout1 = scope->varval (".nargout.").int_value ();
 
   Matrix ignored;
-  octave_value tmp = symtab.varval (".ignored.");
+  octave_value tmp = scope->varval (".ignored.");
   if (tmp.is_defined ())
     ignored = tmp.matrix_value ();
 
--- a/libinterp/parse-tree/lex.ll	Thu Jun 15 10:47:50 2017 -0400
+++ b/libinterp/parse-tree/lex.ll	Thu Jun 15 19:15:06 2017 -0400
@@ -2108,10 +2108,10 @@
   {
     if (empty ())
       {
-        symbol_table& symtab
-          = octave::__get_symbol_table__ ("lexical_feedback::symbol_table_context::curr_scope");
-
-        return symtab.current_scope ();
+        symbol_table::scope *scope
+          = octave::__get_current_scope__ ("lexical_feedback::symbol_table_context::curr_scope");
+
+        return scope;
       }
     else
       return frame_stack.front ();
--- a/libinterp/parse-tree/oct-parse.in.yy	Thu Jun 15 10:47:50 2017 -0400
+++ b/libinterp/parse-tree/oct-parse.in.yy	Thu Jun 15 19:15:06 2017 -0400
@@ -3396,7 +3396,9 @@
         symbol_table& symtab
           = octave::__get_symbol_table__ ("base_parser::finish_function");
 
-        symtab.cache_name (fcn->scope (), tmp);
+
+        symbol_table::scope *fcn_scope = fcn->scope ();
+        fcn_scope->cache_name (tmp);
 
         if (lc)
           fcn->stash_leading_comment (lc);
@@ -3407,29 +3409,27 @@
           {
             fcn->stash_fcn_location (l, c);
 
+            octave_value ov_fcn (fcn);
+
             if (endfunction_found && function_scopes.size () > 1)
               {
                 symbol_table::scope *pscope = function_scopes.parent_scope ();
 
-                symtab.install_nestfunction (nm, octave_value (fcn), pscope);
+                pscope->install_nestfunction (nm, ov_fcn);
               }
             else
               {
                 fcn->mark_as_subfunction ();
                 subfunction_names.push_back (nm);
 
-                symtab.install_subfunction (nm, octave_value (fcn),
-                                            primary_fcn_scope);
+                primary_fcn_scope->install_subfunction (nm, ov_fcn);
                }
           }
 
-        if (fcn)
-          {
-            if (parsing_local_functions )
-              symtab.install_local_function (nm, octave_value (fcn), file);
-            else if (curr_fcn_depth == 1)
-              symtab.update_nest (fcn->scope ());
-          }
+        if (parsing_local_functions )
+          symtab.install_local_function (nm, octave_value (fcn), file);
+        else if (curr_fcn_depth == 1)
+          fcn_scope->update_nest ();
 
         if (! lexer.reading_fcn_file && curr_fcn_depth == 1)
           {
@@ -4572,11 +4572,9 @@
 
         if (retval->is_user_function ())
           {
-            symbol_table::scope *id = retval->scope ();
-
-            symbol_table& symtab = octave::__get_symbol_table__ ("load_fcn_from_file");
-
-            symtab.stash_dir_name_for_subfunctions (id, dir_name);
+            symbol_table::scope *scope = retval->scope ();
+
+            scope->stash_dir_name_for_subfunctions (dir_name);
           }
       }
 
@@ -5443,9 +5441,10 @@
       if (octave::is_keyword (nm))
         error ("assignin: invalid assignment to keyword '%s'", nm.c_str ());
 
-      symbol_table& symtab = interp.get_symbol_table ();
-
-      symtab.assign (nm, args(2));
+      symbol_table::scope *scope = interp.get_current_scope ();
+
+      if (scope)
+        scope->assign (nm, args(2));
     }
   else
     error ("assignin: invalid variable name in argument VARNAME");
--- a/libinterp/parse-tree/pt-eval.cc	Thu Jun 15 10:47:50 2017 -0400
+++ b/libinterp/parse-tree/pt-eval.cc	Thu Jun 15 19:15:06 2017 -0400
@@ -106,7 +106,7 @@
     symbol_table::scope *new_scope = af_scope ? af_scope->dup () : 0;
 
     if (new_scope && af_parent_scope)
-      symtab.inherit (new_scope, af_parent_scope);
+      new_scope->inherit (af_parent_scope);
 
     tree_parameter_list *param_list_dup
       = param_list ? param_list->dup (*new_scope) : 0;
@@ -126,8 +126,7 @@
       = new octave_user_function (new_scope, param_list_dup, ret_list,
                                   stmt_list);
 
-    if (af_parent_scope)
-      symtab.set_parent (new_scope, af_parent_scope);
+    new_scope->set_parent (af_parent_scope);
 
     octave_function *curr_fcn = m_call_stack.current ();
 
@@ -481,9 +480,10 @@
 
     int count = 0;
 
-    symbol_table& symtab = m_interpreter.get_symbol_table ();
-
-    octave_value tmp = symtab.varval (".ignored.");
+    symbol_table::scope *scope
+      = m_interpreter.require_current_scope ("tree_evaluator::initialize_undefined_parameter_list_elements");
+
+    octave_value tmp = scope->varval (".ignored.");
     const Matrix ignored = (tmp.is_defined () ? tmp.matrix_value () : Matrix ());
 
     octave_idx_type k = 0;
@@ -973,7 +973,10 @@
         // Make sure that any variable with the same name as the new
         // function is cleared.
 
-        symtab.assign (nm);
+        symbol_table::scope *scope = symtab.current_scope ();
+
+        if (scope)
+          scope->assign (nm);
       }
   }
 
--- a/libinterp/parse-tree/pt-fcn-handle.cc	Thu Jun 15 10:47:50 2017 -0400
+++ b/libinterp/parse-tree/pt-fcn-handle.cc	Thu Jun 15 19:15:06 2017 -0400
@@ -83,6 +83,10 @@
 
     symbol_table::scope *new_scope = af_scope ? af_scope->dup () : 0;
 
+    // FIXME: why should we inherit from the current scope here?  That
+    // doesn't seem right, but with the way things work now it appears
+    // to be required for bug-31371.tst to pass.
+
     if (new_scope)
       symtab.inherit (new_scope);
 
--- a/libinterp/parse-tree/pt-jit.cc	Thu Jun 15 10:47:50 2017 -0400
+++ b/libinterp/parse-tree/pt-jit.cc	Thu Jun 15 19:15:06 2017 -0400
@@ -118,9 +118,9 @@
 jit_convert::jit_convert (tree& tee, jit_type *for_bounds)
   : converting_function (false)
 {
-  symbol_table& symtab = octave::__get_symbol_table__ ("jit_convert::jit_convert");
-
-  initialize (symtab.current_scope ());
+  symbol_table::scope *scope = octave::__get_current_scope__ ("jit_convert::jit_convert");
+
+  initialize (scope);
 
   if (for_bounds)
     create_variable (next_for_bounds (false), for_bounds);
@@ -2510,9 +2510,9 @@
 
   if (iter == extra_vars.end ())
     {
-      symbol_table& symtab = octave::__get_symbol_table__ ("jit_convert::find");
-
-      return symtab.varval (vname);
+      symbol_table::scope *scope = octave::__require_current_scope__ ("jit_convert::find");
+
+      return scope->varval (vname);
     }
   else
     return *iter->second;