Mercurial > octave
changeset 27873:020d0e8f7ac6
reafactor mlock, munlock, and mislocked functions
* interpreter.h, interpreter.cc (interpreter::mlock,
interpreter::munlock, interpreter::mislocked): Revamp. Provide
versions that act on current function in the call stack (possibly
skipping the first found) and versions of munlock and mislocked that
accept function names.
* call-stack.h, call-stack.cc (call_stack::current): Delete.
(call_stack::current_function): New function. Change all uses of
call_stack::current to use this function instead.
(call_stack::caller): Delete.
(call_stack::caller_function): New function, define in terms of
current_function. Change all uses of call_stack::caller to use this
function instead.
(call_stack::mlock): Delete.
* ov-fcn.h (octave_function::islocked): Now const.
* pt-eval.h, pt-eval.cc (tree_evaluator::current_function,
tree_evaluator::current_function_name, tree_evaluator::mlock):
New argument, SKIP_FIRST.
(tree_evaluator::munlock, tree_evaluator::mislocked): New functions.
* variables.cc (Fmlock, Fmunlock, Fmislocked): Simplify. Decode
arguments and call interpreter fucntions.
author | John W. Eaton <jwe@octave.org> |
---|---|
date | Tue, 17 Dec 2019 12:26:09 -0500 |
parents | 103e20bd439f |
children | 07efc76a47a9 |
files | libinterp/corefcn/call-stack.cc libinterp/corefcn/call-stack.h libinterp/corefcn/interpreter.cc libinterp/corefcn/interpreter.h libinterp/corefcn/variables.cc libinterp/octave-value/ov-fcn.h libinterp/parse-tree/pt-eval.cc libinterp/parse-tree/pt-eval.h libinterp/parse-tree/pt-fcn-handle.cc |
diffstat | 9 files changed, 148 insertions(+), 120 deletions(-) [+] |
line wrap: on
line diff
--- a/libinterp/corefcn/call-stack.cc Thu Dec 26 08:11:00 2019 -0800 +++ b/libinterp/corefcn/call-stack.cc Tue Dec 17 12:26:09 2019 -0500 @@ -64,6 +64,29 @@ push (symbol_scope ("top scope")); } + octave_function * call_stack::current_function (bool skip_first) const + { + if (m_cs.empty ()) + error ("current_function: call stack is empty"); + + octave_function *fcn = nullptr; + + size_t idx = size (); + + if (idx > 1 && skip_first) + --idx; + + while (--idx) + { + fcn = m_cs[idx]->function (); + + if (fcn) + break; + } + + return fcn; + } + int call_stack::current_line (void) const { int retval = -1; @@ -275,7 +298,7 @@ { dispatch_class = ""; - octave_function *f = current (); + octave_function *f = current_function (); bool retval = (f && f->is_class_method ()); @@ -289,7 +312,7 @@ { dispatch_class = ""; - octave_function *f = current (); + octave_function *f = current_function (); bool retval = (f && f->is_class_constructor ()); @@ -720,41 +743,6 @@ pop (); } - void call_stack::mlock (void) const - { - if (m_cs.empty ()) - error ("mlock: call stack is empty"); - - octave_function *fcn = nullptr; - - size_t idx = size (); - - while (--idx) - { - const stack_frame *elt = m_cs[idx]; - fcn = elt->function (); - - if (fcn) - { - if (fcn->is_builtin_function ()) - { - if (fcn->name () == "mlock") - continue; - - warning ("mlock: locking built-in function has no effect"); - return; - } - - break; - } - } - - if (! fcn) - error ("mlock: invalid use outside a function"); - - fcn->lock (); - } - symbol_info_list call_stack::all_variables (void) { return m_cs[m_curr_frame]->all_variables (); @@ -1095,12 +1083,12 @@ { if (verbose) { - std::string caller_function_name; - octave_function *caller_function = caller (); - if (caller_function) - caller_function_name = caller_function->name (); + std::string caller_fcn_name; + octave_function *caller_fcn = caller_function (); + if (caller_fcn) + caller_fcn_name = caller_fcn->name (); - return symbol_stats.map_value (caller_function_name, 1); + return symbol_stats.map_value (caller_fcn_name, 1); } else return Cell (string_vector (symbol_names));
--- a/libinterp/corefcn/call-stack.h Thu Dec 26 08:11:00 2019 -0800 +++ b/libinterp/corefcn/call-stack.h Tue Dec 17 12:26:09 2019 -0500 @@ -62,18 +62,16 @@ call_stack (tree_evaluator& evaluator); - // Current function (top of stack). - octave_function * current (void) const - { - octave_function *retval = nullptr; + // Lock current function. Look for the first stack frame that is + // a function. If SKIP_FIST is true, then skip the first frame. + // That allows functions like Fmlock to find and lock the calling + // function instead of locking Fmlock itself. - if (! m_cs.empty ()) - { - const stack_frame *elt = m_cs[m_curr_frame]; - retval = elt->function (); - } + octave_function * current_function (bool skip_first = false) const; - return retval; + octave_function * caller_function (void) const + { + return current_function (true); } // Current line in current function. @@ -82,14 +80,6 @@ // Current column in current function. int current_column (void) const; - // Caller function, may be built-in. - - octave_function * caller (void) const - { - return (m_curr_frame > 1 - ? m_cs[m_curr_frame-1]->function () : m_cs[0]->function ()); - } - size_t current_frame (void) const { return m_curr_frame; } size_t size (void) const { return m_cs.size (); } @@ -255,14 +245,6 @@ void clear (void); - // Lock current function. Skip built-in functions (mlock is skipped - // silently; warn for others) and look for the first caller that is - // a user-defined (m-file) or dynamically loaded (.oct or .mex) - // function. That allows the built-in Fmlock function to lock the - // calling function instead of locking istelf. - - void mlock (void) const; - symbol_info_list all_variables (void); std::list<symbol_record> glob (const std::string& pattern) const;
--- a/libinterp/corefcn/interpreter.cc Thu Dec 26 08:11:00 2019 -0800 +++ b/libinterp/corefcn/interpreter.cc Tue Dec 17 12:26:09 2019 -0500 @@ -1363,9 +1363,27 @@ return cd_ok; } - void interpreter::mlock (void) + void interpreter::mlock (bool skip_first) const + { + m_evaluator.mlock (skip_first); + } + + void interpreter::munlock (bool skip_first) const { - m_evaluator.mlock (); + m_evaluator.munlock (skip_first); + } + + bool interpreter::mislocked (bool skip_first) const + { + return m_evaluator.mislocked (skip_first); + } + + void interpreter::munlock (const char *nm) + { + if (! nm) + error ("munlock: invalid value for NAME"); + + munlock (std::string (nm)); } void interpreter::munlock (const std::string& nm) @@ -1381,6 +1399,14 @@ } } + bool interpreter::mislocked (const char *nm) + { + if (! nm) + error ("mislocked: invalid value for NAME"); + + return mislocked (std::string (nm)); + } + bool interpreter::mislocked (const std::string& nm) { bool retval = false;
--- a/libinterp/corefcn/interpreter.h Thu Dec 26 08:11:00 2019 -0800 +++ b/libinterp/corefcn/interpreter.h Tue Dec 17 12:26:09 2019 -0500 @@ -299,10 +299,16 @@ int chdir (const std::string& dir); - void mlock (void); + void mlock (bool skip_first = false) const; + void munlock (bool skip_first = false) const; + bool mislocked (bool skip_first = false) const; + // NOTE: since we have a version that accepts a bool argument, we + // can't rely on automatic conversion from char* to std::string. + void munlock (const char *nm); void munlock (const std::string& nm); + bool mislocked (const char *nm); bool mislocked (const std::string& nm); std::string mfilename (const std::string& opt = "") const;
--- a/libinterp/corefcn/variables.cc Thu Dec 26 08:11:00 2019 -0800 +++ b/libinterp/corefcn/variables.cc Tue Dec 17 12:26:09 2019 -0500 @@ -822,6 +822,15 @@ return retval; } +// NOTE: Calling Fmlock directly (without an associated stack frame) +// will probably not do what you expect because it will lock the calling +// function. You should use interpreter::mlock directly if you want to +// lock a .oct function. For .mex, you would normally use mexLock. +// +// FIXME: with the current implementation, calling "builtin ('mlock')" +// will also not do what you expect. Is there any reasonable way to fix +// that? + DEFMETHOD (mlock, interp, args, , doc: /* -*- texinfo -*- @deftypefn {} {} mlock () @@ -833,14 +842,7 @@ if (args.length () != 0) print_usage (); - octave::tree_evaluator& tw = interp.get_evaluator (); - - octave_function *fcn = tw.caller_function (); - - if (! fcn) - error ("mlock: invalid use outside a function"); - - fcn->lock (); + interp.mlock (true); return ovl (); } @@ -863,21 +865,13 @@ if (nargin == 1) { - std::string name = args(0).xstring_value ("munlock: FCN must be a string"); + std::string name + = args(0).xstring_value ("munlock: FCN must be a string"); interp.munlock (name); } else - { - octave::tree_evaluator& tw = interp.get_evaluator (); - - octave_function *fcn = tw.caller_function (); - - if (! fcn) - error ("munlock: invalid use outside a function"); - - fcn->unlock (); - } + interp.munlock (true); return ovl (); } @@ -897,27 +891,15 @@ if (nargin > 1) print_usage (); - octave_value retval; - if (nargin == 1) { - std::string name = args(0).xstring_value ("mislocked: FCN must be a string"); + std::string name + = args(0).xstring_value ("mislocked: FCN must be a string"); - retval = interp.mislocked (name); + return ovl (interp.mislocked (name)); } else - { - octave::tree_evaluator& tw = interp.get_evaluator (); - - octave_function *fcn = tw.caller_function (); - - if (! fcn) - error ("mislocked: invalid use outside a function"); - - retval = fcn->islocked (); - } - - return retval; + return ovl (interp.mislocked (true)); } // Deleting names from the symbol tables.
--- a/libinterp/octave-value/ov-fcn.h Thu Dec 26 08:11:00 2019 -0800 +++ b/libinterp/octave-value/ov-fcn.h Tue Dec 17 12:26:09 2019 -0500 @@ -174,7 +174,10 @@ locked = false; } - bool islocked (void) const { return locked; } + bool islocked (void) const + { + return locked; + } virtual void lock_subfunctions (void) { }
--- a/libinterp/parse-tree/pt-eval.cc Thu Dec 26 08:11:00 2019 -0800 +++ b/libinterp/parse-tree/pt-eval.cc Tue Dec 17 12:26:09 2019 -0500 @@ -1581,14 +1581,14 @@ return m_call_stack.debug_user_code (); } - octave_function * tree_evaluator::current_function (void) const + octave_function * tree_evaluator::current_function (bool skip_first) const { - return m_call_stack.current (); + return m_call_stack.current_function (skip_first); } octave_function * tree_evaluator::caller_function (void) const { - return m_call_stack.caller (); + return m_call_stack.current_function (true); } bool tree_evaluator::goto_frame (size_t n, bool verbose) @@ -1724,9 +1724,46 @@ return m_call_stack.current_scope (); } - void tree_evaluator::mlock (void) const + void tree_evaluator::mlock (bool skip_first) const + { + octave_function *fcn = m_call_stack.current_function (skip_first); + + if (! fcn) + error ("mlock: invalid use outside a function"); + + if (fcn->is_builtin_function ()) + { + warning ("mlock: locking built-in function has no effect"); + return; + } + + fcn->lock (); + } + + void tree_evaluator::munlock (bool skip_first) const { - m_call_stack.mlock (); + octave_function *fcn = m_call_stack.current_function (skip_first); + + if (! fcn) + error ("munlock: invalid use outside a function"); + + if (fcn->is_builtin_function ()) + { + warning ("munlock: unlocking built-in function has no effect"); + return; + } + + fcn->unlock (); + } + + bool tree_evaluator::mislocked (bool skip_first) const + { + octave_function *fcn = m_call_stack.current_function (skip_first); + + if (! fcn) + error ("mislocked: invalid use outside a function"); + + return fcn->islocked (); } octave_value @@ -1973,9 +2010,9 @@ } std::string - tree_evaluator::current_function_name (void) const + tree_evaluator::current_function_name (bool skip_first) const { - octave_function *curfcn = m_call_stack.current (); + octave_function *curfcn = m_call_stack.current_function (skip_first); if (curfcn) return curfcn->name (); @@ -3535,7 +3572,7 @@ void tree_evaluator::maybe_set_echo_state (void) { - octave_function *caller = m_call_stack.caller (); + octave_function *caller = caller_function (); if (caller && caller->is_user_code ()) { @@ -3766,7 +3803,7 @@ { std::string prefix = command_editor::decode_prompt_string (m_PS4); - octave_function *curr_fcn = m_call_stack.current (); + octave_function *curr_fcn = m_call_stack.current_function (); if (curr_fcn && curr_fcn->is_user_code ()) {
--- a/libinterp/parse-tree/pt-eval.h Thu Dec 26 08:11:00 2019 -0800 +++ b/libinterp/parse-tree/pt-eval.h Tue Dec 17 12:26:09 2019 -0500 @@ -422,7 +422,7 @@ // Current function that we are debugging. octave_user_code * debug_user_code (void) const; - octave_function * current_function (void) const; + octave_function * current_function (bool skip_first = false) const; octave_function * caller_function (void) const; @@ -467,7 +467,11 @@ symbol_scope get_top_scope (void) const; symbol_scope get_current_scope (void) const; - void mlock (void) const; + void mlock (bool skip_first = false) const; + + void munlock (bool skip_first = false) const; + + bool mislocked (bool skip_first = false) const; octave_value max_stack_depth (const octave_value_list& args, int nargout); @@ -511,7 +515,7 @@ octave_user_code * get_user_code (const std::string& fname = "", const std::string& class_name = ""); - std::string current_function_name (void) const; + std::string current_function_name (bool skip_first = false) const; bool in_user_code (void) const;
--- a/libinterp/parse-tree/pt-fcn-handle.cc Thu Dec 26 08:11:00 2019 -0800 +++ b/libinterp/parse-tree/pt-fcn-handle.cc Tue Dec 17 12:26:09 2019 -0500 @@ -145,7 +145,7 @@ = new octave_user_function (new_scope, param_list_dup, ret_list, stmt_list, local_var_init_vals); - octave_function *curr_fcn = cs.current (); + octave_function *curr_fcn = cs.current_function (); if (curr_fcn) {