# HG changeset patch # User Jaroslav Hajek # Date 1274096817 -7200 # Node ID 9cd5aa83fa62ad38e83057c7bba055c267350cb9 # Parent c170eb1c067f161c05121d6007c46ebddd46036b implement 'local' parameter to pseudo-variables diff -r c170eb1c067f -r 9cd5aa83fa62 src/ChangeLog --- 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 + + * 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 * symtab.cc (symtab::do_mark_global, symtab::do_mark_hidden): Force diff -r c170eb1c067f -r 9cd5aa83fa62 src/ov-usr-fcn.cc --- 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); diff -r c170eb1c067f -r 9cd5aa83fa62 src/ov-usr-fcn.h --- 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 + 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; diff -r c170eb1c067f -r 9cd5aa83fa62 src/variables.cc --- 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 +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 (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 ();