changeset 33333:66a5438cc405

Make "symbol_scope_rep" a sub-class of "symbol_scope". * libinterp/corefcn/symscope.h (octave::symbol_scope::symbol_scope_rep): Make "symbol_scope_rep" a sub-class of "symbol_scope" so that both are complete classes when used in the context of each other. This fixes a compilation error with clang++ in C++20 mode. * libinterp/corefcn/symscope.cc: Adapt for that change. * libinterp/corefcn/symrec.h: Remove forward declaration of "class symbol_scope_rep". See: https://octave.discourse.group/t/5337
author Markus Mützel <markus.muetzel@gmx.de>
date Sun, 31 Mar 2024 13:46:25 +0200
parents d7f1aae5be0f
children 000e4454fbcc
files libinterp/corefcn/symrec.h libinterp/corefcn/symscope.cc libinterp/corefcn/symscope.h
diffstat 3 files changed, 315 insertions(+), 317 deletions(-) [+]
line wrap: on
line diff
--- a/libinterp/corefcn/symrec.h	Thu Apr 04 22:50:56 2024 -0400
+++ b/libinterp/corefcn/symrec.h	Sun Mar 31 13:46:25 2024 +0200
@@ -40,9 +40,7 @@
 
 OCTAVE_BEGIN_NAMESPACE(octave)
 
-class symbol_scope_rep;
-
-class symbol_record
+class OCTINTERP_API symbol_record
 {
 public:
 
--- a/libinterp/corefcn/symscope.cc	Thu Apr 04 22:50:56 2024 -0400
+++ b/libinterp/corefcn/symscope.cc	Sun Mar 31 13:46:25 2024 +0200
@@ -42,7 +42,7 @@
 
 OCTAVE_BEGIN_NAMESPACE(octave)
 
-symbol_record symbol_scope_rep::insert_local (const std::string& name)
+symbol_record symbol_scope::symbol_scope_rep::insert_local (const std::string& name)
 {
   symbol_record sym (name);
 
@@ -52,7 +52,7 @@
 }
 
 void
-symbol_scope_rep::insert_symbol_record (symbol_record& sr)
+symbol_scope::symbol_scope_rep::insert_symbol_record (symbol_record& sr)
 {
   std::size_t data_offset = num_symbols ();
   std::string name = sr.name ();
@@ -63,7 +63,7 @@
 }
 
 symbol_record
-symbol_scope_rep::insert (const std::string& name)
+symbol_scope::symbol_scope_rep::insert (const std::string& name)
 {
   table_iterator p = m_symbols.find (name);
 
@@ -95,7 +95,7 @@
 }
 
 std::list<octave_value>
-symbol_scope_rep::localfunctions () const
+symbol_scope::symbol_scope_rep::localfunctions () const
 {
   std::list<octave_value> retval;
 
@@ -133,7 +133,7 @@
 }
 
 octave_value
-symbol_scope_rep::dump () const
+symbol_scope::symbol_scope_rep::dump () const
 {
   std::map<std::string, octave_value> m
   = {{ "name", m_name },
@@ -148,7 +148,7 @@
 }
 
 octave_value
-symbol_scope_rep::dump_symbols_map () const
+symbol_scope::symbol_scope_rep::dump_symbols_map () const
 {
   std::map<std::string, octave_value> info_map;
 
@@ -163,7 +163,7 @@
 }
 
 std::list<symbol_record>
-symbol_scope_rep::symbol_list () const
+symbol_scope::symbol_scope_rep::symbol_list () const
 {
   std::list<symbol_record> retval;
 
@@ -174,7 +174,7 @@
 }
 
 octave_value
-symbol_scope_rep::find_subfunction (const std::string& name) const
+symbol_scope::symbol_scope_rep::find_subfunction (const std::string& name) const
 {
   subfunctions_const_iterator p = m_subfunctions.find (name);
 
@@ -190,7 +190,7 @@
 }
 
 void
-symbol_scope_rep::mark_subfunctions_in_scope_as_private (const std::string& class_name)
+symbol_scope::symbol_scope_rep::mark_subfunctions_in_scope_as_private (const std::string& class_name)
 {
   for (auto& nm_sf : m_subfunctions)
     {
@@ -202,7 +202,7 @@
 }
 
 std::list<std::string>
-symbol_scope_rep::parent_fcn_names () const
+symbol_scope::symbol_scope_rep::parent_fcn_names () const
 {
   std::list<std::string> retval;
 
@@ -219,25 +219,25 @@
 }
 
 void
-symbol_scope_rep::set_parent (const std::shared_ptr<symbol_scope_rep>& parent)
+symbol_scope::symbol_scope_rep::set_parent (const std::shared_ptr<symbol_scope::symbol_scope_rep>& parent)
 {
-  m_parent = std::weak_ptr<symbol_scope_rep> (parent);
+  m_parent = std::weak_ptr<symbol_scope::symbol_scope_rep> (parent);
 }
 
 void
-symbol_scope_rep::set_primary_parent (const std::shared_ptr<symbol_scope_rep>& parent)
+symbol_scope::symbol_scope_rep::set_primary_parent (const std::shared_ptr<symbol_scope::symbol_scope_rep>& parent)
 {
-  m_primary_parent = std::weak_ptr<symbol_scope_rep> (parent);
+  m_primary_parent = std::weak_ptr<symbol_scope::symbol_scope_rep> (parent);
 }
 
 void
-symbol_scope_rep::cache_dir_name (const std::string& name)
+symbol_scope::symbol_scope_rep::cache_dir_name (const std::string& name)
 {
   m_dir_name = sys::canonicalize_file_name (name);
 }
 
 bool
-symbol_scope_rep::is_relative (const std::shared_ptr<symbol_scope_rep>& scope) const
+symbol_scope::symbol_scope_rep::is_relative (const std::shared_ptr<symbol_scope::symbol_scope_rep>& scope) const
 {
   if (is_nested ())
     {
@@ -276,7 +276,7 @@
 }
 
 void
-symbol_scope_rep::mark_as_variable (const std::string& nm)
+symbol_scope::symbol_scope_rep::mark_as_variable (const std::string& nm)
 {
   table_iterator p = m_symbols.find (nm);
 
@@ -285,14 +285,14 @@
 }
 
 void
-symbol_scope_rep::mark_as_variables (const std::list<std::string>& lst)
+symbol_scope::symbol_scope_rep::mark_as_variables (const std::list<std::string>& lst)
 {
   for (const auto& nm : lst)
     mark_as_variable (nm);
 }
 
 bool
-symbol_scope_rep::is_variable (const std::string& nm) const
+symbol_scope::symbol_scope_rep::is_variable (const std::string& nm) const
 {
   table_const_iterator p = m_symbols.find (nm);
 
@@ -312,7 +312,7 @@
 }
 
 void
-symbol_scope_rep::update_nest ()
+symbol_scope::symbol_scope_rep::update_nest ()
 {
   auto t_parent = m_parent.lock ();
 
@@ -344,9 +344,9 @@
 }
 
 bool
-symbol_scope_rep::look_nonlocal (const std::string& name,
-                                 std::size_t offset,
-                                 symbol_record& result)
+symbol_scope::symbol_scope_rep::look_nonlocal (const std::string& name,
+                                               std::size_t offset,
+                                               symbol_record& result)
 {
   offset++;
 
@@ -388,7 +388,7 @@
   if (is_primary_fcn_scope ())
     return m_rep->localfunctions ();
 
-  std::shared_ptr<symbol_scope_rep> ppsr
+  std::shared_ptr<symbol_scope::symbol_scope_rep> ppsr
     = m_rep->primary_parent_scope_rep ();
 
   if (! ppsr)
--- a/libinterp/corefcn/symscope.h	Thu Apr 04 22:50:56 2024 -0400
+++ b/libinterp/corefcn/symscope.h	Sun Mar 31 13:46:25 2024 +0200
@@ -48,327 +48,327 @@
 
 OCTAVE_BEGIN_NAMESPACE(octave)
 
-class symbol_scope;
-
-class symbol_scope_rep
-  : public std::enable_shared_from_this<symbol_scope_rep>
+class OCTINTERP_API symbol_scope
 {
-public:
-
-  typedef std::map<std::string, symbol_record>::const_iterator
-    table_const_iterator;
-  typedef std::map<std::string, symbol_record>::iterator
-    table_iterator;
-
-  typedef std::map<std::string, octave_value>::const_iterator
-    subfunctions_const_iterator;
-  typedef std::map<std::string, octave_value>::iterator
-    subfunctions_iterator;
-
-  symbol_scope_rep (const std::string& name = "", bool add_ans = true)
-    : m_name (name), m_symbols (), m_subfunctions (),
-      m_persistent_values (), m_code (nullptr), m_fcn_name (),
-      m_fcn_file_name (), m_dir_name (), m_parent (),
-      m_primary_parent (), m_children (), m_nesting_depth (0),
-      m_is_static (false), m_is_primary_fcn_scope (false)
-  {
-    // Most scopes have ans as the first symbol, initially undefined.
-    if (add_ans)
-      insert_local ("ans");
-  }
-
-  OCTAVE_DISABLE_COPY_MOVE (symbol_scope_rep)
-
-  ~symbol_scope_rep () = default;
-
-  std::size_t num_symbols () const { return m_symbols.size (); }
-
-  // Simply inserts symbol.  No non-local searching.
-
-  symbol_record insert_local (const std::string& name);
-
-  void insert_symbol_record (symbol_record& sr);
-
-  bool is_nested () const { return m_nesting_depth > 0; }
-
-  std::size_t nesting_depth () const { return m_nesting_depth; }
-
-  void set_nesting_depth (std::size_t depth) { m_nesting_depth = depth; }
-
-  bool is_parent () const { return ! m_children.empty (); }
-
-  bool is_static () const { return m_is_static; }
-
-  void mark_static () { m_is_static = true; }
-
-  std::shared_ptr<symbol_scope_rep> parent_scope_rep () const
-  {
-    return m_parent.lock ();
-  }
-
-  std::shared_ptr<symbol_scope_rep> primary_parent_scope_rep () const
-  {
-    return m_primary_parent.lock ();
-  }
-
-  std::shared_ptr<symbol_scope_rep> dup () const
-  {
-    std::shared_ptr<symbol_scope_rep> new_sid
-      = std::shared_ptr<symbol_scope_rep> (new symbol_scope_rep (m_name));
-
-    for (const auto& nm_sr : m_symbols)
-      new_sid->m_symbols[nm_sr.first] = nm_sr.second.dup ();
-
-    new_sid->m_subfunctions = m_subfunctions;
-    new_sid->m_persistent_values = m_persistent_values;
-    new_sid->m_subfunction_names = m_subfunction_names;
-    new_sid->m_code = m_code;
-    new_sid->m_fcn_name = m_fcn_name;
-    new_sid->m_fcn_file_name = m_fcn_file_name;
-    new_sid->m_dir_name = m_dir_name;
-    new_sid->m_parent = m_parent;
-    new_sid->m_primary_parent = m_primary_parent;
-    new_sid->m_children = m_children;
-    new_sid->m_nesting_depth = m_nesting_depth;
-    new_sid->m_is_static = m_is_static;
-    new_sid->m_is_primary_fcn_scope = m_is_primary_fcn_scope;
-
-    return new_sid;
-  }
-
-  octave_value& persistent_varref (std::size_t data_offset)
-  {
-    return m_persistent_values[data_offset];
-  }
-
-  octave_value persistent_varval (std::size_t data_offset) const
-  {
-    auto p = m_persistent_values.find (data_offset);
-
-    return p == m_persistent_values.end () ? octave_value () : p->second;
-  }
-
-  symbol_record find_symbol (const std::string& name)
-  {
-    auto p = m_symbols.find (name);
-
-    if (p == m_symbols.end ())
-      return insert (name);
-    else
-      return p->second;
-  }
-
-  symbol_record lookup_symbol (const std::string& name) const
-  {
-    auto p = m_symbols.find (name);
-
-    return p == m_symbols.end () ? symbol_record () : p->second;
-  }
-
-  symbol_record insert (const std::string& name);
-
-  void rename (const std::string& old_name, const std::string& new_name)
-  {
-    auto p = m_symbols.find (old_name);
-
-    if (p != m_symbols.end ())
-      {
-        symbol_record sr = p->second;
-
-        sr.rename (new_name);
-
-        m_symbols.erase (p);
-
-        m_symbols[new_name] = sr;
-      }
-  }
-
-  void install_subfunction (const std::string& name,
-                            const octave_value& fval)
-  {
-    m_subfunctions[name] = fval;
-  }
-
-  void install_nestfunction (const std::string& name,
-                             const octave_value& fval,
-                             const symbol_scope& fcn_scope)
-  {
-    m_subfunctions[name] = fval;
-
-    m_children.push_back (fcn_scope);
-  }
-
-  octave_value find_subfunction (const std::string& name) const;
-
-  void lock_subfunctions ()
-  {
-    for (auto& nm_sf : m_subfunctions)
-      nm_sf.second.lock ();
-  }
-
-  void unlock_subfunctions ()
-  {
-    for (auto& nm_sf : m_subfunctions)
-      nm_sf.second.unlock ();
-  }
-
-  // Pairs of name, function objects.
-  std::map<std::string, octave_value> subfunctions () const
-  {
-    return m_subfunctions;
-  }
-
-  void erase_subfunctions ()
-  {
-    m_subfunctions.clear ();
-  }
-
-  void mark_subfunctions_in_scope_as_private (const std::string& class_name);
-
-  bool has_subfunctions () const
-  {
-    return ! m_subfunction_names.empty ();
-  }
-
-  void stash_subfunction_names (const std::list<std::string>& names)
-  {
-    m_subfunction_names = names;
-  }
-
-  std::list<std::string> subfunction_names () const
-  {
-    return m_subfunction_names;
-  }
-
-  std::list<octave_value> localfunctions () const;
-
-  octave_value dump () const;
-
-  std::string name () const { return m_name; }
-
-  void cache_name (const std::string& name) { m_name = name; }
-
-  std::string fcn_name () const { return m_fcn_name; }
-
-  void cache_fcn_name (const std::string& name) { m_fcn_name = name; }
-
-  std::list<std::string> parent_fcn_names () const;
-
-  octave_user_code * user_code () const { return m_code; }
-
-  void set_user_code (octave_user_code *code) { m_code = code; }
-
-  void set_parent (const std::shared_ptr<symbol_scope_rep>& parent);
-
-  void set_primary_parent (const std::shared_ptr<symbol_scope_rep>& parent);
-
-  void cache_fcn_file_name (const std::string& name)
-  {
-    m_fcn_file_name = name;
-  }
-
-  std::string fcn_file_name () const { return m_fcn_file_name; }
-
-  void cache_dir_name (const std::string& name);
-
-  std::string dir_name () const { return m_dir_name; }
-
-  void mark_primary_fcn_scope () { m_is_primary_fcn_scope = true; }
-
-  bool is_primary_fcn_scope () const { return m_is_primary_fcn_scope; }
-
-  bool is_relative (const std::shared_ptr<symbol_scope_rep>& scope) const;
-
-  void mark_as_variable (const std::string& nm);
-  void mark_as_variables (const std::list<std::string>& lst);
-
-  bool is_variable (const std::string& nm) const;
-
-  void update_nest ();
-
-  bool look_nonlocal (const std::string& name, std::size_t offset,
-                      symbol_record& result);
-
-  octave_value dump_symbols_map () const;
-
-  const std::map<std::string, symbol_record>& symbols () const
-  {
-    return m_symbols;
-  }
-
-  std::map<std::string, symbol_record>& symbols ()
-  {
-    return m_symbols;
-  }
-
-  std::list<symbol_record> symbol_list () const;
-
 private:
 
-  //! Name for this scope (usually the corresponding filename of the
-  //! function corresponding to the scope).
+  class symbol_scope_rep
+    : public std::enable_shared_from_this<symbol_scope_rep>
+  {
+  public:
+
+    typedef std::map<std::string, symbol_record>::const_iterator
+      table_const_iterator;
+    typedef std::map<std::string, symbol_record>::iterator
+      table_iterator;
+
+    typedef std::map<std::string, octave_value>::const_iterator
+      subfunctions_const_iterator;
+    typedef std::map<std::string, octave_value>::iterator
+      subfunctions_iterator;
 
-  std::string m_name;
+    symbol_scope_rep (const std::string& name = "", bool add_ans = true)
+      : m_name (name), m_symbols (), m_subfunctions (),
+        m_persistent_values (), m_code (nullptr), m_fcn_name (),
+        m_fcn_file_name (), m_dir_name (), m_parent (),
+        m_primary_parent (), m_children (), m_nesting_depth (0),
+        m_is_static (false), m_is_primary_fcn_scope (false)
+    {
+      // Most scopes have ans as the first symbol, initially undefined.
+      if (add_ans)
+        insert_local ("ans");
+    }
+
+    OCTAVE_DISABLE_COPY_MOVE (symbol_scope_rep)
+
+    ~symbol_scope_rep () = default;
+
+    std::size_t num_symbols () const { return m_symbols.size (); }
 
-  //! Map from symbol names to symbol info.
+    // Simply inserts symbol.  No non-local searching.
+
+    symbol_record insert_local (const std::string& name);
+
+    void insert_symbol_record (symbol_record& sr);
+
+    bool is_nested () const { return m_nesting_depth > 0; }
 
-  std::map<std::string, symbol_record> m_symbols;
+    std::size_t nesting_depth () const { return m_nesting_depth; }
+
+    void set_nesting_depth (std::size_t depth) { m_nesting_depth = depth; }
+
+    bool is_parent () const { return ! m_children.empty (); }
+
+    bool is_static () const { return m_is_static; }
+
+    void mark_static () { m_is_static = true; }
 
-  //! Map from symbol names to subfunctions.
+    std::shared_ptr<symbol_scope_rep> parent_scope_rep () const
+    {
+      return m_parent.lock ();
+    }
 
-  std::map<std::string, octave_value> m_subfunctions;
+    std::shared_ptr<symbol_scope_rep> primary_parent_scope_rep () const
+    {
+      return m_primary_parent.lock ();
+    }
+
+    std::shared_ptr<symbol_scope_rep> dup () const
+    {
+      std::shared_ptr<symbol_scope_rep> new_sid
+        = std::shared_ptr<symbol_scope_rep> (new symbol_scope_rep (m_name));
+
+      for (const auto& nm_sr : m_symbols)
+        new_sid->m_symbols[nm_sr.first] = nm_sr.second.dup ();
 
-  //! Map from data offset to persistent values in this scope.
-  std::map<std::size_t, octave_value> m_persistent_values;
+      new_sid->m_subfunctions = m_subfunctions;
+      new_sid->m_persistent_values = m_persistent_values;
+      new_sid->m_subfunction_names = m_subfunction_names;
+      new_sid->m_code = m_code;
+      new_sid->m_fcn_name = m_fcn_name;
+      new_sid->m_fcn_file_name = m_fcn_file_name;
+      new_sid->m_dir_name = m_dir_name;
+      new_sid->m_parent = m_parent;
+      new_sid->m_primary_parent = m_primary_parent;
+      new_sid->m_children = m_children;
+      new_sid->m_nesting_depth = m_nesting_depth;
+      new_sid->m_is_static = m_is_static;
+      new_sid->m_is_primary_fcn_scope = m_is_primary_fcn_scope;
+
+      return new_sid;
+    }
 
-  //! The list of subfunctions (if any) in the order they appear in
-  //! the function file.
+    octave_value& persistent_varref (std::size_t data_offset)
+    {
+      return m_persistent_values[data_offset];
+    }
+
+    octave_value persistent_varval (std::size_t data_offset) const
+    {
+      auto p = m_persistent_values.find (data_offset);
+
+      return p == m_persistent_values.end () ? octave_value () : p->second;
+    }
 
-  std::list<std::string> m_subfunction_names;
+    symbol_record find_symbol (const std::string& name)
+    {
+      auto p = m_symbols.find (name);
+
+      if (p == m_symbols.end ())
+        return insert (name);
+      else
+        return p->second;
+    }
+
+    symbol_record lookup_symbol (const std::string& name) const
+    {
+      auto p = m_symbols.find (name);
 
-  //! The associated user code (may be null).
+      return p == m_symbols.end () ? symbol_record () : p->second;
+    }
+
+    symbol_record insert (const std::string& name);
+
+    void rename (const std::string& old_name, const std::string& new_name)
+    {
+      auto p = m_symbols.find (old_name);
 
-  octave_user_code *m_code;
+      if (p != m_symbols.end ())
+        {
+          symbol_record sr = p->second;
+
+          sr.rename (new_name);
+
+          m_symbols.erase (p);
+
+          m_symbols[new_name] = sr;
+        }
+    }
 
-  //! Simple name of the function corresponding to this scope.
+    void install_subfunction (const std::string& name,
+                              const octave_value& fval)
+    {
+      m_subfunctions[name] = fval;
+    }
 
-  std::string m_fcn_name;
+    void install_nestfunction (const std::string& name,
+                               const octave_value& fval,
+                               const symbol_scope& fcn_scope)
+    {
+      m_subfunctions[name] = fval;
 
-  //! The file name associated with m_code.
+      m_children.push_back (fcn_scope);
+    }
+
+    octave_value find_subfunction (const std::string& name) const;
+
+    void lock_subfunctions ()
+    {
+      for (auto& nm_sf : m_subfunctions)
+        nm_sf.second.lock ();
+    }
 
-  std::string m_fcn_file_name;
+    void unlock_subfunctions ()
+    {
+      for (auto& nm_sf : m_subfunctions)
+        nm_sf.second.unlock ();
+    }
 
-  //! The directory associated with m_code.
+    // Pairs of name, function objects.
+    std::map<std::string, octave_value> subfunctions () const
+    {
+      return m_subfunctions;
+    }
+
+    void erase_subfunctions ()
+    {
+      m_subfunctions.clear ();
+    }
+
+    void mark_subfunctions_in_scope_as_private (const std::string& class_name);
 
-  std::string m_dir_name;
+    bool has_subfunctions () const
+    {
+      return ! m_subfunction_names.empty ();
+    }
+
+    void stash_subfunction_names (const std::list<std::string>& names)
+    {
+      m_subfunction_names = names;
+    }
 
-  //! Parent of nested function (may be null).
+    std::list<std::string> subfunction_names () const
+    {
+      return m_subfunction_names;
+    }
+
+    std::list<octave_value> localfunctions () const;
+
+    octave_value dump () const;
+
+    std::string name () const { return m_name; }
 
-  std::weak_ptr<symbol_scope_rep> m_parent;
+    void cache_name (const std::string& name) { m_name = name; }
+
+    std::string fcn_name () const { return m_fcn_name; }
+
+    void cache_fcn_name (const std::string& name) { m_fcn_name = name; }
+
+    std::list<std::string> parent_fcn_names () const;
+
+    octave_user_code * user_code () const { return m_code; }
+
+    void set_user_code (octave_user_code *code) { m_code = code; }
+
+    void set_parent (const std::shared_ptr<symbol_scope_rep>& parent);
+
+    void set_primary_parent (const std::shared_ptr<symbol_scope_rep>& parent);
 
-  //! Primary (top) parent of nested function (may be null).  Used
-  //! to determine whether two nested functions are related.
+    void cache_fcn_file_name (const std::string& name)
+    {
+      m_fcn_file_name = name;
+    }
+
+    std::string fcn_file_name () const { return m_fcn_file_name; }
+
+    void cache_dir_name (const std::string& name);
+
+    std::string dir_name () const { return m_dir_name; }
 
-  std::weak_ptr<symbol_scope_rep> m_primary_parent;
+    void mark_primary_fcn_scope () { m_is_primary_fcn_scope = true; }
+
+    bool is_primary_fcn_scope () const { return m_is_primary_fcn_scope; }
+
+    bool is_relative (const std::shared_ptr<symbol_scope_rep>& scope) const;
 
-  //! Child nested functions.
+    void mark_as_variable (const std::string& nm);
+    void mark_as_variables (const std::list<std::string>& lst);
+
+    bool is_variable (const std::string& nm) const;
+
+    void update_nest ();
 
-  std::vector<symbol_scope> m_children;
+    bool look_nonlocal (const std::string& name, std::size_t offset,
+                        symbol_record& result);
+
+    octave_value dump_symbols_map () const;
 
-  //! If true, then this scope belongs to a nested function.
+    const std::map<std::string, symbol_record>& symbols () const
+    {
+      return m_symbols;
+    }
+
+    std::map<std::string, symbol_record>& symbols ()
+    {
+      return m_symbols;
+    }
+
+    std::list<symbol_record> symbol_list () const;
+
+  private:
 
-  std::size_t m_nesting_depth;
+    //! Name for this scope (usually the corresponding filename of the
+    //! function corresponding to the scope).
+
+    std::string m_name;
+
+    //! Map from symbol names to symbol info.
+
+    std::map<std::string, symbol_record> m_symbols;
 
-  //! If true then no variables can be added.
+    //! Map from symbol names to subfunctions.
+
+    std::map<std::string, octave_value> m_subfunctions;
+
+    //! Map from data offset to persistent values in this scope.
+    std::map<std::size_t, octave_value> m_persistent_values;
+
+    //! The list of subfunctions (if any) in the order they appear in
+    //! the function file.
+
+    std::list<std::string> m_subfunction_names;
 
-  bool m_is_static;
+    //! The associated user code (may be null).
+
+    octave_user_code *m_code;
+
+    //! Simple name of the function corresponding to this scope.
+
+    std::string m_fcn_name;
+
+    //! The file name associated with m_code.
+
+    std::string m_fcn_file_name;
+
+    //! The directory associated with m_code.
+
+    std::string m_dir_name;
+
+    //! Parent of nested function (may be null).
+
+    std::weak_ptr<symbol_scope_rep> m_parent;
 
-  //! If true, this is the scope of a primary function.
-  bool m_is_primary_fcn_scope;
-};
+    //! Primary (top) parent of nested function (may be null).  Used
+    //! to determine whether two nested functions are related.
+
+    std::weak_ptr<symbol_scope_rep> m_primary_parent;
+
+    //! Child nested functions.
+
+    std::vector<symbol_scope> m_children;
+
+    //! If true, then this scope belongs to a nested function.
 
-class symbol_scope
-{
+    std::size_t m_nesting_depth;
+
+    //! If true then no variables can be added.
+
+    bool m_is_static;
+
+    //! If true, this is the scope of a primary function.
+    bool m_is_primary_fcn_scope;
+  };
+
 public:
 
   symbol_scope () = delete;