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)
       {