changeset 32141:e1aacfd46471

new value class to manage references to octave_value objects * ov-ref.h, ov-ref.cc: New files. * libinterp/octave-value/module.mk: Update. * ov-base.h, ov-base.cc (octave_base_value::is_ref, octave_base_value::ref_rep): New virtual functions. * ov.h (octave_value::is_ref, octave_value::ref_rep): New functions.
author Petter T. <petter.vilhelm@gmail.com>
date Mon, 19 Jun 2023 13:13:03 -0400
parents 8877fb5301b6
children 53ba75432f02
files libinterp/octave-value/module.mk libinterp/octave-value/ov-base.cc libinterp/octave-value/ov-base.h libinterp/octave-value/ov-ref.cc libinterp/octave-value/ov-ref.h libinterp/octave-value/ov.h
diffstat 6 files changed, 261 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- a/libinterp/octave-value/module.mk	Mon Jun 19 12:01:24 2023 -0400
+++ b/libinterp/octave-value/module.mk	Mon Jun 19 13:13:03 2023 -0400
@@ -62,6 +62,7 @@
   %reldir%/ov-perm.h \
   %reldir%/ov-range-traits.h \
   %reldir%/ov-range.h \
+  %reldir%/ov-ref.h \
   %reldir%/ov-re-diag.h \
   %reldir%/ov-re-mat.h \
   %reldir%/ov-scalar.h \
@@ -128,6 +129,7 @@
   %reldir%/ov-oncleanup.cc \
   %reldir%/ov-perm.cc \
   %reldir%/ov-range.cc \
+  %reldir%/ov-ref.cc \
   %reldir%/ov-re-diag.cc \
   %reldir%/ov-re-mat.cc \
   %reldir%/ov-scalar.cc \
--- a/libinterp/octave-value/ov-base.cc	Mon Jun 19 12:01:24 2023 -0400
+++ b/libinterp/octave-value/ov-base.cc	Mon Jun 19 13:13:03 2023 -0400
@@ -950,6 +950,14 @@
   return nullptr;
 }
 
+octave_value_ref *
+octave_base_value::ref_rep ()
+{
+  err_wrong_type_arg ("octave_base_value::ref_value()", type_name ());
+
+  return nullptr;
+}
+
 octave_user_function *
 octave_base_value::user_function_value (bool silent)
 {
--- a/libinterp/octave-value/ov-base.h	Mon Jun 19 12:01:24 2023 -0400
+++ b/libinterp/octave-value/ov-base.h	Mon Jun 19 13:13:03 2023 -0400
@@ -805,6 +805,10 @@
 
   virtual octave_base_value * make_storable_value (void);
 
+  virtual bool is_ref () const { return false; }
+
+  virtual octave_value_ref * ref_rep ();
+
   virtual bool maybe_update_double (double d);
 
   virtual bool is_trivial_range () const { return false; };
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libinterp/octave-value/ov-ref.cc	Mon Jun 19 13:13:03 2023 -0400
@@ -0,0 +1,123 @@
+////////////////////////////////////////////////////////////////////////
+//
+// Copyright (C) 2007-2023 The Octave Project Developers
+//
+// See the file COPYRIGHT.md in the top-level directory of this
+// distribution or <https://octave.org/copyright/>.
+//
+// This file is part of Octave.
+//
+// Octave is free software: you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Octave is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Octave; see the file COPYING.  If not, see
+// <https://www.gnu.org/licenses/>.
+//
+////////////////////////////////////////////////////////////////////////
+
+#if defined (HAVE_CONFIG_H)
+#  include "config.h"
+#endif
+
+#include "ov.h"
+#include "ov-ref.h"
+
+
+#include "interpreter.h"
+#include "interpreter-private.h"
+
+DEFINE_OV_TYPEID_FUNCTIONS_AND_DATA (octave_value_ref_global,
+                                     "global value reference",
+                                     "global value reference");
+DEFINE_OV_TYPEID_FUNCTIONS_AND_DATA (octave_value_ref_persistent,
+                                     "global value persistent",
+                                     "global value persistent");
+void
+octave_value_ref::maybe_call_dtor ()
+{
+  ref ().m_rep->maybe_call_dtor ();
+}
+
+bool
+octave_value_ref::is_defined () const
+{
+  return const_cast<octave_value_ref*> (this)->ref ().m_rep->is_defined ();
+}
+
+bool
+octave_value_ref::is_maybe_function () const
+{
+  return const_cast<octave_value_ref*> (this)->ref ().m_rep->is_maybe_function ();
+}
+
+octave_base_value *
+octave_value_ref::unique_clone () 
+{
+  return ref ().m_rep->unique_clone ();
+}
+
+octave_value 
+octave_value_ref::simple_subsasgn (char type, octave_value_list& idx, const octave_value& rhs)
+{
+  octave_value ans = ref ().m_rep->simple_subsasgn (type, idx, rhs);
+  ref () = ans;
+  return octave_value {this, true};
+}
+
+octave_value
+octave_value_ref::subsasgn (const std::string& type,
+                            const std::list<octave_value_list>& idx,
+                            const octave_value& rhs)
+{
+  octave_value ans = ref ().m_rep->subsasgn (type, idx, rhs);
+  ref () = ans;
+  return octave_value {this, true};
+}
+
+octave_value
+octave_value_ref_global::deref ()
+{
+  auto &interp = octave::__get_interpreter__();
+  return interp.global_varval (m_name);
+}
+
+void
+octave_value_ref_global::set_value (octave_value val)
+{
+  auto &interp = octave::__get_interpreter__();
+  interp.global_assign (m_name, val);
+}
+
+octave_value&
+octave_value_ref_global::ref ()
+{
+  auto& tw = octave::__get_evaluator__();
+  return tw.global_varref (m_name);
+}
+
+octave_value
+octave_value_ref_persistent::deref ()
+{
+  return m_scope.persistent_varval (m_offset);
+}
+
+void
+octave_value_ref_persistent::set_value (octave_value val)
+{
+  octave_value &ov_pers = m_scope.persistent_varref (m_offset);
+  ov_pers = val;
+}
+
+octave_value &
+octave_value_ref_persistent::ref ()
+{
+  return m_scope.persistent_varref (m_offset);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libinterp/octave-value/ov-ref.h	Mon Jun 19 13:13:03 2023 -0400
@@ -0,0 +1,117 @@
+////////////////////////////////////////////////////////////////////////
+//
+// Copyright (C) 1996-2023 The Octave Project Developers
+//
+// See the file COPYRIGHT.md in the top-level directory of this
+// distribution or <https://octave.org/copyright/>.
+//
+// This file is part of Octave.
+//
+// Octave is free software: you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Octave is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Octave; see the file COPYING.  If not, see
+// <https://www.gnu.org/licenses/>.
+//
+////////////////////////////////////////////////////////////////////////
+
+#if ! defined (octave_ov_ref_h)
+#define octave_ov_ref_h 1
+
+#include "octave-config.h"
+
+#include "ov-base.h"
+#include "ovl.h"
+#include "symscope.h"
+
+#include <string>
+#include <memory>
+
+// octave_value_ref is to be used by the VM to implement
+// global and persistent values.
+//
+// octave_value_ref need to overload any virtual call
+// used by the assign and push slot op-codes.
+//
+// Any octave_value_ref should never leave the VM slots
+// on the VM stack.
+
+// Abstract type
+class OCTINTERP_API
+octave_value_ref : public octave_base_value
+{
+public:
+    octave_value_ref () = default;
+    ~octave_value_ref () = default;
+
+    octave_value_ref * ref_rep () { return this; }
+    bool is_ref () const { return true; }
+
+    virtual octave_value deref () = 0;
+    virtual void set_value (octave_value val) = 0;
+    virtual octave_value & ref () = 0;
+    virtual void maybe_save_state  () {};
+
+    virtual bool is_global_ref () { return false; }
+    virtual bool is_persistent_ref () { return false; }
+
+    void maybe_call_dtor ();
+    octave_value simple_subsasgn (char type, octave_value_list& idx, const octave_value& rhs);
+    octave_value subsasgn (const std::string& type, const std::list<octave_value_list>& idx, const octave_value& rhs);
+    octave_base_value * unique_clone ();
+    bool is_defined () const;
+    bool is_maybe_function (void) const;
+};
+
+class OCTINTERP_API
+octave_value_ref_global : public octave_value_ref
+{
+public:
+    octave_value_ref_global () = default;
+    ~octave_value_ref_global () = default;
+    octave_value_ref_global (std::string name)
+        : m_name (name) {};
+
+    octave_value deref ();
+    octave_value & ref ();
+    void set_value (octave_value val);
+    
+    bool is_global_ref () { return true; }
+
+private:
+    std::string m_name;
+
+    DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA
+};
+
+class OCTINTERP_API
+octave_value_ref_persistent : public octave_value_ref
+{
+public:
+    octave_value_ref_persistent () = default;
+    ~octave_value_ref_persistent () = default;
+    octave_value_ref_persistent (octave::symbol_scope scope, int offset)
+        : m_offset (offset), m_scope (scope) {};
+
+    octave_value deref ();
+    octave_value & ref ();
+    void set_value (octave_value val);
+    
+    bool is_persistent_ref () { return true; }
+
+private:
+    int m_offset;
+    octave::symbol_scope m_scope;
+
+    DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA
+};
+
+#endif
--- a/libinterp/octave-value/ov.h	Mon Jun 19 12:01:24 2023 -0400
+++ b/libinterp/octave-value/ov.h	Mon Jun 19 13:13:03 2023 -0400
@@ -1535,6 +1535,13 @@
 
 protected:
 
+  // Functions for use by the VM.
+  friend class octave_value_ref;
+
+  bool is_ref () const { return m_rep->is_ref (); }
+
+  octave_value_ref * ref_rep () { return m_rep->ref_rep (); }
+
   // True for the types based on ov-base-mat
   bool is_full_num_matrix () const
   { return m_rep->is_full_num_matrix (); }