Mercurial > octave
diff libinterp/octave-value/ov-fcn-handle.h @ 26847:8bd9fd99c12a
lazily evaluate fcn handles; fix overload resolution (bug #29447, bug #31821, bug #48802)
* ov-fcn-handle.h, ov-fcn-handle.cc (octave_fcn_handle::has_overloads,
octave_fcn_handle::builtin_overloads, octave_fcn_handle::overloads):
Delete member variables and all uses.
(octave_fcn_handle::set_overload, octave_fcn_handle::set_overload,
octave_fcn_handle::builtin_type, octave_fcn_handle::is_overloaded):
Delete.
(octave_fcn_handle::m_scope): New member variable. Store scop where
handle is created along with function name to allow proper lookup and
overload resolution.
(octave_fcn_handle::m_generic_fcn): New member variable.
(octave_fcn_handle::function_value, octave_fcn_handle::user_function_value):
Store octave_value object containing discovered function in
m_generic_fcn so we can safely return a pointer to the underlying
function object.
(make_fcn_handle, octave_fcn_handle::subsref): Greatly simplify.
* pt-eval.cc (tree_evaluator::execute_user_function): Push closure
context for any handle created inside a nested function or parent of a
nested function.
* cellfun.cc (Fcellfun): Eliminate special checks for "overloaded"
function handles.
* graphics.cc (gh_manager::do_execute_callback): If callback is a
function handle, pass it directly to feval instead of extracting
function value from it first.
* cdef-class.cc (make_fcn_handle): Accept interpreter as argument.
Change all uses. Create octave_fcn_handle object with current scope.
author | John W. Eaton <jwe@octave.org> |
---|---|
date | Tue, 05 Mar 2019 22:30:09 +0000 |
parents | 6e9034836239 |
children | ab97008be411 |
line wrap: on
line diff
--- a/libinterp/octave-value/ov-fcn-handle.h Tue Mar 05 07:32:38 2019 +0000 +++ b/libinterp/octave-value/ov-fcn-handle.h Tue Mar 05 22:30:09 2019 +0000 @@ -33,6 +33,7 @@ #include "ov-base.h" #include "ov-fcn.h" #include "ov-typeinfo.h" +#include "symscope.h" namespace octave { @@ -56,27 +57,26 @@ static const std::string anonymous; octave_fcn_handle (void) - : fcn (), nm (), has_overloads (false), overloads (), - m_is_nested (false), m_closure_frames (nullptr) - { } - - octave_fcn_handle (const std::string& n) - : fcn (), nm (n), has_overloads (false), overloads (), - m_is_nested (false), m_closure_frames (nullptr) + : fcn (), nm (), m_scope (), m_is_nested (false), + m_closure_frames (nullptr) { } - octave_fcn_handle (const octave_value& f, const std::string& n = anonymous); + octave_fcn_handle (const octave::symbol_scope& scope, const std::string& n) + : fcn (), nm (n), m_scope (scope), m_is_nested (false), + m_closure_frames (nullptr) + { + if (! nm.empty () && nm[0] == '@') + nm = nm.substr (1); + } - octave_fcn_handle (const octave_fcn_handle& fh) - : octave_base_value (fh), fcn (fh.fcn), nm (fh.nm), - has_overloads (fh.has_overloads), overloads (), - m_is_nested (fh.m_is_nested), m_closure_frames (fh.m_closure_frames) - { - for (int i = 0; i < btyp_num_types; i++) - builtin_overloads[i] = fh.builtin_overloads[i]; + octave_fcn_handle (const octave::symbol_scope& scope, + const octave_value& f, + const std::string& n = anonymous); - overloads = fh.overloads; - } + octave_fcn_handle (const octave_value& f, + const std::string& n = anonymous); + + octave_fcn_handle (const octave_fcn_handle& fh) = default; ~octave_fcn_handle (void); @@ -100,23 +100,14 @@ bool is_function_handle (void) const { return true; } - builtin_type_t builtin_type (void) const { return btyp_func_handle; } - - bool is_overloaded (void) const { return has_overloads; } - bool is_nested (void) const { return m_is_nested; } dim_vector dims (void) const; - octave_function * function_value (bool = false) - { - return fcn.function_value (); - } - - octave_user_function * user_function_value (bool = false) - { - return fcn.user_function_value (); - } + // 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_fcn_handle * fcn_handle_value (bool = false) { return this; } @@ -128,23 +119,6 @@ octave_value workspace (void) const; - void set_overload (builtin_type_t btyp, const octave_value& ov_fcn) - { - if (btyp != btyp_unknown) - { - has_overloads = true; - builtin_overloads[btyp] = ov_fcn; - } - - } - - void set_overload (const std::string& dispatch_type, - const octave_value& ov_fcn) - { - has_overloads = true; - overloads[dispatch_type] = ov_fcn; - } - bool is_equal_to (const octave_fcn_handle&) const; octave_value convert_to_str_internal (bool pad, bool force, char type) const; @@ -177,20 +151,22 @@ protected: - // The function we are handling. + // 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 funtion handle object was created. octave_value fcn; - // The name of the handle, including the "@". + // 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 nm; - // Whether the function is overloaded at all. - bool has_overloads; - - // Overloads for builtin types. We use array to make lookup faster. - octave_value builtin_overloads[btyp_num_types]; - - // Overloads for other classes. - str_ov_map overloads; + // 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;