Mercurial > octave
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 {