changeset 27021:a20ead51515d

move core of evalin function to evaluator * pt-eval.h, pt-eval.cc (tree_evaluator::evalin): New functions created from Fevalin function. * interpreter.h, interpreter.cc (interpreter::evalin): New functions. * which.m: Pass empty string as third argument of evalin instead of using false().
author John W. Eaton <jwe@octave.org>
date Mon, 01 Apr 2019 12:51:58 +0000
parents 24b7e6326e26
children 6cb675912f2b
files libinterp/corefcn/interpreter.cc libinterp/corefcn/interpreter.h libinterp/parse-tree/oct-parse.yy libinterp/parse-tree/pt-eval.cc libinterp/parse-tree/pt-eval.h scripts/help/which.m
diffstat 6 files changed, 129 insertions(+), 65 deletions(-) [+]
line wrap: on
line diff
--- a/libinterp/corefcn/interpreter.cc	Mon Apr 01 12:11:33 2019 +0000
+++ b/libinterp/corefcn/interpreter.cc	Mon Apr 01 12:51:58 2019 +0000
@@ -1191,6 +1191,21 @@
     return m_evaluator.eval_string (arg, silent, parse_status, nargout);
   }
 
+  octave_value_list interpreter::evalin (const std::string& context,
+                                         const std::string& try_code,
+                                         int nargout)
+  {
+    return m_evaluator.evalin (context, try_code, nargout);
+  }
+
+  octave_value_list interpreter::evalin (const std::string& context,
+                                         const std::string& try_code,
+                                         const std::string& catch_code,
+                                         int nargout)
+  {
+    return m_evaluator.evalin (context, try_code, catch_code, nargout);
+  }
+
   void interpreter::install_variable (const std::string& name,
                                       const octave_value& value, bool global)
   {
--- a/libinterp/corefcn/interpreter.h	Mon Apr 01 12:11:33 2019 +0000
+++ b/libinterp/corefcn/interpreter.h	Mon Apr 01 12:51:58 2019 +0000
@@ -251,6 +251,13 @@
     octave_value_list eval_string (const octave_value& arg, bool silent,
                                    int& parse_status, int nargout);
 
+    octave_value_list evalin (const std::string& context,
+                              const std::string& try_code, int nargout);
+
+    octave_value_list evalin (const std::string& context,
+                              const std::string& try_code,
+                              const std::string& catch_code, int nargout);
+
     void install_variable (const std::string& name, const octave_value& value,
                            bool global);
 
--- a/libinterp/parse-tree/oct-parse.yy	Mon Apr 01 12:11:33 2019 +0000
+++ b/libinterp/parse-tree/oct-parse.yy	Mon Apr 01 12:51:58 2019 +0000
@@ -5196,77 +5196,26 @@
 @seealso{eval, assignin}
 @end deftypefn */)
 {
-
-  octave_value_list retval;
-
   int nargin = args.length ();
 
-  if (nargin < 2)
+  if (nargin < 2 || nargin > 3)
     print_usage ();
 
-  std::string context = args(0).xstring_value ("evalin: CONTEXT must be a string");
-
-  octave::unwind_protect frame;
-
-  octave::call_stack& cs = interp.get_call_stack ();
-
-  frame.add_method (cs, &octave::call_stack::restore_frame,
-                    cs.current_frame ());
-
-  if (context == "caller")
-    cs.goto_caller_frame ();
-  else if (context == "base")
-    cs.goto_base_frame ();
-  else
-    error ("evalin: CONTEXT must be \"caller\" or \"base\"");
-
-  if (nargin > 2)
+  std::string context
+    = args(0).xstring_value ("evalin: CONTEXT must be a string");
+
+  std::string try_code
+    = args(1).xstring_value ("evalin: TRY must be a string");
+
+  if (nargin == 3)
     {
-      frame.protect_var (buffer_error_messages);
-      buffer_error_messages++;
+      std::string catch_code
+        = args(2).xstring_value ("evalin: CATCH must be a string");
+
+      return interp.evalin (context, try_code, catch_code, nargout);
     }
 
-  int parse_status = 0;
-
-  bool execution_error = false;
-
-  octave_value_list tmp;
-
-  try
-    {
-      tmp = interp.eval_string (args(1), nargout > 0, parse_status, nargout);
-    }
-  catch (const octave::execution_exception&)
-    {
-      octave::interpreter::recover_from_exception ();
-
-      execution_error = true;
-    }
-
-  if (nargin > 2 && (parse_status != 0 || execution_error))
-    {
-      // Set up for letting the user print any messages from
-      // errors that occurred in the first part of this eval().
-
-      buffer_error_messages--;
-
-      tmp = interp.eval_string (args(2), nargout > 0, parse_status, nargout);
-
-      retval = (nargout > 0) ? tmp : octave_value_list ();
-    }
-  else
-    {
-      if (nargout > 0)
-        retval = tmp;
-
-      // FIXME: we should really be rethrowing whatever
-      // exception occurred, not just throwing an
-      // execution exception.
-      if (execution_error)
-        octave_throw_execution_exception ();
-    }
-
-  return retval;
+  return interp.evalin (context, try_code, nargout);
 }
 
 static void
--- a/libinterp/parse-tree/pt-eval.cc	Mon Apr 01 12:11:33 2019 +0000
+++ b/libinterp/parse-tree/pt-eval.cc	Mon Apr 01 12:51:58 2019 +0000
@@ -330,6 +330,92 @@
     return eval_string (s, silent, parse_status, nargout);
   }
 
+  octave_value_list tree_evaluator::evalin (const std::string& context,
+                                            const std::string& try_code,
+                                            int nargout)
+  {
+    octave::unwind_protect frame;
+
+    frame.add_method (m_call_stack, &call_stack::restore_frame,
+                      m_call_stack.current_frame ());
+
+    if (context == "caller")
+      m_call_stack.goto_caller_frame ();
+    else if (context == "base")
+      m_call_stack.goto_base_frame ();
+    else
+      error ("evalin: CONTEXT must be \"caller\" or \"base\"");
+
+    int parse_status = 0;
+
+    return eval_string (try_code, nargout > 0, parse_status, nargout);
+  }
+
+  octave_value_list tree_evaluator::evalin (const std::string& context,
+                                            const std::string& try_code,
+                                            const std::string& catch_code,
+                                            int nargout)
+  {
+    octave_value_list retval;
+
+    octave::unwind_protect frame;
+
+    frame.add_method (m_call_stack, &call_stack::restore_frame,
+                      m_call_stack.current_frame ());
+
+    if (context == "caller")
+      m_call_stack.goto_caller_frame ();
+    else if (context == "base")
+      m_call_stack.goto_base_frame ();
+    else
+      error ("evalin: CONTEXT must be \"caller\" or \"base\"");
+
+    frame.protect_var (buffer_error_messages);
+    buffer_error_messages++;
+
+    int parse_status = 0;
+
+    bool execution_error = false;
+
+    octave_value_list tmp;
+
+    try
+      {
+        tmp = eval_string (try_code, nargout > 0, parse_status, nargout);
+      }
+    catch (const octave::execution_exception&)
+      {
+        octave::interpreter::recover_from_exception ();
+
+        execution_error = true;
+      }
+
+    if (parse_status != 0 || execution_error)
+      {
+        // Set up for letting the user print any messages from
+        // errors that occurred in the first part of this eval().
+
+        buffer_error_messages--;
+
+        tmp = eval_string (catch_code, nargout > 0, parse_status, nargout);
+
+        retval = (nargout > 0) ? tmp : octave_value_list ();
+      }
+    else
+      {
+        if (nargout > 0)
+          retval = tmp;
+
+        // FIXME: we should really be rethrowing whatever
+        // exception occurred, not just throwing an
+        // execution exception.
+        if (execution_error)
+          octave_throw_execution_exception ();
+      }
+
+    return retval;
+  }
+
   void
   tree_evaluator::visit_anon_fcn_handle (tree_anon_fcn_handle& anon_fh)
   {
--- a/libinterp/parse-tree/pt-eval.h	Mon Apr 01 12:11:33 2019 +0000
+++ b/libinterp/parse-tree/pt-eval.h	Mon Apr 01 12:51:58 2019 +0000
@@ -168,6 +168,13 @@
     octave_value_list eval_string (const octave_value& arg, bool silent,
                                    int& parse_status, int nargout);
 
+    octave_value_list evalin (const std::string& context,
+                              const std::string& try_code, int nargout);
+
+    octave_value_list evalin (const std::string& context,
+                              const std::string& try_code,
+                              const std::string& catch_code, int nargout);
+
     void visit_anon_fcn_handle (tree_anon_fcn_handle&);
 
     void visit_argument_list (tree_argument_list&);
--- a/scripts/help/which.m	Mon Apr 01 12:11:33 2019 +0000
+++ b/scripts/help/which.m	Mon Apr 01 12:51:58 2019 +0000
@@ -37,7 +37,7 @@
   ## functions in name resolution.
   for i = 1:nargin
     m(i).is_variable = evalin ("caller",
-                               ['exist ("' undo_string_escapes(m(i).name) '", "var")'], false);
+                               ['exist ("' undo_string_escapes(m(i).name) '", "var")'], "");
     if (m(i).is_variable)
       m(i).file = "variable";
     endif