GNU Octave  4.4.1
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
ov-usr-fcn.cc
Go to the documentation of this file.
1 /*
2 
3 Copyright (C) 1996-2018 John W. Eaton
4 
5 This file is part of Octave.
6 
7 Octave is free software: you can redistribute it and/or modify it
8 under the terms of the GNU General Public License as published by
9 the Free Software Foundation, either version 3 of the License, or
10 (at your option) any later version.
11 
12 Octave is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16 
17 You should have received a copy of the GNU General Public License
18 along with Octave; see the file COPYING. If not, see
19 <https://www.gnu.org/licenses/>.
20 
21 */
22 
23 #if defined (HAVE_CONFIG_H)
24 # include "config.h"
25 #endif
26 
27 #include <sstream>
28 
29 #include "file-info.h"
30 #include "file-stat.h"
31 #include "str-vec.h"
32 
33 #include "builtin-defun-decls.h"
34 #include "call-stack.h"
35 #include "defaults.h"
36 #include "Cell.h"
37 #include "defun.h"
38 #include "error.h"
39 #include "errwarn.h"
40 #include "input.h"
41 #include "ovl.h"
42 #include "ov-usr-fcn.h"
43 #include "ov.h"
44 #include "pager.h"
45 #include "pt-eval.h"
46 #include "pt-jit.h"
47 #include "pt-jump.h"
48 #include "pt-misc.h"
49 #include "pt-pr-code.h"
50 #include "pt-stmt.h"
51 #include "pt-walk.h"
52 #include "symtab.h"
53 #include "interpreter-private.h"
54 #include "interpreter.h"
55 #include "unwind-prot.h"
56 #include "utils.h"
57 #include "parse.h"
58 #include "profiler.h"
59 #include "variables.h"
60 #include "ov-fcn-handle.h"
61 
62 // Whether to optimize subsasgn method calls.
63 static bool Voptimize_subsasgn_calls = true;
64 
66 {
67  delete m_file_info;
68 }
69 
70 void
72 {
73  std::string file_name = fcn_file_name ();
74 
75  m_file_info = new octave::file_info (file_name);
76 
77  octave::sys::file_stat fs (file_name);
78 
79  if (fs && (fs.mtime () > time_parsed ()))
80  warning ("function file '%s' changed since it was parsed",
81  file_name.c_str ());
82 }
83 
86 {
87  if (! m_file_info)
88  get_file_info ();
89 
90  return m_file_info->get_line (line);
91 }
92 
93 std::deque<std::string>
94 octave_user_code::get_code_lines (size_t line, size_t num_lines)
95 {
96  if (! m_file_info)
97  get_file_info ();
98 
99  return m_file_info->get_lines (line, num_lines);
100 }
101 
102 void
104  const octave::sys::time& timestamp)
105 {
106  if (m_file_info)
107  delete m_file_info;
108 
109  if (timestamp > time_parsed ())
110  warning ("help text for function is newer than function");
111 
112  m_file_info = new octave::file_info (text, timestamp);
113 }
114 
115 std::map<std::string, octave_value>
117 {
118  return std::map<std::string, octave_value> ();
119 }
120 
121 // User defined scripts.
122 
124  "user-defined script",
125  "user-defined script");
126 
128  : octave_user_code (), cmd_list (nullptr), file_name (),
129  t_parsed (static_cast<time_t> (0)),
130  t_checked (static_cast<time_t> (0)),
131  call_depth (-1)
132 { }
133 
135  (const std::string& fnm, const std::string& nm,
137  const std::string& ds)
138  : octave_user_code (nm, scope, ds), cmd_list (cmds), file_name (fnm),
139  t_parsed (static_cast<time_t> (0)),
140  t_checked (static_cast<time_t> (0)),
141  call_depth (-1)
142 {
143  if (cmd_list)
144  cmd_list->mark_as_script_body ();
145 }
146 
148  (const std::string& fnm, const std::string& nm,
149  const octave::symbol_scope& scope, const std::string& ds)
150  : octave_user_code (nm, scope, ds), cmd_list (nullptr), file_name (fnm),
151  t_parsed (static_cast<time_t> (0)),
152  t_checked (static_cast<time_t> (0)),
153  call_depth (-1)
154 { }
155 
157 {
158  if (cmd_list)
160 
161  delete cmd_list;
162 }
163 
166  const octave_value_list& args)
167 {
169 
171 
172  if (args.length () != 0 || nargout != 0)
173  error ("invalid call to script %s", file_name.c_str ());
174 
175  if (cmd_list)
176  {
178  call_depth++;
179 
180  if (call_depth >= tw.max_recursion_depth ())
181  error ("max_recursion_depth exceeded");
182 
184  = octave::__get_call_stack__ ("octave_user_script::call");
185 
186  cs.push (this);
187 
188  // Set pointer to the current unwind_protect frame to allow
189  // certain builtins register simple cleanup in a very optimized manner.
190  // This is *not* intended as a general-purpose on-cleanup mechanism,
193 
195 
196  // Update line number even if debugging.
198  Vtrack_line_num = true;
199 
202 
203  octave::profiler& profiler = tw.get_profiler ();
204 
205  octave::profiler::enter<octave_user_script> block (profiler, *this);
206 
210 
211  if (tw.echo ())
213  file_name);
214 
215  cmd_list->accept (tw);
216 
219 
222  }
223 
224  return retval;
225 }
226 
227 void
229 {
230  tw.visit_octave_user_script (*this);
231 }
232 
233 // User defined functions.
234 
236  "user-defined function",
237  "user-defined function");
238 
239 // Ugh. This really needs to be simplified (code/data?
240 // extrinsic/intrinsic state?).
241 
245  : octave_user_code ("", scope, ""),
246  param_list (pl), ret_list (rl), cmd_list (cl),
247  lead_comm (), trail_comm (), file_name (),
248  location_line (0), location_column (0),
249  parent_name (), t_parsed (static_cast<time_t> (0)),
250  t_checked (static_cast<time_t> (0)),
251  system_fcn_file (false), call_depth (-1),
252  num_named_args (param_list ? param_list->length () : 0),
253  subfunction (false), inline_function (false),
254  anonymous_function (false), nested_function (false),
255  class_constructor (none), class_method (false)
256 #if defined (HAVE_LLVM)
257  , jit_info (0)
258 #endif
259 {
260  if (cmd_list)
261  cmd_list->mark_as_function_body ();
262 
263  if (m_scope)
264  m_scope.set_function (this);
265 }
266 
268 {
269  // FIXME: shouldn't this happen automatically when deleting cmd_list?
270  if (cmd_list)
272 
273  delete param_list;
274  delete ret_list;
275  delete cmd_list;
276  delete lead_comm;
277  delete trail_comm;
278 
279 #if defined (HAVE_LLVM)
280  delete jit_info;
281 #endif
282 }
283 
286 {
287  ret_list = t;
288 
289  return this;
290 }
291 
292 void
294 {
295  file_name = nm;
296 }
297 
298 // If there is no explicit end statement at the end of the function,
299 // relocate the no_op that was generated for the end of file condition
300 // to appear on the next line after the last statement in the file, or
301 // the next line after the function keyword if there are no statements.
302 // More precisely, the new location should probably be on the next line
303 // after the end of the parameter list, but we aren't tracking that
304 // information (yet).
305 
306 void
308 {
309  if (cmd_list && ! cmd_list->empty ())
310  {
311  octave::tree_statement *last_stmt = cmd_list->back ();
312 
313  if (last_stmt && last_stmt->is_end_of_fcn_or_script ()
314  && last_stmt->is_end_of_file ())
315  {
317  next_to_last_elt = cmd_list->rbegin ();
318 
319  next_to_last_elt++;
320 
321  int new_eof_line;
322  int new_eof_col;
323 
324  if (next_to_last_elt == cmd_list->rend ())
325  {
326  new_eof_line = beginning_line ();
327  new_eof_col = beginning_column ();
328  }
329  else
330  {
331  octave::tree_statement *next_to_last_stmt = *next_to_last_elt;
332 
333  new_eof_line = next_to_last_stmt->line ();
334  new_eof_col = next_to_last_stmt->column ();
335  }
336 
337  last_stmt->set_location (new_eof_line + 1, new_eof_col);
338  }
339  }
340 }
341 
342 void
344 {
345  std::map<std::string, octave_value> fcns = subfunctions ();
346 
347  if (! fcns.empty ())
348  {
349  for (auto& nm_fnval : fcns)
350  {
351  octave_user_function *f = nm_fnval.second.user_function_value ();
352 
353  if (f)
354  f->maybe_relocate_end_internal ();
355  }
356  }
357 
359 }
360 
361 void
363 {
364  m_scope.set_parent (ps);
365 }
366 
369 {
370  std::ostringstream result;
371 
372  if (is_anonymous_function ())
373  result << "anonymous@" << fcn_file_name ()
374  << ':' << location_line << ':' << location_column;
375  else if (is_subfunction ())
376  result << parent_fcn_name () << '>' << name ();
377  else if (is_class_method ())
378  result << '@' << dispatch_class () << '/' << name ();
379  else if (is_class_constructor () || is_classdef_constructor ())
380  result << '@' << name ();
381  else if (is_inline_function ())
382  result << "inline@" << fcn_file_name ()
383  << ':' << location_line << ':' << location_column;
384  else
385  result << name ();
386 
387  return result.str ();
388 }
389 
390 void
391 octave_user_function::mark_as_system_fcn_file (void)
392 {
393  if (! file_name.empty ())
394  {
395  // We really should stash the whole path to the file we found,
396  // when we looked it up, to avoid possible race conditions...
397  // FIXME
398  //
399  // We probably also don't need to get the library directory
400  // every time, but since this function is only called when the
401  // function file is parsed, it probably doesn't matter that
402  // much.
403 
405 
407  if (fcn_file_dir == ff_name.substr (0, fcn_file_dir.length ()))
408  system_fcn_file = true;
409  }
410  else
411  system_fcn_file = false;
412 }
413 
414 void
416 {
418 }
419 
420 bool
422 {
423  return (param_list && param_list->takes_varargs ());
424 }
425 
426 bool
428 {
429  return (ret_list && ret_list->takes_varargs ());
430 }
431 
432 void
434 {
436 
438 }
439 
440 void
442 {
444 }
445 
446 void
448 {
450 }
451 
452 std::map<std::string, octave_value>
454 {
455  return m_scope.subfunctions ();
456 }
457 
458 bool
460 {
461  return m_scope.has_subfunctions ();
462 }
463 
464 void
465 octave_user_function::stash_subfunction_names (const std::list<std::string>& names)
466 {
468 }
469 
470 std::list<std::string>
472 {
473  return m_scope.subfunction_names ();
474 }
475 
478 {
480 
481  octave_idx_type n = args.length () - num_named_args;
482 
483  if (n > 0)
484  retval = args.slice (num_named_args, n);
485 
486  return retval;
487 }
488 
491  const octave_value_list& _args)
492 {
494 
495  if (! cmd_list)
496  return retval;
497 
498  // If this function is a classdef constructor, extract the first input
499  // argument, which must be the partially constructed object instance.
500 
501  octave_value_list args (_args);
502  octave_value_list ret_args;
503 
505  {
506  if (args.length () > 0)
507  {
508  ret_args = args.slice (0, 1, true);
509  args = args.slice (1, args.length () - 1, true);
510  }
511  else
512  panic_impossible ();
513  }
514 
515 #if defined (HAVE_LLVM)
516  if (is_special_expr ()
517  && octave::tree_jit::execute (*this, args, retval))
518  return retval;
519 #endif
520 
522 
524  call_depth++;
525 
526  if (call_depth >= tw.max_recursion_depth ())
527  error ("max_recursion_depth exceeded");
528 
529  // Save old and set current symbol table context, for
530  // eval_undefined_error().
531 
533  = octave::__get_call_stack__ ("octave_user_function::call");
534 
537 
538  cs.push (this, m_scope, context);
539 
540  // Set pointer to the current unwind_protect frame to allow
541  // certain builtins register simple cleanup in a very optimized manner.
542  // This is *not* intended as a general-purpose on-cleanup mechanism,
545 
547  Vtrack_line_num = true; // update source line numbers, even if debugging
549 
550  if (call_depth > 0 && ! is_anonymous_function ())
551  {
553 
554 #if 0
555  std::cerr << name () << " scope: " << m_scope
556  << " call depth: " << call_depth
557  << " context: " << m_scope.current_context () << std::endl;
558 #endif
559 
561  }
562 
563  string_vector arg_names = _args.name_tags ();
564 
565  if (param_list && ! param_list->varargs_only ())
566  {
567 #if 0
568  std::cerr << "defining param list, scope: " << m_scope
569  << ", context: " << m_scope.current_context () << std::endl;
570 #endif
572  }
573 
574  // For classdef constructor, pre-populate the output arguments
575  // with the pre-initialized object instance, extracted above.
576 
578  {
579  if (! ret_list)
580  error ("%s: invalid classdef constructor, no output argument defined",
581  dispatch_class ().c_str ());
582 
584  }
585 
586  // Force parameter list to be undefined when this function exits.
587  // Doing so decrements the reference counts on the values of local
588  // variables that are also named function parameters.
589 
590  if (param_list)
592  param_list);
593 
594  // Force return list to be undefined when this function exits.
595  // Doing so decrements the reference counts on the values of local
596  // variables that are also named values returned by this function.
597 
598  if (ret_list)
600  ret_list);
601 
602  if (call_depth == 0)
603  {
604  // Force symbols to be undefined again when this function
605  // exits.
606  //
607  // This cleanup function is added to the unwind_protect stack
608  // after the calls to clear the parameter lists so that local
609  // variables will be cleared before the parameter lists are
610  // cleared. That way, any function parameters that have been
611  // declared global will be unmarked as global before they are
612  // undefined by the clear_param_list cleanup function.
613 
615  }
616 
617  bind_automatic_vars (tw, arg_names, args.length (), nargout,
618  all_va_args (args));
619 
621 
622  // Evaluate the commands that make up the function.
623 
626 
627  {
628  octave::profiler& profiler = tw.get_profiler ();
629 
630  octave::profiler::enter<octave_user_function> block (profiler, *this);
631 
632  if (tw.echo ())
634  file_name);
635 
636  if (is_special_expr ())
637  {
638  assert (cmd_list->length () == 1);
639 
641 
642  octave::tree_expression *expr = stmt->expression ();
643 
644  if (expr)
645  {
646  cs.set_location (stmt->line (), stmt->column ());
647 
648  retval = tw.evaluate_n (expr, nargout);
649  }
650  }
651  else
652  cmd_list->accept (tw);
653  }
654 
657 
660 
661  // Copy return values out.
662 
663  if (ret_list && ! is_special_expr ())
664  {
665  Cell varargout;
666 
667  if (ret_list->takes_varargs ())
668  {
669  octave_value varargout_varval = m_scope.varval ("varargout");
670 
671  if (varargout_varval.is_defined ())
672  varargout = varargout_varval.xcell_value ("varargout must be a cell array object");
673  }
674 
676  }
677 
678  return retval;
679 }
680 
681 void
683 {
684  tw.visit_octave_user_function (*this);
685 }
686 
689 {
690  assert (is_special_expr ());
691  assert (cmd_list->length () == 1);
692 
694  return stmt->expression ();
695 }
696 
697 bool
699 {
700  bool retval = false;
702  && param_list && ret_list
703  && param_list->length () > 0 && ! param_list->varargs_only ()
704  && ret_list->length () == 1 && ! ret_list->takes_varargs ())
705  {
708  retval = par1->name () == ret1->name ();
709  }
710 
711  return retval;
712 }
713 
716 {
718 
719  switch (class_constructor)
720  {
721  case none:
722  retval = "none";
723  break;
724 
725  case legacy:
726  retval = "legacy";
727  break;
728 
729  case classdef:
730  retval = "classdef";
731  break;
732 
733  default:
734  retval = "unrecognized enum value";
735  break;
736  }
737 
738  return retval;
739 }
740 
743 {
744  std::map<std::string, octave_value> m
745  = {{ "file_name", file_name },
746  { "line", location_line },
747  { "col", location_column },
748  { "end_line", end_location_line },
749  { "end_col", end_location_column },
750  { "time_parsed", t_parsed },
751  { "time_checked", t_checked },
752  { "parent_name", parent_name },
753  { "system_fcn_file", system_fcn_file },
754  { "call_depth", call_depth },
755  { "num_named_args", num_named_args },
756  { "subfunction", subfunction },
757  { "inline_function", inline_function },
758  { "anonymous_function", anonymous_function },
759  { "nested_function", nested_function },
760  { "ctor_type", ctor_type_str () },
761  { "class_method", class_method },
762  { "scope_info", m_scope ? m_scope.dump () : "0x0" }};
763 
764  return octave_value (m);
765 }
766 
767 void
769 {
771 
773 }
774 
775 void
777 {
779 
781 }
782 
783 void
785  (octave::tree_evaluator& tw, const string_vector& arg_names,
786  int nargin, int nargout, const octave_value_list& va_args)
787 {
788  if (! arg_names.empty ())
789  {
790  // It is better to save this in the hidden variable .argn. and
791  // then use that in the inputname function instead of using argn,
792  // which might be redefined in a function. Keep the old argn name
793  // for backward compatibility of functions that use it directly.
794 
795  charMatrix chm (arg_names, tw.string_fill_char ());
796  m_scope.force_assign ("argn", chm);
797  m_scope.force_assign (".argn.", Cell (arg_names));
798 
799  m_scope.mark_hidden (".argn.");
800 
801  m_scope.mark_automatic ("argn");
802  m_scope.mark_automatic (".argn.");
803  }
804 
805  m_scope.force_assign (".nargin.", nargin);
806  m_scope.force_assign (".nargout.", nargout);
807 
808  m_scope.mark_hidden (".nargin.");
809  m_scope.mark_hidden (".nargout.");
810 
811  m_scope.mark_automatic (".nargin.");
812  m_scope.mark_automatic (".nargout.");
813 
814  m_scope.force_assign (".saved_warning_states.", octave_value ());
815 
816  m_scope.mark_automatic (".saved_warning_states.");
817  m_scope.mark_automatic (".saved_warning_states.");
818 
819  if (takes_varargs ())
820  m_scope.assign ("varargin", va_args.cell_value ());
821 
822  Matrix ignored_fcn_outputs = tw.ignored_fcn_outputs ();
823 
824  m_scope.force_assign (".ignored.", ignored_fcn_outputs);
825 
826  m_scope.mark_hidden (".ignored.");
827  m_scope.mark_automatic (".ignored.");
828 }
829 
830 void
832 {
833  octave_value val = m_scope.varval (".saved_warning_states.");
834 
835  if (val.is_defined ())
836  {
837  // Fail spectacularly if .saved_warning_states. is not an
838  // octave_map (or octave_scalar_map) object.
839 
840  if (! val.isstruct ())
841  panic_impossible ();
842 
843  octave_map m = val.map_value ();
844 
845  Cell ids = m.contents ("identifier");
846  Cell states = m.contents ("state");
847 
848  octave::interpreter& interp
849  = octave::__get_interpreter__ ("octave_user_function::restore_warning_states");
850 
851  for (octave_idx_type i = 0; i < m.numel (); i++)
852  Fwarning (interp, ovl (states(i), ids(i)));
853  }
854 }
855 
856 DEFMETHOD (nargin, interp, args, ,
857  doc: /* -*- texinfo -*-
858 @deftypefn {} {} nargin ()
859 @deftypefnx {} {} nargin (@var{fcn})
860 Report the number of input arguments to a function.
861 
862 Called from within a function, return the number of arguments passed to the
863 function. At the top level, return the number of command line arguments
864 passed to Octave.
865 
866 If called with the optional argument @var{fcn}---a function name or
867 handle---return the declared number of arguments that the function can
868 accept.
869 
870 If the last argument to @var{fcn} is @var{varargin} the returned value is
871 negative. For example, the function @code{union} for sets is declared as
872 
873 @example
874 @group
875 function [y, ia, ib] = union (a, b, varargin)
876 
877 and
878 
879 nargin ("union")
880 @result{} -3
881 @end group
882 @end example
883 
884 Programming Note: @code{nargin} does not work on compiled functions
885 (@file{.oct} files) such as built-in or dynamically loaded functions.
886 @seealso{nargout, narginchk, varargin, inputname}
887 @end deftypefn */)
888 {
889  int nargin = args.length ();
890 
891  if (nargin > 1)
892  print_usage ();
893 
895 
896  octave::symbol_table& symtab = interp.get_symbol_table ();
897 
898  if (nargin == 1)
899  {
900  octave_value func = args(0);
901 
902  if (func.is_string ())
903  {
904  std::string name = func.string_value ();
905  func = symtab.find_function (name);
906  if (func.is_undefined ())
907  error ("nargin: invalid function name: %s", name.c_str ());
908  }
909 
910  octave_function *fcn_val = func.function_value (true);
911  if (! fcn_val)
912  error ("nargin: FCN must be a string or function handle");
913 
914  octave_user_function *fcn = fcn_val->user_function_value (true);
915 
916  if (! fcn)
917  {
918  // Matlab gives up for histc, so maybe it's ok that we
919  // give up sometimes too?
920 
921  std::string type = fcn_val->type_name ();
922  error ("nargin: number of input arguments unavailable for %s objects",
923  type.c_str ());
924  }
925 
926  octave::tree_parameter_list *param_list = fcn->parameter_list ();
927 
928  retval = (param_list ? param_list->length () : 0);
929  if (fcn->takes_varargs ())
930  retval = -1 - retval;
931  }
932  else
933  {
934  octave::symbol_scope scope = symtab.require_current_scope ("nargin");
935  retval = scope.varval (".nargin.");
936 
937  if (retval.is_undefined ())
938  retval = 0;
939  }
940 
941  return retval;
942 }
943 
944 DEFMETHOD (nargout, interp,args, ,
945  doc: /* -*- texinfo -*-
946 @deftypefn {} {} nargout ()
947 @deftypefnx {} {} nargout (@var{fcn})
948 Report the number of output arguments from a function.
949 
950 Called from within a function, return the number of values the caller
951 expects to receive. At the top level, @code{nargout} with no argument is
952 undefined and will produce an error.
953 
954 If called with the optional argument @var{fcn}---a function name or
955 handle---return the number of declared output values that the function can
956 produce.
957 
958 If the final output argument is @var{varargout} the returned value is
959 negative.
960 
961 For example,
962 
963 @example
964 f ()
965 @end example
966 
967 @noindent
968 will cause @code{nargout} to return 0 inside the function @code{f} and
969 
970 @example
971 [s, t] = f ()
972 @end example
973 
974 @noindent
975 will cause @code{nargout} to return 2 inside the function @code{f}.
976 
977 In the second usage,
978 
979 @example
980 nargout (@@histc) # or nargout ("histc") using a string input
981 @end example
982 
983 @noindent
984 will return 2, because @code{histc} has two outputs, whereas
985 
986 @example
987 nargout (@@imread)
988 @end example
989 
990 @noindent
991 will return -2, because @code{imread} has two outputs and the second is
992 @var{varargout}.
993 
994 Programming Note. @code{nargout} does not work for built-in functions and
995 returns -1 for all anonymous functions.
996 @seealso{nargin, varargout, isargout, nthargout}
997 @end deftypefn */)
998 {
999  int nargin = args.length ();
1000 
1001  if (nargin > 1)
1002  print_usage ();
1003 
1005 
1006  octave::symbol_table& symtab = interp.get_symbol_table ();
1007 
1008  if (nargin == 1)
1009  {
1010  octave_value func = args(0);
1011 
1012  if (func.is_string ())
1013  {
1014  std::string name = func.string_value ();
1015  func = symtab.find_function (name);
1016  if (func.is_undefined ())
1017  error ("nargout: invalid function name: %s", name.c_str ());
1018  }
1019 
1020  if (func.is_inline_function ())
1021  return ovl (1);
1022 
1023  if (func.is_function_handle ())
1024  {
1025  octave_fcn_handle *fh = func.fcn_handle_value ();
1026  std::string fh_nm = fh->fcn_name ();
1027 
1028  if (fh_nm == octave_fcn_handle::anonymous)
1029  return ovl (-1);
1030  }
1031 
1032  octave_function *fcn_val = func.function_value (true);
1033  if (! fcn_val)
1034  error ("nargout: FCN must be a string or function handle");
1035 
1036  octave_user_function *fcn = fcn_val->user_function_value (true);
1037 
1038  if (! fcn)
1039  {
1040  // Matlab gives up for histc, so maybe it's ok that we
1041  // give up sometimes too?
1042 
1043  std::string type = fcn_val->type_name ();
1044  error ("nargout: number of output arguments unavailable for %s objects",
1045  type.c_str ());
1046  }
1047 
1048  octave::tree_parameter_list *ret_list = fcn->return_list ();
1049 
1050  retval = (ret_list ? ret_list->length () : 0);
1051 
1052  if (fcn->takes_var_return ())
1053  retval = -1 - retval;
1054  }
1055  else
1056  {
1057  if (symtab.at_top_level ())
1058  error ("nargout: invalid call at top level");
1059 
1060  octave::symbol_scope scope = symtab.require_current_scope ("nargout");
1061  retval = scope.varval (".nargout.");
1062 
1063  if (retval.is_undefined ())
1064  retval = 0;
1065  }
1066 
1067  return retval;
1068 }
1069 
1070 DEFUN (optimize_subsasgn_calls, args, nargout,
1071  doc: /* -*- texinfo -*-
1072 @deftypefn {} {@var{val} =} optimize_subsasgn_calls ()
1073 @deftypefnx {} {@var{old_val} =} optimize_subsasgn_calls (@var{new_val})
1074 @deftypefnx {} {} optimize_subsasgn_calls (@var{new_val}, "local")
1075 Query or set the internal flag for @code{subsasgn} method call
1076 optimizations.
1077 
1078 If true, Octave will attempt to eliminate the redundant copying when calling
1079 the @code{subsasgn} method of a user-defined class.
1080 
1081 When called from inside a function with the @qcode{"local"} option, the
1082 variable is changed locally for the function and any subroutines it calls.
1083 The original variable value is restored when exiting the function.
1084 @seealso{subsasgn}
1085 @end deftypefn */)
1086 {
1087  return SET_INTERNAL_VARIABLE (optimize_subsasgn_calls);
1088 }
1089 
1090 static bool val_in_table (const Matrix& table, double val)
1091 {
1092  if (table.isempty ())
1093  return false;
1094 
1095  octave_idx_type i = table.lookup (val, ASCENDING);
1096  return (i > 0 && table(i-1) == val);
1097 }
1098 
1099 static bool isargout1 (int nargout, const Matrix& ignored, double k)
1100 {
1101  if (k != octave::math::round (k) || k <= 0)
1102  error ("isargout: K must be a positive integer");
1103 
1104  return (k == 1 || k <= nargout) && ! val_in_table (ignored, k);
1105 }
1106 
1107 DEFMETHOD (isargout, interp, args, ,
1108  doc: /* -*- texinfo -*-
1109 @deftypefn {} {} isargout (@var{k})
1110 Within a function, return a logical value indicating whether the argument
1111 @var{k} will be assigned to a variable on output.
1112 
1113 If the result is false, the argument has been ignored during the function
1114 call through the use of the tilde (~) special output argument. Functions
1115 can use @code{isargout} to avoid performing unnecessary calculations for
1116 outputs which are unwanted.
1117 
1118 If @var{k} is outside the range @code{1:max (nargout)}, the function returns
1119 false. @var{k} can also be an array, in which case the function works
1120 element-by-element and a logical array is returned. At the top level,
1121 @code{isargout} returns an error.
1122 @seealso{nargout, varargout, nthargout}
1123 @end deftypefn */)
1124 {
1125  if (args.length () != 1)
1126  print_usage ();
1127 
1128  octave::symbol_table& symtab = interp.get_symbol_table ();
1129 
1130  if (symtab.at_top_level ())
1131  error ("isargout: invalid call at top level");
1132 
1133  octave::symbol_scope scope = symtab.require_current_scope ("isargout");
1134 
1135  int nargout1 = scope.varval (".nargout.").int_value ();
1136 
1137  Matrix ignored;
1138  octave_value tmp = scope.varval (".ignored.");
1139  if (tmp.is_defined ())
1140  ignored = tmp.matrix_value ();
1141 
1142  if (args(0).is_scalar_type ())
1143  {
1144  double k = args(0).double_value ();
1145 
1146  return ovl (isargout1 (nargout1, ignored, k));
1147  }
1148  else if (args(0).isnumeric ())
1149  {
1150  const NDArray ka = args(0).array_value ();
1151 
1152  boolNDArray r (ka.dims ());
1153  for (octave_idx_type i = 0; i < ka.numel (); i++)
1154  r(i) = isargout1 (nargout1, ignored, ka(i));
1155 
1156  return ovl (r);
1157  }
1158  else
1159  err_wrong_type_arg ("isargout", args(0));
1160 
1161  return ovl ();
1162 }
1163 
1164 /*
1165 %!function [x, y] = try_isargout ()
1166 %! if (isargout (1))
1167 %! if (isargout (2))
1168 %! x = 1; y = 2;
1169 %! else
1170 %! x = -1;
1171 %! endif
1172 %! else
1173 %! if (isargout (2))
1174 %! y = -2;
1175 %! else
1176 %! error ("no outputs requested");
1177 %! endif
1178 %! endif
1179 %!endfunction
1180 %!
1181 %!function [a, b] = try_isargout2 (x, y)
1182 %! a = y;
1183 %! b = {isargout(1), isargout(2), x};
1184 %!endfunction
1185 %!
1186 %!test
1187 %! [x, y] = try_isargout ();
1188 %! assert ([x, y], [1, 2]);
1189 %!
1190 %!test
1191 %! [x, ~] = try_isargout ();
1192 %! assert (x, -1);
1193 %!
1194 %!test
1195 %! [~, y] = try_isargout ();
1196 %! assert (y, -2);
1197 %!
1198 %!error [~, ~] = try_isargout ()
1199 %!
1200 ## Check to see that isargout isn't sticky:
1201 %!test
1202 %! [x, y] = try_isargout ();
1203 %! assert ([x, y], [1, 2]);
1204 %!
1205 ## It should work without ():
1206 %!test
1207 %! [~, y] = try_isargout;
1208 %! assert (y, -2);
1209 %!
1210 ## It should work in function handles, anonymous functions, and cell
1211 ## arrays of handles or anonymous functions.
1212 %!test
1213 %! fh = @try_isargout;
1214 %! af = @() try_isargout;
1215 %! c = {fh, af};
1216 %! [~, y] = fh ();
1217 %! assert (y, -2);
1218 %! [~, y] = af ();
1219 %! assert (y, -2);
1220 %! [~, y] = c{1}();
1221 %! assert (y, -2);
1222 %! [~, y] = c{2}();
1223 %! assert (y, -2);
1224 %!
1225 ## Nesting, anyone?
1226 %!test
1227 %! [~, b] = try_isargout2 (try_isargout, rand);
1228 %! assert (b, {0, 1, -1});
1229 %!test
1230 %! [~, b] = try_isargout2 ({try_isargout, try_isargout}, rand);
1231 %! assert (b, {0, 1, {-1, -1}});
1232 */
std::string profiler_name(void) const
Definition: ov-usr-fcn.cc:368
void print_code_function_trailer(const std::string &prefix)
Definition: ov-usr-fcn.cc:776
void set_location(int l, int c)
Definition: pt-stmt.cc:123
virtual std::map< std::string, octave_value > subfunctions(void) const
Definition: ov-usr-fcn.cc:116
static bool Voptimize_subsasgn_calls
Definition: ov-usr-fcn.cc:63
void unbind_script_symbols(void)
Definition: symscope.h:964
octave_value find_function(const std::string &name, const octave_value_list &args=octave_value_list(), bool local_funcs=true)
Definition: symtab.cc:412
void lock_subfunctions(void)
Definition: symscope.h:867
void undefine_parameter_list(tree_parameter_list *param_list)
Definition: pt-eval.cc:574
octave::tree_expression * special_expr(void)
Definition: ov-usr-fcn.cc:688
Definition: Cell.h:37
virtual octave::sys::time time_parsed(void) const
Definition: ov-fcn.h:90
~octave_user_code(void)
Definition: ov-usr-fcn.cc:65
int int_value(bool req_int=false, bool frc_str_conv=false) const
Definition: ov.h:793
static const std::string anonymous
Definition: ov-fcn-handle.h:55
void stash_subfunction_names(const std::list< std::string > &names)
Definition: symscope.h:903
#define DEFMETHOD(name, interp_name, args_name, nargout_name, doc)
Macro to define a builtin method.
Definition: defun.h:135
void accept(octave::tree_walker &tw)
Definition: ov-usr-fcn.cc:228
interpreter & __get_interpreter__(const std::string &who)
int line(void) const
Definition: pt-stmt.cc:107
std::string string_value(bool force=false) const
Definition: ov.h:955
void set_location(int l, int c)
Definition: call-stack.h:191
bool is_end_of_fcn_or_script(void) const
Definition: pt-stmt.cc:140
void push_echo_state(unwind_protect &frame, int type, const std::string &file_name, size_t pos=1)
Definition: pt-eval.cc:3013
bp_table::intmap remove_all_breakpoints(const std::string &file)
Definition: pt-stmt.cc:270
octave_value dump(void) const
Definition: ov-usr-fcn.cc:742
octave_user_function * define_ret_list(octave::tree_parameter_list *t)
Definition: ov-usr-fcn.cc:285
octave::comment_list * lead_comm
Definition: ov-usr-fcn.h:432
bool isempty(void) const
Definition: Array.h:565
OCTINTERP_API void print_usage(void)
Definition: defun.cc:54
octave_value_list slice(octave_idx_type offset, octave_idx_type len, bool tags=false) const
Definition: ovl.h:114
identity matrix If supplied two scalar respectively For allows like xample val
Definition: data.cc:4986
F77_RET_T const F77_REAL const F77_REAL F77_REAL &F77_RET_T const F77_DBLE const F77_DBLE F77_DBLE &F77_RET_T const F77_DBLE F77_DBLE &F77_RET_T const F77_REAL F77_REAL &F77_RET_T const F77_DBLE const F77_DBLE * f
octave::sys::time t_parsed
Definition: ov-usr-fcn.h:450
void mark_subfunctions_in_scope_as_private(const std::string &class_name)
Definition: symscope.h:892
OCTINTERP_API std::string fcn_file_in_path(const std::string &)
octave_value_list all_va_args(const octave_value_list &args)
Definition: ov-usr-fcn.cc:477
void maybe_relocate_end_internal(void)
Definition: ov-usr-fcn.cc:307
for large enough k
Definition: lu.cc:617
bool is_special_expr(void) const
Definition: ov-usr-fcn.h:347
octave::file_info * m_file_info
Definition: ov-usr-fcn.h:115
octave::sys::time t_checked
Definition: ov-usr-fcn.h:454
bool is_end_of_file(void) const
Definition: pt-stmt.cc:157
std::string get_code_line(size_t line)
Definition: ov-usr-fcn.cc:85
void bind_script_symbols(const symbol_scope &curr_scope)
Definition: symscope.h:958
size_t length(void) const
Definition: base-list.h:50
#define DEFUN(name, args_name, nargout_name, doc)
Macro to define a builtin function.
Definition: defun.h:53
void error(const char *fmt,...)
Definition: error.cc:578
int beginning_column(void) const
Definition: ov-usr-fcn.h:248
#define SET_INTERNAL_VARIABLE(NM)
Definition: variables.h:109
elt_type & back(void)
Definition: base-list.h:98
virtual void visit_octave_user_function(octave_user_function &)=0
const dim_vector & dims(void) const
Return a const-reference so that dims ()(i) works efficiently.
Definition: Array.h:442
void visit_octave_user_function_trailer(octave_user_function &)
Definition: pt-pr-code.cc:419
std::map< std::string, octave_value > subfunctions(void) const
Definition: ov-usr-fcn.cc:453
#define DEFINE_OV_TYPEID_FUNCTIONS_AND_DATA(t, n, c)
Definition: ov-base.h:180
bool is_defined(void) const
Definition: ov.h:523
octave_value_list call(octave::tree_evaluator &tw, int nargout=0, const octave_value_list &args=octave_value_list())
Definition: ov-usr-fcn.cc:490
std::deque< std::string > get_code_lines(size_t line, size_t num_lines)
Definition: ov-usr-fcn.cc:94
static llvm::LLVMContext & context
Definition: jit-typeinfo.cc:79
void print_code_function_header(const std::string &prefix)
Definition: ov-usr-fcn.cc:768
OCTAVE_EXPORT octave_value_list return the number of command line arguments passed to Octave If called with the optional argument the function t
Definition: ov-usr-fcn.cc:997
bool at_top_level(void)
Definition: symtab.h:140
void restore_warning_states(void)
Definition: ov-usr-fcn.cc:831
octave::jit_function_info * jit_info
Definition: ov-usr-fcn.h:486
bool takes_varargs(void) const
Definition: pt-misc.h:76
octave_value echo(const octave_value_list &args, int nargout)
Definition: pt-eval.cc:3090
virtual std::string fcn_file_name(void) const
Definition: ov-fcn.h:74
void push_context(void)
Definition: symscope.h:737
std::list< tree_statement * >::reverse_iterator reverse_iterator
Definition: base-list.h:43
octave_value_list evaluate_n(tree_expression *expr, int nargout=1)
Definition: pt-eval.h:325
OCTAVE_EXPORT octave_value_list isnumeric
Definition: data.cc:3157
std::string fcn_file_dir(void)
Definition: defaults.cc:294
void push(octave_function *fcn)
Definition: call-stack.cc:357
Matrix ignored_fcn_outputs(void) const
Definition: pt-eval.cc:449
octave_function * fcn
Definition: ov-class.cc:1754
void pop_context(void)
Definition: symscope.h:743
int beginning_line(void) const
Definition: ov-usr-fcn.h:247
octave::call_stack & cs
Definition: ov-class.cc:1752
bool takes_varargs(void) const
Definition: ov-usr-fcn.cc:421
bool is_subfunction(void) const
Definition: ov-usr-fcn.h:324
reverse_iterator rbegin(void)
Definition: base-list.h:89
void bind_automatic_vars(octave::tree_evaluator &tw, const string_vector &arg_names, int nargin, int nargout, const octave_value_list &va_args)
Definition: ov-usr-fcn.cc:785
void get_file_info(void)
Definition: ov-usr-fcn.cc:71
nd deftypefn *std::string name
Definition: sysdep.cc:647
OCTAVE_EXPORT octave_value_list isdir nd deftypefn *std::string nm
Definition: utils.cc:975
std::string fcn_name(void) const
octave_idx_type lookup(const T &value, sortmode mode=UNSORTED) const
Do a binary lookup in a sorted array.
Definition: Array.cc:2147
virtual octave_user_function * user_function_value(bool silent=false)
Definition: ov-base.cc:880
OCTAVE_EXPORT octave_value_list return the number of command line arguments passed to Octave If called with the optional argument the function xample nargout(@histc)
Definition: ov-usr-fcn.cc:997
std::string get_line(size_t line) const
Definition: file-info.cc:38
octave::tree_parameter_list * ret_list
Definition: ov-usr-fcn.h:426
void accept(octave::tree_walker &tw)
Definition: ov-usr-fcn.cc:682
bool is_function_handle(void) const
Definition: ov.h:749
std::list< std::string > subfunction_names(void) const
Definition: symscope.h:909
void lock_subfunctions(void)
Definition: ov-usr-fcn.cc:441
std::string dispatch_class(void) const
Definition: ov-fcn.h:122
std::map< std::string, octave_value > subfunctions(void) const
Definition: symscope.h:879
void refresh(void)
Definition: symscope.h:749
bool Vtrack_line_num
Definition: input.cc:102
symbol_record::context_id current_context(void) const
Definition: symscope.h:669
octave_value_list convert_return_list_to_const_vector(tree_parameter_list *ret_list, int nargout, const Cell &varargout)
Definition: pt-eval.cc:586
void maybe_relocate_end(void)
Definition: ov-usr-fcn.cc:343
void stash_subfunction_names(const std::list< std::string > &names)
Definition: ov-usr-fcn.cc:465
bool takes_var_return(void) const
Definition: ov-usr-fcn.cc:427
void accept(tree_walker &tw)
Definition: pt-stmt.h:188
void unlock_subfunctions(void)
Definition: ov-usr-fcn.cc:447
virtual bool takes_varargs(void) const
Definition: ov-fcn.h:108
void erase_subfunctions(void)
Definition: symscope.h:886
double tmp
Definition: data.cc:6252
virtual void mark_as_private_function(const std::string &cname="")
Definition: ov-fcn.h:129
octave_value retval
Definition: data.cc:6246
virtual bool takes_var_return(void) const
Definition: ov-fcn.h:110
#define panic_impossible()
Definition: error.h:40
octave_function * function_value(bool silent=false) const
const Cell & contents(const_iterator p) const
Definition: oct-map.h:317
std::deque< std::string > get_lines(size_t line, size_t num_lines) const
Definition: file-info.cc:61
idx type
Definition: ov.cc:3114
Definition: dMatrix.h:36
symbol_scope require_current_scope(const std::string &who)
Definition: symtab.h:79
bool has_subfunctions(void) const
Definition: ov-usr-fcn.cc:459
octave_idx_type numel(void) const
Definition: oct-map.h:375
octave_value varval(const std::string &name) const
Definition: symscope.h:727
bool empty(void) const
Definition: str-vec.h:79
void err_wrong_type_arg(const char *name, const char *s)
Definition: errwarn.cc:162
With real return the complex result
Definition: data.cc:3260
friend class octave_value
Definition: ov-base.h:228
std::string file_name
Definition: ov-usr-fcn.h:188
bool is_anonymous_function(void) const
Definition: ov-usr-fcn.h:332
void cache_function_text(const std::string &text, const octave::sys::time &timestamp)
Definition: ov-usr-fcn.cc:103
void warning(const char *fmt,...)
Definition: error.cc:801
int max_recursion_depth(void) const
Definition: pt-eval.h:377
octave::unwind_protect frame
Definition: graphics.cc:12190
octave::tree_statement_list * cmd_list
Definition: ov-usr-fcn.h:429
std::string file_name
Definition: ov-usr-fcn.h:438
octave::tree_parameter_list * param_list
Definition: ov-usr-fcn.h:422
bool empty(void) const
Definition: base-list.h:47
std::string fcn_file_name(void) const
Definition: ov-usr-fcn.h:277
bool subsasgn_optimization_ok(void)
Definition: ov-usr-fcn.cc:698
octave_fcn_handle * fcn_handle_value(bool silent=false) const
#define octave_stdout
Definition: pager.h:174
std::string ctor_type_str(void) const
Definition: ov-usr-fcn.cc:715
void erase_subfunctions(void)
Definition: ov-usr-fcn.cc:415
bool is_undefined(void) const
Definition: ov.h:526
string_vector name_tags(void) const
Definition: ovl.h:146
void visit_octave_user_function_header(octave_user_function &)
Definition: pt-pr-code.cc:329
OCTAVE_EXPORT octave_value_list isa nd deftypefn *return ovl(args(0).isinteger())
octave::unwind_protect * curr_unwind_protect_frame
Definition: ov-usr-fcn.h:118
void unlock_subfunctions(void)
Definition: symscope.h:873
bool has_subfunctions(void) const
Definition: symscope.h:898
call_stack & __get_call_stack__(const std::string &who)
void stash_parent_fcn_scope(const octave::symbol_scope &ps)
Definition: ov-usr-fcn.cc:362
std::string parent_name
Definition: ov-usr-fcn.h:447
octave::tree_statement_list * cmd_list
Definition: ov-usr-fcn.h:185
Cell cell_value(void) const
Definition: ovl.h:88
octave_idx_type length(void) const
Definition: ovl.h:96
class_ctor_type class_constructor
Definition: ov-usr-fcn.h:480
virtual void visit_octave_user_script(octave_user_script &)=0
elt_type & front(void)
Definition: base-list.h:97
virtual std::string type_name(void) const
Definition: ov-base.h:876
symbol_scope get_current_scope(void)
Definition: pt-eval.cc:688
void define_parameter_list_from_arg_vector(tree_parameter_list *param_list, const octave_value_list &args)
Definition: pt-eval.cc:548
octave::sys::file_stat fs(filename)
double round(double x)
Definition: lo-mappers.h:145
void add_method(T *obj, void(T::*method)(void))
void assign(const idx_vector &i, const Array< T > &rhs, const T &rfv)
Indexed assignment (always with resize & fill).
Definition: Array.cc:1115
args.length() nargin
Definition: file-io.cc:589
std::string name(void) const
Definition: pt-id.h:72
char string_fill_char(void) const
Definition: pt-eval.h:401
int column(void) const
Definition: pt-stmt.cc:115
for i
Definition: data.cc:5264
static bool execute(tree_simple_for_command &cmd, const octave_value &bounds)
Definition: pt-jit.h:490
bool is_string(void) const
Definition: ov.h:577
octave::comment_list * trail_comm
Definition: ov-usr-fcn.h:435
std::list< std::string > subfunction_names(void) const
Definition: ov-usr-fcn.cc:471
static stmt_list_type statement_context
Definition: pt-eval.h:265
bool is_classdef_constructor(const std::string &cname="") const
Definition: ov-usr-fcn.h:366
void stash_fcn_file_name(const std::string &nm)
Definition: ov-usr-fcn.cc:293
octave_value dump(void) const
Definition: symscope.h:914
octave_idx_type numel(void) const
Number of elements in the array.
Definition: Array.h:366
tree_identifier * ident(void)
Definition: pt-decl.h:98
void set_parent(const symbol_scope &p)
Definition: symscope.h:941
reverse_iterator rend(void)
Definition: base-list.h:93
std::string name(void) const
Definition: ov-fcn.h:182
profiler & get_profiler(void)
Definition: pt-eval.h:373
static int call_depth
Definition: daspk.cc:59
If this string is the system will ring the terminal sometimes it is useful to be able to print the original representation of the string
Definition: utils.cc:888
sys::time mtime(void) const
Definition: file-stat.h:128
Cell xcell_value(const char *fmt,...) const
octave_value_list call(octave::tree_evaluator &tw, int nargout=0, const octave_value_list &args=octave_value_list())
Definition: ov-usr-fcn.cc:165
octave::symbol_scope m_scope
Definition: ov-usr-fcn.h:111
bool is_inline_function(void) const
Definition: ov.h:755
void mark_as_private_function(const std::string &cname="")
Definition: ov-usr-fcn.cc:433
octave_user_function(const octave::symbol_scope &scope=octave::symbol_scope(), octave::tree_parameter_list *pl=nullptr, octave::tree_parameter_list *rl=nullptr, octave::tree_statement_list *cl=nullptr)
Definition: ov-usr-fcn.cc:243
tree_expression * expression(void)
Definition: pt-stmt.h:92
OCTAVE_EXPORT octave_value_list directory
Definition: variables.cc:593