Mercurial > octave
changeset 25360:bc5f225bc578
eliminate some global accesses to the breakpoint table
* pt-eval.h, pt-eval.cc (tree_evaluator::m_bp_table): Store breakpoint
table in evaluator, not interpreter. Change all uses.
(tree_evaluator::get_user_code): Move here from interpreter.
(tree_evaluator::m_dbstep_flag, tree_evaluator::m_in_loop_command):
Now a member variables instead of static. Change all uses.
(tree_evaluator::reset_debug_state): Now a member function instead of
static. Change all uses. New overload that accepts mode directly.
(tree_evaluator::final_index_error): Now a member function instead of
static. Change all uses.
* bp-table.h, bp-table.cc (bp_table::m_evaluator): Store reference to
the evaluator in bp_table instead of a reference to the interpreter.
Change all uses.
* debug.cc (Fdbstep, Fdbcont, Fdbquit): Define with DEFMETHOD.
* octave-cmd.h, octave-cmd.cc (octave_cmd_exec::execute,
octave_cmd_eval::execute, octave_cmd_debug::execute): Accept reference
to interpreter as argument.
(octave_command_queue::execute_command_callback): Pass interpreter to
execute functions.
author | John W. Eaton <jwe@octave.org> |
---|---|
date | Tue, 08 May 2018 11:53:34 -0400 |
parents | b93522e36446 |
children | 82445187633e |
files | libgui/src/octave-cmd.cc libgui/src/octave-cmd.h libinterp/corefcn/debug.cc libinterp/corefcn/interpreter-private.cc libinterp/corefcn/interpreter.cc libinterp/corefcn/interpreter.h libinterp/octave-value/ov-classdef.cc libinterp/parse-tree/bp-table.cc libinterp/parse-tree/bp-table.h libinterp/parse-tree/pt-eval.cc libinterp/parse-tree/pt-eval.h |
diffstat | 11 files changed, 236 insertions(+), 213 deletions(-) [+] |
line wrap: on
line diff
--- a/libgui/src/octave-cmd.cc Fri May 04 16:18:30 2018 -0400 +++ b/libgui/src/octave-cmd.cc Tue May 08 11:53:34 2018 -0400 @@ -28,14 +28,16 @@ #include "octave-cmd.h" -#include "octave-qt-link.h" +#include "builtin-defun-decls.h" #include "cmd-edit.h" -#include "builtin-defun-decls.h" +#include "interpreter-private.h" +#include "interpreter.h" +#include "octave-qt-link.h" #include "utils.h" namespace octave { - void octave_cmd_exec::execute (void) + void octave_cmd_exec::execute (interpreter&) { std::string pending_input = command_editor::get_current_line (); @@ -45,7 +47,7 @@ command_editor::accept_line (); } - void octave_cmd_eval::execute (void) + void octave_cmd_eval::execute (interpreter&) { QString function_name = m_info.fileName (); function_name.chop (m_info.suffix ().length () + 1); @@ -73,24 +75,24 @@ command_editor::accept_line (); } - void octave_cmd_debug::execute (void) + void octave_cmd_debug::execute (interpreter& interp) { if (m_cmd == "step") { F__db_next_breakpoint_quiet__ (ovl (m_suppress_dbg_location)); - Fdbstep (); + Fdbstep (interp); } else if (m_cmd == "cont") { F__db_next_breakpoint_quiet__ (ovl (m_suppress_dbg_location)); - Fdbcont (); + Fdbcont (interp); } else if (m_cmd == "quit") - Fdbquit (); + Fdbquit (interp); else { F__db_next_breakpoint_quiet__ (ovl (m_suppress_dbg_location)); - Fdbstep (ovl (m_cmd.toStdString ())); + Fdbstep (interp, ovl (m_cmd.toStdString ())); } command_editor::interrupt (true); @@ -126,7 +128,13 @@ repost = true; // not empty, repost at end m_queue_mutex.unlock (); - cmd->execute (); + // FIXME: Could we store a reference to the interpreter in the + // octave_command_queue object? If so, where is the proper + // place to initialize that? + + interpreter& interp = __get_interpreter__ ("octave_command_queue::execute_command_callback"); + + cmd->execute (interp); delete cmd; }
--- a/libgui/src/octave-cmd.h Fri May 04 16:18:30 2018 -0400 +++ b/libgui/src/octave-cmd.h Tue May 08 11:53:34 2018 -0400 @@ -34,6 +34,8 @@ namespace octave { + class interpreter; + class octave_cmd { public: @@ -42,7 +44,7 @@ virtual ~octave_cmd (void) = default; - virtual void execute (void) { } + virtual void execute (interpreter&) { } }; class octave_cmd_exec : public octave_cmd @@ -51,7 +53,7 @@ octave_cmd_exec (const QString& cmd) : octave_cmd () { m_cmd = cmd; } - void execute (void); + void execute (interpreter& interp); protected: @@ -64,7 +66,7 @@ octave_cmd_eval (const QFileInfo& info) : octave_cmd () { m_info = info; } - void execute (void); + void execute (interpreter& interp); protected: @@ -78,7 +80,7 @@ octave_cmd_debug (const QString& cmd, bool suppress_location) : octave_cmd_exec (cmd), m_suppress_dbg_location (suppress_location) { } - void execute (void); + void execute (interpreter& interp); protected:
--- a/libinterp/corefcn/debug.cc Fri May 04 16:18:30 2018 -0400 +++ b/libinterp/corefcn/debug.cc Tue May 08 11:53:34 2018 -0400 @@ -176,7 +176,9 @@ std::string condition = ""; octave_value retval; - octave::bp_table& bptab = interp.get_bp_table (); + octave::tree_evaluator& tw = interp.get_evaluator (); + + octave::bp_table& bptab = tw.get_bp_table (); if (args.length() >= 1 && ! args(0).isstruct ()) { @@ -302,7 +304,9 @@ int nargin = args.length (); - octave::bp_table& bptab = interp.get_bp_table (); + octave::tree_evaluator& tw = interp.get_evaluator (); + + octave::bp_table& bptab = tw.get_bp_table (); bptab.parse_dbfunction_params ("dbclear", args, symbol_name, lines, dummy); @@ -374,7 +378,9 @@ octave::bp_table::fname_bp_map bp_list; std::string symbol_name; - octave::bp_table& bptab = interp.get_bp_table (); + octave::tree_evaluator& tw = interp.get_evaluator (); + + octave::bp_table& bptab = tw.get_bp_table (); if (nargin == 1) { @@ -390,7 +396,7 @@ /* if (Vdebugging) { - octave_user_code *dbg_fcn = interp.get_user_code (); + octave_user_code *dbg_fcn = tw.get_user_code (); if (dbg_fcn) { symbol_name = dbg_fcn->name (); @@ -538,7 +544,9 @@ @seealso{dbstack, dblist, dbstatus, dbcont, dbstep, dbup, dbdown} @end deftypefn */) { - octave_user_code *dbg_fcn = interp.get_user_code (); + octave::tree_evaluator& tw = interp.get_evaluator (); + + octave_user_code *dbg_fcn = tw.get_user_code (); if (! dbg_fcn) { @@ -635,10 +643,12 @@ string_vector argv = args.make_argv ("dbtype"); + octave::tree_evaluator& tw = interp.get_evaluator (); + switch (args.length ()) { case 0: // dbtype - dbg_fcn = interp.get_user_code (); + dbg_fcn = tw.get_user_code (); if (! dbg_fcn) error ("dbtype: must be inside a user function to give no arguments to dbtype\n"); @@ -656,7 +666,7 @@ if (ind != std::string::npos) // (dbtype start:end) { - dbg_fcn = interp.get_user_code (); + dbg_fcn = tw.get_user_code (); if (dbg_fcn) { @@ -686,7 +696,7 @@ if (line == 0) // (dbtype func) { - dbg_fcn = interp.get_user_code (arg); + dbg_fcn = tw.get_user_code (arg); if (! dbg_fcn) error ("dbtype: function <%s> not found\n", arg.c_str ()); @@ -699,7 +709,7 @@ if (line <= 0) error ("dbtype: start and end lines must be >= 1\n"); - dbg_fcn = interp.get_user_code (); + dbg_fcn = tw.get_user_code (); if (dbg_fcn) do_dbtype (octave_stdout, dbg_fcn->fcn_file_name (), @@ -711,7 +721,7 @@ case 2: // (dbtype func start:end) || (dbtype func start) { - dbg_fcn = interp.get_user_code (argv[1]); + dbg_fcn = tw.get_user_code (argv[1]); if (! dbg_fcn) error ("dbtype: function <%s> not found\n", argv[1].c_str ()); @@ -784,7 +794,9 @@ error ("dblist: N must be a non-negative integer"); } - octave_user_code *dbg_fcn = interp.get_user_code (); + octave::tree_evaluator& tw = interp.get_evaluator (); + + octave_user_code *dbg_fcn = tw.get_user_code (); if (! dbg_fcn) error ("dblist: must be inside a user function to use dblist\n"); @@ -1050,8 +1062,8 @@ return ovl (); } -DEFUN (dbstep, args, , - doc: /* -*- texinfo -*- +DEFMETHOD (dbstep, interp, args, , + doc: /* -*- texinfo -*- @deftypefn {} {} dbstep @deftypefnx {} {} dbstep @var{n} @deftypefnx {} {} dbstep in @@ -1081,6 +1093,8 @@ if (nargin > 1) print_usage (); + octave::tree_evaluator& tw = interp.get_evaluator (); + if (nargin == 1) { std::string arg = args(0).xstring_value ("dbstep: input argument must be a string"); @@ -1090,14 +1104,14 @@ Vdebugging = false; Vtrack_line_num = true; - octave::tree_evaluator::dbstep_flag = -1; + tw.set_dbstep_flag (-1); } else if (arg == "out") { Vdebugging = false; Vtrack_line_num = true; - octave::tree_evaluator::dbstep_flag = -2; + tw.set_dbstep_flag (-2); } else { @@ -1109,7 +1123,7 @@ Vdebugging = false; Vtrack_line_num = true; - octave::tree_evaluator::dbstep_flag = n; + tw.set_dbstep_flag (n); } } else @@ -1117,7 +1131,7 @@ Vdebugging = false; Vtrack_line_num = true; - octave::tree_evaluator::dbstep_flag = 1; + tw.set_dbstep_flag (1); } return ovl (); @@ -1125,8 +1139,8 @@ DEFALIAS (dbnext, dbstep); -DEFUN (dbcont, args, , - doc: /* -*- texinfo -*- +DEFMETHOD (dbcont, interp, args, , + doc: /* -*- texinfo -*- @deftypefn {} {} dbcont Leave command-line debugging mode and continue code execution normally. @seealso{dbstep, dbquit} @@ -1141,13 +1155,15 @@ Vdebugging = false; Vtrack_line_num = true; - octave::tree_evaluator::reset_debug_state (); + octave::tree_evaluator& tw = interp.get_evaluator (); + + tw.reset_debug_state (); return ovl (); } -DEFUN (dbquit, args, , - doc: /* -*- texinfo -*- +DEFMETHOD (dbquit, interp, args, , + doc: /* -*- texinfo -*- @deftypefn {} {} dbquit Quit debugging mode immediately without further code execution and return to the Octave prompt. @@ -1164,8 +1180,9 @@ Vdebugging = false; - octave::tree_evaluator::reset_debug_state (); - octave::tree_evaluator::debug_mode = false; + octave::tree_evaluator& tw = interp.get_evaluator (); + + tw.reset_debug_state (false); throw octave::interrupt_exception ();
--- a/libinterp/corefcn/interpreter-private.cc Fri May 04 16:18:30 2018 -0400 +++ b/libinterp/corefcn/interpreter-private.cc Tue May 08 11:53:34 2018 -0400 @@ -114,9 +114,9 @@ bp_table& __get_bp_table__ (const std::string& who) { - interpreter& interp = __get_interpreter__ (who); + tree_evaluator& tw = __get_evaluator__ (who); - return interp.get_bp_table (); + return tw.get_bp_table (); } call_stack& __get_call_stack__ (const std::string& who)
--- a/libinterp/corefcn/interpreter.cc Fri May 04 16:18:30 2018 -0400 +++ b/libinterp/corefcn/interpreter.cc Tue May 08 11:53:34 2018 -0400 @@ -29,7 +29,6 @@ #include "cmd-edit.h" #include "cmd-hist.h" -#include "file-ops.h" #include "file-stat.h" #include "fpucw-wrappers.h" #include "lo-blas-proto.h" @@ -332,7 +331,6 @@ m_type_info (), m_symbol_table (), m_evaluator (*this), - m_bp_table (*this), m_stream_list (*this), m_child_list (), m_url_handle_manager (), @@ -941,7 +939,7 @@ parser.reset (); if (m_symbol_table.at_top_level ()) - tree_evaluator::reset_debug_state (); + m_evaluator.reset_debug_state (); retval = parser.run (); @@ -1182,46 +1180,6 @@ return m_evaluator.get_profiler (); } - // Return a pointer to the user-defined function FNAME. If FNAME is empty, - // search backward for the first user-defined function in the - // current call stack. - - octave_user_code * - interpreter::get_user_code (const std::string& fname) - { - octave_user_code *user_code = nullptr; - - if (fname.empty ()) - { - call_stack& cs = get_call_stack (); - - user_code = cs.debug_user_code (); - } - else - { - std::string name = fname; - - if (sys::file_ops::dir_sep_char () != '/' && name[0] == '@') - { - auto beg = name.begin () + 2; // never have @/method - auto end = name.end () - 1; // never have trailing '/' - std::replace (beg, end, '/', sys::file_ops::dir_sep_char ()); - } - - size_t name_len = name.length (); - - if (name_len > 2 && name.substr (name_len-2) == ".m") - name = name.substr (0, name_len-2); - - octave_value fcn = m_symbol_table.find_function (name); - - if (fcn.is_defined () && fcn.is_user_code ()) - user_code = fcn.user_code_value (); - } - - return user_code; - } - void interpreter::mlock (void) { call_stack& cs = get_call_stack ();
--- a/libinterp/corefcn/interpreter.h Fri May 04 16:18:30 2018 -0400 +++ b/libinterp/corefcn/interpreter.h Tue May 08 11:53:34 2018 -0400 @@ -31,7 +31,6 @@ #include "quit.h" #include "str-vec.h" -#include "bp-table.h" #include "dynamic-ld.h" #include "environment.h" #include "gtk-manager.h" @@ -53,8 +52,6 @@ // TRUE means we've processed all the init code and we are good to go. extern OCTINTERP_API bool octave_initialized; -class octave_user_code; - namespace octave { class profiler; @@ -181,11 +178,6 @@ symbol_scope get_current_scope (void); symbol_scope require_current_scope (const std::string& who); - bp_table& get_bp_table (void) - { - return m_bp_table; - } - call_stack& get_call_stack (void); profiler& get_profiler (void); @@ -211,8 +203,6 @@ return m_gtk_manager; } - octave_user_code * get_user_code (const std::string& fname = ""); - void mlock (void); void munlock (const std::string& nm); @@ -269,8 +259,6 @@ tree_evaluator m_evaluator; - bp_table m_bp_table; - stream_list m_stream_list; child_list m_child_list;
--- a/libinterp/octave-value/ov-classdef.cc Fri May 04 16:18:30 2018 -0400 +++ b/libinterp/octave-value/ov-classdef.cc Tue May 08 11:53:34 2018 -0400 @@ -1139,7 +1139,7 @@ octave_function * function_value (bool = false) { return this; } octave_value_list - call (octave::tree_evaluator&, int nargout, const octave_value_list& idx) + call (octave::tree_evaluator& tw, int nargout, const octave_value_list& idx) { octave_value_list retval; @@ -1163,12 +1163,11 @@ error ("`%s' is not a direct superclass of `%s'", cname.c_str (), ctx.get_name ().c_str ()); - if (! is_constructed_object (mname)) + if (! is_constructed_object (tw, mname)) error ("cannot call superclass constructor with variable `%s'", mname.c_str ()); - octave::symbol_scope scope - = octave::__require_current_scope__ ("octave_classdef_superclass_ref::call"); + octave::symbol_scope scope = tw.get_current_scope (); octave_value sym = scope.varval (mname); @@ -1211,10 +1210,10 @@ } private: - bool is_constructed_object (const std::string nm) + bool is_constructed_object (octave::tree_evaluator& tw, + const std::string& nm) { - octave::call_stack& cs - = octave::__get_call_stack__ ("octave_classdef_superclass_ref::is_constructed_object"); + octave::call_stack& cs = tw.get_call_stack (); octave_function *of = cs.current (); @@ -3773,8 +3772,7 @@ if (pos == std::string::npos) { - octave::symbol_table& symtab - = octave::__get_symbol_table__ ("cdef_manager::find_class"); + octave::symbol_table& symtab = m_interpreter.get_symbol_table (); ov_cls = symtab.find (name); } @@ -3851,8 +3849,7 @@ } else { - octave::load_path& lp - = octave::__get_load_path__ ("cdef_manager::find_package"); + octave::load_path& lp = m_interpreter.get_load_path (); if (load_if_not_found && lp.find_package (name)) {
--- a/libinterp/parse-tree/bp-table.cc Fri May 04 16:18:30 2018 -0400 +++ b/libinterp/parse-tree/bp-table.cc Tue May 08 11:53:34 2018 -0400 @@ -341,8 +341,7 @@ { // It was a line number. Get function name from debugger. if (Vdebugging) - symbol_name - = m_interpreter.get_user_code ()->profiler_name (); + symbol_name = m_evaluator.get_user_code ()->profiler_name (); else error ("%s: function name must come before line number " "and 'if'", who); @@ -561,7 +560,7 @@ const bp_table::intmap& line, const std::string& condition) { - octave_user_code *main_fcn = m_interpreter.get_user_code (fname); + octave_user_code *main_fcn = m_evaluator.get_user_code (fname); if (! main_fcn) error ("add_breakpoint: unable to find function '%s'\n", fname.c_str ()); @@ -659,7 +658,7 @@ } else { - octave_user_code *dbg_fcn = m_interpreter.get_user_code (fname); + octave_user_code *dbg_fcn = m_evaluator.get_user_code (fname); if (! dbg_fcn) error ("remove_breakpoint: unable to find function %s\n", @@ -701,7 +700,7 @@ { intmap retval; - octave_user_code *dbg_fcn = m_interpreter.get_user_code (fname); + octave_user_code *dbg_fcn = m_evaluator.get_user_code (fname); if (dbg_fcn) { @@ -771,7 +770,7 @@ if (fname_list.empty () || find_bkpt_list (fname_list, bp_fname) != "") { - octave_user_code *dbg_fcn = m_interpreter.get_user_code (bp_fname); + octave_user_code *dbg_fcn = m_evaluator.get_user_code (bp_fname); if (dbg_fcn) { @@ -934,8 +933,8 @@ octave_user_code * get_user_code (const std::string& fname) { - interpreter& interp = __get_interpreter__ ("get_user_code"); + tree_evaluator& tw = __get_evaluator__ ("get_user_code"); - return interp.get_user_code (fname); + return tw.get_user_code (fname); } }
--- a/libinterp/parse-tree/bp-table.h Fri May 04 16:18:30 2018 -0400 +++ b/libinterp/parse-tree/bp-table.h Tue May 08 11:53:34 2018 -0400 @@ -36,7 +36,7 @@ namespace octave { - class interpreter; + class tree_evaluator; struct bp_type { @@ -51,8 +51,8 @@ { public: - bp_table (interpreter& interp) - : m_interpreter (interp), m_bp_set (), m_errors_that_stop (), + bp_table (tree_evaluator& tw) + : m_evaluator (tw), m_bp_set (), m_errors_that_stop (), m_caught_that_stop (), m_warnings_that_stop () { } @@ -130,7 +130,7 @@ typedef std::set<std::string>::const_iterator const_bp_set_iterator; typedef std::set<std::string>::iterator bp_set_iterator; - interpreter& m_interpreter; + tree_evaluator& m_evaluator; // Set of function (.m file) names containing at least one breakpoint. std::set<std::string> m_bp_set;
--- a/libinterp/parse-tree/pt-eval.cc Fri May 04 16:18:30 2018 -0400 +++ b/libinterp/parse-tree/pt-eval.cc Tue May 08 11:53:34 2018 -0400 @@ -32,6 +32,7 @@ #include <typeinfo> #include "cmd-edit.h" +#include "file-ops.h" #include "oct-env.h" #include "bp-table.h" @@ -60,8 +61,6 @@ namespace octave { - int tree_evaluator::dbstep_flag = 0; - size_t tree_evaluator::current_frame = 0; bool tree_evaluator::debug_mode = false; @@ -71,8 +70,6 @@ tree_evaluator::stmt_list_type tree_evaluator::statement_context = tree_evaluator::other; - bool tree_evaluator::in_loop_command = false; - // Normal evaluator. void @@ -342,7 +339,7 @@ if (debug_mode) do_breakpoint (cmd.is_breakpoint (true)); - if (in_loop_command) + if (m_in_loop_command) tree_break_command::breaking = 1; else error ("break must appear in a loop in the same file as loop command"); @@ -424,7 +421,7 @@ if (debug_mode) do_breakpoint (cmd.is_breakpoint (true)); - if (in_loop_command) + if (m_in_loop_command) tree_continue_command::continuing = 1; } @@ -438,11 +435,17 @@ void tree_evaluator::reset_debug_state (void) { - bp_table& bptab = __get_bp_table__ ("tree_evaluator::reset_debug_state"); - - debug_mode = bptab.have_breakpoints () || Vdebugging; - - dbstep_flag = 0; + debug_mode = m_bp_table.have_breakpoints () || Vdebugging; + + m_dbstep_flag = 0; + } + + void + tree_evaluator::reset_debug_state (bool mode) + { + debug_mode = mode; + + m_dbstep_flag = 0; } Matrix @@ -692,6 +695,44 @@ return symtab.current_scope (); } + // Return a pointer to the user-defined function FNAME. If FNAME is empty, + // search backward for the first user-defined function in the + // current call stack. + + octave_user_code * + tree_evaluator::get_user_code (const std::string& fname) + { + octave_user_code *user_code = nullptr; + + if (fname.empty ()) + user_code = m_call_stack.debug_user_code (); + else + { + std::string name = fname; + + if (sys::file_ops::dir_sep_char () != '/' && name[0] == '@') + { + auto beg = name.begin () + 2; // never have @/method + auto end = name.end () - 1; // never have trailing '/' + std::replace (beg, end, '/', sys::file_ops::dir_sep_char ()); + } + + size_t name_len = name.length (); + + if (name_len > 2 && name.substr (name_len-2) == ".m") + name = name.substr (0, name_len-2); + + symbol_table& symtab = m_interpreter.get_symbol_table (); + + octave_value fcn = symtab.find_function (name); + + if (fcn.is_defined () && fcn.is_user_code ()) + user_code = fcn.user_code_value (); + } + + return user_code; + } + void tree_evaluator::visit_decl_command (tree_decl_command& cmd) { @@ -796,9 +837,9 @@ unwind_protect frame; - frame.protect_var (in_loop_command); - - in_loop_command = true; + frame.protect_var (m_in_loop_command); + + m_in_loop_command = true; tree_expression *expr = cmd.control_expr (); @@ -931,9 +972,9 @@ unwind_protect frame; - frame.protect_var (in_loop_command); - - in_loop_command = true; + frame.protect_var (m_in_loop_command); + + m_in_loop_command = true; tree_expression *expr = cmd.control_expr (); @@ -1151,49 +1192,6 @@ } } - // Final step of processing an indexing error. Add the name of the - // variable being indexed, if any, then issue an error. (Will this also - // be needed by pt-lvalue, which calls subsref?) - - static void - final_index_error (index_exception& e, - const tree_expression *expr) - { - std::string extra_message; - - // FIXME: make this a member function for direct access to symbol - // table and scope? - - symbol_scope scope - = __require_current_scope__ ("final_index_error"); - - symbol_record::context_id context = scope.current_context (); - - if (expr->is_identifier () - && dynamic_cast<const tree_identifier *> (expr)->is_variable (context)) - { - std::string var = expr->name (); - - e.set_var (var); - - symbol_table& symtab = __get_symbol_table__ ("final_index_error"); - - octave_value fcn = symtab.find_function (var); - - if (fcn.is_function ()) - { - octave_function *fp = fcn.function_value (); - - if (fp && fp->name () == var) - extra_message = " (note: variable '" + var + "' shadows function)"; - } - } - - std::string msg = e.message () + extra_message; - - error_with_id (e.err_id (), msg.c_str ()); - } - // Unlike Matlab, which does not allow the result of a function call // or array indexing expression to be further indexed, Octave attempts // to handle arbitrary index expressions. For example, Octave allows @@ -2156,7 +2154,7 @@ reset_debug_state (); } else if (statement_context == function || statement_context == script - || in_loop_command) + || m_in_loop_command) tree_return_command::returning = 1; } @@ -2665,9 +2663,9 @@ unwind_protect frame; - frame.protect_var (in_loop_command); - - in_loop_command = true; + frame.protect_var (m_in_loop_command); + + m_in_loop_command = true; tree_expression *expr = cmd.condition (); @@ -2715,9 +2713,9 @@ unwind_protect frame; - frame.protect_var (in_loop_command); - - in_loop_command = true; + frame.protect_var (m_in_loop_command); + + m_in_loop_command = true; tree_expression *expr = cmd.condition (); int until_line = cmd.line (); @@ -2779,14 +2777,14 @@ } void - tree_evaluator::do_breakpoint (tree_statement& stmt) const + tree_evaluator::do_breakpoint (tree_statement& stmt) { do_breakpoint (stmt.is_breakpoint (true), stmt.is_end_of_fcn_or_script ()); } void tree_evaluator::do_breakpoint (bool is_breakpoint, - bool is_end_of_fcn_or_script) const + bool is_end_of_fcn_or_script) { bool break_on_this_statement = false; @@ -2802,15 +2800,15 @@ { break_on_this_statement = true; - dbstep_flag = 0; + m_dbstep_flag = 0; current_frame = m_call_stack.current_frame (); } - else if (dbstep_flag > 0) + else if (m_dbstep_flag > 0) { if (m_call_stack.current_frame () == current_frame) { - if (dbstep_flag == 1 || is_end_of_fcn_or_script) + if (m_dbstep_flag == 1 || is_end_of_fcn_or_script) { // We get here if we are doing a "dbstep" or a "dbstep N" and the // count has reached 1 so that we must stop and return to debug @@ -2820,17 +2818,17 @@ break_on_this_statement = true; - dbstep_flag = 0; + m_dbstep_flag = 0; } else { // Executing "dbstep N". Decrease N by one and continue. - dbstep_flag--; + m_dbstep_flag--; } } - else if (dbstep_flag == 1 + else if (m_dbstep_flag == 1 && m_call_stack.current_frame () < current_frame) { // We stepped out from the end of a function. @@ -2839,20 +2837,20 @@ break_on_this_statement = true; - dbstep_flag = 0; + m_dbstep_flag = 0; } } - else if (dbstep_flag == -1) + else if (m_dbstep_flag == -1) { // We get here if we are doing a "dbstep in". break_on_this_statement = true; - dbstep_flag = 0; + m_dbstep_flag = 0; current_frame = m_call_stack.current_frame (); } - else if (dbstep_flag == -2) + else if (m_dbstep_flag == -2) { // We get here if we are doing a "dbstep out". Check for end of // function and whether the current frame is the same as the @@ -2862,7 +2860,7 @@ if (is_end_of_fcn_or_script && m_call_stack.current_frame () == current_frame) - dbstep_flag = -1; + m_dbstep_flag = -1; } if (break_on_this_statement) @@ -3226,6 +3224,45 @@ octave_stdout << prefix << elt << std::endl; } } + + // Final step of processing an indexing error. Add the name of the + // variable being indexed, if any, then issue an error. (Will this also + // be needed by pt-lvalue, which calls subsref?) + + void tree_evaluator::final_index_error (index_exception& e, + const tree_expression *expr) + { + std::string extra_message; + + symbol_scope scope = get_current_scope (); + + symbol_record::context_id ctxt = scope.current_context (); + + if (expr->is_identifier () + && dynamic_cast<const tree_identifier *> (expr)->is_variable (ctxt)) + { + std::string var = expr->name (); + + e.set_var (var); + + symbol_table& symtab = m_interpreter.get_symbol_table (); + + octave_value fcn = symtab.find_function (var); + + if (fcn.is_function ()) + { + octave_function *fp = fcn.function_value (); + + if (fp && fp->name () == var) + extra_message + = " (note: variable '" + var + "' shadows function)"; + } + } + + std::string msg = e.message () + extra_message; + + error_with_id (e.err_id (), msg.c_str ()); + } } DEFMETHOD (max_recursion_depth, interp, args, nargout,
--- a/libinterp/parse-tree/pt-eval.h Fri May 04 16:18:30 2018 -0400 +++ b/libinterp/parse-tree/pt-eval.h Tue May 08 11:53:34 2018 -0400 @@ -30,6 +30,7 @@ #include <stack> #include <string> +#include "bp-table.h" #include "call-stack.h" #include "ov.h" #include "ovl.h" @@ -37,6 +38,8 @@ #include "pt-exp.h" #include "pt-walk.h" +class octave_user_code; + namespace octave { class symbol_scope; @@ -126,11 +129,11 @@ : m_interpreter (interp), m_result_type (RT_UNDEFINED), m_expr_result_value (), m_expr_result_value_list (), m_lvalue_list_stack (), m_nargout_stack (), - m_call_stack (interp), m_profiler (), + m_bp_table (*this), m_call_stack (interp), m_profiler (), m_max_recursion_depth (256), m_silent_functions (false), - m_string_fill_char (' '), m_PS4 ("+ "), m_echo (ECHO_OFF), - m_echo_state (false), m_echo_file_name (), m_echo_file_pos (1), - m_echo_files () + m_string_fill_char (' '), m_PS4 ("+ "), m_dbstep_flag (0), + m_echo (ECHO_OFF), m_echo_state (false), m_echo_file_name (), + m_echo_file_pos (1), m_echo_files (), m_in_loop_command (false) { } // No copying! @@ -238,13 +241,11 @@ bool statement_printing_enabled (void); - static void reset_debug_state (void); + void reset_debug_state (void); - // If > 0, stop executing at the (N-1)th stopping point, counting - // from the the current execution point in the current frame. - // - // If < 0, stop executing at the next possible stopping point. - static int dbstep_flag; + void reset_debug_state (bool mode); + + void set_dbstep_flag (int step) { m_dbstep_flag = step; } // The number of the stack frame we are currently debugging. static size_t current_frame; @@ -264,9 +265,6 @@ // The context for the current evaluation. static stmt_list_type statement_context; - // TRUE means we are evaluating some kind of looping construct. - static bool in_loop_command; - Matrix ignored_fcn_outputs (void) const; bool isargout (int nargout, int iout) const; @@ -368,12 +366,18 @@ bool switch_case_label_matches (tree_switch_case *expr, const octave_value& val); + interpreter& get_interpreter (void) { return m_interpreter; } + + bp_table& get_bp_table (void) { return m_bp_table; } + call_stack& get_call_stack (void) { return m_call_stack; } profiler& get_profiler (void) { return m_profiler; } symbol_scope get_current_scope (void); + octave_user_code * get_user_code (const std::string& fname = ""); + int max_recursion_depth (void) const { return m_max_recursion_depth; } int max_recursion_depth (int n) @@ -445,10 +449,10 @@ bool maybe_push_echo_state_cleanup (void); - void do_breakpoint (tree_statement& stmt) const; + void do_breakpoint (tree_statement& stmt); void do_breakpoint (bool is_breakpoint, - bool is_end_of_fcn_or_script = false) const; + bool is_end_of_fcn_or_script = false); virtual octave_value do_keyboard (const octave_value_list& args = octave_value_list ()) const; @@ -481,6 +485,8 @@ void echo_code (size_t line); + void final_index_error (index_exception& e, const tree_expression *expr); + interpreter& m_interpreter; result_type m_result_type; @@ -491,6 +497,8 @@ value_stack<int> m_nargout_stack; + bp_table m_bp_table; + call_stack m_call_stack; profiler m_profiler; @@ -509,6 +517,12 @@ // String printed before echoed commands (enabled by --echo-commands). std::string m_PS4; + // If > 0, stop executing at the (N-1)th stopping point, counting + // from the the current execution point in the current frame. + // + // If < 0, stop executing at the next possible stopping point. + int m_dbstep_flag; + // Echo commands as they are executed? // // 1 ==> echo commands read from script files @@ -527,6 +541,9 @@ size_t m_echo_file_pos; std::map<std::string, bool> m_echo_files; + + // TRUE means we are evaluating some kind of looping construct. + bool m_in_loop_command; }; }