Mercurial > octave
changeset 28433:d05a4194f1ad stable
move make_fcn_handle to tree_evaluator class
* pt-eval.h, pt-eval.cc (tree_evaluator::make_fcn_handle):
New function. Change all uses of global make_fcn_handle to use this
member function instead.
(get_operator_function_name): New function.
* ov-fcn-handle.h, ov-fcn-handle.cc (make_fcn_handle): Deprecate.
Now a wrapper for tree_evaluator::make_fcn_handle.
(octave_fcn_handle::octave_fcn_handle (const std::string& name)):
New constructor.
* interpreter.h, interpreter.cc (interpreter::make_function_handle):
New function.
author | John W. Eaton <jwe@octave.org> |
---|---|
date | Wed, 15 Apr 2020 23:14:06 -0400 |
parents | 71c34141cc2d |
children | 48c1e8d88ea2 |
files | libinterp/corefcn/interpreter.cc libinterp/corefcn/interpreter.h libinterp/corefcn/ls-mat5.cc libinterp/octave-value/ov-fcn-handle.cc libinterp/octave-value/ov-fcn-handle.h libinterp/parse-tree/pt-eval.cc libinterp/parse-tree/pt-eval.h libinterp/parse-tree/pt-fcn-handle.cc |
diffstat | 8 files changed, 271 insertions(+), 192 deletions(-) [+] |
line wrap: on
line diff
--- a/libinterp/corefcn/interpreter.cc Fri Apr 03 22:00:06 2020 -0400 +++ b/libinterp/corefcn/interpreter.cc Wed Apr 15 23:14:06 2020 -0400 @@ -1577,6 +1577,11 @@ return feval (f_arg, tmp_args, nargout); } + octave_value interpreter::make_function_handle (const std::string& name) + { + return m_evaluator.make_fcn_handle (name); + } + void interpreter::install_variable (const std::string& name, const octave_value& value, bool global) {
--- a/libinterp/corefcn/interpreter.h Fri Apr 03 22:00:06 2020 -0400 +++ b/libinterp/corefcn/interpreter.h Wed Apr 15 23:14:06 2020 -0400 @@ -361,6 +361,8 @@ octave_value_list feval (const octave_value_list& args, int nargout = 0); + octave_value make_function_handle (const std::string& name); + void install_variable (const std::string& name, const octave_value& value, bool global);
--- a/libinterp/corefcn/ls-mat5.cc Fri Apr 03 22:00:06 2020 -0400 +++ b/libinterp/corefcn/ls-mat5.cc Wed Apr 15 23:14:06 2020 -0400 @@ -860,8 +860,13 @@ if (ftype == "simple" || ftype == "scopedfunction") { if (fpath.empty ()) - // We have a builtin function - tc = make_fcn_handle (interp, fname); + { + octave::tree_evaluator& tw = interp.get_evaluator (); + + // We have a builtin function + // XXX FCN_HANDLE: SIMPLE/SCOPED + tc = tw.make_fcn_handle (fname); + } else { std::string mroot = m0.contents ("matlabroot").string_value ();
--- a/libinterp/octave-value/ov-fcn-handle.cc Fri Apr 03 22:00:06 2020 -0400 +++ b/libinterp/octave-value/ov-fcn-handle.cc Wed Apr 15 23:14:06 2020 -0400 @@ -83,6 +83,38 @@ const std::string octave_fcn_handle::anonymous ("@<anonymous>"); +octave_fcn_handle::octave_fcn_handle (const std::string& n) + : m_fcn (), m_obj (), m_name (n), m_scope (), m_is_nested (false), + m_closure_frames (), m_local_vars (nullptr), m_dispatch_class () +{ + if (! m_name.empty () && m_name[0] == '@') + m_name = m_name.substr (1); + + size_t pos = m_name.find ('.'); + + if (pos != std::string::npos) + { + // If we are looking at + // + // obj . meth + // + // Store the object so that calling METH for OBJ will work even if + // it is done outside of the scope whre OBJ was initially defined + // or if OBJ is cleared before the method call is made through the + // function handle. + + std::string obj_name = m_name.substr (0, pos); + + octave::interpreter& interp + = octave::__get_interpreter__ ("octave_fcn_handle::octave_fcn_handle"); + + octave_value val = interp.varval (obj_name); + + if (val.is_classdef_object ()) + m_obj = val; + } +} + octave_fcn_handle::octave_fcn_handle (const octave::symbol_scope& scope, const std::string& n) : m_fcn (), m_obj (), m_name (n), m_scope (scope), m_is_nested (false), @@ -1673,193 +1705,17 @@ namespace octave { - // Hmm, should this function be a member of the interpreter class, - // possibly forwarded to an actual implementation in the - // tree_evaluator class? + // DEPRECATED in Octave 6. octave_value make_fcn_handle (interpreter& interp, const std::string& nm) { - octave_value retval; - - // Bow to the god of compatibility. - - // FIXME: it seems ugly to put this here, but there is no single - // function in the parser that converts from the operator name to - // the corresponding function name. At least try to do it without N - // string compares. - - std::string tnm = nm; - - size_t len = nm.length (); - - if (len == 3 && nm == ".**") - tnm = "power"; - else if (len == 2) - { - if (nm[0] == '.') - { - switch (nm[1]) - { - case '\'': - tnm = "transpose"; - break; - - case '+': - tnm = "plus"; - break; - - case '-': - tnm = "minus"; - break; - - case '*': - tnm = "times"; - break; - - case '/': - tnm = "rdivide"; - break; - - case '^': - tnm = "power"; - break; - - case '\\': - tnm = "ldivide"; - break; - } - } - else if (nm[1] == '=') - { - switch (nm[0]) - { - case '<': - tnm = "le"; - break; - - case '=': - tnm = "eq"; - break; - - case '>': - tnm = "ge"; - break; - - case '~': - case '!': - tnm = "ne"; - break; - } - } - else if (nm == "**") - tnm = "mpower"; - } - else if (len == 1) - { - switch (nm[0]) - { - case '~': - case '!': - tnm = "not"; - break; - - case '\'': - tnm = "ctranspose"; - break; - - case '+': - tnm = "plus"; - break; - - case '-': - tnm = "minus"; - break; - - case '*': - tnm = "mtimes"; - break; - - case '/': - tnm = "mrdivide"; - break; - - case '^': - tnm = "mpower"; - break; - - case '\\': - tnm = "mldivide"; - break; - - case '<': - tnm = "lt"; - break; - - case '>': - tnm = "gt"; - break; - - case '&': - tnm = "and"; - break; - - case '|': - tnm = "or"; - break; - } - } - tree_evaluator& tw = interp.get_evaluator (); - symbol_scope curr_scope = tw.get_current_scope (); - - octave_fcn_handle *fh = new octave_fcn_handle (curr_scope, tnm); - - std::string dispatch_class; - - if (tw.is_class_method_executing (dispatch_class) - || tw.is_class_constructor_executing (dispatch_class)) - fh->set_dispatch_class (dispatch_class); - - return octave_value (fh); + return tw.make_fcn_handle (nm); } } -/* -%!test -%! x = {".**", "power"; -%! ".'", "transpose"; -%! ".+", "plus"; -%! ".-", "minus"; -%! ".*", "times"; -%! "./", "rdivide"; -%! ".^", "power"; -%! ".\\", "ldivide"; -%! "<=", "le"; -%! "==", "eq"; -%! ">=", "ge"; -%! "!=", "ne"; -%! "~=", "ne"; -%! "**", "mpower"; -%! "~", "not"; -%! "!", "not"; -%! "\'", "ctranspose"; -%! "+", "plus"; -%! "-", "minus"; -%! "*", "mtimes"; -%! "/", "mrdivide"; -%! "^", "mpower"; -%! "\\", "mldivide"; -%! "<", "lt"; -%! ">", "gt"; -%! "&", "and"; -%! "|", "or"}; -%! for i = 1:rows (x) -%! assert (functions (str2func (x{i,1})).function, x{i,2}); -%! endfor -*/ - DEFUN (functions, args, , doc: /* -*- texinfo -*- @deftypefn {} {@var{s} =} functions (@var{fcn_handle}) @@ -2024,18 +1880,31 @@ if (nargin < 1 || nargin > 2) print_usage (); - std::string nm = args(0).xstring_value ("str2func: FCN_NAME must be a string"); + std::string nm + = args(0).xstring_value ("str2func: FCN_NAME must be a string"); - octave_value retval; + if (nm.empty ()) + error ("str2func: invalid function name"); if (nm[0] == '@') { + // Unlike the anon_fcn_handle::parse method, don't set up + // temporary scope to use for evaluating the text that defines + // the anonymous function. Here we want + // + // str2fun ("@(args) expr") + // + // to behave the same as if + // + // @(args) expr + // + // were evaluated in the current scope. + int parse_status; - octave_value anon_fcn_handle - = interp.eval_string (nm, true, parse_status); + octave_value afh = interp.eval_string (nm, true, parse_status); if (parse_status == 0) - retval = anon_fcn_handle; + return afh; } else { @@ -2043,10 +1912,12 @@ warning_with_id ("Octave:str2func-global-argument", "str2func: second argument ignored"); - retval = octave::make_fcn_handle (interp, nm); + octave::tree_evaluator& tw = interp.get_evaluator (); + + return tw.make_fcn_handle (nm); } - return retval; + return ovl (); } /*
--- a/libinterp/octave-value/ov-fcn-handle.h Fri Apr 03 22:00:06 2020 -0400 +++ b/libinterp/octave-value/ov-fcn-handle.h Wed Apr 15 23:14:06 2020 -0400 @@ -59,16 +59,29 @@ m_closure_frames (), m_local_vars (nullptr), m_dispatch_class () { } - octave_fcn_handle (const octave::symbol_scope& scope, const std::string& n); + // OCTAVE_DEPRECATED (6, "foobar-1") + octave_fcn_handle (const std::string& name); + // OCTAVE_DEPRECATED (6, "foobar-2") + octave_fcn_handle (const octave::symbol_scope& scope, + const std::string& name); + + // OCTAVE_DEPRECATED (6, "foobar-3") octave_fcn_handle (const octave::symbol_scope& scope, - const octave_value& f, const std::string& n); + const octave_value& f, const std::string& name); + + // OCTAVE_DEPRECATED (6, "foobar-4") + octave_fcn_handle (const octave_value& f, const std::string& name); - octave_fcn_handle (const octave_value& f, const std::string& n); + // OCTAVE_DEPRECATED (6, "foobar-5") + octave_fcn_handle (const octave_value& fcn, const std::string& name, + const std::list<std::string>& parentage); - octave_fcn_handle (const octave_value& f, + // OCTAVE_DEPRECATED (6, "foobar-6") + 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); @@ -202,6 +215,7 @@ namespace octave { + OCTAVE_DEPRECATED (6, "use 'tree_evaluator::make_fcn_handle' instead") extern octave_value make_fcn_handle (interpreter& interp, const std::string& name); }
--- a/libinterp/parse-tree/pt-eval.cc Fri Apr 03 22:00:06 2020 -0400 +++ b/libinterp/parse-tree/pt-eval.cc Wed Apr 15 23:14:06 2020 -0400 @@ -882,6 +882,185 @@ return retval; } + // If NAME is an operator (like "+", "-", ...), convert it to the + // corresponding function name ("plus", "minus", ...). + + static std::string + get_operator_function_name (const std::string& name) + { + // Bow to the god of compatibility. + + // FIXME: it seems ugly to put this here, but there is no single + // function in the parser that converts from the operator name to + // the corresponding function name. At least try to do it without N + // string compares. + + size_t len = name.length (); + + if (len == 3 && name == ".**") + return "power"; + else if (len == 2) + { + if (name[0] == '.') + { + switch (name[1]) + { + case '\'': + return "transpose"; + + case '+': + return "plus"; + + case '-': + return "minus"; + + case '*': + return "times"; + + case '/': + return "rdivide"; + + case '^': + return "power"; + + case '\\': + return "ldivide"; + + default: + break; + } + } + else if (name[1] == '=') + { + switch (name[0]) + { + case '<': + return "le"; + + case '=': + return "eq"; + + case '>': + return "ge"; + + case '~': + case '!': + return "ne"; + + default: + break; + } + } + else if (name == "**") + return "mpower"; + } + else if (len == 1) + { + switch (name[0]) + { + case '~': + case '!': + return "not"; + + case '\'': + return "ctranspose"; + + case '+': + return "plus"; + + case '-': + return "minus"; + + case '*': + return "mtimes"; + + case '/': + return "mrdivide"; + + case '^': + return "mpower"; + + case '\\': + return "mldivide"; + + case '<': + return "lt"; + + case '>': + return "gt"; + + case '&': + return "and"; + + case '|': + return "or"; + + default: + break; + } + } + + return name; + } + + octave_value + tree_evaluator::make_fcn_handle (const std::string& name) + { + octave_value retval; + + std::string fcn_name = get_operator_function_name (name); + + if (fcn_name != name) + return octave_value (new octave_fcn_handle (fcn_name)); + + symbol_scope curr_scope = get_current_scope (); + + // FCN_HANDLE: CONTEXT DEPENDENT + octave_fcn_handle *fh = new octave_fcn_handle (curr_scope, name); + + std::string dispatch_class; + + if (is_class_method_executing (dispatch_class) + || is_class_constructor_executing (dispatch_class)) + fh->set_dispatch_class (dispatch_class); + + return octave_value (fh); + } + +/* +%!test +%! x = {".**", "power"; +%! ".'", "transpose"; +%! ".+", "plus"; +%! ".-", "minus"; +%! ".*", "times"; +%! "./", "rdivide"; +%! ".^", "power"; +%! ".\\", "ldivide"; +%! "<=", "le"; +%! "==", "eq"; +%! ">=", "ge"; +%! "!=", "ne"; +%! "~=", "ne"; +%! "**", "mpower"; +%! "~", "not"; +%! "!", "not"; +%! "\'", "ctranspose"; +%! "+", "plus"; +%! "-", "minus"; +%! "*", "mtimes"; +%! "/", "mrdivide"; +%! "^", "mpower"; +%! "\\", "mldivide"; +%! "<", "lt"; +%! ">", "gt"; +%! "&", "and"; +%! "|", "or"}; +%! for i = 1:rows (x) +%! assert (functions (str2func (x{i,1})).function, x{i,2}); +%! endfor +*/ + octave_value tree_evaluator::evaluate (tree_decl_elt *elt) {
--- a/libinterp/parse-tree/pt-eval.h Fri Apr 03 22:00:06 2020 -0400 +++ b/libinterp/parse-tree/pt-eval.h Wed Apr 15 23:14:06 2020 -0400 @@ -298,6 +298,8 @@ Matrix ignored_fcn_outputs (void) const; + octave_value make_fcn_handle (const std::string& nm); + octave_value evaluate (tree_decl_elt *); void install_variable (const std::string& name,
--- a/libinterp/parse-tree/pt-fcn-handle.cc Fri Apr 03 22:00:06 2020 -0400 +++ b/libinterp/parse-tree/pt-fcn-handle.cc Wed Apr 15 23:14:06 2020 -0400 @@ -63,7 +63,8 @@ octave_value tree_fcn_handle::evaluate (tree_evaluator& tw, int) { - return make_fcn_handle (tw.get_interpreter (), m_name); + // XXX FCN_HANDLE: CONTEXT DEPENDENT + return tw.make_fcn_handle (m_name); } tree_anon_fcn_handle::~tree_anon_fcn_handle (void)