changeset 27745:7a45100a40c4

allow private scripts to be called from other private scripts This issue was discovered in bug #57236 but that report is not specifically about this problem. * symscope.cc, symscope.h (symbol_scope_rep::m_code): Rename from m_fcn. Change all uses. (symbol_scope_rep::user_code, symbol_scope::user_code): Rename from function. Change all uses. (symbol_scope_rep::set_user_code, symbol_scope::set_user_code): Rename from set_function. Change all uses. * ov-usr-fcn.h, ov-usr-fcn.cc (octave_user_code::octave_user_code): Call symbol_scope::set_user_code. (octave_user_code::octave_user_function): Don't call symbol_scope::set_function. * oct-parse.yy (base_parser::make_script): Also call stash_dir_name for scripts. * test/private-functions: New test directory. * test/module.mk: Include test/private-function/module.mk.
author John W. Eaton <jwe@octave.org>
date Sun, 24 Nov 2019 14:01:16 -0600
parents b2b23c7d5a24
children ae821ac9ec74
files libinterp/corefcn/fcn-info.cc libinterp/corefcn/help.cc libinterp/corefcn/load-path.cc libinterp/corefcn/symscope.h libinterp/octave-value/ov-usr-fcn.cc libinterp/octave-value/ov-usr-fcn.h libinterp/parse-tree/oct-parse.yy test/module.mk test/private-functions/fcn.m test/private-functions/module.mk test/private-functions/private-functions.tst test/private-functions/private/ascript.m test/private-functions/private/bscript.m test/private-functions/private/pfcn1.m test/private-functions/private/pfcn2.m
diffstat 15 files changed, 71 insertions(+), 31 deletions(-) [+]
line wrap: on
line diff
--- a/libinterp/corefcn/fcn-info.cc	Sun Nov 24 13:38:37 2019 -0600
+++ b/libinterp/corefcn/fcn-info.cc	Sun Nov 24 14:01:16 2019 -0600
@@ -626,8 +626,8 @@
   fcn_info::fcn_info_rep::xfind (const symbol_scope& search_scope,
                                  const octave_value_list& args)
   {
-    octave_user_function *current_fcn
-      = search_scope ? search_scope.function () : nullptr;
+    octave_user_code *curr_code
+      = search_scope ? search_scope.user_code () : nullptr;
 
     // Subfunction.  I think it only makes sense to check for
     // subfunctions if we are currently executing a function defined
@@ -643,9 +643,9 @@
 
     // Local function.
 
-    if (current_fcn)
+    if (curr_code)
       {
-        std::string fcn_file = current_fcn->fcn_file_name ();
+        std::string fcn_file = curr_code->fcn_file_name ();
 
         // For anonymous functions we look at the parent scope so that if
         // they were defined within class methods and use local functions
@@ -669,9 +669,9 @@
 
     // Private function.
 
-    if (current_fcn)
+    if (curr_code)
       {
-        std::string dir_name = current_fcn->dir_name ();
+        std::string dir_name = curr_code->dir_name ();
 
         if (! dir_name.empty ())
           {
@@ -847,12 +847,12 @@
 
     // Private function.
 
-    octave_user_function *current_fcn
-      = search_scope ? search_scope.function () : nullptr;
+    octave_user_code *curr_code
+      = search_scope ? search_scope.user_code () : nullptr;
 
-    if (current_fcn)
+    if (curr_code)
       {
-        std::string dir_name = current_fcn->dir_name ();
+        std::string dir_name = curr_code->dir_name ();
 
         if (! dir_name.empty ())
           {
@@ -887,9 +887,9 @@
 
     // Local function.
 
-    if (current_fcn)
+    if (curr_code)
       {
-        std::string fcn_file = current_fcn->fcn_file_name ();
+        std::string fcn_file = curr_code->fcn_file_name ();
 
         if (! fcn_file.empty ())
           {
--- a/libinterp/corefcn/help.cc	Sun Nov 24 13:38:37 2019 -0600
+++ b/libinterp/corefcn/help.cc	Sun Nov 24 14:01:16 2019 -0600
@@ -499,7 +499,7 @@
     while (curr_fcn->is_subfunction ())
       {
         symbol_scope pscope = curr_fcn->parent_fcn_scope ();
-        curr_fcn = pscope.function ();
+        curr_fcn = pscope.user_code ();
       }
 
     // Get subfunctions.
--- a/libinterp/corefcn/load-path.cc	Sun Nov 24 13:38:37 2019 -0600
+++ b/libinterp/corefcn/load-path.cc	Sun Nov 24 14:01:16 2019 -0600
@@ -157,15 +157,15 @@
 
     symbol_scope scope = __get_current_scope__ ("find_private_file");
 
-    octave_user_function *curr_fcn = scope ? scope.function () : nullptr;
-
-    if (curr_fcn)
+    octave_user_code *curr_code = scope ? scope.user_code () : nullptr;
+
+    if (curr_code)
       {
         // Even for private functions, dir_name doesn't contain the
         // "private" directory component so we append it here in all
         // cases.
 
-        std::string dir_name = curr_fcn->dir_name ();
+        std::string dir_name = curr_code->dir_name ();
 
         if (! dir_name.empty ())
           {
--- a/libinterp/corefcn/symscope.h	Sun Nov 24 13:38:37 2019 -0600
+++ b/libinterp/corefcn/symscope.h	Sun Nov 24 14:01:16 2019 -0600
@@ -65,7 +65,7 @@
 
     symbol_scope_rep (const std::string& name = "")
       : m_name (name), m_symbols (), m_subfunctions (),
-        m_persistent_values (), m_fcn (nullptr), m_parent (),
+        m_persistent_values (), m_code (nullptr), m_parent (),
         m_primary_parent (), m_children (), m_nesting_depth (0),
         m_is_static (false)
     {
@@ -123,7 +123,7 @@
       new_sid->m_subfunctions = m_subfunctions;
       new_sid->m_persistent_values = m_persistent_values;
       new_sid->m_subfunction_names = m_subfunction_names;
-      new_sid->m_fcn = m_fcn;
+      new_sid->m_code = m_code;
       new_sid->m_parent = m_parent;
       new_sid->m_primary_parent = m_primary_parent;
       new_sid->m_children = m_children;
@@ -242,9 +242,9 @@
 
     void cache_name (const std::string& name) { m_name = name; }
 
-    octave_user_function *function (void) const { return m_fcn; }
+    octave_user_code *user_code (void) const { return m_code; }
 
-    void set_function (octave_user_function *fcn) { m_fcn = fcn; }
+    void set_user_code (octave_user_code *code) { m_code = code; }
 
     void set_parent (const std::shared_ptr<symbol_scope_rep>& parent);
 
@@ -296,7 +296,7 @@
 
     //! The associated user code (may be null).
 
-    octave_user_function *m_fcn;
+    octave_user_code *m_code;
 
     //! Parent of nested function (may be null).
 
@@ -525,15 +525,15 @@
         m_rep->cache_name (name);
     }
 
-    octave_user_function * function (void) const
+    octave_user_code * user_code (void) const
     {
-      return m_rep ? m_rep->function () : nullptr;
+      return m_rep ? m_rep->user_code () : nullptr;
     }
 
-    void set_function (octave_user_function *fcn)
+    void set_user_code (octave_user_code *code)
     {
       if (m_rep)
-        m_rep->set_function (fcn);
+        m_rep->set_user_code (code);
     }
 
     void set_parent (const symbol_scope& p)
--- a/libinterp/octave-value/ov-usr-fcn.cc	Sun Nov 24 13:38:37 2019 -0600
+++ b/libinterp/octave-value/ov-usr-fcn.cc	Sun Nov 24 14:01:16 2019 -0600
@@ -67,7 +67,7 @@
   // the corresponding scope.
   // FIXME: would it be better to use shared/weak pointers for this job
   // instead of storing a bare pointer in the scope object?
-  m_scope.set_function (nullptr);
+  m_scope.set_user_code (nullptr);
 
   // FIXME: shouldn't this happen automatically when deleting cmd_list?
   if (cmd_list)
@@ -212,9 +212,6 @@
 {
   if (cmd_list)
     cmd_list->mark_as_function_body ();
-
-  if (m_scope)
-    m_scope.set_function (this);
 }
 
 octave_user_function::~octave_user_function (void)
--- a/libinterp/octave-value/ov-usr-fcn.h	Sun Nov 24 13:38:37 2019 -0600
+++ b/libinterp/octave-value/ov-usr-fcn.h	Sun Nov 24 14:01:16 2019 -0600
@@ -68,7 +68,10 @@
       t_parsed (static_cast<time_t> (0)),
       t_checked (static_cast<time_t> (0)),
       m_file_info (nullptr), cmd_list (cmds)
-  { }
+  {
+    if (m_scope)
+      m_scope.set_user_code (this);
+  }
 
 public:
 
--- a/libinterp/parse-tree/oct-parse.yy	Sun Nov 24 13:38:37 2019 -0600
+++ b/libinterp/parse-tree/oct-parse.yy	Sun Nov 24 14:01:16 2019 -0600
@@ -3281,6 +3281,7 @@
     sys::time now;
 
     script->stash_fcn_file_time (now);
+    script->stash_dir_name (m_lexer.m_dir_name);
 
     m_primary_fcn = octave_value (script);
   }
--- a/test/module.mk	Sun Nov 24 13:38:37 2019 -0600
+++ b/test/module.mk	Sun Nov 24 14:01:16 2019 -0600
@@ -89,6 +89,7 @@
 include %reldir%/local-functions/module.mk
 include %reldir%/mex/module.mk
 include %reldir%/nest/module.mk
+include %reldir%/private-functions/module.mk
 include %reldir%/publish/module.mk
 include %reldir%/pkg/module.mk
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/private-functions/fcn.m	Sun Nov 24 14:01:16 2019 -0600
@@ -0,0 +1,9 @@
+function retval = fcn ()
+  ## Call private function.
+  assert (pfcn1 (), "pfcn1");
+  ## Execute private script.
+  a = "";
+  ascript;
+  assert (a, "ascript");
+  retval = true;
+endfunction
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/private-functions/module.mk	Sun Nov 24 14:01:16 2019 -0600
@@ -0,0 +1,9 @@
+private_functions_TEST_FILES = \
+  %reldir%/fcn.m \
+  %reldir%/private-functions.tst \
+  %reldir%/private/ascript.m \
+  %reldir%/private/bscript.m \
+  %reldir%/private/pfcn1.m \
+  %reldir%/private/pfcn2.m
+
+TEST_FILES += $(private_functions_TEST_FILES)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/private-functions/private-functions.tst	Sun Nov 24 14:01:16 2019 -0600
@@ -0,0 +1,1 @@
+%!assert (fcn ())
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/private-functions/private/ascript.m	Sun Nov 24 14:01:16 2019 -0600
@@ -0,0 +1,5 @@
+a = "ascript";
+
+b = "";
+bscript;
+assert (b, "bscript");
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/private-functions/private/bscript.m	Sun Nov 24 14:01:16 2019 -0600
@@ -0,0 +1,1 @@
+b = "bscript";
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/private-functions/private/pfcn1.m	Sun Nov 24 14:01:16 2019 -0600
@@ -0,0 +1,7 @@
+function r = pfcn1 ()
+  r = "pfcn1";
+  a = "";
+  ascript;
+  assert (a, "ascript");
+  assert (pfcn2 (), "pfcn2");
+endfunction
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/private-functions/private/pfcn2.m	Sun Nov 24 14:01:16 2019 -0600
@@ -0,0 +1,6 @@
+function r = pfcn2 ()
+  r = "pfcn2";
+  a = "";
+  ascript;
+  assert (a, "ascript");
+endfunction