GNU Octave  8.1.0
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
pt-eval.cc
Go to the documentation of this file.
1 ////////////////////////////////////////////////////////////////////////
2 //
3 // Copyright (C) 2009-2023 The Octave Project Developers
4 //
5 // See the file COPYRIGHT.md in the top-level directory of this
6 // distribution or <https://octave.org/copyright/>.
7 //
8 // This file is part of Octave.
9 //
10 // Octave is free software: you can redistribute it and/or modify it
11 // under the terms of the GNU General Public License as published by
12 // the Free Software Foundation, either version 3 of the License, or
13 // (at your option) any later version.
14 //
15 // Octave is distributed in the hope that it will be useful, but
16 // WITHOUT ANY WARRANTY; without even the implied warranty of
17 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 // GNU General Public License for more details.
19 //
20 // You should have received a copy of the GNU General Public License
21 // along with Octave; see the file COPYING. If not, see
22 // <https://www.gnu.org/licenses/>.
23 //
24 ////////////////////////////////////////////////////////////////////////
25 
26 #if defined (HAVE_CONFIG_H)
27 # include "config.h"
28 #endif
29 
30 #include <cctype>
31 
32 #include <condition_variable>
33 #include <iostream>
34 #include <list>
35 #include <mutex>
36 #include <string>
37 #include <thread>
38 
39 #include "cmd-edit.h"
40 #include "file-ops.h"
41 #include "file-stat.h"
42 #include "lo-array-errwarn.h"
43 #include "lo-ieee.h"
44 #include "oct-env.h"
45 
46 #include "bp-table.h"
47 #include "call-stack.h"
48 #include "cdef-manager.h"
49 #include "defun.h"
50 #include "error.h"
51 #include "errwarn.h"
52 #include "event-manager.h"
53 #include "input.h"
54 #include "interpreter-private.h"
55 #include "interpreter.h"
56 #include "mex-private.h"
57 #include "octave.h"
58 #include "ov-classdef.h"
59 #include "ov-fcn-handle.h"
60 #include "ov-mex-fcn.h"
61 #include "ov-usr-fcn.h"
62 #include "ov-re-sparse.h"
63 #include "ov-cx-sparse.h"
64 #include "parse.h"
65 #include "profiler.h"
66 #include "pt-all.h"
67 #include "pt-anon-scopes.h"
68 #include "pt-eval.h"
69 #include "pt-tm-const.h"
70 #include "stack-frame.h"
71 #include "symtab.h"
72 #include "unwind-prot.h"
73 #include "utils.h"
74 #include "variables.h"
75 
77 
78 // Normal evaluator.
79 
81 {
82 public:
83 
84  quit_debug_exception (bool all = false) : m_all (all) { }
85 
87 
88  quit_debug_exception& operator = (const quit_debug_exception&) = default;
89 
90  ~quit_debug_exception (void) = default;
91 
92  bool all (void) const { return m_all; }
93 
94 private:
95 
96  bool m_all;
97 };
98 
99 class debugger
100 {
101 public:
102 
104  {
107  EX_QUIT = 2,
108  EX_QUIT_ALL = 3
109  };
110 
111  debugger (interpreter& interp, std::size_t level)
112  : m_interpreter (interp), m_level (level),
114  { }
115 
116  int server_loop (void);
117 
118  void repl (const std::string& prompt = "debug> ");
119 
120  bool in_debug_repl (void) const { return m_in_debug_repl; }
121 
123 
124  void dbquit (bool all = false)
125  {
126  if (all)
128  else
130  }
131 
132  bool quitting_debugger (void) const;
133 
134 private:
135 
137 
138  std::size_t m_level;
141 };
142 
143 // FIXME: Could the debugger server_loop and repl functions be merged
144 // with the corresponding tree_evaluator functions or do they need to
145 // remain separate? They perform nearly the same functions.
146 
148 {
149  // Process events from the event queue.
150 
152 
153  void (tree_evaluator::*server_mode_fptr) (bool)
155  unwind_action act (server_mode_fptr, &tw, true);
156 
157  int exit_status = 0;
158 
159  do
160  {
161  if (m_execution_mode == EX_CONTINUE || tw.dbstep_flag ())
162  break;
163 
164  if (quitting_debugger ())
165  break;
166 
167  try
168  {
169  // FIXME: Should we call octave_quit in the octave::sleep
170  // and/or command_editor::run_event_hooks functions?
171 
172  octave_quit ();
173 
174  // FIXME: Running the event queue should be decoupled from
175  // the command_editor.
176 
177  // FIXME: Is it OK to use command_editor::run_event_hooks
178  // here? It may run more than one queued function per call,
179  // and it seems that the checks at the top of the loop
180  // probably need to be done after each individual event
181  // function is executed. For now, maybe the simplest thing
182  // would be to pass a predicate function (lambda expression)
183  // to the command_editor::run_event_hooks and have it check
184  // that and break out of the eval loop(s) if the condition
185  // is met?
186 
187  // FIXME: We should also use a condition variable to manage
188  // the execution of entries in the queue and eliminate the
189  // need for the busy-wait loop.
190 
192 
194 
195  sleep (0.1);
196  }
197  catch (const interrupt_exception&)
198  {
201 
202  // Required newline when the user does Ctrl+C at the prompt.
203  if (m_interpreter.interactive ())
204  octave_stdout << "\n";
205  }
206  catch (const index_exception& e)
207  {
209 
210  std::cerr << "error: unhandled index exception: "
211  << e.message () << " -- trying to return to prompt"
212  << std::endl;
213  }
214  catch (const execution_exception& ee)
215  {
217 
218  es.save_exception (ee);
219  es.display_exception (ee);
220 
221  if (m_interpreter.interactive ())
222  {
224  }
225  else
226  {
227  // We should exit with a nonzero status.
228  exit_status = 1;
229  break;
230  }
231  }
232  catch (const quit_debug_exception& qde)
233  {
234  if (qde.all ())
235  throw;
236 
237  // Continue in this debug level.
238  }
239  catch (const std::bad_alloc&)
240  {
242 
243  std::cerr << "error: out of memory -- trying to return to prompt"
244  << std::endl;
245  }
246  }
247  while (exit_status == 0);
248 
249  if (exit_status == EOF)
250  {
251  if (m_interpreter.interactive ())
252  octave_stdout << "\n";
253 
254  exit_status = 0;
255  }
256 
257  return exit_status;
258 }
259 
260 void debugger::repl (const std::string& prompt_arg)
261 {
262  unwind_protect frame;
263 
266 
267  m_in_debug_repl = true;
268 
270 
271  bool silent = tw.quiet_breakpoint_flag (false);
272 
273  frame.add (&tree_evaluator::restore_frame, &tw,
275 
276  tw.goto_frame (tw.debug_frame ());
277 
278  octave_user_code *caller = tw.current_user_code ();
279  std::string fcn_file_nm, fcn_nm;
280 
281  if (caller)
282  {
283  fcn_file_nm = caller->fcn_file_name ();
284  fcn_nm = fcn_file_nm.empty () ? caller->name () : fcn_file_nm;
285  }
286 
287  int curr_debug_line = tw.current_line ();
288 
289  std::ostringstream buf;
290 
292 
294 
295  if (! fcn_nm.empty ())
296  {
297  if (input_sys.gud_mode ())
298  {
299  static char ctrl_z = 'Z' & 0x1f;
300 
301  buf << ctrl_z << ctrl_z << fcn_nm << ':' << curr_debug_line;
302  }
303  else
304  {
305  // FIXME: we should come up with a clean way to detect
306  // that we are stopped on the no-op command that marks the
307  // end of a function or script.
308 
309  if (! silent)
310  {
311  std::shared_ptr<stack_frame> frm = tw.current_user_frame ();
312 
313  frm->display_stopped_in_message (buf);
314  }
315 
316  evmgr.enter_debugger_event (fcn_nm, fcn_file_nm, curr_debug_line);
317 
318  evmgr.set_workspace ();
319 
321  fcn_nm, curr_debug_line);
322 
323  if (! silent)
324  {
325  std::string line_buf;
326 
327  if (caller)
328  line_buf = caller->get_code_line (curr_debug_line);
329 
330  if (! line_buf.empty ())
331  buf << curr_debug_line << ": " << line_buf;
332  }
333  }
334  }
335 
336  if (silent)
338 
339  std::string stopped_in_msg = buf.str ();
340 
341  if (m_interpreter.server_mode ())
342  {
343  if (! stopped_in_msg.empty ())
344  octave_stdout << stopped_in_msg << std::endl;
345 
346  evmgr.push_event_queue ();
347 
348  frame.add (&event_manager::pop_event_queue, &evmgr);
349 
350  frame.add (&tree_evaluator::set_parser, &tw, tw.get_parser ());
351 
352  std::shared_ptr<push_parser>
353  debug_parser (new push_parser (m_interpreter));
354 
355  tw.set_parser (debug_parser);
356 
357  server_loop ();
358  }
359  else
360  {
361  if (! stopped_in_msg.empty ())
362  std::cerr << stopped_in_msg << std::endl;
363 
364  std::string tmp_prompt = prompt_arg;
365  if (m_level > 0)
366  tmp_prompt = "[" + std::to_string (m_level) + "]" + prompt_arg;
367 
368  frame.add (&input_system::set_PS1, &input_sys, input_sys.PS1 ());
369  input_sys.PS1 (tmp_prompt);
370 
371  if (! m_interpreter.interactive ())
372  {
373  void (interpreter::*interactive_fptr) (bool)
375  frame.add (interactive_fptr, &m_interpreter,
377 
378  m_interpreter.interactive (true);
379 
380  // FIXME: should debugging be possible in an embedded
381  // interpreter?
382 
383  application *app = application::app ();
384 
385  if (app)
386  {
387  void (application::*forced_interactive_fptr) (bool)
389  frame.add (forced_interactive_fptr, app,
390  app->forced_interactive ());
391 
392  app->forced_interactive (true);
393  }
394  }
395 
396 #if defined (OCTAVE_ENABLE_COMMAND_LINE_PUSH_PARSER)
397 
398  input_reader reader (m_interpreter);
399 
400  push_parser debug_parser (m_interpreter);
401 
402 #else
403 
404  parser debug_parser (m_interpreter);
405 
406 #endif
407 
409 
410  while (m_in_debug_repl)
411  {
412  if (m_execution_mode == EX_CONTINUE || tw.dbstep_flag ())
413  break;
414 
415  if (quitting_debugger ())
416  break;
417 
418  try
419  {
420  debug_parser.reset ();
421 
422 #if defined (OCTAVE_ENABLE_COMMAND_LINE_PUSH_PARSER)
423 
424  int retval = 0;
425 
426  std::string prompt
428 
429  do
430  {
431  bool eof = false;
432  std::string input_line = reader.get_input (prompt, eof);
433 
434  if (eof)
435  {
436  retval = EOF;
437  break;
438  }
439 
440  retval = debug_parser.run (input_line, false);
441 
442  prompt = command_editor::decode_prompt_string (input_sys.PS2 ());
443  }
444  while (retval < 0);
445 
446 #else
447 
448  int retval = debug_parser.run ();
449 
450 #endif
451  if (command_editor::interrupt (false))
452  {
453  // Break regardless of m_execution_mode value.
454 
456 
457  break;
458  }
459  else
460  {
461  if (retval == 0)
462  {
463  std::shared_ptr<tree_statement_list> stmt_list
464  = debug_parser.statement_list ();
465 
466  if (stmt_list)
467  stmt_list->accept (tw);
468 
471 
472  // FIXME: the following statement is here because
473  // the last command may have been a dbup, dbdown, or
474  // dbstep command that changed the current debug
475  // frame. If so, we need to reset the current frame
476  // for the call stack. But is this right way to do
477  // this job? What if the statement list was
478  // something like "dbup; dbstack"? Will the call to
479  // dbstack use the right frame? If not, how can we
480  // fix this problem?
481  tw.goto_frame (tw.debug_frame ());
482  }
483 
484  octave_quit ();
485  }
486  }
487  catch (const execution_exception& ee)
488  {
489  es.save_exception (ee);
490  es.display_exception (ee);
491 
492  // Ignore errors when in debugging mode;
494  }
495  catch (const quit_debug_exception& qde)
496  {
497  if (qde.all ())
498  throw;
499 
500  // Continue in this debug level.
501  }
502  }
503  }
504 }
505 
507 {
508  if (m_execution_mode == EX_QUIT)
509  {
510  // If there is no enclosing debug level or the top-level
511  // repl is not active, handle dbquit the same as dbcont.
512 
513  if (m_level > 0 || m_interpreter.server_mode ()
515  throw quit_debug_exception ();
516  else
517  return true;
518  }
519 
521  {
522  // If the top-level repl is not active, handle "dbquit all"
523  // the same as dbcont.
524 
526  throw quit_debug_exception (true);
527  else
528  return true;
529  }
530 
531  return false;
532 }
533 
535 {
536  return m_call_stack.at_top_level ();
537 }
538 
539 std::string
540 tree_evaluator::mfilename (const std::string& opt) const
541 {
542  std::string fname;
543 
545 
546  if (fcn)
547  {
548  fname = fcn->fcn_file_name ();
549 
550  if (fname.empty ())
551  fname = fcn->name ();
552  }
553 
554  if (opt == "fullpathext")
555  return fname;
556 
557  std::size_t dpos = fname.rfind (sys::file_ops::dir_sep_char ());
558  std::size_t epos = fname.rfind ('.');
559 
560  if (epos <= dpos+1)
561  epos = std::string::npos;
562 
563  if (epos != std::string::npos)
564  fname = fname.substr (0, epos);
565 
566  if (opt == "fullpath")
567  return fname;
568 
569  if (dpos != std::string::npos)
570  fname = fname.substr (dpos+1);
571 
572  return fname;
573 }
574 
575 void tree_evaluator::parse_and_execute (const std::string& input,
576  bool& incomplete_parse)
577 {
578  incomplete_parse = false;
579 
581 
582  if (at_top_level ())
583  {
584  dbstep_flag (0);
586  }
587 
588  // FIXME: OK to do this job here, or should it be in the functions
589  // that do the actual prompting?
590 
591  // Update the time stamp for the "prompt" so that automatically
592  // finding modified files based on file modification times will
593  // work. In the future, we may do something completely different to
594  // check for changes to files but for now, we rely on the prompt
595  // time stamp to limit the checks for file modification times.
596 
597  Vlast_prompt_time.stamp ();
598 
599  bool eof = false;
600 
602 
604  evmgr.append_history (input);
605 
606  m_exit_status = m_parser->run (input, eof);
607 
608  if (m_exit_status == 0)
609  {
610  std::shared_ptr<tree_statement_list>
611  stmt_list = m_parser->statement_list ();
612 
613  if (stmt_list)
614  {
616 
617  eval (stmt_list, m_interpreter.interactive ());
618 
619  evmgr.set_workspace ();
620  }
621  else if (m_parser->at_end_of_input ())
622  m_exit_status = EOF;
623  }
624  else
625  incomplete_parse = true;
626 
627  // FIXME: Should we be checking m_exit_status or incomplete_parse or
628  // both here? Could EOF have a value other than -1, and is there
629  // possible confusion between that state and the parser returning -1?
630 
631  if (m_exit_status == -1)
632  m_exit_status = 0;
633  else
634  m_parser->reset ();
635 
636  evmgr.pre_input_event ();
637 }
638 
640 {
641  std::mutex mtx;
642  std::unique_lock<std::mutex> lock (mtx);
643  std::condition_variable cv;
644  bool incomplete_parse = false;
645  bool evaluation_pending = false;
646  bool exiting = false;
647 
650 
651  while (true)
652  {
653  // FIXME: Detect EOF? Use readline? If
654  // so, then we need to disable idle event loop hook function
655  // execution.
656 
657  std::string ps = incomplete_parse ? input_sys.PS2 () : input_sys.PS1 ();
658 
659  std::cout << command_editor::decode_prompt_string (ps);
660 
661  std::string input;
662  std::getline (std::cin, input);
663 
664  if (input.empty ())
665  continue;
666 
667  incomplete_parse = false;
668  evaluation_pending = true;
669  exiting = false;
670 
671  evmgr.post_event
672  ([&] (interpreter& interp)
673  {
674  // INTERPRETER THREAD
675 
676  std::lock_guard<std::mutex> local_lock (mtx);
677 
678  try
679  {
680  interp.parse_and_execute (input, incomplete_parse);
681  }
682  catch (const exit_exception&)
683  {
684  evaluation_pending = false;
685  exiting = true;
686  cv.notify_all ();
687  throw;
688  }
689  catch (const execution_exception& ee)
690  {
692 
693  es.save_exception (ee);
694  es.display_exception (ee);
695 
696  if (m_interpreter.interactive ())
697  {
699  m_parser->reset ();
700  evaluation_pending = false;
701  cv.notify_all ();
702  }
703  else
704  {
705  evaluation_pending = false;
706  cv.notify_all ();
707  throw exit_exception (1);
708  }
709  }
710  catch (...)
711  {
712  evaluation_pending = false;
713  cv.notify_all ();
714  throw;
715  }
716 
717  evaluation_pending = false;
718  cv.notify_all ();
719  });
720 
721  // Wait until evaluation is finished before prompting for input
722  // again.
723 
724  cv.wait (lock, [&] { return ! evaluation_pending; });
725 
726  if (exiting)
727  break;
728  }
729 }
730 
732 {
733  // The big loop. Read, Eval, Print, Loop. Normally user
734  // interaction at the command line in a terminal session, but we may
735  // also end up here when reading from a pipe or when stdin is
736  // connected to a file by the magic of input redirection.
737 
738  int exit_status = 0;
739 
740  // FIXME: should this choice be a command-line option? Note that we
741  // intend that the push parser interface only be used for
742  // interactive sessions.
743 
744 #if defined (OCTAVE_ENABLE_COMMAND_LINE_PUSH_PARSER)
745  static bool use_command_line_push_parser = true;
746 #else
747  static bool use_command_line_push_parser = false;
748 #endif
749 
750  // The following logic is written as it is to allow easy transition
751  // to setting USE_COMMAND_LINE_PUSH_PARSER at run time and to
752  // simplify the logic of the main loop below by using the same
753  // base_parser::run interface for both push and pull parsers.
754 
755  std::shared_ptr<base_parser> repl_parser;
756 
757  if (m_interpreter.interactive ())
758  {
759  if (use_command_line_push_parser)
760  {
761  push_parser *pp
762  = new push_parser (m_interpreter,
764 
765  repl_parser = std::shared_ptr<base_parser> (pp);
766  }
767  else
768  {
769  parser *pp = new parser (new lexer (m_interpreter));
770  repl_parser = std::shared_ptr<base_parser> (pp);
771  }
772  }
773  else
774  {
775  parser *pp = new parser (new lexer (stdin, m_interpreter));
776  repl_parser = std::shared_ptr<base_parser> (pp);
777  }
778 
779  do
780  {
781  try
782  {
784 
785  repl_parser->reset ();
786 
787  if (at_top_level ())
788  {
789  dbstep_flag (0);
791  }
792 
793  exit_status = repl_parser->run ();
794 
795  if (exit_status == 0)
796  {
797  std::shared_ptr<tree_statement_list>
798  stmt_list = repl_parser->statement_list ();
799 
800  if (stmt_list)
801  {
803 
804  eval (stmt_list, m_interpreter.interactive ());
805  }
806  else if (repl_parser->at_end_of_input ())
807  {
808  exit_status = EOF;
809  break;
810  }
811  }
812  }
813  catch (const interrupt_exception&)
814  {
816 
817  // Required newline when the user does Ctrl+C at the prompt.
818  if (m_interpreter.interactive ())
819  octave_stdout << "\n";
820  }
821  catch (const index_exception& ie)
822  {
824 
825  std::cerr << "error: unhandled index exception: "
826  << ie.message () << " -- trying to return to prompt"
827  << std::endl;
828  }
829  catch (const execution_exception& ee)
830  {
832 
833  es.save_exception (ee);
834  es.display_exception (ee);
835 
836  if (m_interpreter.interactive ())
838  else
839  {
840  // We should exit with a nonzero status.
841  exit_status = 1;
842  break;
843  }
844  }
845  catch (const quit_debug_exception&)
846  {
848 
849  // FIXME: Does anything else need to happen here?
850  }
851  catch (const std::bad_alloc&)
852  {
854 
855  std::cerr << "error: out of memory -- trying to return to prompt"
856  << std::endl;
857  }
858  }
859  while (exit_status == 0);
860 
861  if (exit_status == EOF)
862  {
863  if (m_interpreter.interactive ())
864  octave_stdout << "\n";
865 
866  exit_status = 0;
867  }
868 
869  return exit_status;
870 }
871 
873 {
874  // Process events from the event queue.
875 
877 
878  m_exit_status = 0;
879 
880  std::shared_ptr<push_parser> parser (new push_parser (m_interpreter));
882 
883  // FIXME: We are currently resetting the parser after every call to
884  // recover_from_exception. This action should probably be handled
885  // in a more consistent way, but resetting the parser in every call
886  // to interpreter::recover_from_exception appears to cause
887  // segfaults in the test suite.
888 
889  do
890  {
891  try
892  {
893  // FIXME: Should we call octave_quit in the octave::sleep
894  // and/or command_editor::run_event_hooks functions?
895 
896  octave_quit ();
897 
898  // FIXME: Running the event queue should be decoupled from
899  // the command_editor. We should also use a condition
900  // variable to manage the execution of entries in the queue
901  // and eliminate the need for the busy-wait loop.
902 
904 
906 
907  sleep (0.1);
908  }
909  catch (const interrupt_exception&)
910  {
913  m_parser->reset ();
914 
915  // Required newline when the user does Ctrl+C at the prompt.
916  if (m_interpreter.interactive ())
917  octave_stdout << "\n";
918  }
919  catch (const index_exception& e)
920  {
922  m_parser->reset ();
923 
924  std::cerr << "error: unhandled index exception: "
925  << e.message () << " -- trying to return to prompt"
926  << std::endl;
927  }
928  catch (const execution_exception& ee)
929  {
931 
932  es.save_exception (ee);
933  es.display_exception (ee);
934 
935  if (m_interpreter.interactive ())
936  {
938  m_parser->reset ();
939  }
940  else
941  {
942  // We should exit with a nonzero status.
943  m_exit_status = 1;
944  break;
945  }
946  }
947  catch (const quit_debug_exception&)
948  {
951  m_parser->reset ();
952  }
953  catch (const exit_exception& xe)
954  {
955  m_exit_status = xe.exit_status ();
956  break;
957  }
958  catch (const std::bad_alloc&)
959  {
961  m_parser->reset ();
962 
963  std::cerr << "error: out of memory -- trying to return to prompt"
964  << std::endl;
965  }
966  }
967  while (m_exit_status == 0);
968 
969  if (m_exit_status == EOF)
970  {
971  if (m_interpreter.interactive ())
972  octave_stdout << "\n";
973 
974  m_exit_status = 0;
975  }
976 
977  return m_exit_status;
978 }
979 
980 void tree_evaluator::eval (std::shared_ptr<tree_statement_list>& stmt_list,
981  bool interactive)
982 {
983  try
984  {
985  stmt_list->accept (*this);
986 
987  octave_quit ();
988 
989  if (! interactive)
990  {
991  bool quit = (m_returning || m_breaking);
992 
993  if (m_returning)
994  m_returning = 0;
995 
996  if (m_breaking)
997  m_breaking--;
998 
999  if (quit)
1000  return;
1001  }
1002 
1005  }
1006  catch (const quit_debug_exception&)
1007  {
1009  }
1010 }
1011 
1013 tree_evaluator::eval_string (const std::string& eval_str, bool silent,
1014  int& parse_status, int nargout)
1015 {
1016  octave_value_list retval;
1017 
1018  parser eval_parser (eval_str, m_interpreter);
1019 
1020  do
1021  {
1022  eval_parser.reset ();
1023 
1024  // If we are looking at
1025  //
1026  // val = eval ("code");
1027  //
1028  // then don't allow code to be parsed as a command.
1029 
1030  if (nargout > 0)
1031  eval_parser.disallow_command_syntax ();
1032 
1033  parse_status = eval_parser.run ();
1034 
1035  if (parse_status == 0)
1036  {
1037  std::shared_ptr<tree_statement_list> stmt_list
1038  = eval_parser.statement_list ();
1039 
1040  if (stmt_list)
1041  {
1042  tree_statement *stmt = nullptr;
1043 
1044  if (stmt_list->length () == 1
1045  && (stmt = stmt_list->front ())
1046  && stmt->is_expression ())
1047  {
1048  tree_expression *expr = stmt->expression ();
1049 
1050  if (silent)
1051  expr->set_print_flag (false);
1052 
1053  retval = expr->evaluate_n (*this, nargout);
1054 
1055  bool do_bind_ans = false;
1056 
1057  if (expr->is_identifier ())
1058  do_bind_ans = ! is_variable (expr);
1059  else
1060  do_bind_ans = ! expr->is_assignment_expression ();
1061 
1062  if (do_bind_ans && ! retval.empty ())
1063  bind_ans (retval(0), expr->print_result ());
1064 
1065  if (nargout == 0)
1066  retval = octave_value_list ();
1067  }
1068  else if (nargout == 0)
1069  stmt_list->accept (*this);
1070  else
1071  error ("eval: invalid use of statement list");
1072 
1073  if (returning () || breaking () || continuing ())
1074  break;
1075  }
1076  else if (eval_parser.at_end_of_input ())
1077  break;
1078  }
1079  }
1080  while (parse_status == 0);
1081 
1082  return retval;
1083 }
1084 
1085 octave_value tree_evaluator::eval_string (const std::string& eval_str,
1086  bool silent, int& parse_status)
1087 {
1088  octave_value retval;
1089 
1090  octave_value_list tmp = eval_string (eval_str, silent, parse_status, 1);
1091 
1092  if (! tmp.empty ())
1093  retval = tmp(0);
1094 
1095  return retval;
1096 }
1097 
1099  bool silent, int& parse_status,
1100  int nargout)
1101 {
1102  std::string s = arg.xstring_value ("eval: expecting string argument");
1103 
1104  return eval_string (s, silent, parse_status, nargout);
1105 }
1106 
1107 octave_value_list tree_evaluator::eval (const std::string& try_code,
1108  int nargout)
1109 {
1110  int parse_status = 0;
1111 
1112  return eval_string (try_code, nargout > 0, parse_status, nargout);
1113 }
1114 
1115 octave_value_list tree_evaluator::eval (const std::string& try_code,
1116  const std::string& catch_code,
1117  int nargout)
1118 {
1119  octave_value_list retval;
1120 
1122 
1123  int parse_status = 0;
1124 
1125  bool execution_error = false;
1126 
1127  octave_value_list tmp;
1128 
1129  try
1130  {
1131  tmp = eval_string (try_code, nargout > 0, parse_status, nargout);
1132  }
1133  catch (const execution_exception& ee)
1134  {
1135  es.save_exception (ee);
1137 
1138  execution_error = true;
1139  }
1140 
1141  if (parse_status != 0 || execution_error)
1142  {
1143  tmp = eval_string (catch_code, nargout > 0, parse_status, nargout);
1144 
1145  retval = (nargout > 0) ? tmp : octave_value_list ();
1146  }
1147  else
1148  {
1149  if (nargout > 0)
1150  retval = tmp;
1151 
1152  // FIXME: we should really be rethrowing whatever
1153  // exception occurred, not just throwing an
1154  // execution exception.
1155  if (execution_error)
1156  throw execution_exception ();
1157  }
1158 
1159  return retval;
1160 }
1161 
1162 octave_value_list tree_evaluator::evalin (const std::string& context,
1163  const std::string& try_code,
1164  int nargout)
1165 {
1166  unwind_action act ([=] (std::size_t frm)
1167  {
1169  }, m_call_stack.current_frame ());
1170 
1171  if (context == "caller")
1173  else if (context == "base")
1175  else
1176  error (R"(evalin: CONTEXT must be "caller" or "base")");
1177 
1178  int parse_status = 0;
1179 
1180  return eval_string (try_code, nargout > 0, parse_status, nargout);
1181 }
1182 
1183 octave_value_list tree_evaluator::evalin (const std::string& context,
1184  const std::string& try_code,
1185  const std::string& catch_code,
1186  int nargout)
1187 {
1188  octave_value_list retval;
1189 
1190  unwind_action act1 ([=] (std::size_t frm)
1191  {
1193  }, m_call_stack.current_frame ());
1194 
1195  if (context == "caller")
1197  else if (context == "base")
1199  else
1200  error (R"(evalin: CONTEXT must be "caller" or "base")");
1201 
1203 
1204  int parse_status = 0;
1205 
1206  bool execution_error = false;
1207 
1208  octave_value_list tmp;
1209 
1210  try
1211  {
1212  tmp = eval_string (try_code, nargout > 0, parse_status, nargout);
1213  }
1214  catch (const execution_exception& ee)
1215  {
1216  es.save_exception (ee);
1218 
1219  execution_error = true;
1220  }
1221 
1222  if (parse_status != 0 || execution_error)
1223  {
1224  tmp = eval_string (catch_code, nargout > 0, parse_status, nargout);
1225 
1226  retval = (nargout > 0) ? tmp : octave_value_list ();
1227  }
1228  else
1229  {
1230  if (nargout > 0)
1231  retval = tmp;
1232 
1233  // FIXME: we should really be rethrowing whatever
1234  // exception occurred, not just throwing an
1235  // execution exception.
1236  if (execution_error)
1237  throw execution_exception ();
1238  }
1239 
1240  return retval;
1241 }
1242 
1243 void
1245 {
1246  panic_impossible ();
1247 }
1248 
1249 void
1251 {
1252  panic_impossible ();
1253 }
1254 
1255 void
1257 {
1258  warning ("function arguments validation blocks are not supported; INCORRECT RESULTS ARE POSSIBLE");
1259 }
1260 
1261 void
1263 {
1264  panic_impossible ();
1265 }
1266 
1267 void
1269 {
1270  panic_impossible ();
1271 }
1272 
1273 void
1275 {
1276  panic_impossible ();
1277 }
1278 
1279 void
1281 {
1282  panic_impossible ();
1283 }
1284 
1285 void
1287 {
1288  panic_impossible ();
1289 }
1290 
1291 void
1293 {
1294  panic_impossible ();
1295 }
1296 
1297 void
1299 {
1300  panic_impossible ();
1301 }
1302 
1303 void
1305 {
1306  panic_impossible ();
1307 }
1308 
1309 void
1311 {
1312  if (m_echo_state)
1313  {
1314  int line = cmd.line ();
1315  if (line < 0)
1316  line = 1;
1317  echo_code (line);
1318  m_echo_file_pos = line + 1;
1319  }
1320 
1321  if (m_debug_mode)
1322  do_breakpoint (cmd.is_active_breakpoint (*this));
1323 
1324  if (m_in_loop_command)
1325  m_breaking = 1;
1326  else
1327  error ("break must appear in a loop in the same file as loop command");
1328 }
1329 
1330 void
1332 {
1333  panic_impossible ();
1334 }
1335 
1336 void
1338 {
1339  if (m_echo_state)
1340  {
1341  int line = cmd.line ();
1342  if (line < 0)
1343  line = 1;
1344  echo_code (line);
1345  m_echo_file_pos = line + 1;
1346  }
1347 
1348  if (m_debug_mode)
1349  do_breakpoint (cmd.is_active_breakpoint (*this));
1350 
1351  if (m_in_loop_command)
1352  m_continuing = 1;
1353 }
1354 
1355 bool
1357 {
1360 }
1361 
1362 void
1364 {
1366  || m_dbstep_flag != 0
1368  || in_debug_repl ());
1369 }
1370 
1371 void
1373 {
1374  m_debug_mode = mode;
1375 }
1376 
1377 void
1378 tree_evaluator::enter_debugger (const std::string& prompt)
1379 {
1380  unwind_protect frame;
1381 
1384 
1386 
1389 
1390  // Don't allow errors or warnings at the debug prompt to push us
1391  // into deeper levels of debugging.
1392 
1394 
1396 
1398  es.debug_on_warning ());
1399 
1400  es.debug_on_error (false);
1401  es.debug_on_warning (false);
1402 
1403  // Go up to the nearest user code frame.
1404 
1406 
1407  // FIXME: probably we just want to print one line, not the
1408  // entire statement, which might span many lines...
1409  //
1410  // tree_print_code tpc (octave_stdout);
1411  // stmt.accept (tpc);
1412 
1413  debugger *dbgr = new debugger (m_interpreter, m_debugger_stack.size ());
1414 
1415  m_debugger_stack.push (dbgr);
1416 
1417  frame.add ([=] (void)
1418  {
1419  delete m_debugger_stack.top ();
1420  m_debugger_stack.pop ();
1421  reset_debug_state ();
1422  });
1423 
1424  dbgr->repl (prompt);
1425 }
1426 
1427 void
1428 tree_evaluator::keyboard (const std::string& prompt)
1429 {
1430  enter_debugger (prompt);
1431 }
1432 
1433 void
1434 tree_evaluator::dbupdown (int n, bool verbose)
1435 {
1436  m_debug_frame = m_call_stack.dbupdown (n, verbose);
1437 }
1438 
1439 Matrix
1441 {
1442  Matrix retval;
1443 
1444  const std::list<octave_lvalue> *lvalues = m_lvalue_list;
1445 
1446  if (! lvalues)
1447  return retval;
1448 
1449  octave_idx_type nbh = 0;
1450 
1451  for (const auto& lval : *lvalues)
1452  nbh += lval.is_black_hole ();
1453 
1454  if (nbh > 0)
1455  {
1456  retval.resize (1, nbh);
1457 
1458  octave_idx_type k = 0;
1459  octave_idx_type l = 0;
1460 
1461  for (const auto& lval : *lvalues)
1462  {
1463  if (lval.is_black_hole ())
1464  retval(l++) = k+1;
1465 
1466  k += lval.numel ();
1467  }
1468  }
1469 
1470  return retval;
1471 }
1472 
1473 // If NAME is an operator (like "+", "-", ...), convert it to the
1474 // corresponding function name ("plus", "minus", ...).
1475 
1476 static std::string
1477 get_operator_function_name (const std::string& name)
1478 {
1479  // Bow to the god of compatibility.
1480 
1481  // FIXME: it seems ugly to put this here, but there is no single
1482  // function in the parser that converts from the operator name to
1483  // the corresponding function name. At least try to do it without N
1484  // string compares.
1485 
1486  // FIXME: .+, .-, **, and .** are deprecated but still need to be
1487  // handled here until they are removed.
1488 
1489  std::size_t len = name.length ();
1490 
1491  if (len == 3 && name == ".**")
1492  // deprecated
1493  return "power";
1494  else if (len == 2)
1495  {
1496  if (name[0] == '.')
1497  {
1498  switch (name[1])
1499  {
1500  case '\'':
1501  return "transpose";
1502 
1503  case '+':
1504  // deprecated
1505  return "plus";
1506 
1507  case '-':
1508  // deprecated
1509  return "minus";
1510 
1511  case '*':
1512  return "times";
1513 
1514  case '/':
1515  return "rdivide";
1516 
1517  case '^':
1518  return "power";
1519 
1520  case '\\':
1521  return "ldivide";
1522 
1523  default:
1524  break;
1525  }
1526  }
1527  else if (name[1] == '=')
1528  {
1529  switch (name[0])
1530  {
1531  case '<':
1532  return "le";
1533 
1534  case '=':
1535  return "eq";
1536 
1537  case '>':
1538  return "ge";
1539 
1540  case '~':
1541  case '!':
1542  return "ne";
1543 
1544  default:
1545  break;
1546  }
1547  }
1548  else if (name == "**")
1549  // deprecated
1550  return "mpower";
1551  }
1552  else if (len == 1)
1553  {
1554  switch (name[0])
1555  {
1556  case '~':
1557  case '!':
1558  return "not";
1559 
1560  case '\'':
1561  return "ctranspose";
1562 
1563  case '+':
1564  return "plus";
1565 
1566  case '-':
1567  return "minus";
1568 
1569  case '*':
1570  return "mtimes";
1571 
1572  case '/':
1573  return "mrdivide";
1574 
1575  case '^':
1576  return "mpower";
1577 
1578  case '\\':
1579  return "mldivide";
1580 
1581  case '<':
1582  return "lt";
1583 
1584  case '>':
1585  return "gt";
1586 
1587  case '&':
1588  return "and";
1589 
1590  case '|':
1591  return "or";
1592 
1593  default:
1594  break;
1595  }
1596  }
1597 
1598  return name;
1599 }
1600 
1601 // Creates a function handle that takes into account the context,
1602 // finding local, nested, private, or sub functions.
1603 
1605 tree_evaluator::make_fcn_handle (const std::string& name)
1606 {
1607  octave_value retval;
1608 
1609  // The str2func function can create a function handle with the name
1610  // of an operator (for example, "+"). If so, it is converted to the
1611  // name of the corresponding function ("+" -> "plus") and we create
1612  // a simple function handle using that name.
1613 
1614  std::string fcn_name = get_operator_function_name (name);
1615 
1616  // If FCN_NAME is different from NAME, then NAME is an operator. As
1617  // of version 2020a, Matlab apparently uses the function name
1618  // corresponding to the operator to search for private and local
1619  // functions in the current scope but not(!) nested functions.
1620 
1621  bool name_is_operator = fcn_name != name;
1622 
1623  std::size_t pos = fcn_name.find ('.');
1624 
1625  if (pos != std::string::npos)
1626  {
1627  // Recognize (some of? which ones?) the following cases
1628  // and create something other than a simple function handle?
1629  // Should we just be checking for the last two when the first
1630  // element of the dot-separated list is an object? If so, then
1631  // should this syntax be limited to a dot-separated list with
1632  // exactly two elements?
1633  //
1634  // object . method
1635  // object . static-method
1636  //
1637  // Code to do that duplicates some of simple_fcn_handle::call.
1638 
1639  // Only accept expressions that contain one '.' separator.
1640 
1641  // FIXME: The logic here is a bit complicated. Is there a good
1642  // way to simplify it?
1643 
1644  std::string meth_nm = fcn_name.substr (pos+1);
1645 
1646  if (meth_nm.find ('.') == std::string::npos)
1647  {
1648  std::string obj_nm = fcn_name.substr (0, pos);
1649 
1650  // If obj_nm is an object in the current scope with a
1651  // method named meth_nm, create a classsimple handle.
1652 
1653  octave_value object = varval (obj_nm);
1654 
1655  if (object.is_defined () && object.is_classdef_object ())
1656  {
1657  octave_classdef *cdef = object.classdef_object_value ();
1658 
1659  if (cdef)
1660  {
1661  std::string class_nm = cdef->class_name ();
1662 
1663  cdef_object cdef_obj = cdef->get_object ();
1664 
1665  cdef_class cls = cdef_obj.get_class ();
1666 
1667  cdef_method meth = cls.find_method (meth_nm);
1668 
1669  if (meth.ok ())
1670  {
1671  // If the method we found is static, create a
1672  // new function name from the class name and
1673  // method name and create a simple function
1674  // handle below. Otherwise, create a class
1675  // simple function handle.
1676 
1677  if (meth.is_static ())
1678  fcn_name = class_nm + '.' + meth_nm;
1679  else
1680  {
1681  octave_value meth_fcn = meth.get_function ();
1682 
1683  octave_fcn_handle *fh
1684  = new octave_fcn_handle (object, meth_fcn,
1685  class_nm, meth_nm);
1686 
1687  return octave_value (fh);
1688  }
1689  }
1690  }
1691  }
1692  }
1693 
1694  // We didn't match anything above, so create handle to SIMPLE
1695  // package function or static class method. Function resolution
1696  // is performed when the handle is used.
1697 
1698  return octave_value (new octave_fcn_handle (fcn_name));
1699  }
1700 
1701  // If the function name refers to a sub/local/private function or a
1702  // class method/constructor, create scoped function handle that is
1703  // bound to that function. Use the same precedence list as
1704  // fcn_info::find but limit search to the following types of
1705  // functions:
1706  //
1707  // nested functions (and subfunctions)
1708  // local functions in the current file
1709  // private function
1710  // class method
1711  //
1712  // For anything else we create a simple function handle that will be
1713  // resolved dynamically in the scope where it is evaluated.
1714 
1715  symbol_scope curr_scope = get_current_scope ();
1716 
1718 
1719  if (curr_scope)
1720  {
1721  octave_value ov_fcn
1722  = symtab.find_scoped_function (fcn_name, curr_scope);
1723 
1724  // If name is operator, we are in Fstr2func, so skip the stack
1725  // frame for that function.
1726 
1727  bool skip_first = name_is_operator;
1728  octave_function *curr_fcn = current_function (skip_first);
1729 
1730  if (ov_fcn.is_defined ())
1731  {
1732  octave_function *fcn = ov_fcn.function_value ();
1733 
1734  if (fcn->is_nested_function ())
1735  {
1736  if (! name_is_operator)
1737  {
1738  // Get current stack frame and return handle to nested
1739  // function.
1740 
1741  std::shared_ptr<stack_frame> frame
1743 
1744  // If we are creating a handle to the current
1745  // function or a handle to a sibling function (i.e.,
1746  // not a child of the current function), then use
1747  // the calling stack frame as the context instead of
1748  // the current stack frame.
1749 
1750  // FIXME: Do we need both checks here or is it
1751  // sufficient to check that the parent of curr_fcn
1752  // is the same as the parent of fcn? Is there any
1753  // case where curr_fcn could be nullptr, or does
1754  // that indicate an internal error of some kind?
1755 
1756  if (curr_fcn
1757  && (fcn_name == curr_fcn->name ()
1758  || fcn->parent_fcn_name () == curr_fcn->parent_fcn_name ()))
1759  frame = frame->access_link ();
1760 
1761  octave_fcn_handle *fh
1762  = new octave_fcn_handle (ov_fcn, fcn_name, frame);
1763 
1764  return octave_value (fh);
1765  }
1766  }
1767  else if (fcn->is_subfunction ()
1768  /* || fcn->is_localfunction () */
1769  || fcn->is_private_function ())
1770  {
1771  // Create handle to SCOPED function (sub/local function
1772  // or private function).
1773 
1774  std::list<std::string> parentage = fcn->parent_fcn_names ();
1775 
1776  octave_fcn_handle *fh
1777  = new octave_fcn_handle (ov_fcn, fcn_name, parentage);
1778 
1779  return octave_value (fh);
1780  }
1781  }
1782 
1783  if (curr_fcn && (curr_fcn->is_class_method ()
1784  || curr_fcn->is_class_constructor ()))
1785  {
1786  std::string dispatch_class = curr_fcn->dispatch_class ();
1787 
1788  octave_value ov_meth
1789  = symtab.find_method (fcn_name, dispatch_class);
1790 
1791  if (ov_meth.is_defined ())
1792  {
1793  octave_function *fcn = ov_meth.function_value ();
1794 
1795  // FIXME: do we need to check that it is a method of
1796  // dispatch_class, or is it sufficient to just check
1797  // that it is a method?
1798 
1799  if (fcn->is_class_method ())
1800  {
1801  // Create CLASSSIMPLE handle to method but don't
1802  // bind to the method. Lookup will be done later.
1803 
1804  octave_fcn_handle *fh
1805  = new octave_fcn_handle (dispatch_class, fcn_name);
1806 
1807  return octave_value (fh);
1808  }
1809  }
1810  }
1811  }
1812 
1813  octave_value ov_fcn = symtab.find_user_function (fcn_name);
1814 
1815  // Create handle to SIMPLE function. If the function is not found
1816  // now, then we will look for it again when the handle is used.
1817 
1818  return octave_value (new octave_fcn_handle (ov_fcn, fcn_name));
1819 }
1820 
1821 /*
1822 %!test
1823 %! x = {".**", "power";
1824 %! ".'", "transpose";
1825 %! ".+", "plus";
1826 %! ".-", "minus";
1827 %! ".*", "times";
1828 %! "./", "rdivide";
1829 %! ".^", "power";
1830 %! ".\\", "ldivide";
1831 %! "<=", "le";
1832 %! "==", "eq";
1833 %! ">=", "ge";
1834 %! "!=", "ne";
1835 %! "~=", "ne";
1836 %! "**", "mpower";
1837 %! "~", "not";
1838 %! "!", "not";
1839 %! "\'", "ctranspose";
1840 %! "+", "plus";
1841 %! "-", "minus";
1842 %! "*", "mtimes";
1843 %! "/", "mrdivide";
1844 %! "^", "mpower";
1845 %! "\\", "mldivide";
1846 %! "<", "lt";
1847 %! ">", "gt";
1848 %! "&", "and";
1849 %! "|", "or"};
1850 %! for i = 1:rows (x)
1851 %! assert (functions (str2func (x{i,1})).function, x{i,2});
1852 %! endfor
1853 */
1854 
1857 {
1858  // Do not allow functions to return null values.
1859 
1860  tree_identifier *id = elt->ident ();
1861 
1862  return id ? id->evaluate (*this).storable_value () : octave_value ();
1863 }
1864 
1865 bool
1866 tree_evaluator::is_variable (const std::string& name) const
1867 {
1868  std::shared_ptr<stack_frame> frame
1870 
1871  return frame->is_variable (name);
1872 }
1873 
1874 bool
1875 tree_evaluator::is_local_variable (const std::string& name) const
1876 {
1877  std::shared_ptr<stack_frame> frame
1879 
1880  return frame->is_local_variable (name);
1881 }
1882 
1883 bool
1885 {
1886  if (expr->is_identifier ())
1887  {
1888  const tree_identifier *id
1889  = dynamic_cast<const tree_identifier *> (expr);
1890 
1891  if (id->is_black_hole ())
1892  return false;
1893 
1894  return is_variable (id->symbol ());
1895  }
1896 
1897  return false;
1898 }
1899 
1900 bool
1902 {
1903  if (expr->is_identifier ())
1904  {
1905  const tree_identifier *id
1906  = dynamic_cast<const tree_identifier *> (expr);
1907 
1908  return is_defined (id->symbol ());
1909  }
1910 
1911  return false;
1912 }
1913 
1914 bool
1916 {
1917  std::shared_ptr<stack_frame> frame
1919 
1920  return frame->is_variable (sym);
1921 }
1922 
1923 bool
1925 {
1926  std::shared_ptr<stack_frame> frame
1928 
1929  return frame->is_defined (sym);
1930 }
1931 
1932 bool tree_evaluator::is_global (const std::string& name) const
1933 {
1934  std::shared_ptr<stack_frame> frame
1936 
1937  return frame->is_global (name);
1938 }
1939 
1942 {
1943  std::shared_ptr<stack_frame> frame
1945 
1946  return frame->varval (sym);
1947 }
1948 
1950 tree_evaluator::varval (const std::string& name) const
1951 {
1952  std::shared_ptr<stack_frame> frame
1954 
1955  return frame->varval (name);
1956 }
1957 
1958 void tree_evaluator::install_variable (const std::string& name,
1959  const octave_value& value,
1960  bool global)
1961 {
1962  std::shared_ptr<stack_frame> frame
1964 
1965  return frame->install_variable (name, value, global);
1966 }
1967 
1969 tree_evaluator::global_varval (const std::string& name) const
1970 {
1971  return m_call_stack.global_varval (name);
1972 }
1973 
1974 octave_value&
1975 tree_evaluator::global_varref (const std::string& name)
1976 {
1977  return m_call_stack.global_varref (name);
1978 }
1979 
1980 void
1981 tree_evaluator::global_assign (const std::string& name,
1982  const octave_value& val)
1983 {
1984  m_call_stack.global_varref (name) = val;
1985 }
1986 
1988 tree_evaluator::top_level_varval (const std::string& name) const
1989 {
1990  return m_call_stack.get_top_level_value (name);
1991 }
1992 
1993 void
1994 tree_evaluator::top_level_assign (const std::string& name,
1995  const octave_value& val)
1996 {
1997  m_call_stack.set_top_level_value (name, val);
1998 }
1999 
2000 void
2001 tree_evaluator::assign (const std::string& name, const octave_value& val)
2002 {
2003  std::shared_ptr<stack_frame> frame
2005 
2006  frame->assign (name, val);
2007 }
2008 
2009 void
2010 tree_evaluator::assignin (const std::string& context,
2011  const std::string& name, const octave_value& val)
2012 {
2013  // FIXME: Can this be done without an unwind-protect frame, simply
2014  // by getting a reference to the caller or base stack frame and
2015  // calling assign on that?
2016 
2017  unwind_action act ([=] (std::size_t frm)
2018  {
2020  }, m_call_stack.current_frame ());
2021 
2022  if (context == "caller")
2024  else if (context == "base")
2026  else
2027  error (R"(assignin: CONTEXT must be "caller" or "base")");
2028 
2029  if (valid_identifier (name))
2030  {
2031  // Put the check here so that we don't slow down assignments
2032  // generally. Any that go through Octave's parser should have
2033  // already been checked.
2034 
2035  if (iskeyword (name))
2036  error ("assignin: invalid assignment to keyword '%s'",
2037  name.c_str ());
2038 
2039  assign (name, val);
2040  }
2041  else
2042  error ("assignin: invalid variable name '%s'", name.c_str ());
2043 }
2044 
2045 void
2046 tree_evaluator::source_file (const std::string& file_name,
2047  const std::string& context,
2048  bool verbose, bool require_file)
2049 {
2050  // Map from absolute name of script file to recursion level. We
2051  // use a map instead of simply placing a limit on recursion in the
2052  // source_file function so that two mutually recursive scripts
2053  // written as
2054  //
2055  // foo1.m:
2056  // ------
2057  // foo2
2058  //
2059  // foo2.m:
2060  // ------
2061  // foo1
2062  //
2063  // and called with
2064  //
2065  // foo1
2066  //
2067  // (for example) will behave the same if they are written as
2068  //
2069  // foo1.m:
2070  // ------
2071  // source ("foo2.m")
2072  //
2073  // foo2.m:
2074  // ------
2075  // source ("foo1.m")
2076  //
2077  // and called with
2078  //
2079  // source ("foo1.m")
2080  //
2081  // (for example).
2082 
2083  static std::map<std::string, int> source_call_depth;
2084 
2085  std::string file_full_name
2086  = sys::file_ops::tilde_expand (file_name);
2087 
2088  std::size_t pos
2089  = file_full_name.find_last_of (sys::file_ops::dir_sep_str ());
2090 
2091  std::string dir_name = file_full_name.substr (0, pos);
2092 
2093  file_full_name = sys::env::make_absolute (file_full_name);
2094 
2095  unwind_protect frame;
2096 
2097  if (source_call_depth.find (file_full_name) == source_call_depth.end ())
2098  source_call_depth[file_full_name] = -1;
2099 
2100  frame.protect_var (source_call_depth[file_full_name]);
2101 
2102  source_call_depth[file_full_name]++;
2103 
2104  if (source_call_depth[file_full_name] >= max_recursion_depth ())
2105  error ("max_recursion_depth exceeded");
2106 
2107  if (! context.empty ())
2108  {
2111 
2112  if (context == "caller")
2114  else if (context == "base")
2116  else
2117  error (R"(source: CONTEXT must be "caller" or "base")");
2118  }
2119 
2120  // Find symbol name that would be in symbol_table, if it were loaded.
2121  std::size_t dir_end
2122  = file_name.find_last_of (sys::file_ops::dir_sep_chars ());
2123  dir_end = (dir_end == std::string::npos) ? 0 : dir_end + 1;
2124 
2125  std::size_t extension = file_name.find_last_of ('.');
2126  if (extension == std::string::npos)
2127  extension = file_name.length ();
2128 
2129  std::string symbol = file_name.substr (dir_end, extension - dir_end);
2130  std::string full_name = sys::canonicalize_file_name (file_name);
2131 
2132  // Check if this file is already loaded (or in the path)
2134  octave_value ov_code = symtab.fcn_table_find (symbol);
2135 
2136  // For compatibility with Matlab, accept both scripts and
2137  // functions.
2138 
2139  if (ov_code.is_user_code ())
2140  {
2141  octave_user_code *code = ov_code.user_code_value ();
2142 
2143  if (! code
2145  != full_name))
2146  {
2147  // Wrong file, so load it below.
2148  ov_code = octave_value ();
2149  }
2150  }
2151  else
2152  {
2153  // Not a script, so load it below.
2154  ov_code = octave_value ();
2155  }
2156 
2157  // If no symbol of this name, or the symbol is for a different
2158  // file, load.
2159 
2160  if (ov_code.is_undefined ())
2161  {
2162  try
2163  {
2164  ov_code = parse_fcn_file (m_interpreter, file_full_name,
2165  file_name, dir_name, "", "",
2166  require_file, true, false, false);
2167  }
2168  catch (execution_exception& ee)
2169  {
2170  error (ee, "source: error sourcing file '%s'",
2171  file_full_name.c_str ());
2172  }
2173  }
2174 
2175  // Return or error if we don't have a valid script or function.
2176 
2177  if (ov_code.is_undefined ())
2178  return;
2179 
2180  if (! ov_code.is_user_code ())
2181  error ("source: %s is not a script", full_name.c_str ());
2182 
2183  if (verbose)
2184  {
2185  octave_stdout << "executing commands from " << full_name << " ... ";
2186  octave_stdout.flush ();
2187  }
2188 
2189  octave_user_code *code = ov_code.user_code_value ();
2190 
2191  code->call (*this, 0, octave_value_list ());
2192 
2193  if (verbose)
2194  octave_stdout << "done." << std::endl;
2195 }
2196 
2197 void
2199  const octave_value& val)
2200 {
2201  m_call_stack.set_auto_fcn_var (avt, val);
2202 }
2203 
2206 {
2207  return m_call_stack.get_auto_fcn_var (avt);
2208 }
2209 
2210 void
2212 (tree_parameter_list *param_list, const octave_value_list& args)
2213 {
2214  if (! param_list || param_list->varargs_only ())
2215  return;
2216 
2217  int i = -1;
2218 
2219  for (tree_decl_elt *elt : *param_list)
2220  {
2221  i++;
2222 
2223  octave_lvalue ref = elt->lvalue (*this);
2224 
2225  if (i < args.length ())
2226  {
2227  if (args(i).is_defined () && args(i).is_magic_colon ())
2228  {
2229  if (! eval_decl_elt (elt))
2230  error ("no default value for argument %d", i+1);
2231  }
2232  else
2233  ref.define (args(i));
2234  }
2235  else
2236  eval_decl_elt (elt);
2237  }
2238 }
2239 
2240 void
2242 {
2243  for (tree_decl_elt *elt : *param_list)
2244  {
2245  octave_lvalue ref = elt->lvalue (*this);
2246 
2248  }
2249 }
2250 
2251 // END is documented in op-kw-docs.
2252 DEFMETHOD (end, interp, args, ,
2253  doc: /* -*- texinfo -*-
2254 @deftypefn {} {} end
2255 Last element of an array or the end of any @code{for}, @code{parfor},
2256 @code{if}, @code{do}, @code{while}, @code{function}, @code{switch},
2257 @code{try}, or @code{unwind_protect} block.
2258 
2259 As an index of an array, the magic index @qcode{"end"} refers to the
2260 last valid entry in an indexing operation.
2261 
2262 Example:
2263 
2264 @example
2265 @group
2266 @var{x} = [ 1 2 3; 4 5 6 ];
2267 @var{x}(1,end)
2268  @result{} 3
2269 @var{x}(end,1)
2270  @result{} 4
2271 @var{x}(end,end)
2272  @result{} 6
2273 @end group
2274 @end example
2275 @seealso{for, parfor, if, do, while, function, switch, try, unwind_protect}
2276 @end deftypefn */)
2277 {
2278  tree_evaluator& tw = interp.get_evaluator ();
2279 
2280  return tw.evaluate_end_expression (args);
2281 }
2282 
2283 /*
2284 %!test <*58830>
2285 %! fail ("__undef_sym__ (end)",
2286 %! "invalid use of 'end': may only be used to index existing value");
2287 
2288 %!test <*58953>
2289 %! x = 1:10;
2290 %! assert (x(end), 10);
2291 %! assert (x(minus (end, 1)), 9);
2292 %! assert (x(minus (minus (end, 1), 1)), 8);
2293 */
2294 
2297 {
2298  std::list<octave_value> arg_vals;
2299 
2300  for (auto elt : *args)
2301  {
2302  // FIXME: is it possible for elt to be invalid?
2303 
2304  if (! elt)
2305  break;
2306 
2307  octave_value tmp = elt->evaluate (*this);
2308 
2309  if (tmp.is_cs_list ())
2310  {
2311  octave_value_list tmp_ovl = tmp.list_value ();
2312 
2313  for (octave_idx_type i = 0; i < tmp_ovl.length (); i++)
2314  arg_vals.push_back (tmp_ovl(i));
2315  }
2316  else if (tmp.is_defined ())
2317  arg_vals.push_back (tmp);
2318  }
2319 
2320  return octave_value_list (arg_vals);
2321 }
2322 
2325 (tree_parameter_list *ret_list, int nargout, const Matrix& ignored_outputs,
2326  const Cell& varargout)
2327 {
2328  octave_idx_type vlen = varargout.numel ();
2329  int len = ret_list->length ();
2330 
2331  // Special case. Will do a shallow copy.
2332  if (len == 0)
2333  return varargout;
2334  else
2335  {
2336  int i = 0;
2337  int k = 0;
2338  int num_ignored = ignored_outputs.numel ();
2339  int ignored = num_ignored > 0 ? ignored_outputs(k) - 1 : -1;
2340 
2341  if (nargout <= len)
2342  {
2343  int nout = nargout > 0 ? nargout : 1;
2344  octave_value_list retval (nout);
2345 
2346  for (tree_decl_elt *elt : *ret_list)
2347  {
2348  if (nargout == 0 && ! is_defined (elt->ident ()))
2349  break;
2350 
2351  if (ignored >= 0 && i == ignored)
2352  {
2353  i++;
2354  k++;
2355  ignored = k < num_ignored ? ignored_outputs(k) - 1 : -1;
2356  }
2357  else
2358  retval(i++) = evaluate (elt);
2359 
2360  if (i == nout)
2361  break;
2362  }
2363 
2364  return retval;
2365  }
2366  else
2367  {
2368  octave_value_list retval (len + vlen);
2369 
2370  for (tree_decl_elt *elt : *ret_list)
2371  {
2372  if (ignored >= 0 && i == ignored)
2373  {
2374  i++;
2375  k++;
2376  ignored = k < num_ignored ? ignored_outputs(k) - 1 : -1;
2377  }
2378  else
2379  retval(i++) = evaluate (elt);
2380  }
2381 
2382  for (octave_idx_type j = 0; j < vlen; j++)
2383  retval(i++) = varargout(j);
2384 
2385  return retval;
2386  }
2387  }
2388 }
2389 
2390 bool
2392 {
2393  bool retval = false;
2394 
2395  tree_identifier *id = elt->ident ();
2396  tree_expression *expr = elt->expression ();
2397 
2398  if (id && expr)
2399  {
2400  octave_lvalue ult = id->lvalue (*this);
2401 
2402  octave_value init_val = expr->evaluate (*this);
2403 
2404  ult.assign (octave_value::op_asn_eq, init_val);
2405 
2406  retval = true;
2407  }
2408 
2409  return retval;
2410 }
2411 
2412 bool
2414  const octave_value& val)
2415 {
2416  tree_expression *label = expr->case_label ();
2417 
2418  octave_value label_value = label->evaluate (*this);
2419 
2420  if (label_value.is_defined ())
2421  {
2422  if (label_value.iscell ())
2423  {
2424  Cell cell (label_value.cell_value ());
2425 
2426  for (octave_idx_type i = 0; i < cell.rows (); i++)
2427  {
2428  for (octave_idx_type j = 0; j < cell.columns (); j++)
2429  {
2430  bool match = val.is_equal (cell(i, j));
2431 
2432  if (match)
2433  return true;
2434  }
2435  }
2436  }
2437  else
2438  return val.is_equal (label_value);
2439  }
2440 
2441  return false;
2442 }
2443 
2445 {
2446  m_call_stack.push (scope);
2447 }
2448 
2450  const std::shared_ptr<stack_frame>& closure_frames)
2451 {
2452  m_call_stack.push (fcn, closure_frames);
2453 }
2454 
2456  const stack_frame::local_vars_map& local_vars,
2457  const std::shared_ptr<stack_frame>& closure_frames)
2458 {
2459  m_call_stack.push (fcn, local_vars, closure_frames);
2460 }
2461 
2463 {
2464  m_call_stack.push (script);
2465 }
2466 
2468 {
2469  m_call_stack.push (fcn);
2470 }
2471 
2473 {
2474  m_call_stack.pop ();
2475 }
2476 
2478 {
2479  return m_call_stack.current_line ();
2480 }
2481 
2483 {
2484  return m_call_stack.current_column ();
2485 }
2486 
2488 {
2490 }
2491 
2493 {
2495 }
2496 
2497 void tree_evaluator::debug_where (std::ostream& os) const
2498 {
2499  std::shared_ptr<stack_frame> frm = m_call_stack.current_user_frame ();
2500 
2501  frm->display_stopped_in_message (os);
2502 }
2503 
2505 {
2506  return m_call_stack.current_user_code ();
2507 }
2508 
2510 {
2512 }
2513 
2515 {
2516  return m_call_stack.debug_user_code ();
2517 }
2518 
2520 {
2521  return m_call_stack.current_function (skip_first);
2522 }
2523 
2525 {
2526  return m_call_stack.current_function (true);
2527 }
2528 
2529 bool tree_evaluator::goto_frame (std::size_t n, bool verbose)
2530 {
2531  return m_call_stack.goto_frame (n, verbose);
2532 }
2533 
2535 {
2537 }
2538 
2540 {
2542 }
2543 
2545 {
2546  return m_call_stack.restore_frame (n);
2547 }
2548 
2549 std::string tree_evaluator::get_dispatch_class (void) const
2550 {
2551  return m_call_stack.get_dispatch_class ();
2552 }
2553 
2554 void tree_evaluator::set_dispatch_class (const std::string& class_name)
2555 {
2556  m_call_stack.set_dispatch_class (class_name);
2557 }
2558 
2559 bool
2561 {
2562  return m_call_stack.is_class_method_executing (dclass);
2563 }
2564 
2565 bool
2567 {
2569 }
2570 
2571 std::list<std::shared_ptr<stack_frame>>
2573 {
2574  return m_call_stack.backtrace_frames (curr_user_frame);
2575 }
2576 
2577 std::list<std::shared_ptr<stack_frame>>
2579 {
2580  return m_call_stack.backtrace_frames ();
2581 }
2582 
2583 std::list<frame_info>
2585  bool print_subfn) const
2586 {
2587  return m_call_stack.backtrace_info (curr_user_frame, print_subfn);
2588 }
2589 
2590 std::list<frame_info> tree_evaluator::backtrace_info (void) const
2591 {
2592  return m_call_stack.backtrace_info ();
2593 }
2594 
2595 octave_map
2597  bool print_subfn) const
2598 {
2599  return m_call_stack.backtrace (curr_user_frame, print_subfn);
2600 }
2601 
2603 {
2604  return m_call_stack.backtrace ();
2605 }
2606 
2608 {
2609  return m_call_stack.empty_backtrace ();
2610 }
2611 
2612 std::string tree_evaluator::backtrace_message (void) const
2613 {
2614  std::list<frame_info> frames = backtrace_info ();
2615 
2616  std::ostringstream buf;
2617 
2618  for (const auto& frm : frames)
2619  {
2620  buf << " " << frm.fcn_name ();
2621 
2622  int line = frm.line ();
2623 
2624  if (line > 0)
2625  {
2626  buf << " at line " << line;
2627 
2628  int column = frm.column ();
2629 
2630  if (column > 0)
2631  buf << " column " << column;
2632 
2633  buf << "\n";
2634  }
2635  }
2636 
2637  return buf.str ();
2638 }
2639 
2640 void tree_evaluator::push_dummy_scope (const std::string& name)
2641 {
2642  symbol_scope dummy_scope (name + "$dummy");
2643 
2644  m_call_stack.push (dummy_scope);
2645 }
2646 
2648 {
2649  m_call_stack.pop ();
2650 }
2651 
2653 {
2654  return m_call_stack.top_scope ();
2655 }
2656 
2658 {
2659  return m_call_stack.current_scope ();
2660 }
2661 
2662 void tree_evaluator::mlock (bool skip_first) const
2663 {
2664  octave_function *fcn = m_call_stack.current_function (skip_first);
2665 
2666  if (! fcn)
2667  error ("mlock: invalid use outside a function");
2668 
2669  if (fcn->is_builtin_function ())
2670  {
2671  warning ("mlock: locking built-in function has no effect");
2672  return;
2673  }
2674 
2675  fcn->lock ();
2676 }
2677 
2678 void tree_evaluator::munlock (bool skip_first) const
2679 {
2680  octave_function *fcn = m_call_stack.current_function (skip_first);
2681 
2682  if (! fcn)
2683  error ("munlock: invalid use outside a function");
2684 
2685  if (fcn->is_builtin_function ())
2686  {
2687  warning ("munlock: unlocking built-in function has no effect");
2688  return;
2689  }
2690 
2691  fcn->unlock ();
2692 }
2693 
2694 bool tree_evaluator::mislocked (bool skip_first) const
2695 {
2696  octave_function *fcn = m_call_stack.current_function (skip_first);
2697 
2698  if (! fcn)
2699  error ("mislocked: invalid use outside a function");
2700 
2701  return fcn->islocked ();
2702 }
2703 
2706 {
2707  return m_call_stack.max_stack_depth (args, nargout);
2708 }
2709 
2711 {
2712  m_call_stack.display ();
2713 }
2714 
2715 octave_value tree_evaluator::find (const std::string& name)
2716 {
2717  std::shared_ptr<stack_frame> frame
2719 
2720  octave_value val = frame->varval (name);
2721 
2722  if (val.is_defined ())
2723  return val;
2724 
2725  // Subfunction. I think it only makes sense to check for
2726  // subfunctions if we are currently executing a function defined
2727  // from a .m file.
2728 
2729  octave_value fcn = frame->find_subfunction (name);
2730 
2731  if (fcn.is_defined ())
2732  return fcn;
2733 
2735 
2736  return symtab.fcn_table_find (name, ovl ());
2737 }
2738 
2740 {
2741  std::shared_ptr<stack_frame> frame
2743 
2744  frame->clear_objects ();
2745 }
2746 
2747 void tree_evaluator::clear_variable (const std::string& name)
2748 {
2749  std::shared_ptr<stack_frame> frame
2751 
2752  frame->clear_variable (name);
2753 }
2754 
2755 void tree_evaluator::clear_variable_pattern (const std::string& pattern)
2756 {
2757  std::shared_ptr<stack_frame> frame
2759 
2760  frame->clear_variable_pattern (pattern);
2761 }
2762 
2763 void tree_evaluator::clear_variable_regexp (const std::string& pattern)
2764 {
2765  std::shared_ptr<stack_frame> frame
2767 
2768  frame->clear_variable_regexp (pattern);
2769 }
2770 
2772 {
2773  std::shared_ptr<stack_frame> frame
2775 
2776  frame->clear_variables ();
2777 }
2778 
2779 void tree_evaluator::clear_global_variable (const std::string& name)
2780 {
2782 }
2783 
2784 void
2786 {
2788 }
2789 
2790 void tree_evaluator::clear_global_variable_regexp(const std::string& pattern)
2791 {
2793 }
2794 
2796 {
2798 }
2799 
2800 void tree_evaluator::clear_all (bool force)
2801 {
2802  // FIXME: should this also clear objects?
2803 
2804  clear_variables ();
2806 
2808 
2809  symtab.clear_functions (force);
2810 }
2811 
2812 void tree_evaluator::clear_symbol (const std::string& name)
2813 {
2814  // FIXME: are we supposed to do both here?
2815 
2816  clear_variable (name);
2817 
2819 
2820  symtab.clear_function (name);
2821 }
2822 
2823 void tree_evaluator::clear_symbol_pattern (const std::string& pattern)
2824 {
2825  // FIXME: are we supposed to do both here?
2826 
2827  clear_variable_pattern (pattern);
2828 
2830 
2831  symtab.clear_function_pattern (pattern);
2832 }
2833 
2834 void tree_evaluator::clear_symbol_regexp (const std::string& pattern)
2835 {
2836  // FIXME: are we supposed to do both here?
2837 
2838  clear_variable_regexp (pattern);
2839 
2841 
2842  symtab.clear_function_regexp (pattern);
2843 }
2844 
2845 std::list<std::string> tree_evaluator::global_variable_names (void) const
2846 {
2848 }
2849 
2850 std::list<std::string> tree_evaluator::top_level_variable_names (void) const
2851 {
2853 }
2854 
2855 std::list<std::string> tree_evaluator::variable_names (void) const
2856 {
2857  return m_call_stack.variable_names ();
2858 }
2859 
2860 // Return a pointer to the user-defined function FNAME. If FNAME is empty,
2861 // search backward for the first user-defined function in the
2862 // current call stack.
2863 
2865 tree_evaluator::get_user_code (const std::string& fname,
2866  const std::string& class_name)
2867 {
2868  octave_user_code *user_code = nullptr;
2869 
2870  if (fname.empty ())
2871  user_code = m_call_stack.debug_user_code ();
2872  else
2873  {
2874  std::string name = fname;
2875 
2876  if (sys::file_ops::dir_sep_char () != '/' && name[0] == '@')
2877  {
2878  auto beg = name.begin () + 2; // never have @/method
2879  auto end = name.end () - 1; // never have trailing '/'
2880  std::replace (beg, end, '/', sys::file_ops::dir_sep_char ());
2881  }
2882 
2883  std::size_t name_len = name.length ();
2884 
2885  if (name_len > 2 && name.substr (name_len-2) == ".m")
2886  name = name.substr (0, name_len-2);
2887 
2888  if (name.empty ())
2889  return nullptr;
2890 
2892 
2893  octave_value fcn;
2894  std::size_t p2 = std::string::npos;
2895 
2896  if (name[0] == '@')
2897  {
2898  std::size_t p1 = name.find (sys::file_ops::dir_sep_char (), 1);
2899 
2900  if (p1 == std::string::npos)
2901  return nullptr;
2902 
2903  std::string dispatch_type = name.substr (1, p1-1);
2904 
2905  p2 = name.find ('>', p1);
2906 
2907  std::string method = name.substr (p1+1, p2-1);
2908 
2909  fcn = symtab.find_method (method, dispatch_type);
2910  }
2911  else if (! class_name.empty ())
2912  {
2914 
2915  fcn = cdm.find_method (class_name, name);
2916 
2917  // If there is no classdef method, then try legacy classes.
2918  if (fcn.is_undefined ())
2919  fcn = symtab.find_method (name, class_name);
2920  }
2921  else
2922  {
2923  p2 = name.find ('>');
2924 
2925  std::string main_fcn = name.substr (0, p2);
2926 
2927  fcn = symtab.find_function (main_fcn);
2928  }
2929 
2930  // List of function names sub1>sub2>...
2931  std::string subfuns;
2932 
2933  if (p2 != std::string::npos)
2934  subfuns = name.substr (p2+1);
2935 
2936  if (fcn.is_defined () && fcn.is_user_code ())
2937  user_code = fcn.user_code_value ();
2938 
2939  if (! user_code || subfuns.empty ())
2940  return user_code;
2941 
2942  fcn = user_code->find_subfunction (subfuns);
2943 
2944  if (fcn.is_undefined ())
2945  return nullptr;
2946 
2947  user_code = fcn.user_code_value ();
2948  }
2949 
2950  return user_code;
2951 }
2952 
2953 std::string
2955 {
2956  octave_function *curfcn = m_call_stack.current_function (skip_first);
2957 
2958  if (curfcn)
2959  return curfcn->name ();
2960 
2961  return "";
2962 }
2963 
2964 bool
2966 {
2967  return m_call_stack.current_user_code () != nullptr;
2968 }
2969 
2970 void
2972 {
2973  if (m_echo_state)
2974  {
2975  int line = cmd.line ();
2976  if (line < 0)
2977  line = 1;
2978  echo_code (line);
2979  m_echo_file_pos = line + 1;
2980  }
2981 
2982  if (m_debug_mode)
2983  do_breakpoint (cmd.is_active_breakpoint (*this));
2984 
2985  // FIXME: tree_decl_init_list is not derived from tree, so should it
2986  // really have an accept method?
2987 
2988  tree_decl_init_list *init_list = cmd.initializer_list ();
2989 
2990  if (init_list)
2991  init_list->accept (*this);
2992 }
2993 
2994 void
2996 {
2997  tree_identifier *id = elt.ident ();
2998 
2999  if (id)
3000  {
3001  if (elt.is_global ())
3002  m_call_stack.make_global (id->symbol ());
3003  else if (elt.is_persistent ())
3005  else
3006  error ("declaration list element not global or persistent");
3007 
3008  octave_lvalue ult = id->lvalue (*this);
3009 
3010  if (ult.is_undefined ())
3011  {
3012  tree_expression *expr = elt.expression ();
3013 
3014  octave_value init_val;
3015 
3016  if (expr)
3017  init_val = expr->evaluate (*this);
3018  else
3019  init_val = Matrix ();
3020 
3021  ult.assign (octave_value::op_asn_eq, init_val);
3022  }
3023  }
3024 }
3025 
3026 template <typename T>
3027 void
3028 tree_evaluator::execute_range_loop (const range<T>& rng, int line,
3029  octave_lvalue& ult,
3030  tree_statement_list *loop_body)
3031 {
3032  octave_idx_type steps = rng.numel ();
3033 
3034  if (math::isinf (rng.limit ()))
3035  warning_with_id ("Octave:infinite-loop",
3036  "FOR loop limit is infinite, will stop after %"
3037  OCTAVE_IDX_TYPE_FORMAT " steps", steps);
3038 
3039  for (octave_idx_type i = 0; i < steps; i++)
3040  {
3041  if (m_echo_state)
3042  m_echo_file_pos = line;
3043 
3044  octave_value val (rng.elem (i));
3045 
3046  ult.assign (octave_value::op_asn_eq, val);
3047 
3048  if (loop_body)
3049  loop_body->accept (*this);
3050 
3051  if (quit_loop_now ())
3052  break;
3053  }
3054 }
3055 
3056 void
3058 {
3059  int line = cmd.line ();
3060  if (line < 0)
3061  line = 1;
3062 
3063  if (m_echo_state)
3064  {
3065  echo_code (line);
3066  line++;
3067  }
3068 
3069  if (m_debug_mode)
3070  do_breakpoint (cmd.is_active_breakpoint (*this));
3071 
3072  // FIXME: need to handle PARFOR loops here using cmd.in_parallel ()
3073  // and cmd.maxproc_expr ();
3074 
3076 
3077  tree_expression *expr = cmd.control_expr ();
3078 
3079  octave_value rhs = expr->evaluate (*this);
3080 
3081  if (rhs.is_undefined ())
3082  return;
3083 
3084  tree_expression *lhs = cmd.left_hand_side ();
3085 
3086  octave_lvalue ult = lhs->lvalue (*this);
3087 
3088  tree_statement_list *loop_body = cmd.body ();
3089 
3090  if (rhs.is_range ())
3091  {
3092  // FIXME: is there a better way to dispatch here?
3093 
3094  if (rhs.is_double_type ())
3095  {
3096  execute_range_loop (rhs.range_value (), line, ult, loop_body);
3097  return;
3098  }
3099 
3100  // For now, disable all but range<double>.
3101 
3102 #if 0
3103  if (rhs.is_int64_type ())
3104  {
3105  execute_range_loop (rhs.int64_range_value (), line, ult, loop_body);
3106  return;
3107  }
3108 
3109  if (rhs.is_uint64_type ())
3110  {
3111  execute_range_loop (rhs.uint64_range_value (), line, ult, loop_body);
3112  return;
3113  }
3114 
3115  if (rhs.is_int32_type ())
3116  {
3117  execute_range_loop (rhs.int32_range_value (), line, ult, loop_body);
3118  return;
3119  }
3120 
3121  if (rhs.is_uint32_type ())
3122  {
3123  execute_range_loop (rhs.uint32_range_value (), line, ult, loop_body);
3124  return;
3125  }
3126 
3127  if (rhs.is_int16_type ())
3128  {
3129  execute_range_loop (rhs.int16_range_value (), line, ult, loop_body);
3130  return;
3131  }
3132 
3133  if (rhs.is_uint16_type ())
3134  {
3135  execute_range_loop (rhs.uint16_range_value (), line, ult, loop_body);
3136  return;
3137  }
3138 
3139  if (rhs.is_int8_type ())
3140  {
3141  execute_range_loop (rhs.int8_range_value (), line, ult, loop_body);
3142  return;
3143  }
3144 
3145  if (rhs.is_uint8_type ())
3146  {
3147  execute_range_loop (rhs.uint8_range_value (), line, ult, loop_body);
3148  return;
3149  }
3150 
3151  if (rhs.is_single_type ())
3152  {
3153  execute_range_loop (rhs.float_range_value (), line, ult, loop_body);
3154  return;
3155  }
3156 #endif
3157  }
3158 
3159  if (rhs.is_scalar_type ())
3160  {
3161  if (m_echo_state)
3162  m_echo_file_pos = line;
3163 
3164  ult.assign (octave_value::op_asn_eq, rhs);
3165 
3166  if (loop_body)
3167  loop_body->accept (*this);
3168 
3169  // Maybe decrement break and continue states.
3170  quit_loop_now ();
3171 
3172  return;
3173  }
3174 
3175  // Also handle any range types not explicitly handled above, though
3176  // not as efficiently as the specialized code above.
3177 
3178  if (rhs.is_range () || rhs.is_matrix_type () || rhs.iscell ()
3179  || rhs.is_string () || rhs.isstruct ())
3180  {
3181  // A matrix or cell is reshaped to 2 dimensions and iterated by
3182  // columns.
3183 
3184  dim_vector dv = rhs.dims ().redim (2);
3185 
3186  octave_idx_type nrows = dv(0);
3187  octave_idx_type steps = dv(1);
3188 
3189  octave_value arg = rhs;
3190  if (rhs.ndims () > 2)
3191  arg = arg.reshape (dv);
3192 
3193  if (nrows > 0 && steps > 0)
3194  {
3195  octave_value_list idx;
3196  octave_idx_type iidx;
3197 
3198  // for row vectors, use single index to speed things up.
3199  if (nrows == 1)
3200  {
3201  idx.resize (1);
3202  iidx = 0;
3203  }
3204  else
3205  {
3206  idx.resize (2);
3207  idx(0) = octave_value::magic_colon_t;
3208  iidx = 1;
3209  }
3210 
3211  for (octave_idx_type i = 1; i <= steps; i++)
3212  {
3213  if (m_echo_state)
3214  m_echo_file_pos = line;
3215 
3216  // index_op expects one-based indices.
3217  idx(iidx) = i;
3218  octave_value val = arg.index_op (idx);
3219 
3220  ult.assign (octave_value::op_asn_eq, val);
3221 
3222  if (loop_body)
3223  loop_body->accept (*this);
3224 
3225  if (quit_loop_now ())
3226  break;
3227  }
3228  }
3229  else
3230  {
3231  // Handle empty cases, while still assigning to loop var.
3232  ult.assign (octave_value::op_asn_eq, arg);
3233  }
3234 
3235  return;
3236  }
3237 
3238  error ("invalid type in for loop expression near line %d, column %d",
3239  cmd.line (), cmd.column ());
3240 }
3241 
3242 void
3244 {
3245  int line = cmd.line ();
3246  if (line < 0)
3247  line = 1;
3248 
3249  if (m_echo_state)
3250  {
3251  echo_code (line);
3252  line++;
3253  }
3254 
3255  if (m_debug_mode)
3256  do_breakpoint (cmd.is_active_breakpoint (*this));
3257 
3259 
3260  tree_expression *expr = cmd.control_expr ();
3261 
3262  octave_value rhs = expr->evaluate (*this);
3263 
3264  if (rhs.is_undefined ())
3265  return;
3266 
3267  if (! rhs.isstruct ())
3268  error ("in statement 'for [X, Y] = VAL', VAL must be a structure");
3269 
3270  // Cycle through structure elements. First element of id_list
3271  // is set to value and the second is set to the name of the
3272  // structure element.
3273 
3274  tree_argument_list *lhs = cmd.left_hand_side ();
3275 
3276  auto p = lhs->begin ();
3277 
3278  tree_expression *elt = *p++;
3279 
3280  octave_lvalue val_ref = elt->lvalue (*this);
3281 
3282  elt = *p;
3283 
3284  octave_lvalue key_ref = elt->lvalue (*this);
3285 
3286  const octave_map tmp_val = rhs.map_value ();
3287 
3288  tree_statement_list *loop_body = cmd.body ();
3289 
3290  string_vector keys = tmp_val.keys ();
3291 
3292  octave_idx_type nel = keys.numel ();
3293 
3294  for (octave_idx_type i = 0; i < nel; i++)
3295  {
3296  if (m_echo_state)
3297  m_echo_file_pos = line;
3298 
3299  std::string key = keys[i];
3300 
3301  const Cell val_lst = tmp_val.contents (key);
3302 
3303  octave_idx_type n = val_lst.numel ();
3304 
3305  octave_value val = (n == 1) ? val_lst(0) : octave_value (val_lst);
3306 
3307  val_ref.assign (octave_value::op_asn_eq, val);
3308  key_ref.assign (octave_value::op_asn_eq, key);
3309 
3310  if (loop_body)
3311  loop_body->accept (*this);
3312 
3313  if (quit_loop_now ())
3314  break;
3315  }
3316 }
3317 
3319 {
3320  // For now, we just execute the commands serially.
3321 
3322  tree_statement_list *body = cmd.body ();
3323 
3324  if (body)
3325  body->accept (*this);
3326 }
3327 
3330 {
3331  // FIXME: should CMD_LIST be limited to a single expression?
3332  // I think that is what Matlab does.
3333 
3334  symbol_scope new_scope;
3335  symbol_scope scope = afh.scope ();
3336  if (scope)
3337  new_scope = scope.dup ();
3338 
3339  tree_parameter_list *param_list = afh.parameter_list ();
3340  tree_parameter_list *param_list_dup
3341  = param_list ? param_list->dup (new_scope) : nullptr;
3342 
3343  tree_parameter_list *ret_list = nullptr;
3344 
3345  tree_statement_list *stmt_list = nullptr;
3346 
3347  symbol_scope parent_scope = get_current_scope ();
3348 
3349  new_scope.set_parent (parent_scope);
3350  new_scope.set_primary_parent (parent_scope);
3351 
3352  tree_expression *expr = afh.expression ();
3353  if (expr)
3354  {
3355  tree_expression *expr_dup = expr->dup (new_scope);
3356  tree_statement *stmt = new tree_statement (expr_dup, nullptr);
3357  stmt_list = new tree_statement_list (stmt);
3358  }
3359 
3360  tree_anon_scopes anon_fcn_ctx (afh);
3361 
3362  std::set<std::string> free_vars = anon_fcn_ctx.free_variables ();
3363 
3364  stack_frame::local_vars_map local_vars;
3365 
3366  std::shared_ptr<stack_frame> frame
3368 
3369  for (auto& name : free_vars)
3370  {
3371  octave_value val = frame->varval (name);
3372 
3373  if (val.is_defined ())
3374  local_vars[name] = val;
3375  }
3376 
3378  = new octave_user_function (new_scope, param_list_dup, ret_list,
3379  stmt_list);
3380 
3382 
3383  bool is_nested = false;
3384 
3385  if (curr_fcn)
3386  {
3387  // FIXME: maybe it would be better to just stash curr_fcn
3388  // instead of individual bits of info about it?
3389 
3390  // An anonymous function defined inside another nested function
3391  // or parent of a nested function also behaves like a nested
3392  // function.
3393 
3394  if (curr_fcn->is_parent_function () || curr_fcn->is_nested_function ())
3395  {
3396  is_nested = true;
3397  af->mark_as_nested_function ();
3398  new_scope.set_nesting_depth (parent_scope.nesting_depth () + 1);
3399  }
3400 
3401  af->stash_dir_name (curr_fcn->dir_name ());
3402 
3403  new_scope.cache_fcn_file_name (curr_fcn->fcn_file_name ());
3404  new_scope.cache_dir_name (curr_fcn->dir_name ());
3405 
3406  // The following is needed so that class method dispatch works
3407  // properly for anonymous functions that wrap class methods.
3408 
3409  if (curr_fcn->is_class_method () || curr_fcn->is_class_constructor ())
3410  af->stash_dispatch_class (curr_fcn->dispatch_class ());
3411 
3412  af->stash_fcn_file_name (curr_fcn->fcn_file_name ());
3413  }
3414 
3416 
3417  octave_value ov_fcn (af);
3418 
3419  return (is_nested
3420  ? octave_value (new octave_fcn_handle (ov_fcn, local_vars, frame))
3421  : octave_value (new octave_fcn_handle (ov_fcn, local_vars)));
3422 }
3423 
3426  int nargout,
3427  const octave_value_list& args)
3428 {
3429  octave_value_list retval;
3430 
3431  if (args.has_magic_colon ())
3432  error ("invalid use of colon in function argument list");
3433 
3434  profiler::enter<octave_builtin> block (m_profiler, builtin_function);
3435 
3436  octave_builtin::fcn fcn = builtin_function.function ();
3437 
3438  if (fcn)
3439  retval = (*fcn) (args, nargout);
3440  else
3441  {
3442  octave_builtin::meth meth = builtin_function.method ();
3443 
3444  retval = (*meth) (m_interpreter, args, nargout);
3445  }
3446 
3447  // Do not allow null values to be returned from functions.
3448  // FIXME: perhaps true builtins should be allowed?
3449 
3450  retval.make_storable_values ();
3451 
3452  // Fix the case of a single undefined value.
3453  // This happens when a compiled function uses
3454  //
3455  // octave_value retval;
3456  //
3457  // instead of
3458  //
3459  // octave_value_list retval;
3460  //
3461  // the idiom is very common, so we solve that here.
3462 
3463  if (retval.length () == 1 && retval.xelem (0).is_undefined ())
3464  retval.clear ();
3465 
3466  return retval;
3467 }
3468 
3471  int nargout,
3472  const octave_value_list& args)
3473 {
3474  octave_value_list retval;
3475 
3476  if (args.has_magic_colon ())
3477  error ("invalid use of colon in function argument list");
3478 
3479  profiler::enter<octave_mex_function> block (m_profiler, mex_function);
3480 
3481  retval = call_mex (mex_function, args, nargout);
3482 
3483  return retval;
3484 }
3485 
3488  int nargout,
3489  const octave_value_list& args)
3490 {
3491  octave_value_list retval;
3492 
3493  std::string file_name = user_script.fcn_file_name ();
3494 
3495  if (args.length () != 0 || nargout != 0)
3496  error ("invalid call to script %s", file_name.c_str ());
3497 
3498  tree_statement_list *cmd_list = user_script.body ();
3499 
3500  if (! cmd_list)
3501  return retval;
3502 
3503  // FIXME: Maybe this check belongs in the places where we push a new
3504  // stack frame? Or in the call_stack push method itself?
3505 
3506  if (m_call_stack.size () >= static_cast<std::size_t> (m_max_recursion_depth))
3507  error ("max_recursion_depth exceeded");
3508 
3510 
3511  profiler::enter<octave_user_script> block (m_profiler, user_script);
3512 
3513  if (echo ())
3515 
3516  // FIXME: Should we be using tree_evaluator::eval here?
3517 
3518  cmd_list->accept (*this);
3519 
3520  if (m_returning)
3521  m_returning = 0;
3522 
3523  if (m_breaking)
3524  m_breaking--;
3525 
3526  return retval;
3527 }
3528 
3529 void
3531 {
3532  // ??
3533  panic_impossible ();
3534 }
3535 
3538  int nargout,
3539  const octave_value_list& xargs)
3540 {
3541  octave_value_list retval;
3542 
3543  // If this function is a classdef constructor, extract the first input
3544  // argument, which must be the partially constructed object instance.
3545 
3546  octave_value_list args (xargs);
3547  octave_value_list ret_args;
3548 
3549  int nargin = args.length ();
3550 
3551  if (user_function.is_classdef_constructor ())
3552  {
3553  if (nargin > 0)
3554  {
3555  ret_args = args.slice (0, 1, true);
3556  --nargin;
3557  args = args.slice (1, nargin, true);
3558  }
3559  else
3560  panic_impossible ();
3561  }
3562 
3563  // FIXME: this probably shouldn't be a double-precision matrix.
3564  Matrix ignored_outputs = ignored_fcn_outputs ();
3565 
3566  tree_parameter_list *param_list = user_function.parameter_list ();
3567 
3568  bool takes_varargs = false;
3569  int max_inputs = 0;
3570 
3571  if (param_list)
3572  {
3573  takes_varargs = param_list->takes_varargs ();
3574  max_inputs = param_list->length ();
3575  }
3576 
3577  if (! takes_varargs && nargin > max_inputs)
3578  {
3579  std::string name = user_function.name ();
3580 
3581  if (name.empty ())
3582  name = "@<anonymous>";
3583 
3584  error_with_id ("Octave:invalid-fun-call",
3585  "%s: function called with too many inputs",
3586  name.c_str ());
3587  }
3588 
3589  define_parameter_list_from_arg_vector (param_list, args);
3590 
3591  tree_parameter_list *ret_list = user_function.return_list ();
3592 
3593  if (ret_list && ! ret_list->takes_varargs ())
3594  {
3595  int max_outputs = ret_list->length ();
3596 
3597  if (nargout > max_outputs)
3598  {
3599  std::string name = user_function.name ();
3600 
3601  error_with_id ("Octave:invalid-fun-call",
3602  "%s: function called with too many outputs",
3603  name.c_str ());
3604  }
3605  }
3606 
3607  bind_auto_fcn_vars (xargs.name_tags (), ignored_outputs, nargin,
3608  nargout, user_function.takes_varargs (),
3609  user_function.all_va_args (args));
3610 
3611  // For classdef constructor, pre-populate the output arguments
3612  // with the pre-initialized object instance, extracted above.
3613 
3614  if (user_function.is_classdef_constructor ())
3615  {
3616  if (! ret_list)
3617  error ("%s: invalid classdef constructor, no output argument defined",
3618  user_function.dispatch_class ().c_str ());
3619 
3620  define_parameter_list_from_arg_vector (ret_list, ret_args);
3621  }
3622 
3623  // FIXME: Maybe this check belongs in the places where we push a
3624  // new stack frame? Or in the call_stack push method itself?
3625 
3626  if (m_call_stack.size () >= static_cast<std::size_t> (m_max_recursion_depth))
3627  error ("max_recursion_depth exceeded");
3628 
3629  unwind_action act2 ([&user_function] ()
3630  {
3631  user_function.restore_warning_states ();
3632  });
3633 
3634  // Evaluate the commands that make up the function.
3635 
3637 
3638  tree_statement_list *cmd_list = user_function.body ();
3639 
3640  if (cmd_list)
3641  {
3643  block (m_profiler, user_function);
3644 
3645  if (echo ())
3647  user_function.fcn_file_name ());
3648 
3649  if (user_function.is_special_expr ())
3650  {
3651  panic_if (cmd_list->length () != 1);
3652 
3653  tree_statement *stmt = cmd_list->front ();
3654 
3655  tree_expression *expr = stmt->expression ();
3656 
3657  if (expr)
3658  {
3659  m_call_stack.set_location (stmt->line (), stmt->column ());
3660 
3661  retval = expr->evaluate_n (*this, nargout);
3662  }
3663  }
3664  else
3665  cmd_list->accept (*this);
3666 
3667  if (m_returning)
3668  m_returning = 0;
3669 
3670  if (m_breaking)
3671  m_breaking--;
3672  }
3673 
3674  // Copy return values out.
3675 
3676  if (ret_list && ! user_function.is_special_expr ())
3677  {
3678  Cell varargout;
3679 
3680  if (ret_list->takes_varargs ())
3681  {
3682  octave_value varargout_varval = varval ("varargout");
3683 
3684  if (varargout_varval.is_defined ())
3685  varargout = varargout_varval.xcell_value ("varargout must be a cell array object");
3686  }
3687 
3688  retval = convert_return_list_to_const_vector (ret_list, nargout,
3689  ignored_outputs,
3690  varargout);
3691  }
3692 
3693  return retval;
3694 }
3695 
3696 void
3698 {
3699  // ??
3700  panic_impossible ();
3701 }
3702 
3703 void
3705 {
3706  panic_impossible ();
3707 }
3708 
3709 void
3711 {
3712  panic_impossible ();
3713 }
3714 
3715 void
3717 {
3718  octave_value fcn = cmd.function ();
3719 
3720  octave_function *f = fcn.function_value ();
3721 
3722  if (f)
3723  {
3724  std::string nm = f->name ();
3725 
3727 
3728  symtab.install_cmdline_function (nm, fcn);
3729 
3730  // Make sure that any variable with the same name as the new
3731  // function is cleared.
3732 
3733  assign (nm);
3734  }
3735 }
3736 
3737 void
3739 {
3740  panic_impossible ();
3741 }
3742 
3743 void
3745 {
3746  panic_impossible ();
3747 }
3748 
3749 void
3751 {
3752  if (m_echo_state)
3753  {
3754  int line = cmd.line ();
3755  if (line < 0)
3756  line = 1;
3757  echo_code (line);
3758  m_echo_file_pos = line + 1;
3759  }
3760 
3761  // FIXME: tree_if_command_list is not derived from tree, so should it
3762  // really have an accept method?
3763 
3764  tree_if_command_list *lst = cmd.cmd_list ();
3765 
3766  if (lst)
3767  lst->accept (*this);
3768 }
3769 
3770 void
3772 {
3773  for (tree_if_clause *tic : lst)
3774  {
3775  tree_expression *expr = tic->condition ();
3776 
3777  if (! (in_debug_repl ()
3779  m_call_stack.set_location (tic->line (), tic->column ());
3780 
3781  if (m_debug_mode && ! tic->is_else_clause ())
3782  do_breakpoint (tic->is_active_breakpoint (*this));
3783 
3784  if (tic->is_else_clause () || is_logically_true (expr, "if"))
3785  {
3786  tree_statement_list *stmt_lst = tic->commands ();
3787 
3788  if (stmt_lst)
3789  stmt_lst->accept (*this);
3790 
3791  break;
3792  }
3793  }
3794 }
3795 
3796 void
3798 {
3799  panic_impossible ();
3800 }
3801 
3802 void
3804 {
3805  panic_impossible ();
3806 }
3807 
3808 void
3810 {
3811  panic_impossible ();
3812 }
3813 
3814 void
3816 {
3817  panic_impossible ();
3818 }
3819 
3820 void
3822 {
3823  if (m_echo_state)
3824  {
3825  int line = cmd.line ();
3826  if (line < 0)
3827  line = 1;
3828  echo_code (line);
3829  m_echo_file_pos = line + 1;
3830  }
3831 
3832  if (m_debug_mode && cmd.is_end_of_fcn_or_script ())
3833  do_breakpoint (cmd.is_active_breakpoint (*this), true);
3834 }
3835 
3836 void
3838 {
3839  panic_impossible ();
3840 }
3841 
3842 void
3844 {
3845  panic_impossible ();
3846 }
3847 
3848 void
3850 {
3851  panic_impossible ();
3852 }
3853 
3854 void
3856 {
3857  panic_impossible ();
3858 }
3859 
3860 void
3862 {
3863  panic_impossible ();
3864 }
3865 
3866 void
3868 {
3869  if (m_echo_state)
3870  {
3871  int line = cmd.line ();
3872  if (line < 0)
3873  line = 1;
3874  echo_code (line);
3875  m_echo_file_pos = line + 1;
3876  }
3877 
3878  if (m_debug_mode)
3879  do_breakpoint (cmd.is_active_breakpoint (*this));
3880 
3881  // Act like dbcont.
3882 
3884  dbcont ();
3885  else if (m_statement_context == SC_FUNCTION
3887  || m_in_loop_command)
3888  m_returning = 1;
3889 }
3890 
3891 void
3893 {
3894  panic_impossible ();
3895 }
3896 
3897 void
3899 {
3900  tree_command *cmd = stmt.command ();
3901  tree_expression *expr = stmt.expression ();
3902 
3903  if (cmd || expr)
3904  {
3905  if (! (in_debug_repl ()
3907  m_call_stack.set_location (stmt.line (), stmt.column ());
3908 
3909  try
3910  {
3911  if (cmd)
3912  {
3914  upv (m_lvalue_list, nullptr);
3915 
3916  cmd->accept (*this);
3917  }
3918  else
3919  {
3920  if (m_echo_state)
3921  {
3922  int line = stmt.line ();
3923  if (line < 0)
3924  line = 1;
3925  echo_code (line);
3926  m_echo_file_pos = line + 1;
3927  }
3928 
3929  if (m_debug_mode)
3930  do_breakpoint (expr->is_active_breakpoint (*this));
3931 
3932  // FIXME: maybe all of this should be packaged in
3933  // one virtual function that returns a flag saying whether
3934  // or not the expression will take care of binding ans and
3935  // printing the result.
3936 
3937  // FIXME: it seems that we should just have to
3938  // evaluate the expression and that should take care of
3939  // everything, binding ans as necessary?
3940 
3941  octave_value tmp_result = expr->evaluate (*this, 0);
3942 
3943  if (tmp_result.is_defined ())
3944  {
3945  bool do_bind_ans = false;
3946 
3947  if (expr->is_identifier ())
3948  do_bind_ans = ! is_variable (expr);
3949  else
3950  do_bind_ans = ! expr->is_assignment_expression ();
3951 
3952  if (do_bind_ans)
3953  bind_ans (tmp_result, expr->print_result ()
3955  }
3956  }
3957  }
3958  catch (const std::bad_alloc&)
3959  {
3960  // FIXME: We want to use error_with_id here so that give users
3961  // control over this error message but error_with_id will
3962  // require some memory allocations. Is there anything we can
3963  // do to make those more likely to succeed?
3964 
3965  error_with_id ("Octave:bad-alloc",
3966  "out of memory or dimension too large for Octave's index type");
3967  }
3968  catch (const interrupt_exception&)
3969  {
3970  // If we are debugging, then continue with next statement.
3971  // Otherwise, jump out of here.
3972 
3973  if (m_debug_mode)
3975  else
3976  throw;
3977  }
3978  catch (const execution_exception& ee)
3979  {
3981 
3982  if ((m_interpreter.interactive ()
3984  && ((es.debug_on_error ()
3986  || (es.debug_on_caught ()
3988  && in_user_code ())
3989  {
3990  es.save_exception (ee);
3991  es.display_exception (ee);
3992 
3993  enter_debugger ();
3994 
3995  // It doesn't make sense to continue execution after an
3996  // error occurs so force the debugger to quit all debug
3997  // levels and return the the top prompt.
3998 
3999  throw quit_debug_exception (true);
4000  }
4001  else
4002  throw;
4003  }
4004  }
4005 }
4006 
4007 void
4009 {
4010  // FIXME: commented out along with else clause below.
4011  // static octave_value_list empty_list;
4012 
4013  auto p = lst.begin ();
4014 
4015  if (p != lst.end ())
4016  {
4017  while (true)
4018  {
4019  tree_statement *elt = *p++;
4020 
4021  if (! elt)
4022  error ("invalid statement found in statement list!");
4023 
4024  octave_quit ();
4025 
4026  elt->accept (*this);
4027 
4028  if (m_breaking || m_continuing)
4029  break;
4030 
4031  if (m_returning)
4032  break;
4033 
4034  if (p == lst.end ())
4035  break;
4036  else
4037  {
4038  // Clear previous values before next statement is
4039  // evaluated so that we aren't holding an extra
4040  // reference to a value that may be used next. For
4041  // example, in code like this:
4042  //
4043  // X = rand (N); # refcount for X should be 1
4044  // # after this statement
4045  //
4046  // X(idx) = val; # no extra copy of X should be
4047  // # needed, but we will be faked
4048  // # out if retval is not cleared
4049  // # between statements here
4050 
4051  // result_values = empty_list;
4052  }
4053  }
4054  }
4055 }
4056 
4057 void
4059 {
4060  panic_impossible ();
4061 }
4062 
4063 void
4065 {
4066  panic_impossible ();
4067 }
4068 
4069 void
4071 {
4072  if (m_echo_state)
4073  {
4074  int line = cmd.line ();
4075  if (line < 0)
4076  line = 1;
4077  echo_code (line);
4078  m_echo_file_pos = line + 1;
4079  }
4080 
4081  if (m_debug_mode)
4082  do_breakpoint (cmd.is_active_breakpoint (*this));
4083 
4084  tree_expression *expr = cmd.switch_value ();
4085 
4086  if (! expr)
4087  error ("missing value in switch command near line %d, column %d",
4088  cmd.line (), cmd.column ());
4089 
4090  octave_value val = expr->evaluate (*this);
4091 
4092  tree_switch_case_list *lst = cmd.case_list ();
4093 
4094  if (lst)
4095  {
4096  for (tree_switch_case *t : *lst)
4097  {
4098  if (t->is_default_case () || switch_case_label_matches (t, val))
4099  {
4100  tree_statement_list *stmt_lst = t->commands ();
4101 
4102  if (stmt_lst)
4103  stmt_lst->accept (*this);
4104 
4105  break;
4106  }
4107  }
4108  }
4109 }
4110 
4111 void
4113 {
4114  if (m_echo_state)
4115  {
4116  int line = cmd.line ();
4117  if (line < 0)
4118  line = 1;
4119  echo_code (line);
4120  m_echo_file_pos = line + 1;
4121  }
4122 
4123  bool execution_error = false;
4124  octave_scalar_map err_map;
4125 
4126  tree_statement_list *try_code = cmd.body ();
4127 
4128  if (try_code)
4129  {
4130  // unwind frame before catch block
4131 
4132  unwind_protect frame;
4133 
4134  interpreter_try (frame);
4135 
4136  // The catch code is *not* added to unwind_protect stack; it
4137  // doesn't need to be run on interrupts.
4138 
4139  try
4140  {
4141  try_code->accept (*this);
4142  }
4143  catch (const execution_exception& ee)
4144  {
4145  execution_error = true;
4146 
4148 
4149  es.save_exception (ee);
4150 
4151  err_map.assign ("message", es.last_error_message ());
4152  err_map.assign ("identifier", es.last_error_id ());
4153  err_map.assign ("stack", es.last_error_stack ());
4154 
4156  }
4157 
4158  // Actions attached to unwind_protect frame will run here, prior
4159  // to executing the catch block.
4160  }
4161 
4162  if (execution_error)
4163  {
4164  tree_statement_list *catch_code = cmd.cleanup ();
4165 
4166  if (catch_code)
4167  {
4168  tree_identifier *expr_id = cmd.identifier ();
4169 
4170  if (expr_id)
4171  {
4172  octave_lvalue ult = expr_id->lvalue (*this);
4173 
4174  ult.assign (octave_value::op_asn_eq, err_map);
4175  }
4176 
4177  // perform actual "catch" block
4178  catch_code->accept (*this);
4179  }
4180  }
4181 }
4182 
4183 void
4185 {
4186  unwind_protect frame;
4187 
4190 
4191  // We want to preserve the last location info for possible
4192  // backtracking.
4193 
4196 
4199 
4200  // Similarly, if we have seen a return or break statement, allow all
4201  // the cleanup code to run before returning or handling the break.
4202  // We don't have to worry about continue statements because they can
4203  // only occur in loops.
4204 
4205  frame.protect_var (m_returning);
4206  m_returning = 0;
4207 
4208  frame.protect_var (m_breaking);
4209  m_breaking = 0;
4210 
4211  try
4212  {
4213  if (list)
4214  list->accept (*this);
4215  }
4216  catch (const execution_exception& ee)
4217  {
4219 
4220  es.save_exception (ee);
4222 
4223  if (m_breaking || m_returning)
4224  frame.discard (2);
4225  else
4226  frame.run (2);
4227 
4228  frame.discard (2);
4229 
4230  throw;
4231  }
4232 
4233  // The unwind_protects are popped off the stack in the reverse of
4234  // the order they are pushed on.
4235 
4236  // FIXME: these statements say that if we see a break or
4237  // return statement in the cleanup block, that we want to use the
4238  // new value of the breaking or returning flag instead of restoring
4239  // the previous value. Is that the right thing to do? I think so.
4240  // Consider the case of
4241  //
4242  // function foo ()
4243  // unwind_protect
4244  // fprintf (stderr, "1: this should always be executed\n");
4245  // break;
4246  // fprintf (stderr, "1: this should never be executed\n");
4247  // unwind_protect_cleanup
4248  // fprintf (stderr, "2: this should always be executed\n");
4249  // return;
4250  // fprintf (stderr, "2: this should never be executed\n");
4251  // end_unwind_protect
4252  // endfunction
4253  //
4254  // If we reset the value of the breaking flag, both the returning
4255  // flag and the breaking flag will be set, and we shouldn't have
4256  // both. So, use the most recent one. If there is no return or
4257  // break in the cleanup block, the values should be reset to
4258  // whatever they were when the cleanup block was entered.
4259 
4260  if (m_breaking || m_returning)
4261  frame.discard (2);
4262  else
4263  frame.run (2);
4264 }
4265 
4266 void
4268 {
4269  if (m_echo_state)
4270  {
4271  int line = cmd.line ();
4272  if (line < 0)
4273  line = 1;
4274  echo_code (line);
4275  m_echo_file_pos = line + 1;
4276  }
4277 
4278  tree_statement_list *cleanup_code = cmd.cleanup ();
4279 
4280  tree_statement_list *unwind_protect_code = cmd.body ();
4281 
4282  if (unwind_protect_code)
4283  {
4284  try
4285  {
4286  unwind_protect_code->accept (*this);
4287  }
4288  catch (const execution_exception& ee)
4289  {
4291 
4292  // FIXME: Maybe we should be able to temporarily set the
4293  // interpreter's exception handling state to something "safe"
4294  // while the cleanup block runs instead of just resetting it
4295  // here?
4296  es.save_exception (ee);
4298 
4299  // Run the cleanup code on exceptions, so that it is run even
4300  // in case of interrupt or out-of-memory.
4301  do_unwind_protect_cleanup_code (cleanup_code);
4302 
4303  // If an error occurs inside the cleanup code, a new
4304  // exception will be thrown instead of the original.
4305  throw;
4306  }
4307  catch (const interrupt_exception&)
4308  {
4309  // The comments above apply here as well.
4311  do_unwind_protect_cleanup_code (cleanup_code);
4312  throw;
4313  }
4314 
4315  // Also execute the unwind_protect_cleanump code if the
4316  // unwind_protect block runs without error.
4317  do_unwind_protect_cleanup_code (cleanup_code);
4318  }
4319 }
4320 
4321 void
4323 {
4324  int line = cmd.line ();
4325  if (line < 0)
4326  line = 1;
4327 
4328  if (m_echo_state)
4329  {
4330  echo_code (line);
4331  line++;
4332  }
4333 
4335 
4336  tree_expression *expr = cmd.condition ();
4337 
4338  if (! expr)
4339  panic_impossible ();
4340 
4341  for (;;)
4342  {
4343  if (m_echo_state)
4344  m_echo_file_pos = line;
4345 
4346  if (m_debug_mode)
4347  do_breakpoint (cmd.is_active_breakpoint (*this));
4348 
4349  if (is_logically_true (expr, "while"))
4350  {
4351  tree_statement_list *loop_body = cmd.body ();
4352 
4353  if (loop_body)
4354  loop_body->accept (*this);
4355 
4356  if (quit_loop_now ())
4357  break;
4358  }
4359  else
4360  break;
4361  }
4362 }
4363 
4364 void
4366 {
4367  int line = cmd.line ();
4368  if (line < 0)
4369  line = 1;
4370 
4371  if (m_echo_state)
4372  {
4373  echo_code (line);
4374  line++;
4375  }
4376 
4378 
4379  tree_expression *expr = cmd.condition ();
4380 
4381  if (! expr)
4382  panic_impossible ();
4383 
4384  for (;;)
4385  {
4386  if (m_echo_state)
4387  m_echo_file_pos = line;
4388 
4389  tree_statement_list *loop_body = cmd.body ();
4390 
4391  if (loop_body)
4392  loop_body->accept (*this);
4393 
4394  if (quit_loop_now ())
4395  break;
4396 
4397  if (m_debug_mode)
4398  do_breakpoint (cmd.is_active_breakpoint (*this));
4399 
4400  if (is_logically_true (expr, "do-until"))
4401  break;
4402  }
4403 }
4404 
4405 void
4407 {
4408  panic_impossible ();
4409 }
4410 
4411 void
4413 {
4414  panic_impossible ();
4415 }
4416 
4417 void tree_evaluator::bind_ans (const octave_value& val, bool print)
4418 {
4419  static std::string ans = "ans";
4420 
4421  if (val.is_defined ())
4422  {
4423  if (val.is_cs_list ())
4424  {
4425  octave_value_list lst = val.list_value ();
4426 
4427  for (octave_idx_type i = 0; i < lst.length (); i++)
4428  bind_ans (lst(i), print);
4429  }
4430  else
4431  {
4432  // FIXME: Maybe assign could also return the assigned value,
4433  // just for convenience?
4434 
4435  assign (ans, val);
4436 
4437  if (print)
4438  {
4439  // Use varval instead of displaying VAL directly so that
4440  // we get the right type and value for things like
4441  // magic_int values that may mutate when stored.
4442 
4443  octave_value_list args = ovl (varval (ans));
4444  args.stash_name_tags (string_vector (ans));
4445  feval ("display", args);
4446  }
4447  }
4448  }
4449 }
4450 
4451 void
4453 {
4454  do_breakpoint (stmt.is_active_breakpoint (*this),
4455  stmt.is_end_of_fcn_or_script ());
4456 }
4457 
4458 void
4459 tree_evaluator::do_breakpoint (bool is_breakpoint,
4460  bool is_end_of_fcn_or_script)
4461 {
4462  bool break_on_this_statement = false;
4463 
4464  if (is_breakpoint)
4465  break_on_this_statement = true;
4466  else if (m_dbstep_flag > 0)
4467  {
4469  {
4470  if (m_dbstep_flag == 1 || is_end_of_fcn_or_script)
4471  {
4472  // We get here if we are doing a "dbstep" or a "dbstep N" and
4473  // the count has reached 1 so that we must stop and return to
4474  // debug prompt. Alternatively, "dbstep N" has been used but
4475  // the end of the frame has been reached so we stop at the last
4476  // line and return to prompt.
4477 
4478  break_on_this_statement = true;
4479  }
4480  else
4481  {
4482  // Executing "dbstep N". Decrease N by one and continue.
4483 
4484  m_dbstep_flag--;
4485  }
4486 
4487  }
4488  else if (m_dbstep_flag == 1
4490  {
4491  // We stepped out from the end of a function.
4492 
4494 
4495  break_on_this_statement = true;
4496  }
4497  }
4498  else if (m_dbstep_flag == -1)
4499  {
4500  // We get here if we are doing a "dbstep in".
4501 
4502  break_on_this_statement = true;
4503 
4505  }
4506  else if (m_dbstep_flag == -2)
4507  {
4508  // We get here if we are doing a "dbstep out". Check for end of
4509  // function and whether the current frame is the same as the
4510  // cached value because we want to step out from the frame where
4511  // "dbstep out" was evaluated, not from any functions called from
4512  // that frame.
4513 
4514  if (is_end_of_fcn_or_script
4516  m_dbstep_flag = -1;
4517  }
4518 
4519  if (! break_on_this_statement)
4520  break_on_this_statement = m_break_on_next_stmt;
4521 
4522  m_break_on_next_stmt = false;
4523 
4524  if (break_on_this_statement)
4525  {
4526  m_dbstep_flag = 0;
4527 
4528  enter_debugger ();
4529  }
4530 }
4531 
4532 bool
4534  const char *warn_for)
4535 {
4536  bool expr_value = false;
4537 
4538  m_call_stack.set_location (expr->line (), expr->column ());
4539 
4540  octave_value t1 = expr->evaluate (*this);
4541 
4542  if (t1.is_defined ())
4543  return t1.is_true ();
4544  else
4545  error ("%s: undefined value used in conditional expression", warn_for);
4546 
4547  return expr_value;
4548 }
4549 
4552  int nargout)
4553 {
4554  return set_internal_variable (m_max_recursion_depth, args, nargout,
4555  "max_recursion_depth", 0);
4556 }
4557 
4559 tree_evaluator::glob_symbol_info (const std::string& pattern) const
4560 {
4561  return m_call_stack.glob_symbol_info (pattern);
4562 }
4563 
4565 tree_evaluator::regexp_symbol_info (const std::string& pattern) const
4566 {
4567  return m_call_stack.regexp_symbol_info (pattern);
4568 }
4569 
4572 {
4573  return m_call_stack.get_symbol_info ();
4574 }
4575 
4578 {
4580 }
4581 
4583 {
4584  Cell fcn_names (dim_vector (m_autoload_map.size (), 1));
4585  Cell file_names (dim_vector (m_autoload_map.size (), 1));
4586 
4587  octave_idx_type i = 0;
4588  for (const auto& fcn_fname : m_autoload_map)
4589  {
4590  fcn_names(i) = fcn_fname.first;
4591  file_names(i) = fcn_fname.second;
4592 
4593  i++;
4594  }
4595 
4596  octave_map m;
4597 
4598  m.assign ("function", fcn_names);
4599  m.assign ("file", file_names);
4600 
4601  return m;
4602 }
4603 
4604 std::string tree_evaluator::lookup_autoload (const std::string& nm) const
4605 {
4606  std::string retval;
4607 
4608  auto p = m_autoload_map.find (nm);
4609 
4610  if (p != m_autoload_map.end ())
4611  {
4613 
4614  retval = lp.find_file (p->second);
4615  }
4616 
4617  return retval;
4618 }
4619 
4620 std::list<std::string> tree_evaluator::autoloaded_functions (void) const
4621 {
4622  std::list<std::string> names;
4623 
4624  for (const auto& fcn_fname : m_autoload_map)
4625  names.push_back (fcn_fname.first);
4626 
4627  return names;
4628 }
4629 
4630 std::list<std::string>
4631 tree_evaluator::reverse_lookup_autoload (const std::string& nm) const
4632 {
4633  std::list<std::string> names;
4634 
4635  for (const auto& fcn_fname : m_autoload_map)
4636  if (nm == fcn_fname.second)
4637  names.push_back (fcn_fname.first);
4638 
4639  return names;
4640 }
4641 
4642 void tree_evaluator::add_autoload (const std::string& fcn,
4643  const std::string& nm)
4644 {
4645  std::string file_name = check_autoload_file (nm);
4646 
4647  m_autoload_map[fcn] = file_name;
4648 }
4649 
4650 void tree_evaluator::remove_autoload (const std::string& fcn,
4651  const std::string& nm)
4652 {
4653  check_autoload_file (nm);
4654 
4655  // Remove function from symbol table and autoload map.
4657 
4658  symtab.clear_dld_function (fcn);
4659 
4660  m_autoload_map.erase (fcn);
4661 }
4662 
4665 {
4666  return set_internal_variable (m_whos_line_format, args, nargout,
4667  "whos_line_format");
4668 }
4669 
4672 {
4673  return set_internal_variable (m_silent_functions, args, nargout,
4674  "silent_functions");
4675 }
4676 
4679 {
4680  return set_internal_variable (m_string_fill_char, args, nargout,
4681  "string_fill_char");
4682 }
4683 
4684 // Final step of processing an indexing error. Add the name of the
4685 // variable being indexed, if any, then issue an error. (Will this also
4686 // be needed by pt-lvalue, which calls subsref?)
4687 
4689  const tree_expression *expr)
4690 {
4691  std::string extra_message;
4692 
4693  if (is_variable (expr))
4694  {
4695  std::string var = expr->name ();
4696 
4697  ie.set_var (var);
4698 
4700 
4701  octave_value fcn = symtab.find_function (var);
4702 
4703  if (fcn.is_function ())
4704  {
4705  octave_function *fp = fcn.function_value ();
4706 
4707  if (fp && fp->name () == var)
4708  extra_message
4709  = " (note: variable '" + var + "' shadows function)";
4710  }
4711  }
4712 
4713  std::string msg = ie.message () + extra_message;
4714 
4715  error_with_id (ie.err_id (), "%s", msg.c_str ());
4716 }
4717 
4719 tree_evaluator::do_who (int argc, const string_vector& argv,
4720  bool return_list, bool verbose)
4721 {
4722  return m_call_stack.do_who (argc, argv, return_list, verbose);
4723 }
4724 
4727  const string_vector& arg_nm)
4728 {
4729  octave_value_list retval;
4730 
4731  if (args)
4732  {
4734  upv (m_lvalue_list, nullptr);
4735 
4736  int len = args->length ();
4737 
4740 
4741  m_num_indices = len;
4742 
4743  std::list<octave_value> arg_vals;
4744 
4745  int k = 0;
4746 
4747  for (auto elt : *args)
4748  {
4749  // FIXME: is it possible for elt to be invalid?
4750 
4751  if (! elt)
4752  break;
4753 
4754  m_index_position = k++;
4755 
4756  octave_value tmp = elt->evaluate (*this);
4757 
4758  if (tmp.is_cs_list ())
4759  {
4760  octave_value_list tmp_ovl = tmp.list_value ();
4761 
4762  for (octave_idx_type i = 0; i < tmp_ovl.length (); i++)
4763  arg_vals.push_back (tmp_ovl(i));
4764  }
4765  else if (tmp.is_defined ())
4766  arg_vals.push_back (tmp);
4767  }
4768 
4769  retval = octave_value_list (arg_vals);
4770  }
4771 
4772  octave_idx_type n = retval.length ();
4773 
4774  if (n > 0)
4775  retval.stash_name_tags (arg_nm);
4776 
4777  return retval;
4778 }
4779 
4780 std::list<octave_lvalue>
4782 {
4783  std::list<octave_lvalue> retval;
4784 
4785  for (tree_expression *elt : *lhs)
4786  retval.push_back (elt->lvalue (*this));
4787 
4788  return retval;
4789 }
4790 
4791 void
4792 tree_evaluator::push_echo_state (int type, const std::string& file_name,
4793  int pos)
4794 {
4796 
4797  if (frame)
4798  {
4799  push_echo_state_cleanup (*frame);
4800 
4801  set_echo_state (type, file_name, pos);
4802  }
4803 }
4804 
4805 void
4806 tree_evaluator::set_echo_state (int type, const std::string& file_name,
4807  int pos)
4808 {
4809  m_echo_state = echo_this_file (file_name, type);
4810  m_echo_file_name = file_name;
4811  m_echo_file_pos = pos;
4812 }
4813 
4814 void
4815 tree_evaluator::uwp_set_echo_state (bool state, const std::string& file_name,
4816  int pos)
4817 {
4818  m_echo_state = state;
4819  m_echo_file_name = file_name;
4820  m_echo_file_pos = pos;
4821 }
4822 
4823 void
4825 {
4826  octave_function *caller = caller_function ();
4827 
4828  if (caller && caller->is_user_code ())
4829  {
4830  octave_user_code *fcn = dynamic_cast<octave_user_code *> (caller);
4831 
4832  int type = fcn->is_user_function () ? ECHO_FUNCTIONS : ECHO_SCRIPTS;
4833 
4834  std::string file_name = fcn->fcn_file_name ();
4835 
4836  // We want the line where "echo" was called, not the line number
4837  // stored in the stack frame that was created for the echo
4838  // function (that will always be -1).
4839 
4840  int pos = m_call_stack.current_user_code_line ();
4841 
4842  if (pos < 0)
4843  pos = 1;
4844 
4845  set_echo_state (type, file_name, pos);
4846  }
4847 }
4848 
4849 void
4851 {
4854 }
4855 
4857 {
4858  // This function is expected to be called from ECHO, which would be
4859  // the top of the call stack. If the caller of ECHO is a
4860  // user-defined function or script, then set up unwind-protect
4861  // elements to restore echo state.
4862 
4864 
4865  if (frame)
4866  {
4867  push_echo_state_cleanup (*frame);
4868  return true;
4869  }
4870 
4871  return false;
4872 }
4873 
4874 
4877 {
4878  bool cleanup_pushed = maybe_push_echo_state_cleanup ();
4879 
4880  string_vector argv = args.make_argv ();
4881 
4882  switch (args.length ())
4883  {
4884  case 0:
4885  if ((m_echo & ECHO_SCRIPTS) || (m_echo & ECHO_FUNCTIONS))
4886  {
4887  m_echo = ECHO_OFF;
4888  m_echo_files.clear ();
4889  }
4890  else
4891  m_echo = ECHO_SCRIPTS;
4892  break;
4893 
4894  case 1:
4895  {
4896  std::string arg0 = argv[0];
4897 
4898  if (arg0 == "on")
4899  m_echo = ECHO_SCRIPTS;
4900  else if (arg0 == "off")
4901  m_echo = ECHO_OFF;
4902  else
4903  {
4904  std::string file = fcn_file_in_path (arg0);
4905  file = sys::env::make_absolute (file);
4906 
4907  if (file.empty ())
4908  error ("echo: no such file %s", arg0.c_str ());
4909 
4910  if (m_echo & ECHO_ALL)
4911  {
4912  // Echo is enabled for all functions, so turn it off
4913  // for this one.
4914 
4915  m_echo_files[file] = false;
4916  }
4917  else
4918  {
4919  // Echo may be enabled for specific functions.
4920 
4921  auto p = m_echo_files.find (file);
4922 
4923  if (p == m_echo_files.end ())
4924  {
4925  // Not this one, so enable it.
4926 
4928  m_echo_files[file] = true;
4929  }
4930  else
4931  {
4932  // This one is already in the list. Flip the
4933  // status for it.
4934 
4935  p->second = ! p->second;
4936  }
4937  }
4938  }
4939  }
4940  break;
4941 
4942  case 2:
4943  {
4944  std::string arg0 = argv[0];
4945  std::string arg1 = argv[1];
4946 
4947  if (arg1 == "on" || arg1 == "off")
4948  std::swap (arg0, arg1);
4949 
4950  if (arg0 == "on")
4951  {
4952  if (arg1 == "all")
4953  {
4955  m_echo_files.clear ();
4956  }
4957  else
4958  {
4959  std::string file = fcn_file_in_path (arg1);
4960  file = sys::env::make_absolute (file);
4961 
4962  if (file.empty ())
4963  error ("echo: no such file %s", arg1.c_str ());
4964 
4966  m_echo_files[file] = true;
4967  }
4968  }
4969  else if (arg0 == "off")
4970  {
4971  if (arg1 == "all")
4972  {
4973  m_echo = ECHO_OFF;
4974  m_echo_files.clear ();
4975  }
4976  else
4977  {
4978  std::string file = fcn_file_in_path (arg1);
4979  file = sys::env::make_absolute (file);
4980 
4981  if (file.empty ())
4982  error ("echo: no such file %s", arg1.c_str ());
4983 
4984  m_echo_files[file] = false;
4985  }
4986  }
4987  else
4988  print_usage ();
4989  }
4990  break;
4991 
4992  default:
4993  print_usage ();
4994  break;
4995  }
4996 
4997  if (cleanup_pushed)
4999 
5000  return octave_value ();
5001 }
5002 
5004 {
5005  return (m_debugger_stack.empty ()
5006  ? false : m_debugger_stack.top()->in_debug_repl ());
5007 }
5008 
5010 {
5011  if (! m_debugger_stack.empty ())
5012  m_debugger_stack.top()->dbcont ();
5013 }
5014 
5015 void tree_evaluator::dbquit (bool all)
5016 {
5017  if (! m_debugger_stack.empty ())
5018  m_debugger_stack.top()->dbquit (all);
5019 }
5020 
5021 static octave_value end_value (const octave_value& value,
5022  octave_idx_type index_position,
5023  octave_idx_type num_indices)
5024 {
5025  dim_vector dv = value.dims ();
5026  int ndims = dv.ndims ();
5027 
5028  if (num_indices < ndims)
5029  {
5030  for (int i = num_indices; i < ndims; i++)
5031  dv(num_indices-1) *= dv(i);
5032 
5033  if (num_indices == 1)
5034  {
5035  ndims = 2;
5036  dv.resize (ndims);
5037  dv(1) = 1;
5038  }
5039  else
5040  {
5041  ndims = num_indices;
5042  dv.resize (ndims);
5043  }
5044  }
5045 
5046  return (index_position < ndims
5047  ? octave_value (dv(index_position)) : octave_value (1.0));
5048 }
5049 
5052 {
5053  int nargin = args.length ();
5054 
5055  if (nargin != 0 && nargin != 3)
5056  print_usage ();
5057 
5058  if (nargin == 3)
5059  {
5061  = args(1).xidx_type_value ("end: K must be integer value");
5062 
5063  if (index_position < 1)
5064  error ("end: K must be greater than zero");
5065 
5067  = args(2).xidx_type_value ("end: N must be integer value");
5068 
5069  if (num_indices < 1)
5070  error ("end: N must be greater than zero");
5071 
5072  return end_value (args(0), index_position-1, num_indices);
5073  }
5074 
5075  // If m_indexed_object is undefined, then this use of 'end' is
5076  // either appearing in a function call argument list or in an
5077  // attempt to index an undefined symbol. There seems to be no
5078  // reasonable way to provide a better error message. So just fail
5079  // with an invalid use message. See bug #58830.
5080 
5082  error ("invalid use of 'end': may only be used to index existing value");
5083 
5084  octave_value expr_result;
5085 
5086  if (m_index_list.empty ())
5087  expr_result = m_indexed_object;
5088  else
5089  {
5090  try
5091  {
5092  // When evaluating "end" with no arguments, we should have
5093  // been called from the built-in Fend function that appears
5094  // in the context of an argument list. Fend will be
5095  // evaluated in its own stack frame. But we need to
5096  // evaluate the partial expression that the special "end"
5097  // token applies to in the calling stack frame.
5098 
5099  unwind_action act ([=] (std::size_t frm)
5100  {
5102  }, m_call_stack.current_frame ());
5103 
5104  std::size_t n = m_call_stack.find_current_user_frame ();
5106 
5107  // End is only valid inside argument lists used for
5108  // indexing. The dispatch class is set by the function that
5109  // evaluates the argument list.
5110 
5111  // Silently ignore extra output values.
5112 
5113  octave_value_list tmp
5115 
5116  expr_result = tmp.length () ? tmp(0) : octave_value ();
5117 
5118  if (expr_result.is_cs_list ())
5120  }
5121  catch (const index_exception&)
5122  {
5123  error ("error evaluating partial expression for END");
5124  }
5125  }
5126 
5127  if (expr_result.isobject ())
5128  {
5129  // FIXME: is there a better way to lookup and execute a method
5130  // that handles all the details like setting the dispatch class
5131  // appropriately?
5132 
5133  std::string dispatch_class = expr_result.class_name ();
5134 
5136 
5137  octave_value meth = symtab.find_method ("end", dispatch_class);
5138 
5139  if (meth.is_defined ())
5140  return m_interpreter.feval
5141  (meth, ovl (expr_result, m_index_position+1, m_num_indices), 1);
5142  }
5143 
5144  return end_value (expr_result, m_index_position, m_num_indices);
5145 }
5146 
5148 tree_evaluator::PS4 (const octave_value_list& args, int nargout)
5149 {
5150  return set_internal_variable (m_PS4, args, nargout, "PS4");
5151 }
5152 
5153 bool tree_evaluator::echo_this_file (const std::string& file, int type) const
5154 {
5155  if ((type & m_echo) == ECHO_SCRIPTS)
5156  {
5157  // Asking about scripts and echo is enabled for them.
5158  return true;
5159  }
5160 
5161  if ((type & m_echo) == ECHO_FUNCTIONS)
5162  {
5163  // Asking about functions and echo is enabled for functions.
5164  // Now, which ones?
5165 
5166  auto p = m_echo_files.find (file);
5167 
5168  if (m_echo & ECHO_ALL)
5169  {
5170  // Return true ulness echo was turned off for a specific
5171  // file.
5172 
5173  return (p == m_echo_files.end () || p->second);
5174  }
5175  else
5176  {
5177  // Return true if echo is specifically enabled for this file.
5178 
5179  return p != m_echo_files.end () && p->second;
5180  }
5181  }
5182 
5183  return false;
5184 }
5185 
5187 {
5188  std::string prefix = command_editor::decode_prompt_string (m_PS4);
5189 
5191 
5192  if (curr_fcn && curr_fcn->is_user_code ())
5193  {
5194  octave_user_code *code = dynamic_cast<octave_user_code *> (curr_fcn);
5195 
5196  int num_lines = line - m_echo_file_pos + 1;
5197 
5198  std::deque<std::string> lines
5199  = code->get_code_lines (m_echo_file_pos, num_lines);
5200 
5201  for (auto& elt : lines)
5202  octave_stdout << prefix << elt << std::endl;
5203  }
5204 }
5205 
5206 // Decide if it's time to quit a for or while loop.
5208 {
5209  octave_quit ();
5210 
5211  // Maybe handle 'continue N' someday...
5212 
5213  if (m_continuing)
5214  m_continuing--;
5215 
5216  bool quit = (m_returning || m_breaking || m_continuing);
5217 
5218  if (m_breaking)
5219  m_breaking--;
5220 
5221  return quit;
5222 }
5223 
5225  const Matrix& ignored_outputs,
5226  int nargin, int nargout,
5227  bool takes_varargs,
5228  const octave_value_list& va_args)
5229 {
5231  set_auto_fcn_var (stack_frame::IGNORED, ignored_outputs);
5235 
5236  if (takes_varargs)
5237  assign ("varargin", va_args.cell_value ());
5238 }
5239 
5240 std::string
5241 tree_evaluator::check_autoload_file (const std::string& nm) const
5242 {
5243  if (sys::env::absolute_pathname (nm))
5244  return nm;
5245 
5246  std::string full_name = nm;
5247 
5249 
5250  bool found = false;
5251 
5252  if (fcn)
5253  {
5254  std::string fname = fcn->fcn_file_name ();
5255 
5256  if (! fname.empty ())
5257  {
5258  fname = sys::env::make_absolute (fname);
5259  fname = fname.substr (0, fname.find_last_of (sys::file_ops::dir_sep_str ()) + 1);
5260 
5261  sys::file_stat fs (fname + nm);
5262 
5263  if (fs.exists ())
5264  {
5265  full_name = fname + nm;
5266  found = true;
5267  }
5268  }
5269  }
5270 
5271  if (! found)
5272  warning_with_id ("Octave:autoload-relative-file-name",
5273  "autoload: '%s' is not an absolute filename",
5274  nm.c_str ());
5275 
5276  return full_name;
5277 }
5278 
5279 DEFMETHOD (max_recursion_depth, interp, args, nargout,
5280  doc: /* -*- texinfo -*-
5281 @deftypefn {} {@var{val} =} max_recursion_depth ()
5282 @deftypefnx {} {@var{old_val} =} max_recursion_depth (@var{new_val})
5283 @deftypefnx {} {@var{old_val} =} max_recursion_depth (@var{new_val}, "local")
5284 Query or set the internal limit on the number of times a function may
5285 be called recursively.
5286 
5287 If the limit is exceeded, an error message is printed and control returns to
5288 the top level.
5289 
5290 When called from inside a function with the @qcode{"local"} option, the
5291 variable is changed locally for the function and any subroutines it calls.
5292 The original variable value is restored when exiting the function.
5293 
5294 @seealso{max_stack_depth}
5295 @end deftypefn */)
5296 {
5297  tree_evaluator& tw = interp.get_evaluator ();
5298 
5299  return tw.max_recursion_depth (args, nargout);
5300 }
5301 
5302 /*
5303 %!test
5304 %! orig_val = max_recursion_depth ();
5305 %! old_val = max_recursion_depth (2*orig_val);
5306 %! assert (orig_val, old_val);
5307 %! assert (max_recursion_depth (), 2*orig_val);
5308 %! max_recursion_depth (orig_val);
5309 %! assert (max_recursion_depth (), orig_val);
5310 
5311 %!error max_recursion_depth (1, 2)
5312 */
5313 
5314 DEFMETHOD (whos_line_format, interp, args, nargout,
5315  doc: /* -*- texinfo -*-
5316 @deftypefn {} {@var{val} =} whos_line_format ()
5317 @deftypefnx {} {@var{old_val} =} whos_line_format (@var{new_val})
5318 @deftypefnx {} {@var{old_val} =} whos_line_format (@var{new_val}, "local")
5319 Query or set the format string used by the command @code{whos}.
5320 
5321 A full format string is:
5322 @c Set example in small font to prevent overfull line
5323 
5324 @smallexample
5325 %[modifier]<command>[:width[:left-min[:balance]]];
5326 @end smallexample
5327 
5328 The following command sequences are available:
5329 
5330 @table @code
5331 @item %a
5332 Prints attributes of variables (c=complex, s=sparse, f=formal parameter,
5333 g=global, p=persistent).
5334 
5335 @item %b
5336 Prints number of bytes occupied by variables.
5337 
5338 @item %c
5339 Prints class names of variables.
5340 
5341 @item %e
5342 Prints elements held by variables.
5343 
5344 @item %n
5345 Prints variable names.
5346 
5347 @item %s
5348 Prints dimensions of variables.
5349 
5350 @item %t
5351 Prints type names of variables.
5352 @end table
5353 
5354 Every command may also have an alignment modifier:
5355 
5356 @table @code
5357 @item l
5358 Left alignment.
5359 
5360 @item r
5361 Right alignment (default).
5362 
5363 @item c
5364 Column-aligned (only applicable to command %s).
5365 @end table
5366 
5367 The @code{width} parameter is a positive integer specifying the minimum
5368 number of columns used for printing. No maximum is needed as the field will
5369 auto-expand as required.
5370 
5371 The parameters @code{left-min} and @code{balance} are only available when
5372 the column-aligned modifier is used with the command @samp{%s}.
5373 @code{balance} specifies the column number within the field width which
5374 will be aligned between entries. Numbering starts from 0 which indicates
5375 the leftmost column. @code{left-min} specifies the minimum field width to
5376 the left of the specified balance column.
5377 
5378 The default format is:
5379 
5380 @example
5381 " %la:5; %ln:6; %cs:16:6:1; %rb:12; %lc:-1;@backslashchar{}n"
5382 @end example
5383 
5384 When called from inside a function with the @qcode{"local"} option, the
5385 variable is changed locally for the function and any subroutines it calls.
5386 The original variable value is restored when exiting the function.
5387 @seealso{whos}
5388 @end deftypefn */)
5389 {
5390  tree_evaluator& tw = interp.get_evaluator ();
5391 
5392  return tw.whos_line_format (args, nargout);
5393 }
5394 
5395 DEFMETHOD (silent_functions, interp, args, nargout,
5396  doc: /* -*- texinfo -*-
5397 @deftypefn {} {@var{val} =} silent_functions ()
5398 @deftypefnx {} {@var{old_val} =} silent_functions (@var{new_val})
5399 @deftypefnx {} {@var{old_val} =} silent_functions (@var{new_val}, "local")
5400 Query or set the internal variable that controls whether internal
5401 output from a function is suppressed.
5402 
5403 If this option is disabled, Octave will display the results produced by
5404 evaluating expressions within a function body that are not terminated with
5405 a semicolon.
5406 
5407 When called from inside a function with the @qcode{"local"} option, the
5408 variable is changed locally for the function and any subroutines it calls.
5409 The original variable value is restored when exiting the function.
5410 @end deftypefn */)
5411 {
5412  tree_evaluator& tw = interp.get_evaluator ();
5413 
5414  return tw.silent_functions (args, nargout);
5415 }
5416 
5417 /*
5418 %!test
5419 %! orig_val = silent_functions ();
5420 %! old_val = silent_functions (! orig_val);
5421 %! assert (orig_val, old_val);
5422 %! assert (silent_functions (), ! orig_val);
5423 %! silent_functions (orig_val);
5424 %! assert (silent_functions (), orig_val);
5425 
5426 %!error silent_functions (1, 2)
5427 */
5428 
5429 DEFMETHOD (string_fill_char, interp, args, nargout,
5430  doc: /* -*- texinfo -*-
5431 @deftypefn {} {@var{val} =} string_fill_char ()
5432 @deftypefnx {} {@var{old_val} =} string_fill_char (@var{new_val})
5433 @deftypefnx {} {@var{old_val} =} string_fill_char (@var{new_val}, "local")
5434 Query or set the internal variable used to pad all rows of a character
5435 matrix to the same length.
5436 
5437 The value must be a single character and the default is @qcode{" "} (a
5438 single space). For example:
5439 
5440 @example
5441 @group
5442 string_fill_char ("X");
5443 [ "these"; "are"; "strings" ]
5444  @result{} "theseXX"
5445  "areXXXX"
5446  "strings"
5447 @end group
5448 @end example
5449 
5450 When called from inside a function with the @qcode{"local"} option, the
5451 variable is changed locally for the function and any subroutines it calls.
5452 The original variable value is restored when exiting the function.
5453 @end deftypefn */)
5454 {
5455  tree_evaluator& tw = interp.get_evaluator ();
5456 
5457  return tw.string_fill_char (args, nargout);
5458 }
5459 
5460 /*
5461 ## string_fill_char() function call must be outside of %!test block
5462 ## due to the way a %!test block is wrapped inside a function
5463 %!shared orig_val, old_val
5464 %! orig_val = string_fill_char ();
5465 %! old_val = string_fill_char ("X");
5466 %!test
5467 %! assert (orig_val, old_val);
5468 %! assert (string_fill_char (), "X");
5469 %! assert (["these"; "are"; "strings"], ["theseXX"; "areXXXX"; "strings"]);
5470 %! string_fill_char (orig_val);
5471 %! assert (string_fill_char (), orig_val);
5472 
5473 %!assert ( [ [], {1} ], {1} )
5474 
5475 %!error string_fill_char (1, 2)
5476 */
5477 
5478 DEFMETHOD (PS4, interp, args, nargout,
5479  doc: /* -*- texinfo -*-
5480 @deftypefn {} {@var{val} =} PS4 ()
5481 @deftypefnx {} {@var{old_val} =} PS4 (@var{new_val})
5482 @deftypefnx {} {@var{old_val} =} PS4 (@var{new_val}, "local")
5483 Query or set the character string used to prefix output produced
5484 when echoing commands is enabled.
5485 
5486 The default value is @qcode{"+ "}.
5487 @xref{Diary and Echo Commands}, for a description of echoing commands.
5488 
5489 When called from inside a function with the @qcode{"local"} option, the
5490 variable is changed locally for the function and any subroutines it calls.
5491 The original variable value is restored when exiting the function.
5492 @seealso{echo, PS1, PS2}
5493 @end deftypefn */)
5494 {
5495  tree_evaluator& tw = interp.get_evaluator ();
5496 
5497  return tw.PS4 (args, nargout);
5498 }
5499 
5500 DEFMETHOD (echo, interp, args, nargout,
5501  doc: /* -*- texinfo -*-
5502 @deftypefn {} {} echo
5503 @deftypefnx {} {} echo on
5504 @deftypefnx {} {} echo off
5505 @deftypefnx {} {} echo on all
5506 @deftypefnx {} {} echo off all
5507 @deftypefnx {} {} echo @var{function} on
5508 @deftypefnx {} {} echo @var{function} off
5509 Control whether commands are displayed as they are executed.
5510 
5511 Valid options are:
5512 
5513 @table @code
5514 @item on
5515 Enable echoing of commands as they are executed in script files.
5516 
5517 @item off
5518 Disable echoing of commands as they are executed in script files.
5519 
5520 @item on all
5521 Enable echoing of commands as they are executed in script files and
5522 functions.
5523 
5524 @item off all
5525 Disable echoing of commands as they are executed in script files and
5526 functions.
5527 
5528 @item @var{function} on
5529 Enable echoing of commands as they are executed in the named function.
5530 
5531 @item @var{function} off
5532 Disable echoing of commands as they are executed in the named function.
5533 @end table
5534 
5535 @noindent
5536 With no arguments, @code{echo} toggles the current echo state.
5537 
5538 @seealso{PS4}
5539 @end deftypefn */)
5540 {
5541  tree_evaluator& tw = interp.get_evaluator ();
5542 
5543  return tw.echo (args, nargout);
5544 }
5545 
5546 /*
5547 %!error echo ([])
5548 %!error echo (0)
5549 %!error echo ("")
5550 %!error echo ("Octave")
5551 %!error echo ("off", "invalid")
5552 %!error echo ("on", "invalid")
5553 %!error echo ("on", "all", "all")
5554 */
5555 
OCTAVE_END_NAMESPACE(octave)
F77_RET_T const F77_DBLE const F77_DBLE const F77_INT const F77_DBLE const F77_DBLE const F77_DBLE F77_DBLE F77_DBLE F77_INT F77_INT const F77_INT const F77_INT F77_INT F77_INT F77_DBLE *F77_RET_T const F77_DBLE const F77_INT const F77_DBLE const F77_DBLE F77_DBLE F77_DBLE F77_INT F77_INT const F77_INT const F77_INT F77_INT F77_INT F77_DBLE *F77_RET_T const F77_REAL const F77_REAL const F77_INT const F77_REAL const F77_REAL const F77_REAL F77_REAL F77_REAL F77_INT F77_INT const F77_INT const F77_INT F77_INT F77_INT F77_REAL *F77_RET_T const F77_REAL const F77_INT const F77_REAL const F77_REAL F77_REAL F77_REAL F77_INT F77_INT const F77_INT const F77_INT F77_INT F77_INT F77_REAL *static F77_INT user_function(const double &x, int &, double &result)
Definition: Quad.cc:80
OCTARRAY_OVERRIDABLE_FUNC_API octave_idx_type columns(void) const
Definition: Array.h:471
OCTARRAY_OVERRIDABLE_FUNC_API octave_idx_type numel(void) const
Number of elements in the array.
Definition: Array.h:414
OCTARRAY_OVERRIDABLE_FUNC_API octave_idx_type rows(void) const
Definition: Array.h:459
Definition: Cell.h:43
Definition: dMatrix.h:42
void resize(octave_idx_type nr, octave_idx_type nc, double rfv=0)
Definition: dMatrix.h:158
void add(F &&fcn, Args &&... args)
void discard(std::size_t num)
OCTAVE_API void run(std::size_t num)
void protect_var(T &var)
static application * app(void)
Definition: octave.h:301
static bool forced_interactive(void)
Definition: octave.cc:327
void forced_interactive(bool arg)
Definition: octave.h:295
iterator end(void)
Definition: base-list.h:68
iterator begin(void)
Definition: base-list.h:65
elt_type & front(void)
Definition: base-list.h:79
std::size_t length(void) const
Definition: base-list.h:53
OCTINTERP_API void disallow_command_syntax(void)
Definition: oct-parse.cc:9582
OCTINTERP_API void statement_list(std::shared_ptr< tree_statement_list > &lst)
Definition: oct-parse.cc:6849
bool at_end_of_input(void) const
Definition: parse.h:178
OCTINTERP_API void reset(void)
Definition: oct-parse.cc:6747
bool debug_on_err(const std::string &id)
Definition: bp-table.h:186
bool have_breakpoints(void)
Definition: bp-table.h:183
bool debug_on_caught(const std::string &id)
Definition: bp-table.h:192
void set_dispatch_class(const std::string &class_name)
Definition: call-stack.cc:293
octave_value do_who(int argc, const string_vector &argv, bool return_list, bool verbose=false)
Definition: call-stack.cc:909
octave_value get_top_level_value(const std::string &name) const
Definition: call-stack.cc:898
octave_value global_varval(const std::string &name) const
Definition: call-stack.cc:886
std::list< frame_info > backtrace_info(octave_idx_type &curr_user_frame, bool print_subfn=true) const
Definition: call-stack.cc:680
void set_column(int c)
Definition: call-stack.h:190
std::shared_ptr< stack_frame > get_current_stack_frame(void) const
Definition: call-stack.h:91
octave_map backtrace(octave_idx_type &curr_user_frame, bool print_subfn=true) const
Definition: call-stack.cc:709
symbol_scope current_scope(void) const
Definition: call-stack.h:101
octave_value & global_varref(const std::string &name)
Definition: call-stack.cc:893
void set_top_level_value(const std::string &name, const octave_value &value)
Definition: call-stack.cc:903
void goto_base_frame(void)
Definition: call-stack.cc:631
octave_value get_auto_fcn_var(stack_frame::auto_var_type avt) const
Definition: call-stack.cc:1132
symbol_info_list top_scope_symbol_info(void) const
Definition: call-stack.cc:864
std::string get_dispatch_class(void) const
Definition: call-stack.cc:288
symbol_info_list regexp_symbol_info(const std::string &pattern) const
Definition: call-stack.cc:854
void make_global(const symbol_record &sym)
Definition: call-stack.cc:881
octave_user_code * current_user_code(void) const
Definition: call-stack.cc:117
int current_line(void) const
Definition: call-stack.cc:91
symbol_info_list get_symbol_info(void)
Definition: call-stack.cc:859
symbol_info_list glob_symbol_info(const std::string &pattern) const
Definition: call-stack.cc:848
void restore_frame(std::size_t n)
Definition: call-stack.h:202
void pop(void)
Definition: call-stack.cc:755
bool is_class_method_executing(std::string &dispatch_class) const
Definition: call-stack.cc:298
bool goto_frame(std::size_t n=0, bool verbose=false)
Definition: call-stack.cc:468
void set_auto_fcn_var(stack_frame::auto_var_type avt, const octave_value &val)
Definition: call-stack.cc:1126
int current_column(void) const
Definition: call-stack.cc:104
void clear_global_variables(void)
Definition: call-stack.cc:841
int current_user_code_line(void) const
Definition: call-stack.cc:136
std::size_t current_frame(void) const
Definition: call-stack.h:87
std::list< std::string > variable_names(void) const
Definition: call-stack.cc:806
std::list< std::shared_ptr< stack_frame > > backtrace_frames(octave_idx_type &curr_user_frame) const
Definition: call-stack.cc:638
void set_location(int l, int c)
Definition: call-stack.h:169
bool is_class_constructor_executing(std::string &dispatch_class) const
Definition: call-stack.cc:312
octave_function * current_function(bool skip_first=false) const
Definition: call-stack.cc:66
void clear_global_variable_pattern(const std::string &pattern)
Definition: call-stack.cc:819
void set_line(int l)
Definition: call-stack.h:180
std::shared_ptr< stack_frame > current_user_frame(void) const
Definition: call-stack.cc:506
void push(const symbol_scope &scope)
Definition: call-stack.cc:378
octave_user_code * debug_user_code(void) const
Definition: call-stack.cc:203
void display(void) const
Definition: call-stack.cc:1112
std::list< std::string > top_level_variable_names(void) const
Definition: call-stack.cc:801
void clear_global_variable(const std::string &name)
Definition: call-stack.cc:811
std::size_t find_current_user_frame(void) const
Definition: call-stack.cc:489
std::list< std::string > global_variable_names(void) const
Definition: call-stack.cc:786
int debug_user_code_line(void) const
Definition: call-stack.cc:229
std::size_t dbupdown(std::size_t start, int n, bool verbose)
Definition: call-stack.cc:517
bool at_top_level(void) const
Definition: call-stack.h:108
std::size_t size(void) const
Definition: call-stack.h:89
int debug_user_code_column(void) const
Definition: call-stack.cc:258
unwind_protect * curr_fcn_unwind_protect_frame(void)
Definition: call-stack.cc:184
void clear_global_variable_regexp(const std::string &pattern)
Definition: call-stack.cc:830
void goto_caller_frame(void)
Definition: call-stack.cc:619
octave_map empty_backtrace(void) const
Definition: call-stack.cc:750
symbol_scope top_scope(void) const
Definition: call-stack.h:96
void make_persistent(const symbol_record &sym)
Definition: call-stack.cc:876
octave_value max_stack_depth(const octave_value_list &args, int nargout)
Definition: call-stack.cc:869
OCTINTERP_API cdef_method find_method(const std::string &nm, bool local=false)
Definition: cdef-class.h:460
OCTINTERP_API octave_value find_method(const std::string &class_name, const std::string &name) const
bool is_static(void) const
Definition: cdef-method.h:184
octave_value get_function(void) const
Definition: cdef-method.h:191
bool ok(void) const
Definition: cdef-object.h:312
OCTINTERP_API cdef_class get_class(void) const
Definition: cdef-object.cc:183
static void run_event_hooks(void)
Definition: cmd-edit.cc:1581
static bool interrupt(bool=true)
Definition: cmd-edit.cc:1625
static void increment_current_command_number(void)
Definition: cmd-edit.cc:1297
static bool erase_empty_line(bool flag)
Definition: cmd-edit.cc:1318
static std::string decode_prompt_string(const std::string &s)
Definition: cmd-edit.cc:1278
static bool add(const std::string &)
Definition: cmd-hist.cc:618
static bool ignoring_entries(void)
Definition: cmd-hist.cc:612
static void ignore_entries(bool=true)
Definition: cmd-hist.cc:605
void dbquit(bool all=false)
Definition: pt-eval.cc:124
std::size_t m_level
Definition: pt-eval.cc:138
bool quitting_debugger(void) const
Definition: pt-eval.cc:506
interpreter & m_interpreter
Definition: pt-eval.cc:136
bool m_in_debug_repl
Definition: pt-eval.cc:140
execution_mode m_execution_mode
Definition: pt-eval.cc:139
void repl(const std::string &prompt="debug> ")
Definition: pt-eval.cc:260
void dbcont(void)
Definition: pt-eval.cc:122
bool in_debug_repl(void) const
Definition: pt-eval.cc:120
int server_loop(void)
Definition: pt-eval.cc:147
debugger(interpreter &interp, std::size_t level)
Definition: pt-eval.cc:111
execution_mode
Definition: pt-eval.cc:104
@ EX_NORMAL
Definition: pt-eval.cc:105
@ EX_QUIT_ALL
Definition: pt-eval.cc:108
@ EX_QUIT
Definition: pt-eval.cc:107
@ EX_CONTINUE
Definition: pt-eval.cc:106
Vector representing the dimensions (size) of an Array.
Definition: dim-vector.h:94
void resize(int n, int fill_value=0)
Definition: dim-vector.h:272
octave_idx_type ndims(void) const
Number of dimensions.
Definition: dim-vector.h:257
OCTAVE_API dim_vector redim(int n) const
Force certain dimensionality, preserving numel ().
Definition: dim-vector.cc:226
OCTINTERP_API octave_value last_error_id(const octave_value_list &args, int nargout)
Definition: error.cc:358
OCTINTERP_API octave_value debug_on_warning(const octave_value_list &args, int nargout)
Definition: error.cc:292
OCTINTERP_API void display_exception(const execution_exception &ee, std::ostream &os) const
Definition: error.cc:905
void set_debug_on_warning(bool flag)
Definition: error.h:88
OCTINTERP_API octave_value debug_on_caught(const octave_value_list &args, int nargout)
Definition: error.cc:285
OCTINTERP_API void save_exception(const execution_exception &ee)
Definition: error.cc:893
OCTINTERP_API octave_value debug_on_error(const octave_value_list &args, int nargout)
Definition: error.cc:278
OCTINTERP_API octave_value last_error_message(const octave_value_list &args, int nargout)
Definition: error.cc:336
octave_map last_error_stack(void) const
Definition: error.h:252
void set_debug_on_error(bool flag)
Definition: error.h:60
Provides threadsafe access to octave.
void append_history(const std::string &hist_entry)
void push_event_queue(void)
OCTINTERP_API void set_workspace(void)
void enter_debugger_event(const std::string &fcn_name, const std::string &fcn_file_name, int line)
void pop_event_queue(void)
OCTINTERP_API void post_event(const fcn_callback &fcn)
void execute_in_debugger_event(const std::string &file, int line)
void pre_input_event(void)
void set_var(const std::string &var_arg="")
virtual const char * err_id(void) const =0
std::string get_input(const std::string &prompt, bool &eof)
Definition: input.h:277
octave_value gud_mode(const octave_value_list &args, int nargout)
void set_PS1(const std::string &s)
Definition: input.h:78
octave_value PS2(const octave_value_list &args, int nargout)
octave_value PS1(const octave_value_list &args, int nargout)
event_manager & get_event_manager(void)
Definition: interpreter.h:328
bool in_top_level_repl(void) const
Definition: interpreter.h:211
bool server_mode(void) const
Definition: interpreter.h:169
error_system & get_error_system(void)
Definition: interpreter.h:251
tree_evaluator & get_evaluator(void)
void parse_and_execute(const std::string &input, bool &incomplete_parse)
Definition: interpreter.cc:832
symbol_table & get_symbol_table(void)
Definition: interpreter.h:298
octave_value_list feval(const char *name, const octave_value_list &args=octave_value_list(), int nargout=0)
Evaluate an Octave function (built-in or interpreted) and return the list of result values.
cdef_manager & get_cdef_manager(void)
Definition: interpreter.h:318
bool interactive(void) const
Definition: interpreter.h:171
void recover_from_exception(void)
input_system & get_input_system(void)
Definition: interpreter.h:263
load_path & get_load_path(void)
Definition: interpreter.h:283
Definition: lex.h:766
std::string find_file(const std::string &file) const
Definition: load-path.cc:602
virtual bool is_user_code(void) const
Definition: ov-base.h:517
virtual bool is_user_function(void) const
Definition: ov-base.h:515
virtual bool is_builtin_function(void) const
Definition: ov-base.h:519
octave_value_list(* fcn)(const octave_value_list &, int)
Definition: ov-builtin.h:63
octave_value_list(* meth)(octave::interpreter &, const octave_value_list &, int)
Definition: ov-builtin.h:60
fcn function(void) const
Definition: ov-builtin.cc:53
meth method(void) const
Definition: ov-builtin.cc:59
octave::cdef_object get_object(void) const
Definition: ov-classdef.h:75
octave_classdef * classdef_object_value(bool=false)
Definition: ov-classdef.h:73
std::string class_name(void) const
Definition: ov-classdef.h:154
std::string dispatch_class(void) const
Definition: ov-fcn.h:150
virtual std::string fcn_file_name(void) const
Definition: ov-fcn.h:79
bool is_private_function(void) const
Definition: ov-fcn.h:163
std::string dir_name(void) const
Definition: ov-fcn.h:172
bool is_class_method(const std::string &cname="") const
Definition: ov-fcn.h:117
virtual bool is_parent_function(void) const
Definition: ov-fcn.h:108
bool is_class_constructor(const std::string &cname="") const
Definition: ov-fcn.h:112
virtual bool is_subfunction(void) const
Definition: ov-fcn.h:110
void unlock(void)
Definition: ov-fcn.h:182
virtual std::list< std::string > parent_fcn_names(void) const
Definition: ov-fcn.h:91
bool islocked(void) const
Definition: ov-fcn.h:188
virtual std::string parent_fcn_name(void) const
Definition: ov-fcn.h:86
void stash_dir_name(const std::string &dir)
Definition: ov-fcn.h:174
virtual octave_value_list call(octave::tree_evaluator &tw, int nargout=0, const octave_value_list &args=octave_value_list())
Definition: ov-fcn.cc:50
void lock(void)
Definition: ov-fcn.h:176
void stash_dispatch_class(const std::string &nm)
Definition: ov-fcn.h:148
std::string name(void) const
Definition: ov-fcn.h:208
virtual bool is_nested_function(void) const
Definition: ov-fcn.h:106
bool is_undefined(void) const
Definition: oct-lvalue.cc:45
void assign(octave_value::assign_op, const octave_value &)
Definition: oct-lvalue.cc:55
void define(const octave_value &v)
Definition: oct-lvalue.cc:50
string_vector keys(void) const
Definition: oct-map.h:356
const Cell & contents(const_iterator p) const
Definition: oct-map.h:331
void assign(const std::string &k, const octave_value &val)
Definition: oct-map.h:238
void stash_fcn_file_name(const std::string &nm)
Definition: ov-usr-fcn.h:96
std::string fcn_file_name(void) const
Definition: ov-usr-fcn.h:107
std::string get_code_line(std::size_t line)
Definition: ov-usr-fcn.cc:100
octave::tree_statement_list * body(void)
Definition: ov-usr-fcn.h:120
std::deque< std::string > get_code_lines(std::size_t line, std::size_t num_lines)
Definition: ov-usr-fcn.cc:109
virtual octave_value find_subfunction(const std::string &) const
Definition: ov-usr-fcn.h:113
void mark_as_anonymous_function(void)
Definition: ov-usr-fcn.h:321
void mark_as_nested_function(void)
Definition: ov-usr-fcn.h:343
void make_storable_values(void)
Definition: ovl.cc:277
Cell cell_value(void) const
Definition: ovl.h:105
octave_value & xelem(octave_idx_type i)
Definition: ovl.h:171
bool empty(void) const
Definition: ovl.h:115
void resize(octave_idx_type n, const octave_value &rfv=octave_value())
Definition: ovl.h:117
void stash_name_tags(const string_vector &nm)
Definition: ovl.h:165
octave_idx_type length(void) const
Definition: ovl.h:113
void clear(void)
Definition: ovl.h:173
string_vector name_tags(void) const
Definition: ovl.h:167
octave_value_list slice(octave_idx_type offset, octave_idx_type len, bool tags=false) const
Definition: ovl.h:131
string_vector make_argv(const std::string &="") const
Definition: ovl.cc:227
bool has_magic_colon(void) const
Definition: ovl.cc:215
bool is_function(void) const
Definition: ov.h:822
octave::range< double > range_value(void) const
Definition: ov.h:1030
OCTINTERP_API octave_function * function_value(bool silent=false) const
bool iscell(void) const
Definition: ov.h:649
OCTINTERP_API octave_value_list list_value(void) const
octave_value subsref(const std::string &type, const std::list< octave_value_list > &idx)
Definition: ov.h:525
OCTINTERP_API std::string xstring_value(const char *fmt,...) const
octave_value index_op(const octave_value_list &idx, bool resize_ok=false)
Definition: ov.h:550
bool is_uint16_type(void) const
Definition: ov.h:766
bool is_true(void) const
Definition: ov.h:803
bool is_int8_type(void) const
Definition: ov.h:751
OCTINTERP_API Cell xcell_value(const char *fmt,...) const
bool is_scalar_type(void) const
Definition: ov.h:789
bool is_cs_list(void) const
Definition: ov.h:715
bool is_string(void) const
Definition: ov.h:682
bool is_user_code(void) const
Definition: ov.h:831
OCTINTERP_API octave_value storable_value(void) const
bool is_defined(void) const
Definition: ov.h:637
bool is_double_type(void) const
Definition: ov.h:740
Cell cell_value(void) const
bool is_equal(const octave_value &) const
std::string class_name(void) const
Definition: ov.h:1454
@ op_asn_eq
Definition: ov.h:133
bool is_uint32_type(void) const
Definition: ov.h:769
int ndims(void) const
Definition: ov.h:596
OCTINTERP_API octave_user_code * user_code_value(bool silent=false) const
bool is_int64_type(void) const
Definition: ov.h:760
bool isstruct(void) const
Definition: ov.h:694
octave_value reshape(const dim_vector &dv) const
Definition: ov.h:616
@ magic_colon_t
Definition: ov.h:168
bool is_matrix_type(void) const
Definition: ov.h:792
bool is_int32_type(void) const
Definition: ov.h:757
bool is_uint64_type(void) const
Definition: ov.h:772
bool is_int16_type(void) const
Definition: ov.h:754
bool is_range(void) const
Definition: ov.h:691
bool is_single_type(void) const
Definition: ov.h:743
OCTINTERP_API octave_map map_value(void) const
bool isobject(void) const
Definition: ov.h:709
bool is_undefined(void) const
Definition: ov.h:640
bool is_uint8_type(void) const
Definition: ov.h:763
dim_vector dims(void) const
Definition: ov.h:586
Definition: parse.h:829
OCTINTERP_API int run(void)
Definition: oct-parse.cc:9703
OCTINTERP_API int run(void)
Definition: oct-parse.cc:9820
~quit_debug_exception(void)=default
bool all(void) const
Definition: pt-eval.cc:92
quit_debug_exception(const quit_debug_exception &)=default
quit_debug_exception(bool all=false)
Definition: pt-eval.cc:84
std::map< std::string, octave_value > local_vars_map
Definition: stack-frame.h:112
@ SAVED_WARNING_STATES
Definition: stack-frame.h:136
octave_idx_type numel(void) const
Definition: str-vec.h:100
std::size_t nesting_depth(void) const
Definition: symscope.h:431
void set_parent(const symbol_scope &p)
Definition: symscope.h:609
void cache_fcn_file_name(const std::string &name)
Definition: symscope.h:621
symbol_scope dup(void) const
Definition: symscope.h:457
void set_nesting_depth(std::size_t depth)
Definition: symscope.h:425
void set_primary_parent(const symbol_scope &p)
Definition: symscope.h:615
void cache_dir_name(const std::string &name)
Definition: symscope.h:627
octave_value find_scoped_function(const std::string &name, const symbol_scope &search_scope)
Definition: symtab.cc:75
octave_value find_method(const std::string &name, const std::string &dispatch_type)
Definition: symtab.cc:125
void clear_function(const std::string &name)
Definition: symtab.cc:434
void clear_function_pattern(const std::string &pat)
Definition: symtab.cc:439
void clear_functions(bool force=false)
Definition: symtab.cc:426
void install_cmdline_function(const std::string &name, const octave_value &fcn)
Definition: symtab.cc:332
void clear_dld_function(const std::string &name)
Definition: symtab.cc:485
octave_value find_function(const std::string &name, const symbol_scope &search_scope=symbol_scope())
Definition: symtab.cc:249
octave_value find_user_function(const std::string &name)
Definition: symtab.cc:288
void clear_function_regexp(const std::string &pat)
Definition: symtab.cc:454
octave_value fcn_table_find(const std::string &name, const octave_value_list &args=ovl(), const symbol_scope &search_scope=symbol_scope())
Definition: symtab.cc:219
symbol_scope scope(void) const
tree_expression * expression(void) const
tree_parameter_list * parameter_list(void) const
std::set< std::string > free_variables(void) const
tree_statement_list * body(void)
Definition: pt-loop.h:249
tree_expression * control_expr(void)
Definition: pt-loop.h:247
tree_argument_list * left_hand_side(void)
Definition: pt-loop.h:245
tree_decl_init_list * initializer_list(void)
Definition: pt-decl.h:201
bool is_global(void) const
Definition: pt-decl.h:83
tree_identifier * ident(void)
Definition: pt-decl.h:88
tree_expression * expression(void)
Definition: pt-decl.h:92
bool is_persistent(void) const
Definition: pt-decl.h:86
void accept(tree_walker &tw)
Definition: pt-decl.h:163
bool m_in_loop_command
Definition: pt-eval.h:985
octave_value_list eval_string(const std::string &eval_str, bool silent, int &parse_status, int nargout)
Definition: pt-eval.cc:1013
bool switch_case_label_matches(tree_switch_case *expr, const octave_value &val)
Definition: pt-eval.cc:2413
void reset_debug_state(void)
Definition: pt-eval.cc:1363
std::size_t m_debug_frame
Definition: pt-eval.h:908
octave_value_list execute_user_function(octave_user_function &user_function, int nargout, const octave_value_list &args)
Definition: pt-eval.cc:3537
int server_loop(void)
Definition: pt-eval.cc:872
std::stack< debugger * > m_debugger_stack
Definition: pt-eval.h:919
void visit_break_command(tree_break_command &)
Definition: pt-eval.cc:1310
bool is_global(const std::string &name) const
Definition: pt-eval.cc:1932
bool quit_loop_now(void)
Definition: pt-eval.cc:5207
void goto_caller_frame(void)
Definition: pt-eval.cc:2534
void visit_octave_user_function(octave_user_function &)
Definition: pt-eval.cc:3697
void visit_unwind_protect_command(tree_unwind_protect_command &)
Definition: pt-eval.cc:4267
bool mislocked(bool skip_first=false) const
Definition: pt-eval.cc:2694
std::list< std::string > autoloaded_functions(void) const
Definition: pt-eval.cc:4620
bool m_server_mode
Definition: pt-eval.h:982
symbol_info_list get_symbol_info(void)
Definition: pt-eval.cc:4571
void bind_ans(const octave_value &val, bool print)
Definition: pt-eval.cc:4417
void visit_return_command(tree_return_command &)
Definition: pt-eval.cc:3867
octave_value_list execute_builtin_function(octave_builtin &builtin_function, int nargout, const octave_value_list &args)
Definition: pt-eval.cc:3425
bool statement_printing_enabled(void)
Definition: pt-eval.cc:1356
void clear_all(bool force=false)
Definition: pt-eval.cc:2800
void visit_statement_list(tree_statement_list &)
Definition: pt-eval.cc:4008
octave_value evaluate(tree_decl_elt *)
Definition: pt-eval.cc:1856
void visit_anon_fcn_handle(tree_anon_fcn_handle &)
Definition: pt-eval.cc:1244
void source_file(const std::string &file_name, const std::string &context="", bool verbose=false, bool require_file=true)
Definition: pt-eval.cc:2046
void visit_cell(tree_cell &)
Definition: pt-eval.cc:3809
void push_echo_state_cleanup(unwind_protect &frame)
Definition: pt-eval.cc:4850
int dbstep_flag(void) const
Definition: pt-eval.h:797
std::list< octave_value_list > m_index_list
Definition: pt-eval.h:999
octave_value echo(const octave_value_list &args, int nargout)
Definition: pt-eval.cc:4876
std::list< frame_info > backtrace_info(void) const
Definition: pt-eval.cc:2590
octave_value_list evaluate_end_expression(const octave_value_list &args)
Definition: pt-eval.cc:5051
void add_autoload(const std::string &fcn, const std::string &nm)
Definition: pt-eval.cc:4642
void visit_constant(tree_constant &)
Definition: pt-eval.cc:3837
void keyboard(const std::string &prompt="keyboard> ")
Definition: pt-eval.cc:1428
void visit_superclass_ref(tree_superclass_ref &)
Definition: pt-eval.cc:4406
void visit_simple_assignment(tree_simple_assignment &)
Definition: pt-eval.cc:3892
interpreter & m_interpreter
Definition: pt-eval.h:889
void dbcont(void)
Definition: pt-eval.cc:5009
octave_value & global_varref(const std::string &name)
Definition: pt-eval.cc:1975
void do_breakpoint(tree_statement &stmt)
Definition: pt-eval.cc:4452
octave_map empty_backtrace(void) const
Definition: pt-eval.cc:2607
symbol_scope get_current_scope(void) const
Definition: pt-eval.cc:2657
void final_index_error(index_exception &ie, const tree_expression *expr)
Definition: pt-eval.cc:4688
symbol_scope get_top_scope(void) const
Definition: pt-eval.cc:2652
char string_fill_char(void) const
Definition: pt-eval.h:654
bool at_top_level(void) const
Definition: pt-eval.cc:534
void visit_args_block_validation_list(tree_args_block_validation_list &)
Definition: pt-eval.cc:1268
bool m_silent_functions
Definition: pt-eval.h:934
int m_continuing
Definition: pt-eval.h:991
void debug_where(std::ostream &os) const
Definition: pt-eval.cc:2497
void goto_base_frame(void)
Definition: pt-eval.cc:2539
octave_user_code * current_user_code(void) const
Definition: pt-eval.cc:2504
void clear_global_variable(const std::string &name)
Definition: pt-eval.cc:2779
int m_index_position
Definition: pt-eval.h:1001
octave_value_list execute_mex_function(octave_mex_function &mex_function, int nargout, const octave_value_list &args)
Definition: pt-eval.cc:3470
bool m_in_top_level_repl
Definition: pt-eval.h:979
void set_dispatch_class(const std::string &class_name)
Definition: pt-eval.cc:2554
void visit_boolean_expression(tree_boolean_expression &)
Definition: pt-eval.cc:1298
void echo_code(int line)
Definition: pt-eval.cc:5186
bool goto_frame(std::size_t n=0, bool verbose=false)
Definition: pt-eval.cc:2529
void visit_switch_case(tree_switch_case &)
Definition: pt-eval.cc:4058
stmt_list_type m_statement_context
Definition: pt-eval.h:894
void munlock(bool skip_first=false) const
Definition: pt-eval.cc:2678
octave_user_code * get_user_code(const std::string &fname="", const std::string &class_name="")
Definition: pt-eval.cc:2865
void visit_arg_validation(tree_arg_validation &)
Definition: pt-eval.cc:1274
void pop_stack_frame(void)
Definition: pt-eval.cc:2472
octave_value get_auto_fcn_var(stack_frame::auto_var_type avt) const
Definition: pt-eval.cc:2205
void remove_autoload(const std::string &fcn, const std::string &nm)
Definition: pt-eval.cc:4650
Matrix ignored_fcn_outputs(void) const
Definition: pt-eval.cc:1440
int max_recursion_depth(void) const
Definition: pt-eval.h:596
bool is_logically_true(tree_expression *expr, const char *warn_for)
Definition: pt-eval.cc:4533
void visit_octave_user_function_header(octave_user_function &)
Definition: pt-eval.cc:3704
void visit_arg_size_spec(tree_arg_size_spec &)
Definition: pt-eval.cc:1280
void visit_multi_assignment(tree_multi_assignment &)
Definition: pt-eval.cc:3815
int repl(void)
Definition: pt-eval.cc:731
void visit_continue_command(tree_continue_command &)
Definition: pt-eval.cc:1337
octave_value find(const std::string &name)
Definition: pt-eval.cc:2715
void visit_while_command(tree_while_command &)
Definition: pt-eval.cc:4322
void visit_do_until_command(tree_do_until_command &)
Definition: pt-eval.cc:4365
std::size_t debug_frame(void) const
Definition: pt-eval.h:631
void visit_index_expression(tree_index_expression &)
Definition: pt-eval.cc:3797
void visit_postfix_expression(tree_postfix_expression &)
Definition: pt-eval.cc:3855
std::list< std::shared_ptr< stack_frame > > backtrace_frames() const
Definition: pt-eval.cc:2578
char m_string_fill_char
Definition: pt-eval.h:937
std::size_t current_call_stack_frame_number(void) const
Definition: pt-eval.h:640
void display_call_stack(void) const
Definition: pt-eval.cc:2710
void define_parameter_list_from_arg_vector(tree_parameter_list *param_list, const octave_value_list &args)
Definition: pt-eval.cc:2212
octave_map get_autoload_map(void) const
Definition: pt-eval.cc:4582
bool is_local_variable(const std::string &name) const
Definition: pt-eval.cc:1875
void visit_decl_command(tree_decl_command &)
Definition: pt-eval.cc:2971
octave_function * caller_function(void) const
Definition: pt-eval.cc:2524
void visit_arg_validation_fcns(tree_arg_validation_fcns &)
Definition: pt-eval.cc:1286
int m_num_indices
Definition: pt-eval.h:1002
int debug_user_code_column(void) const
Definition: pt-eval.cc:2492
octave_map backtrace(void) const
Definition: pt-eval.cc:2602
void visit_function_def(tree_function_def &)
Definition: pt-eval.cc:3716
void visit_switch_command(tree_switch_command &)
Definition: pt-eval.cc:4070
void clear_symbol_pattern(const std::string &pattern)
Definition: pt-eval.cc:2823
void clear_symbol(const std::string &name)
Definition: pt-eval.cc:2812
std::list< std::string > top_level_variable_names(void) const
Definition: pt-eval.cc:2850
std::map< std::string, std::string > m_autoload_map
Definition: pt-eval.h:899
void visit_arguments_block(tree_arguments_block &)
Definition: pt-eval.cc:1256
void dbquit(bool all=false)
Definition: pt-eval.cc:5015
void restore_frame(std::size_t n)
Definition: pt-eval.cc:2544
int returning(void) const
Definition: pt-eval.h:788
void visit_if_command(tree_if_command &)
Definition: pt-eval.cc:3750
bool is_class_method_executing(std::string &dispatch_class) const
Definition: pt-eval.cc:2560
void visit_spmd_command(tree_spmd_command &)
Definition: pt-eval.cc:3318
octave_value_list convert_to_const_vector(tree_argument_list *arg_list)
Definition: pt-eval.cc:2296
octave_value m_indexed_object
Definition: pt-eval.h:998
octave_user_code * debug_user_code(void) const
Definition: pt-eval.cc:2514
void visit_try_catch_command(tree_try_catch_command &)
Definition: pt-eval.cc:4112
unwind_protect * curr_fcn_unwind_protect_frame(void)
Definition: pt-eval.cc:2509
int index_position(void) const
Definition: pt-eval.h:754
void clear_global_variables(void)
Definition: pt-eval.cc:2795
bool m_echo_state
Definition: pt-eval.h:962
void clear_variables(void)
Definition: pt-eval.cc:2771
bool echo_this_file(const std::string &file, int type) const
Definition: pt-eval.cc:5153
void visit_colon_expression(tree_colon_expression &)
Definition: pt-eval.cc:1331
std::string PS4(void) const
Definition: pt-eval.h:706
int current_line(void) const
Definition: pt-eval.cc:2477
void push_dummy_scope(const std::string &name)
Definition: pt-eval.cc:2640
void pop_scope(void)
Definition: pt-eval.cc:2647
void visit_simple_for_command(tree_simple_for_command &)
Definition: pt-eval.cc:3057
int m_exit_status
Definition: pt-eval.h:923
octave_value_list make_value_list(tree_argument_list *args, const string_vector &arg_nm)
Definition: pt-eval.cc:4726
std::shared_ptr< push_parser > m_parser
Definition: pt-eval.h:891
int num_indices(void) const
Definition: pt-eval.h:756
void clear_variable(const std::string &name)
Definition: pt-eval.cc:2747
void visit_matrix(tree_matrix &)
Definition: pt-eval.cc:3803
bool is_variable(const std::string &name) const
Definition: pt-eval.cc:1866
bool is_class_constructor_executing(std::string &dispatch_class) const
Definition: pt-eval.cc:2566
void visit_octave_user_script(octave_user_script &)
Definition: pt-eval.cc:3530
std::string lookup_autoload(const std::string &nm) const
Definition: pt-eval.cc:4604
std::list< std::string > global_variable_names(void) const
Definition: pt-eval.cc:2845
void visit_if_clause(tree_if_clause &)
Definition: pt-eval.cc:3744
std::list< std::string > reverse_lookup_autoload(const std::string &nm) const
Definition: pt-eval.cc:4631
void visit_args_block_attribute_list(tree_args_block_attribute_list &)
Definition: pt-eval.cc:1262
bool in_debug_repl(void) const
Definition: pt-eval.cc:5003
bool maybe_push_echo_state_cleanup(void)
Definition: pt-eval.cc:4856
bool quiet_breakpoint_flag(void) const
Definition: pt-eval.h:645
octave_value do_who(int argc, const string_vector &argv, bool return_list, bool verbose=false)
Definition: pt-eval.cc:4719
void set_parser(const std::shared_ptr< push_parser > &parser)
Definition: pt-eval.h:164
int debug_user_code_line(void) const
Definition: pt-eval.cc:2487
symbol_info_list glob_symbol_info(const std::string &pattern) const
Definition: pt-eval.cc:4559
bool in_user_code(void) const
Definition: pt-eval.cc:2965
void clear_global_variable_pattern(const std::string &pattern)
Definition: pt-eval.cc:2785
bool m_break_on_next_stmt
Definition: pt-eval.h:950
void visit_argument_list(tree_argument_list &)
Definition: pt-eval.cc:1250
int m_breaking
Definition: pt-eval.h:988
void assign(const std::string &name, const octave_value &val=octave_value())
Definition: pt-eval.cc:2001
int current_column(void) const
Definition: pt-eval.cc:2482
void assignin(const std::string &context, const std::string &name, const octave_value &val=octave_value())
Definition: pt-eval.cc:2010
const std::list< octave_lvalue > * m_lvalue_list
Definition: pt-eval.h:896
void visit_statement(tree_statement &)
Definition: pt-eval.cc:3898
void bind_auto_fcn_vars(const string_vector &arg_names, const Matrix &ignored_outputs, int nargin, int nargout, bool takes_varargs, const octave_value_list &va_args)
Definition: pt-eval.cc:5224
int m_dbstep_flag
Definition: pt-eval.h:946
octave_value top_level_varval(const std::string &name) const
Definition: pt-eval.cc:1988
std::string backtrace_message(void) const
Definition: pt-eval.cc:2612
void clear_objects(void)
Definition: pt-eval.cc:2739
void dbupdown(int n, bool verbose=false)
Definition: pt-eval.cc:1434
octave_value evaluate_anon_fcn_handle(tree_anon_fcn_handle &afh)
Definition: pt-eval.cc:3329
void undefine_parameter_list(tree_parameter_list *param_list)
Definition: pt-eval.cc:2241
std::string check_autoload_file(const std::string &nm) const
Definition: pt-eval.cc:5241
octave_value max_stack_depth(const octave_value_list &args, int nargout)
Definition: pt-eval.cc:2705
void visit_identifier(tree_identifier &)
Definition: pt-eval.cc:3738
bool server_mode(void) const
Definition: pt-eval.h:187
void clear_symbol_regexp(const std::string &pattern)
Definition: pt-eval.cc:2834
@ ECHO_FUNCTIONS
Definition: pt-eval.h:75
int m_max_recursion_depth
Definition: pt-eval.h:927
void visit_octave_user_function_trailer(octave_user_function &)
Definition: pt-eval.cc:3710
void push_echo_state(int type, const std::string &file_name, int pos=1)
Definition: pt-eval.cc:4792
void visit_fcn_handle(tree_fcn_handle &)
Definition: pt-eval.cc:3843
int m_returning
Definition: pt-eval.h:994
octave_value_list execute_user_script(octave_user_script &user_script, int nargout, const octave_value_list &args)
Definition: pt-eval.cc:3487
void uwp_set_echo_state(bool state, const std::string &file_name, int pos)
Definition: pt-eval.cc:4815
void eval(std::shared_ptr< tree_statement_list > &stmt_list, bool interactive)
Definition: pt-eval.cc:980
symbol_info_list top_scope_symbol_info(void) const
Definition: pt-eval.cc:4577
octave_value_list evalin(const std::string &context, const std::string &try_code, int nargout)
Definition: pt-eval.cc:1162
bool is_defined(const tree_expression *expr) const
Definition: pt-eval.cc:1901
octave_value global_varval(const std::string &name) const
Definition: pt-eval.cc:1969
void top_level_assign(const std::string &name, const octave_value &val=octave_value())
Definition: pt-eval.cc:1994
void install_variable(const std::string &name, const octave_value &value, bool global)
Definition: pt-eval.cc:1958
void visit_binary_expression(tree_binary_expression &)
Definition: pt-eval.cc:1292
void set_echo_state(int type, const std::string &file_name, int pos)
Definition: pt-eval.cc:4806
std::string m_echo_file_name
Definition: pt-eval.h:964
std::list< std::string > variable_names(void) const
Definition: pt-eval.cc:2855
symbol_info_list regexp_symbol_info(const std::string &pattern) const
Definition: pt-eval.cc:4565
void set_auto_fcn_var(stack_frame::auto_var_type avt, const octave_value &val=octave_value())
Definition: pt-eval.cc:2198
void get_line_and_eval(void)
Definition: pt-eval.cc:639
int m_echo_file_pos
Definition: pt-eval.h:974
bool eval_decl_elt(tree_decl_elt *elt)
Definition: pt-eval.cc:2391
void maybe_set_echo_state(void)
Definition: pt-eval.cc:4824
call_stack m_call_stack
Definition: pt-eval.h:903
void clear_global_variable_regexp(const std::string &pattern)
Definition: pt-eval.cc:2790
void visit_decl_elt(tree_decl_elt &)
Definition: pt-eval.cc:2995
void execute_range_loop(const range< T > &rng, int line, octave_lvalue &ult, tree_statement_list *loop_body)
Definition: pt-eval.cc:3028
void parse_and_execute(const std::string &input, bool &incomplete_parse)
Definition: pt-eval.cc:575
std::shared_ptr< stack_frame > current_user_frame(void) const
Definition: pt-eval.h:453
void visit_parameter_list(tree_parameter_list &)
Definition: pt-eval.cc:3849
std::list< octave_lvalue > make_lvalue_list(tree_argument_list *)
Definition: pt-eval.cc:4781
void enter_debugger(const std::string &prompt="debug> ")
Definition: pt-eval.cc:1378
std::string m_whos_line_format
Definition: pt-eval.h:930
void visit_complex_for_command(tree_complex_for_command &)
Definition: pt-eval.cc:3243
std::shared_ptr< push_parser > get_parser(void)
Definition: pt-eval.h:159
octave_value whos_line_format(const octave_value_list &args, int nargout)
Definition: pt-eval.cc:4664
void global_assign(const std::string &name, const octave_value &val=octave_value())
Definition: pt-eval.cc:1981
octave_value make_fcn_handle(const std::string &nm)
Definition: pt-eval.cc:1605
void mlock(bool skip_first=false) const
Definition: pt-eval.cc:2662
int echo(void) const
Definition: pt-eval.h:827
bp_table m_bp_table
Definition: pt-eval.h:901
void visit_metaclass_query(tree_metaclass_query &)
Definition: pt-eval.cc:4412
void visit_compound_binary_expression(tree_compound_binary_expression &)
Definition: pt-eval.cc:1304
octave_value_list convert_return_list_to_const_vector(tree_parameter_list *ret_list, int nargout, const Matrix &ignored_outputs, const Cell &varargout)
Definition: pt-eval.cc:2325
std::string m_PS4
Definition: pt-eval.h:940
void do_unwind_protect_cleanup_code(tree_statement_list *list)
Definition: pt-eval.cc:4184
octave_value varval(const symbol_record &sym) const
Definition: pt-eval.cc:1941
void visit_switch_case_list(tree_switch_case_list &)
Definition: pt-eval.cc:4064
octave_value PS4(const octave_value_list &args, int nargout)
Definition: pt-eval.cc:5148
void push_stack_frame(const symbol_scope &scope)
Definition: pt-eval.cc:2444
std::string mfilename(const std::string &opt="") const
Definition: pt-eval.cc:540
bool m_debug_mode
Definition: pt-eval.h:910
bool silent_functions(void) const
Definition: pt-eval.h:608
std::string whos_line_format(void) const
Definition: pt-eval.h:619
void visit_prefix_expression(tree_prefix_expression &)
Definition: pt-eval.cc:3861
int continuing(void) const
Definition: pt-eval.h:779
profiler m_profiler
Definition: pt-eval.h:905
std::string get_dispatch_class(void) const
Definition: pt-eval.cc:2549
int breaking(void) const
Definition: pt-eval.h:770
void clear_variable_regexp(const std::string &pattern)
Definition: pt-eval.cc:2763
void visit_no_op_command(tree_no_op_command &)
Definition: pt-eval.cc:3821
octave_function * current_function(bool skip_first=false) const
Definition: pt-eval.cc:2519
void clear_variable_pattern(const std::string &pattern)
Definition: pt-eval.cc:2755
std::string m_index_type
Definition: pt-eval.h:1000
std::string current_function_name(bool skip_first=false) const
Definition: pt-eval.cc:2954
std::map< std::string, bool > m_echo_files
Definition: pt-eval.h:976
void visit_if_command_list(tree_if_command_list &)
Definition: pt-eval.cc:3771
virtual bool is_assignment_expression(void) const
Definition: pt-exp.h:74
virtual octave_value evaluate(tree_evaluator &tw, int nargout=1)=0
virtual std::string name(void) const
Definition: pt-exp.h:106
virtual tree_expression * dup(symbol_scope &scope) const =0
tree_expression * set_print_flag(bool print)
Definition: pt-exp.h:126
bool print_result(void) const
Definition: pt-exp.h:102
virtual octave_lvalue lvalue(tree_evaluator &)
Definition: pt-exp.cc:43
virtual bool is_identifier(void) const
Definition: pt-exp.h:70
virtual octave_value_list evaluate_n(tree_evaluator &tw, int nargout=1)=0
octave_value function(void)
Definition: pt-cmd.h:119
symbol_record symbol(void) const
Definition: pt-id.h:110
virtual bool is_black_hole(void) const
Definition: pt-id.h:75
octave_lvalue lvalue(tree_evaluator &tw)
Definition: pt-id.cc:69
octave_value evaluate(tree_evaluator &tw, int nargout=1)
Definition: pt-id.h:96
void accept(tree_walker &tw)
Definition: pt-select.h:117
tree_if_command_list * cmd_list(void)
Definition: pt-select.h:145
bool is_end_of_fcn_or_script(void) const
Definition: pt-cmd.h:81
bool varargs_only(void)
Definition: pt-misc.h:87
tree_parameter_list * dup(symbol_scope &scope) const
Definition: pt-misc.cc:69
bool takes_varargs(void) const
Definition: pt-misc.h:85
tree_expression * left_hand_side(void)
Definition: pt-loop.h:177
tree_statement_list * body(void)
Definition: pt-loop.h:183
tree_expression * control_expr(void)
Definition: pt-loop.h:179
tree_statement_list * body(void)
Definition: pt-spmd.h:59
void accept(tree_walker &tw)
Definition: pt-stmt.h:199
bool is_active_breakpoint(tree_evaluator &tw) const
Definition: pt-stmt.cc:103
int column(void) const
Definition: pt-stmt.cc:127
int line(void) const
Definition: pt-stmt.cc:119
bool is_expression(void) const
Definition: pt-stmt.h:80
tree_command * command(void)
Definition: pt-stmt.h:99
bool is_end_of_fcn_or_script(void) const
Definition: pt-stmt.cc:152
tree_expression * expression(void)
Definition: pt-stmt.h:101
void accept(tree_walker &tw)
Definition: pt-stmt.h:122
tree_expression * case_label(void)
Definition: pt-select.h:197
tree_switch_case_list * case_list(void)
Definition: pt-select.h:274
tree_expression * switch_value(void)
Definition: pt-select.h:272
tree_statement_list * cleanup(void)
Definition: pt-except.h:74
tree_statement_list * body(void)
Definition: pt-except.h:72
tree_identifier * identifier(void)
Definition: pt-except.h:70
tree_statement_list * body(void)
Definition: pt-except.h:139
tree_statement_list * cleanup(void)
Definition: pt-except.h:141
tree_expression * condition(void)
Definition: pt-loop.h:77
tree_statement_list * body(void)
Definition: pt-loop.h:79
virtual int column(void) const
Definition: pt.h:62
bool is_active_breakpoint(tree_evaluator &tw) const
Definition: pt.h:99
virtual int line(void) const
Definition: pt.h:60
virtual void accept(tree_walker &tw)=0
OCTAVE_BEGIN_NAMESPACE(octave) static octave_value daspk_fcn
OCTINTERP_API void print_usage(void)
Definition: defun-int.h:72
#define DEFMETHOD(name, interp_name, args_name, nargout_name, doc)
Macro to define a builtin method.
Definition: defun.h:111
void interpreter_try(unwind_protect &frame)
Definition: error.cc:2177
void error_with_id(const char *id, const char *fmt,...)
Definition: error.cc:1024
void warning(const char *fmt,...)
Definition: error.cc:1054
void warning_with_id(const char *id, const char *fmt,...)
Definition: error.cc:1069
void error(const char *fmt,...)
Definition: error.cc:979
void panic_if(bool cond)
Definition: error.h:512
#define panic_impossible()
Definition: error.h:508
void err_indexed_cs_list(void)
Definition: errwarn.cc:65
std::string canonicalize_file_name(const std::string &name)
Definition: file-ops.cc:744
std::string dir_sep_str(void)
Definition: file-ops.cc:240
std::string tilde_expand(const std::string &name)
Definition: file-ops.cc:283
octave::sys::time Vlast_prompt_time
Definition: input.cc:84
bool octave_completion_matches_called
Definition: input.cc:87
bool iskeyword(const std::string &s)
Definition: lex.cc:1359
bool isinf(double x)
Definition: lo-mappers.h:203
F77_RET_T const F77_DBLE const F77_DBLE * f
OCTINTERP_API octave_value_list call_mex(octave_mex_function &mex_fcn, const octave_value_list &args, int nargout_arg)
Definition: mex.cc:4787
class OCTAVE_API Matrix
Definition: mx-fwd.h:31
T octave_idx_type m
Definition: mx-inlines.cc:773
octave_idx_type n
Definition: mx-inlines.cc:753
octave_value_list feval(const char *name, const octave_value_list &args, int nargout)
Evaluate an Octave function (built-in or interpreted) and return the list of result values.
Definition: oct-parse.cc:10370
octave_value parse_fcn_file(interpreter &interp, const std::string &full_file, const std::string &file, const std::string &dir_name, const std::string &dispatch_type, const std::string &package_name, bool require_file, bool force_script, bool autoload, bool relative_lookup)
Definition: oct-parse.cc:9860
int release_unreferenced_dynamic_libraries(void)
Definition: oct-shlib.cc:70
static int input(yyscan_t yyscanner)
return octave_value(v1.char_array_value() . concat(v2.char_array_value(), ra_idx),((a1.is_sq_string()||a2.is_sq_string()) ? '\'' :'"'))
octave_value_list ovl(const OV_Args &... args)
Construct an octave_value_list with less typing.
Definition: ovl.h:211
#define octave_stdout
Definition: pager.h:314
static std::string get_operator_function_name(const std::string &name)
Definition: pt-eval.cc:1477
static octave_value end_value(const octave_value &value, octave_idx_type index_position, octave_idx_type num_indices)
Definition: pt-eval.cc:5021
sig_atomic_t octave_interrupt_state
Definition: quit.cc:38
static uint32_t state[624]
Definition: randmtzig.cc:193
static bool absolute_pathname(const std::string &s)
Definition: shared-fcns.h:148
static const char dir_sep_char
Definition: shared-fcns.h:90
static std::string dir_sep_chars
Definition: shared-fcns.h:96
static string_vector make_absolute(const string_vector &sv)
Definition: utils.cc:536
bool valid_identifier(const char *s)
Definition: utils.cc:78
void sleep(double seconds, bool do_graphics_events)
Definition: utils.cc:1532
std::string fcn_file_in_path(const std::string &name)
Definition: utils.cc:742
octave_value set_internal_variable(bool &var, const octave_value_list &args, int nargout, const char *nm)
Definition: variables.cc:584
F77_RET_T len
Definition: xerbla.cc:61