changeset 10637:9cd5aa83fa62

implement 'local' parameter to pseudo-variables
author Jaroslav Hajek <highegg@gmail.com>
date Mon, 17 May 2010 13:46:57 +0200
parents c170eb1c067f
children e1559a8a60b4
files src/ChangeLog src/ov-usr-fcn.cc src/ov-usr-fcn.h src/variables.cc
diffstat 4 files changed, 102 insertions(+), 1 deletions(-) [+]
line wrap: on
line diff
--- a/src/ChangeLog	Mon May 17 11:52:59 2010 +0200
+++ b/src/ChangeLog	Mon May 17 13:46:57 2010 +0200
@@ -1,3 +1,15 @@
+2010-05-17  Jaroslav Hajek  <highegg@gmail.com>
+
+	* ov-usr-fcn.h (octave_user_function::curr_unwind_protect_frame): New
+	field.
+	(octave_user_function::local_protect): New template method.
+	* ov-usr-fcn.cc (octave_user_function::octave_user_function):
+	Initialize it here.
+	(octave_user_function::do_multi_index_op): Set and restore it here.
+	* variables.cc (wants_local_change, try_local_protect): New helper
+	funcs.
+	(set_internal_variable): Call them in all overloads.
+
 2010-05-14  Jaroslav Hajek  <highegg@gmail.com>
 
 	* symtab.cc (symtab::do_mark_global, symtab::do_mark_hidden): Force
--- a/src/ov-usr-fcn.cc	Mon May 17 11:52:59 2010 +0200
+++ b/src/ov-usr-fcn.cc	Mon May 17 13:46:57 2010 +0200
@@ -182,7 +182,8 @@
     num_named_args (param_list ? param_list->length () : 0),
     nested_function (false), inline_function (false),
     class_constructor (false), class_method (false),
-    parent_scope (-1), local_scope (sid)
+    parent_scope (-1), local_scope (sid),
+    curr_unwind_protect_frame (0)
 {
   if (cmd_list)
     cmd_list->mark_as_function_body ();
@@ -398,6 +399,12 @@
   if (echo_commands)
     print_code_function_header ();
 
+  // Set pointer to the current unwind_protect frame to allow
+  // certain builtins register simple cleanup in a very optimized manner.
+  // This is *not* intended as a general-purpose on-cleanup mechanism,
+  frame.protect_var (curr_unwind_protect_frame);
+  curr_unwind_protect_frame = &frame;
+
   // Evaluate the commands that make up the function.
 
   frame.protect_var (tree_evaluator::in_fcn_or_script_body);
--- a/src/ov-usr-fcn.h	Mon May 17 11:52:59 2010 +0200
+++ b/src/ov-usr-fcn.h	Mon May 17 13:46:57 2010 +0200
@@ -34,6 +34,7 @@
 #include "ov-fcn.h"
 #include "ov-typeinfo.h"
 #include "symtab.h"
+#include "unwind-prot.h"
 
 class string_vector;
 
@@ -284,6 +285,18 @@
 
   void accept (tree_walker& tw);
 
+  template <class T>
+  bool local_protect (T& variable)
+    {
+      if (curr_unwind_protect_frame)
+        {
+          curr_unwind_protect_frame->protect_var (variable);
+          return true;
+        }
+      else
+        return false;
+    }
+
 #if 0
   void print_symtab_info (std::ostream& os) const;
 #endif
@@ -347,6 +360,9 @@
 
   symbol_table::scope_id local_scope;
 
+  // pointer to the current unwind_protect frame of this function.
+  unwind_protect *curr_unwind_protect_frame;
+
 #if 0
   // The symbol record for argn in the local symbol table.
   octave_value& argn_varref;
--- a/src/variables.cc	Mon May 17 11:52:59 2010 +0200
+++ b/src/variables.cc	Mon May 17 13:46:57 2010 +0200
@@ -638,6 +638,42 @@
 
 // Variable values.
 
+static bool
+wants_local_change (const octave_value_list& args, int& nargin)
+{
+  bool retval = false;
+
+  if (nargin == 2)
+    {
+      if (args(1).is_string () && args(1).string_value () == "local")
+        {
+          nargin = 1;
+          retval = true;
+        }
+      else
+        {
+          error_with_cfn ("expecting second argument to be \"local\"");
+          nargin = 0;
+        }
+    }
+
+  return retval;
+}
+
+template <class T>
+bool try_local_protect (T& var)
+{
+  octave_user_code *curr_usr_code = octave_call_stack::caller_user_code ();
+  octave_user_function *curr_usr_fcn = 0;
+  if (curr_usr_code && curr_usr_code->is_user_function ())
+    curr_usr_fcn = dynamic_cast<octave_user_function *> (curr_usr_code);
+
+  if (curr_usr_fcn && curr_usr_fcn->local_protect (var))
+    return true;
+  else
+    return false;
+}
+
 octave_value
 set_internal_variable (bool& var, const octave_value_list& args,
                        int nargout, const char *nm)
@@ -649,6 +685,12 @@
   if (nargout > 0 || nargin == 0)
     retval = var;
 
+  if (wants_local_change (args, nargin))
+    {
+      if (! try_local_protect (var))
+        warning ("\"local\" has no effect outside a function");
+    }
+
   if (nargin == 1)
     {
       bool bval = args(0).bool_value ();
@@ -675,6 +717,12 @@
   if (nargout > 0 || nargin == 0)
     retval = var;
 
+  if (wants_local_change (args, nargin))
+    {
+      if (! try_local_protect (var))
+        warning ("\"local\" has no effect outside a function");
+    }
+
   if (nargin == 1)
     {
       std::string sval = args(0).string_value ();
@@ -717,6 +765,12 @@
   if (nargout > 0 || nargin == 0)
     retval = var;
 
+  if (wants_local_change (args, nargin))
+    {
+      if (! try_local_protect (var))
+        warning ("\"local\" has no effect outside a function");
+    }
+
   if (nargin == 1)
     {
       int ival = args(0).int_value ();
@@ -752,6 +806,12 @@
   if (nargout > 0 || nargin == 0)
     retval = var;
 
+  if (wants_local_change (args, nargin))
+    {
+      if (! try_local_protect (var))
+        warning ("\"local\" has no effect outside a function");
+    }
+
   if (nargin == 1)
     {
       double dval = args(0).scalar_value ();
@@ -785,6 +845,12 @@
   if (nargout > 0 || nargin == 0)
     retval = var;
 
+  if (wants_local_change (args, nargin))
+    {
+      if (! try_local_protect (var))
+        warning ("\"local\" has no effect outside a function");
+    }
+
   if (nargin == 1)
     {
       std::string sval = args(0).string_value ();