Mercurial > octave
changeset 32692:b1f779dc05d2 bytecode-interpreter
maint: Merge default to bytecode-interpreter
author | Arun Giridhar <arungiridhar@gmail.com> |
---|---|
date | Sun, 07 Jan 2024 21:05:00 -0500 |
parents | 2d3074d82ab3 (current diff) a11d7442f9cd (diff) |
children | 563cbf676eea |
files | libinterp/corefcn/stack-frame.cc libinterp/corefcn/stack-frame.h libinterp/parse-tree/pt-eval.cc libinterp/parse-tree/pt-eval.h |
diffstat | 9 files changed, 184 insertions(+), 166 deletions(-) [+] |
line wrap: on
line diff
--- a/libinterp/corefcn/graphics.cc Thu Dec 14 17:16:13 2023 +0100 +++ b/libinterp/corefcn/graphics.cc Sun Jan 07 21:05:00 2024 -0500 @@ -413,12 +413,12 @@ } /* -## Test default colormap returns as 256 color viridis +## Test default colormap returns a 256-color viridis map %!test %! hf = figure ("visible", "off"); %! unwind_protect %! hax = axes ("parent", hf); -%! assert (get (hax, "colormap"), viridis (256), eps); +%! assert (get (hax, "colormap"), viridis (256)); %! unwind_protect_cleanup %! delete (hf); %! end_unwind_protect
--- a/libinterp/corefcn/interpreter.cc Thu Dec 14 17:16:13 2023 +0100 +++ b/libinterp/corefcn/interpreter.cc Sun Jan 07 21:05:00 2024 -0500 @@ -1655,6 +1655,12 @@ return feval (f_arg, tmp_args, nargout); } +std::string +interpreter::inputname (int n, bool ids_only) const +{ + return m_evaluator.inputname (n, ids_only); +} + octave_value interpreter::make_function_handle (const std::string& name) {
--- a/libinterp/corefcn/interpreter.h Thu Dec 14 17:16:13 2023 +0100 +++ b/libinterp/corefcn/interpreter.h Sun Jan 07 21:05:00 2024 -0500 @@ -405,6 +405,8 @@ octave_value_list feval (const octave_value_list& args, int nargout = 0); + std::string inputname (int n, bool ids_only = true) const; + octave_value make_function_handle (const std::string& name); void install_variable (const std::string& name, const octave_value& value,
--- a/libinterp/corefcn/stack-frame.cc Thu Dec 14 17:16:13 2023 +0100 +++ b/libinterp/corefcn/stack-frame.cc Sun Jan 07 21:05:00 2024 -0500 @@ -1884,6 +1884,14 @@ ); } + std::string inputname (int n, bool ids_only) const + { + // Look in closest stack frame that contains values (either the + // top scope, or a user-defined function or script). + + return m_static_link->inputname (n, ids_only); + } + void mark_scope (const symbol_record& sym, scope_flags flag) { // Look in closest stack frame that contains values (either the @@ -2013,6 +2021,11 @@ #endif ); + std::string inputname (int n, bool ids_only) const + { + return m_access_link->inputname (n, ids_only); + } + void mark_scope (const symbol_record& sym, scope_flags flag); void display (bool follow = true) const; @@ -2297,6 +2310,8 @@ #endif ); + std::string inputname (int n, bool ids_only) const; + void mark_scope (const symbol_record& sym, scope_flags flag); void display (bool follow = true) const; @@ -2371,6 +2386,14 @@ #endif ); + std::string inputname (int, bool) const + { + if (m_index == 0) + error ("invalid call to inputname outside of a function"); + + return ""; + } + void mark_scope (const symbol_record& sym, scope_flags flag); void display (bool follow = true) const; @@ -3289,6 +3312,15 @@ panic_impossible (); } +std::string +stack_frame::inputname (int, bool) const +{ + // This function should only be called for user_fcn_stack_frame. + // Anything else indicates an error in the implementation. + + panic_impossible (); +} + void stack_frame::clear_objects () { @@ -4330,6 +4362,25 @@ error ("internal error: invalid switch case"); } +std::string +user_fcn_stack_frame::inputname (int n, bool ids_only) const +{ + std::string name; + + Array<std::string> arg_names + = m_auto_vars.at (stack_frame::ARG_NAMES).cellstr_value (); + + if (n >= 0 && n < arg_names.numel ()) + { + name = arg_names(n); + + if (ids_only && ! m_static_link->is_variable (name)) + name = ""; + } + + return name; +} + void user_fcn_stack_frame::mark_scope (const symbol_record& sym, scope_flags flag) {
--- a/libinterp/corefcn/stack-frame.h Thu Dec 14 17:16:13 2023 +0100 +++ b/libinterp/corefcn/stack-frame.h Sun Jan 07 21:05:00 2024 -0500 @@ -510,6 +510,8 @@ #endif ); + virtual std::string inputname (int n, bool ids_only) const; + void assign (const symbol_record& sym, const octave_value& val) { octave_value& lhs = varref (sym);
--- a/libinterp/parse-tree/pt-eval.cc Thu Dec 14 17:16:13 2023 +0100 +++ b/libinterp/parse-tree/pt-eval.cc Sun Jan 07 21:05:00 2024 -0500 @@ -1477,6 +1477,13 @@ return retval; } +std::string tree_evaluator::inputname (int n, bool ids_only) const +{ + std::shared_ptr<stack_frame> frame = m_call_stack.current_user_frame (); + + return frame->inputname (n, ids_only); +} + // If NAME is an operator (like "+", "-", ...), convert it to the // corresponding function name ("plus", "minus", ...). @@ -5606,4 +5613,116 @@ %!error echo ("on", "all", "all") */ +/* +FIXME: Actually, it probably *isn't* worth fixing, but there is one small +difference between Octave and Matlab. + +If inputname is not called from a function, Matlab walks up the stack until it +finds some valid code and then works from there. This could be relevant for +mex files or anonymous functions. + +fcn = @(x) inputname (x); +a = 1:4; +arrayfun (fcn, a, 'uniformoutput', false) +% output is {'fcn', 'a', '', ''} +*/ +DEFMETHOD (inputname, interp, args, , + doc: /* -*- texinfo -*- +@deftypefn {} {@var{namestr} =} inputname (@var{n}) +@deftypefnx {} {@var{namestr} =} inputname (@var{n}, @var{ids_only}) +Return the name of the @var{n}-th argument to the calling function. + +If the argument is not a simple variable name, return an empty string. +Examples which will return @qcode{""} are numbers (@code{5.1}), expressions +(@code{@var{y}/2}), and cell or structure indexing (@code{@var{c}@{1@}} or +@code{@var{s}.@var{field}}). + +@code{inputname} is only useful within a function. When used at the command +line or within a script it always returns an empty string. + +By default, return an empty string if the @var{n}-th argument is not a valid +variable name. If the optional argument @var{ids_only} is false, return the +text of the argument even if it is not a valid variable name. This is an +Octave extension that allows the programmer to view exactly how the function +was invoked even when the inputs are complex expressions. +@seealso{nargin, narginchk} +@end deftypefn */) +{ + int nargin = args.length (); + + if (nargin < 1) + print_usage (); + + dim_vector dims = args(0).dims (); + if (! dims.all_ones ()) + error ("inputname: N must be a scalar index"); + + int n = args(0).xint_value ("inputname: N must be a scalar index"); + + if (n < 1) + error ("inputname: N must be a scalar index"); + + bool ids_only = true; + + if (nargin == 2) + ids_only = args(1).xbool_value ("inputname: IDS_ONLY must be a logical value"); + + // Use zero-based indexing internally. + return ovl (interp.inputname (n-1, ids_only)); +} + +/* +%!function name = __iname1__ (arg1, arg2, arg3) +%! name = inputname (1); +%!endfunction + +%!function name = __iname1_ID__ (arg1, arg2, arg3) +%! name = inputname (1, false); +%!endfunction + +%!function name = __iname2__ (arg1, arg2, arg3) +%! name = inputname (2); +%!endfunction + +%!function names = __iname3__ (arg1, arg2, arg3) +%! names = cell (1, 3); +%! for i = 1:3 +%! names{i} = inputname (i); +%! endfor +%!endfunction + +%!test +%! assert (__iname1__ ('xvar'), ""); +%! xvar = 1; +%! assert (__iname1__ (xvar), "xvar"); + +%!test +%! xvar = 1; yvar = 2; +%! assert (__iname2__ (xvar), ""); +%! assert (__iname2__ (xvar, yvar), "yvar"); + +%!test +%! xvar = 1; yvar = 2; +%! assert (__iname3__ (xvar), {"xvar", "", ""}); +%! assert (__iname3__ (xvar, yvar), {"xvar", "yvar", ""}); +%! assert (__iname3__ (xvar, 3, yvar), {"xvar", "", "yvar"}); + +## Test numbers, expressions, indexing operations +%!test +%! assert (__iname1__ (1.0), ""); +%! x = 1; +%! assert (__iname1__ (x / 2), ""); +%! assert (__iname1__ (Inf), ""); + +%!test +%! assert (__iname1_ID__ (1.0), "1.0"); +%! x = 1; +%! assert (__iname1_ID__ (x / 2), "x / 2"); +%! assert (__iname1_ID__ (Inf), "Inf"); + +%!error <Invalid call> inputname () +%!error <N must be a scalar> inputname (ones (2,2)) +%!error <N must be a scalar index> inputname (-1) +*/ + OCTAVE_END_NAMESPACE(octave)
--- a/libinterp/parse-tree/pt-eval.h Thu Dec 14 17:16:13 2023 +0100 +++ b/libinterp/parse-tree/pt-eval.h Sun Jan 07 21:05:00 2024 -0500 @@ -357,6 +357,8 @@ Matrix ignored_fcn_outputs () const; + std::string inputname (int n, bool ids_only = true) const; + octave_value make_fcn_handle (const std::string& nm); octave_value evaluate (tree_decl_elt *);
--- a/scripts/miscellaneous/inputname.m Thu Dec 14 17:16:13 2023 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,163 +0,0 @@ -######################################################################## -## -## Copyright (C) 2004-2024 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/>. -## -######################################################################## -## -## Original version by Paul Kienzle distributed as free software in the -## public domain. - -## -*- texinfo -*- -## @deftypefn {} {@var{namestr} =} inputname (@var{n}) -## @deftypefnx {} {@var{namestr} =} inputname (@var{n}, @var{ids_only}) -## Return the name of the @var{n}-th argument to the calling function. -## -## If the argument is not a simple variable name, return an empty string. -## Examples which will return @qcode{""} are numbers (@code{5.1}), -## expressions (@code{@var{y}/2}), and cell or structure indexing -## (@code{@var{c}@{1@}} or @code{@var{s}.@var{field}}). -## -## @code{inputname} is only useful within a function. When used at the command -## line or within a script it always returns an empty string. -## -## By default, return an empty string if the @var{n}-th argument is not a valid -## variable name. If the optional argument @var{ids_only} is false, return the -## text of the argument even if it is not a valid variable name. This is an -## Octave extension that allows the programmer to view exactly how the function -## was invoked even when the inputs are complex expressions. -## @seealso{nargin, narginchk} -## @end deftypefn - -## FIXME: Actually, it probably *isn't* worth fixing, but there are small -## differences between Octave and Matlab. -## -## 1) When called from the top-level or a script, Matlab throws an error -## -## inputname (1) % at command prompt -## % Octave returns "", Matlab throws an error -## -## 2) cell or struct indexing causes all further names to be returned as "" -## -## c = {'a', 'b'} -## y = 1; z = 2; -## fcn (c, y, z) -## % inputname() would return 'c', 'y', 'z' for the inputs. -## fcn (c{1}, y, z) -## % inputname() would return '', '', '' for the inputs. -## -## 3) If inputname is not called from a function, Matlab walks up the stack -## until it finds some valid code and then works from there. This could -## be relevant for mex files or anonymous functions. -## -## f = @(x) inputname (x); -## a = 1:4; -## arrayfun (fn, a, 'uniformoutput', false) -## % output is {'fn', 'a', '', ''} - -function namestr = inputname (n, ids_only = true) - - if (nargin < 1) - print_usage (); - endif - - if (! isscalar (n) || ! isindex (n)) - error ("inputname: N must be a scalar index"); - endif - - try - namestr = evalin ("caller", sprintf ("__varval__ ('.argn.'){%d}", n)); - catch - namestr = ""; - return; - end_try_catch - - ## For compatibility with Matlab, return empty string if argument name is - ## not a valid identifier. - if (ids_only && ! isvarname (namestr)) - namestr = ""; - elseif (ids_only) - ## More complicated checking is required to verify name (bug #59103). - ## NAME may be text, like "Inf", which is an acceptable variable name - ## that passes isvarname(), but that does not mean it is an actual - ## variable name, rather than a function or IEEE number. - try - v = evalin ("caller", - sprintf ("evalin ('caller', '__varval__ (\"%s\")')", namestr)); - catch - namestr = ""; - end_try_catch - endif - -endfunction - - -%!function name = __iname1__ (arg1, arg2, arg3) -%! name = inputname (1); -%!endfunction - -%!function name = __iname1_ID__ (arg1, arg2, arg3) -%! name = inputname (1, false); -%!endfunction - -%!function name = __iname2__ (arg1, arg2, arg3) -%! name = inputname (2); -%!endfunction - -%!function names = __iname3__ (arg1, arg2, arg3) -%! names = cell (1, 3); -%! for i = 1:3 -%! names{i} = inputname (i); -%! endfor -%!endfunction - -%!test -%! assert (__iname1__ ('xvar'), ""); -%! xvar = 1; -%! assert (__iname1__ (xvar), "xvar"); - -%!test -%! xvar = 1; yvar = 2; -%! assert (__iname2__ (xvar), ""); -%! assert (__iname2__ (xvar, yvar), "yvar"); - -%!test -%! xvar = 1; yvar = 2; -%! assert (__iname3__ (xvar), {"xvar", "", ""}); -%! assert (__iname3__ (xvar, yvar), {"xvar", "yvar", ""}); -%! assert (__iname3__ (xvar, 3, yvar), {"xvar", "", "yvar"}); - -## Test numbers, expressions, indexing operations -%!test -%! assert (__iname1__ (1.0), ""); -%! x = 1; -%! assert (__iname1__ (x / 2), ""); -%! assert (__iname1__ (Inf), ""); - -%!test -%! assert (__iname1_ID__ (1.0), "1.0"); -%! x = 1; -%! assert (__iname1_ID__ (x / 2), "x / 2"); -%! assert (__iname1_ID__ (Inf), "Inf"); - -%!error <Invalid call> inputname () -%!error <N must be a scalar> inputname (ones (2,2)) -%!error <N must be a scalar index> inputname (-1)
--- a/scripts/miscellaneous/module.mk Thu Dec 14 17:16:13 2023 +0100 +++ b/scripts/miscellaneous/module.mk Sun Jan 07 21:05:00 2024 -0500 @@ -34,7 +34,6 @@ %reldir%/gunzip.m \ %reldir%/info.m \ %reldir%/inputParser.m \ - %reldir%/inputname.m \ %reldir%/isdeployed.m \ %reldir%/isfile.m \ %reldir%/isfolder.m \