diff libinterp/octave-value/ov-fcn-handle.h @ 28439:e760fef2829c stable

refactor octave_fcn_handle class * ov-fcn-handle.h, ov-fcn-handle.cc (class octave_fcn_handle): split octave_fcn_handle internally into separate sub-classes for the following types of function handles: simple, scoped, nested, classsimple, and anonymous. Update all uses. * load-path.cc (load_path::package_info::find_private_fcn): Don't search for private files that are not already in the private function map. * ls-mat5.cc (read_mat5_binary_element): Update handling of local variables for anonymous functions. * stack-frame.h, stack-frame.cc (stack_frame::set_closure_links, stack_frame::dup, compiled_fcn_stack_frame::dup, script_stack_frame::dup, user_fcn_stack_frame::dup, scope_stack_frame::dup): Delete unnecessary functions. * ov-fcn.h (octave_function::is_nested_function, octave_function::is_parent_function): New virtual functions.
author John W. Eaton <jwe@octave.org>
date Wed, 29 Apr 2020 14:10:27 -0400
parents d05a4194f1ad
children 1be719d8b375
line wrap: on
line diff
--- a/libinterp/octave-value/ov-fcn-handle.h	Wed Jun 10 17:01:31 2020 -0400
+++ b/libinterp/octave-value/ov-fcn-handle.h	Wed Apr 29 14:10:27 2020 -0400
@@ -32,6 +32,7 @@
 #include <list>
 #include <string>
 
+#include "oct-map.h"
 #include "ov-base.h"
 #include "ov-fcn.h"
 #include "ov-typeinfo.h"
@@ -42,9 +43,118 @@
 {
   class interpreter;
   class tree_evaluator;
-}
+
+  // Function handles.
+
+  class base_fcn_handle
+  {
+  public:
+
+    base_fcn_handle (const std::string& name = "",
+                     const std::string& file = "")
+      : m_name (name), m_file (file)
+    { }
+
+    base_fcn_handle (const base_fcn_handle&) = default;
+
+    virtual ~base_fcn_handle (void) = default;
+
+    virtual base_fcn_handle * clone (void) const = 0;
+
+    virtual std::string type (void) const = 0;
+
+    virtual bool is_internal (void) const { return false; }
+
+    virtual bool is_simple (void) const { return false; }
+
+    virtual bool is_scoped (void) const { return false; }
+
+    virtual bool is_nested (void) const { return false; }
+
+    virtual bool is_class_simple (void) const { return false; }
+
+    virtual bool is_anonymous (void) const { return false; }
+
+    std::string fcn_name (void) const { return m_name; }
+
+    std::string file (void) const { return m_file; }
+
+    octave_value_list
+    subsref (const std::string& type, const std::list<octave_value_list>& idx,
+             int nargout);
+
+    virtual octave_value_list
+    call (int nargout, const octave_value_list& args) = 0;
+
+    // FIXME: These must go away.  They don't do the right thing for
+    // scoping or overloads.
+    virtual octave_function * function_value (bool = false)
+    {
+      return nullptr;
+    }
+
+    virtual octave_user_function * user_function_value (bool = false)
+    {
+      return nullptr;
+    }
 
-// Function handles.
+    virtual octave_value fcn_val (void) { return octave_value (); }
+
+    virtual octave_value workspace (void) const { return octave_value (); }
+
+    // Should be const.
+    virtual octave_scalar_map info (void) { return octave_scalar_map (); }
+
+    virtual void set_dispatch_class (const std::string& /*class_name*/) { }
+
+    virtual std::string get_dispatch_class (void) const { return ""; }
+
+    octave_value convert_to_str_internal (bool pad, bool force, char type) const;
+
+    virtual bool save_ascii (std::ostream& os);
+
+    virtual bool load_ascii (std::istream& is);
+
+    virtual bool save_binary (std::ostream& os, bool save_as_floats);
+
+    virtual bool load_binary (std::istream& is, bool swap,
+                              mach_info::float_format fmt);
+
+    virtual bool save_hdf5 (octave_hdf5_id loc_id, const char *name,
+                            bool save_as_floats);
+
+    virtual bool load_hdf5 (octave_hdf5_id& group_hid,
+                            octave_hdf5_id& space_hid,
+                            octave_hdf5_id& type_hid);
+
+    virtual void print_raw (std::ostream&, bool /*pr_as_read_syntax*/,
+                            int /*current_print_indent_level*/) const
+    { }
+
+    // Function handles are printed without a newline by default.
+    virtual bool print_as_scalar (void) const { return true; }
+
+    virtual bool
+    set_fcn (const std::string& /*octaveroot*/, const std::string& /*fpath*/)
+    {
+      return false;
+    }
+
+  protected:
+
+    void warn_load (const char *file_type) const;
+    void warn_save (const char *file_type) const;
+
+    void unimplemented (const char *op, const char *fmt) const;
+
+    // The name of the handle, not including the "@", or the text of the
+    // anonymous function.
+    std::string m_name;
+
+    // The name of the file where the named function was defined.
+    std::string m_file;
+  };
+}
 
 class
 OCTINTERP_API
@@ -54,42 +164,56 @@
 
   static const std::string anonymous;
 
-  octave_fcn_handle (void)
-    : m_fcn (), m_obj (), m_name (), m_scope (), m_is_nested (false),
-      m_closure_frames (), m_local_vars (nullptr), m_dispatch_class ()
-  { }
+  // Creates an invalid function handle.  Used to create generic
+  // function handle objects when loading function handles.  Further
+  // dispatch happens in the octave_fcn_handle load/save functions.
+  octave_fcn_handle (void);
 
-  // OCTAVE_DEPRECATED (6, "foobar-1")
+  // Create a handle to a built-in or internal function.
+  octave_fcn_handle (const octave_value& fcn);
+
+  // Create a simple function handle that is not bound to a function.
+  // Lookup happens when a function call is attempted.
   octave_fcn_handle (const std::string& name);
 
-  // OCTAVE_DEPRECATED (6, "foobar-2")
-  octave_fcn_handle (const octave::symbol_scope& scope,
-                     const std::string& name);
+  // Create a simple function handle that is bound to a function.
+  octave_fcn_handle (const octave_value& fcn, const std::string& name);
+
+  // Create a function handle bound to a class method.
+  octave_fcn_handle (const octave_value& fcn, const std::string& class_nm,
+                     const std::string& meth_nm);
 
-  // OCTAVE_DEPRECATED (6, "foobar-3")
-  octave_fcn_handle (const octave::symbol_scope& scope,
-                     const octave_value& f, const std::string& name);
+  // Create a function handle bound to a class method.
+  octave_fcn_handle (const octave_value& obj, const octave_value& fcn,
+                     const std::string& class_nm,
+                     const std::string& meth_nm);
 
-  // OCTAVE_DEPRECATED (6, "foobar-4")
-  octave_fcn_handle (const octave_value& f, const std::string& name);
-
-  // OCTAVE_DEPRECATED (6, "foobar-5")
+  // Create a function handle bound to a scoped function.
   octave_fcn_handle (const octave_value& fcn, const std::string& name,
                      const std::list<std::string>& parentage);
 
-  // OCTAVE_DEPRECATED (6, "foobar-6")
+  // Create a handle to a nested function.
+  octave_fcn_handle (const octave_value& fcn, const std::string& name,
+                     const std::shared_ptr<octave::stack_frame>& closure_frames);
+
+  // Create an anonymous function handle with local variable values
+  // provided in LOCAL_VARS.
   octave_fcn_handle (const octave_value& fcn,
                      const octave::stack_frame::local_vars_map& local_vars);
 
-  // OCTAVE_DEPRECATED (6, "foobar-7")
   octave_fcn_handle (const octave_fcn_handle& fh);
 
-  ~octave_fcn_handle (void);
+  ~octave_fcn_handle (void) = default;
 
   octave_base_value * clone (void) const
-  { return new octave_fcn_handle (*this); }
+  {
+    return new octave_fcn_handle (*this);
+  }
+
   octave_base_value * empty_clone (void) const
-  { return new octave_fcn_handle (); }
+  {
+    return new octave_fcn_handle ();
+  }
 
   // We don't need to override all three forms of subsref.  The using
   // declaration will avoid warnings about partially-overloaded virtual
@@ -105,43 +229,71 @@
 
   octave_value_list subsref (const std::string& type,
                              const std::list<octave_value_list>& idx,
-                             int nargout);
+                             int nargout)
+  {
+    return m_rep->subsref (type, idx, nargout);
+  }
+
+  octave_value_list call (int nargout, const octave_value_list& args);
 
   bool is_defined (void) const { return true; }
 
   bool is_function_handle (void) const { return true; }
 
-  bool is_anonymous (void) const { return m_name == anonymous; }
+  bool is_internal (void) const { return m_rep->is_internal (); }
+
+  bool is_simple (void) const { return m_rep->is_simple (); }
+
+  bool is_scoped (void) const { return m_rep->is_scoped (); }
 
-  bool is_nested (void) const { return m_is_nested; }
+  bool is_nested (void) const { return m_rep->is_nested (); }
+
+  bool is_class_simple (void) const { return m_rep->is_class_simple (); }
+
+  bool is_anonymous (void) const { return m_rep->is_anonymous (); }
 
   dim_vector dims (void) const;
 
   // FIXME: These must go away.  They don't do the right thing for
   // scoping or overloads.
-  octave_function * function_value (bool = false);
-  octave_user_function * user_function_value (bool = false);
+  octave_function * function_value (bool = false)
+  {
+    return m_rep->function_value ();
+  }
+
+  octave_user_function * user_function_value (bool = false)
+  {
+    return m_rep->user_function_value ();
+  }
 
   octave_fcn_handle * fcn_handle_value (bool = false) { return this; }
 
-  octave_value fcn_val (void) const { return m_fcn; }
+  octave_value fcn_val (void) { return m_rep->fcn_val (); }
 
-  std::string fcn_name (void) const { return m_name; }
+  // FCN_NAME should be eliminated.
+  std::string fcn_name (void) const { return m_rep->fcn_name (); }
 
-  void push_closure_context (octave::tree_evaluator& tw);
+  octave_value workspace (void) const
+  {
+    return m_rep->workspace ();
+  }
 
-  octave_value workspace (void) const;
+  octave_scalar_map info (void) { return m_rep->info (); }
 
   void set_dispatch_class (const std::string& class_name)
   {
-    m_dispatch_class = class_name;
+    m_rep->set_dispatch_class (class_name);
   }
 
-  std::string get_dispatch_class (void) const { return m_dispatch_class; }
+  std::string get_dispatch_class (void) const
+  {
+    return m_rep->get_dispatch_class ();
+  }
 
-  bool is_equal_to (const octave_fcn_handle&) const;
-
-  octave_value convert_to_str_internal (bool pad, bool force, char type) const;
+  octave_value convert_to_str_internal (bool pad, bool force, char type) const
+  {
+    return m_rep->convert_to_str_internal (pad, force, type);
+  }
 
   bool save_ascii (std::ostream& os);
 
@@ -161,57 +313,24 @@
   void print_raw (std::ostream& os, bool pr_as_read_syntax = false) const;
 
   // Simple function handles are printed without a newline.
-  bool print_as_scalar (void) const { return m_name != anonymous; }
+  bool print_as_scalar (void) const { return m_rep->print_as_scalar (); }
+
+  friend bool
+  is_equal_to (const octave_fcn_handle& fh1, const octave_fcn_handle& fh2);
 
 private:
 
-  bool set_fcn (const std::string& octaveroot, const std::string& fpath);
+  octave::base_fcn_handle *m_rep;
+
+  octave_fcn_handle (octave::base_fcn_handle *rep);
+
+  octave::base_fcn_handle * get_rep (void) const { return m_rep; }
 
   DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA
-
-protected:
-
-  // The function we are handling (this should be valid for handles to
-  // anonymous functions and some other special cases).  Otherwise, we
-  // perform dynamic lookup based on the name of the function we are
-  // handling and the scope where the function handle object was created.
-  octave_value m_fcn;
-
-  // If defined, this is the classdef object corresponding to the
-  // classdef method we are handling.
-  octave_value m_obj;
-
-  // The function we would find without considering argument types.  We
-  // cache this value so that the function_value and user_function_value
-  // methods may continue to work.
-  octave_value m_generic_fcn;
-
-  // The name of the handle, not including the "@".
-  std::string m_name;
+};
 
-  // The scope where this object was defined.
-  octave::symbol_scope m_scope;
-
-  // TRUE means this is a handle to a nested function.
-  bool m_is_nested;
-
-  // Saved stack frames for handles to nested functions.  This allows us
-  // to access non-locals and other context info when calling nested
-  // functions indirectly through handles.
-  std::shared_ptr<octave::stack_frame> m_closure_frames;
-
-  // List of captured variable values for anonymous fucntions.
-  octave::stack_frame::local_vars_map *m_local_vars;
-
-  // The name of the class in which this handle was created, if any.
-  // Used to determine access permission when the referenced function is
-  // called.
-  std::string m_dispatch_class;
-
-  bool parse_anon_fcn_handle (const std::string& fcn_text);
-
-  virtual octave_value_list call (int nargout, const octave_value_list& args);
-};
+extern bool
+is_equal_to (const octave_fcn_handle& fh1, const octave_fcn_handle& fh2);
 
 namespace octave
 {