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 \