Mercurial > hg > octave-lyh
changeset 10832:1b2fcd122c6a
allow user detect ignored outputs in m-functions
author | Jaroslav Hajek <highegg@gmail.com> |
---|---|
date | Thu, 29 Jul 2010 12:45:23 +0200 |
parents | 1646bd8e3735 |
children | e5c752231985 |
files | src/ChangeLog src/ov-base.cc src/ov-base.h src/ov-usr-fcn.cc src/ov-usr-fcn.h src/ov.cc src/ov.h src/pt-assign.cc src/pt-exp.cc src/pt-exp.h src/pt-idx.cc src/pt-idx.h src/pt-misc.cc |
diffstat | 13 files changed, 255 insertions(+), 13 deletions(-) [+] |
line wrap: on
line diff
--- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,31 @@ +2010-07-29 Jaroslav Hajek <highegg@gmail.com> + + * ov.cc (octave_value::subsref (..., const std::list<octave_lvalue> *) + octave_value::do_multi_index_op (..., const std::list<octave_lvalue> *)): + New methods. + * ov.h: Declare them. + * ov-base.cc (octave_base_value::subsref (..., const std::list<octave_lvalue> *) + octave_base_value::do_multi_index_op (..., const std::list<octave_lvalue> *)): + New methods. + * ov-base.h: Declare them. + * ov-usr-fcn.cc (octave_user_function::subsref (..., const std::list<octave_lvalue> *) + octave_user_function::do_multi_index_op (..., const std::list<octave_lvalue> *)): + New virtual method overrides. Move code here. + (octave_user_function::bind_automatic_vars): Add lvalue_list + parameter. Bind automatic variable ".ignored.". + (Fis_ignored_output): New defun. + * ov-usr-fcn.h: Update decls. + * pt-misc.cc (tree_parameter_list::initialize_undefined_elements): + Skip warning if outputs are ignored. + * pt-exp.cc (tree_expression::rvalue (..., const + std::list<octave_lvalue> *)): New method overload. + * pt-exp.h: Declare it. + * pt-idx.cc (tree_index_expression::rvalue (..., const + std::list<octave_lvalue> *)): New method override. Move code here. + * pt-idx.h: Declare it. + * pt-assign.cc (tree_multi_assignment::rvalue): Pass in the pointer to + lvalue_list. + 2010-07-28 John W. Eaton <jwe@octave.org> * DLD-FUNCTIONS/find.cc (Ffind): Reorder cases to check for
--- a/src/ov-base.cc +++ b/src/ov-base.cc @@ -179,6 +179,16 @@ return subsref (type, idx); } +octave_value_list +octave_base_value::subsref (const std::string& type, + const std::list<octave_value_list>& idx, + int nargout, + const std::list<octave_lvalue> *) +{ + // Fall back to call without passing lvalue list. + return subsref (type, idx, nargout); +} + octave_value octave_base_value::do_index_op (const octave_value_list&, bool) { @@ -195,6 +205,14 @@ return octave_value (); } +octave_value_list +octave_base_value::do_multi_index_op (int nargout, const octave_value_list& idx, + const std::list<octave_lvalue> *) +{ + // Fall back. + return do_multi_index_op (nargout, idx); +} + idx_vector octave_base_value::index_vector (void) const {
--- a/src/ov-base.h +++ b/src/ov-base.h @@ -260,12 +260,22 @@ const std::list<octave_value_list>& idx, bool auto_add); + virtual octave_value_list + subsref (const std::string& type, + const std::list<octave_value_list>& idx, + int nargout, + const std::list<octave_lvalue> *lvalue_list); + virtual octave_value do_index_op (const octave_value_list& idx, bool resize_ok = false); virtual octave_value_list do_multi_index_op (int nargout, const octave_value_list& idx); + virtual octave_value_list + do_multi_index_op (int nargout, const octave_value_list& idx, + const std::list<octave_lvalue> *lvalue_list); + virtual void assign (const std::string&, const octave_value&) { } virtual octave_value
--- a/src/ov-usr-fcn.cc +++ b/src/ov-usr-fcn.cc @@ -31,6 +31,7 @@ #include "Cell.h" #include "defun.h" #include "error.h" +#include "gripes.h" #include "input.h" #include "oct-obj.h" #include "ov-usr-fcn.h" @@ -282,6 +283,14 @@ const std::list<octave_value_list>& idx, int nargout) { + return octave_user_function::subsref (type, idx, nargout, 0); +} + +octave_value_list +octave_user_function::subsref (const std::string& type, + const std::list<octave_value_list>& idx, + int nargout, const std::list<octave_lvalue>* lvalue_list) +{ octave_value_list retval; switch (type[0]) @@ -290,7 +299,8 @@ { int tmp_nargout = (type.length () > 1 && nargout == 0) ? 1 : nargout; - retval = do_multi_index_op (tmp_nargout, idx.front ()); + retval = do_multi_index_op (tmp_nargout, idx.front (), + idx.size () == 1 ? lvalue_list : 0); } break; @@ -320,6 +330,14 @@ octave_user_function::do_multi_index_op (int nargout, const octave_value_list& args) { + return do_multi_index_op (nargout, args, 0); +} + +octave_value_list +octave_user_function::do_multi_index_op (int nargout, + const octave_value_list& args, + const std::list<octave_lvalue>* lvalue_list) +{ octave_value_list retval; if (error_state) @@ -392,7 +410,8 @@ frame.add_fcn (symbol_table::clear_variables); } - bind_automatic_vars (arg_names, nargin, nargout, all_va_args (args)); + bind_automatic_vars (arg_names, nargin, nargout, all_va_args (args), + lvalue_list); bool echo_commands = (Vecho_executing_commands & ECHO_FUNCTIONS); @@ -522,7 +541,7 @@ void octave_user_function::bind_automatic_vars (const string_vector& arg_names, int nargin, int nargout, - const octave_value_list& va_args) + const octave_value_list& va_args, const std::list<octave_lvalue> *lvalue_list) { if (! arg_names.empty ()) symbol_table::varref ("argn") = arg_names; @@ -535,6 +554,31 @@ if (takes_varargs ()) symbol_table::varref ("varargin") = va_args.cell_value (); + + if (lvalue_list) + { + octave_idx_type nbh = 0; + for (std::list<octave_lvalue>::const_iterator p = lvalue_list->begin (); + p != lvalue_list->end (); p++) + nbh += p->is_black_hole (); + + if (nbh > 0) + { + // Only assign the hidden variable if black holes actually present. + Matrix bh (1, nbh); + octave_idx_type k = 0, l = 0; + for (std::list<octave_lvalue>::const_iterator p = lvalue_list->begin (); + p != lvalue_list->end (); p++) + { + if (p->is_black_hole ()) + bh(l++) = k+1; + k += p->numel (); + } + + symbol_table::varref (".ignored.") = bh; + symbol_table::mark_hidden (".ignored."); + } + } } DEFUN (nargin, args, , @@ -683,3 +727,69 @@ { return SET_INTERNAL_VARIABLE (optimize_subsasgn_calls); } + +static bool val_in_table (const Matrix& table, double val) +{ + if (table.is_empty ()) + return false; + + octave_idx_type i = table.lookup (val, ASCENDING); + return (i > 0 && table(i-1) == val); +} + +DEFUN (is_ignored_output, args, , + "-*- texinfo -*-\n\ +@deftypefn {Built-in Function} {} is_ignored_output (@var{k})\n\ +Within a function, given an index @var{k} within the range @code{1:nargout},\n\ +return a logical value indicating whether the argument will be ignored on output\n\ +using the tilde (~) special output argument. If @var{k} is outside the range,\n\ +the function yields false. @var{k} can also be an array, in which case the function\n\ +works element-wise and a logical array is returned.\n\ +\n\ +At the top level, @code{is_ignored_output} returns an error.\n\ +@seealso{nargout, nargin, varargin, varargout}\n\ +@end deftypefn") +{ + octave_value retval; + + int nargin = args.length (); + + if (nargin == 1) + { + if (! symbol_table::at_top_level ()) + { + Matrix ignored; + octave_value tmp = symbol_table::varval (".ignored."); + if (tmp.is_defined ()) + ignored = tmp.matrix_value (); + + if (args(0).is_scalar_type ()) + { + double k = args(0).double_value (); + if (! error_state) + retval = val_in_table (ignored, k); + } + else if (args(0).is_numeric_type ()) + { + const NDArray ka = args(0).array_value (); + if (! error_state) + { + boolNDArray r (ka.dims ()); + for (octave_idx_type i = 0; i < ka.numel (); i++) + r(i) = val_in_table (ignored, ka(i)); + + retval = r; + } + } + else + gripe_wrong_type_arg ("is_ignored_output", args(0)); + } + else + error ("is_ignored_output: invalid call at top level"); + } + else + print_usage (); + + return retval; +} +
--- a/src/ov-usr-fcn.h +++ b/src/ov-usr-fcn.h @@ -268,9 +268,17 @@ const std::list<octave_value_list>& idx, int nargout); + octave_value_list subsref (const std::string& type, + const std::list<octave_value_list>& idx, + int nargout, const std::list<octave_lvalue>* lvalue_list); + octave_value_list do_multi_index_op (int nargout, const octave_value_list& args); + octave_value_list + do_multi_index_op (int nargout, const octave_value_list& args, + const std::list<octave_lvalue>* lvalue_list); + tree_parameter_list *parameter_list (void) { return param_list; } tree_parameter_list *return_list (void) { return ret_list; } @@ -382,7 +390,8 @@ void print_code_function_trailer (void); void bind_automatic_vars (const string_vector& arg_names, int nargin, - int nargout, const octave_value_list& va_args); + int nargout, const octave_value_list& va_args, + const std::list<octave_lvalue> *lvalue_list); // No copying!
--- a/src/ov.cc +++ b/src/ov.cc @@ -1202,6 +1202,17 @@ return rep->subsref (type, idx, nargout); } +octave_value_list +octave_value::subsref (const std::string& type, + const std::list<octave_value_list>& idx, int nargout, + const std::list<octave_lvalue> *lvalue_list) +{ + if (lvalue_list) + return rep->subsref (type, idx, nargout, lvalue_list); + else + return subsref (type, idx, nargout); +} + octave_value octave_value::next_subsref (const std::string& type, const std::list<octave_value_list>& idx, @@ -1256,6 +1267,13 @@ return rep->do_multi_index_op (nargout, idx); } +octave_value_list +octave_value::do_multi_index_op (int nargout, const octave_value_list& idx, + const std::list<octave_lvalue> *lvalue_list) +{ + return rep->do_multi_index_op (nargout, idx, lvalue_list); +} + #if 0 static void gripe_assign_failed (const std::string& on, const std::string& tn1,
--- a/src/ov.h +++ b/src/ov.h @@ -391,6 +391,11 @@ const std::list<octave_value_list>& idx, int nargout); + octave_value_list subsref (const std::string& type, + const std::list<octave_value_list>& idx, + int nargout, + const std::list<octave_lvalue> *lvalue_list); + octave_value next_subsref (const std::string& type, const std::list<octave_value_list>& idx, size_t skip = 1); @@ -411,6 +416,10 @@ octave_value_list do_multi_index_op (int nargout, const octave_value_list& idx); + octave_value_list + do_multi_index_op (int nargout, const octave_value_list& idx, + const std::list<octave_lvalue> *lvalue_list); + octave_value subsasgn (const std::string& type, const std::list<octave_value_list>& idx, const octave_value& rhs);
--- a/src/pt-assign.cc +++ b/src/pt-assign.cc @@ -354,7 +354,7 @@ if (error_state) return retval; - int n_out = 0; + octave_idx_type n_out = 0; for (std::list<octave_lvalue>::const_iterator p = lvalue_list.begin (); p != lvalue_list.end (); @@ -362,7 +362,7 @@ n_out += p->numel (); // The following trick is used to keep rhs_val constant. - const octave_value_list rhs_val1 = rhs->rvalue (n_out); + const octave_value_list rhs_val1 = rhs->rvalue (n_out, &lvalue_list); const octave_value_list rhs_val = (rhs_val1.length () == 1 && rhs_val1(0).is_cs_list () ? rhs_val1(0).list_value () : rhs_val1);
--- a/src/pt-exp.cc +++ b/src/pt-exp.cc @@ -69,6 +69,12 @@ return octave_value_list (); } +octave_value_list +tree_expression::rvalue (int nargout, const std::list<octave_lvalue> *) +{ + return rvalue (nargout); +} + octave_lvalue tree_expression::lvalue (void) {
--- a/src/pt-exp.h +++ b/src/pt-exp.h @@ -25,6 +25,7 @@ #define octave_tree_expr_h 1 #include <string> +#include <list> class octave_value; class octave_lvalue; @@ -78,6 +79,9 @@ virtual octave_value_list rvalue (int nargout); + virtual octave_value_list rvalue (int nargout, + const std::list<octave_lvalue> *lvalue_list); + virtual octave_lvalue lvalue (void); int paren_count (void) const { return num_parens; }
--- a/src/pt-idx.cc +++ b/src/pt-idx.cc @@ -275,6 +275,12 @@ octave_value_list tree_index_expression::rvalue (int nargout) { + return tree_index_expression::rvalue (nargout, 0); +} + +octave_value_list +tree_index_expression::rvalue (int nargout, const std::list<octave_lvalue> *lvalue_list) +{ octave_value_list retval; if (error_state) @@ -398,7 +404,8 @@ } if (! error_state) - retval = tmp.subsref (type.substr (tmpi, n - tmpi), idx, nargout); + retval = tmp.subsref (type.substr (tmpi, n - tmpi), idx, nargout, + lvalue_list); } return retval;
--- a/src/pt-idx.h +++ b/src/pt-idx.h @@ -86,6 +86,8 @@ octave_value_list rvalue (int nargout); + octave_value_list rvalue (int nargout, const std::list<octave_lvalue> *lvalue_list); + octave_lvalue lvalue (void); tree_index_expression *dup (symbol_table::scope_id scope,
--- a/src/pt-misc.cc +++ b/src/pt-misc.cc @@ -125,13 +125,17 @@ void tree_parameter_list::initialize_undefined_elements (const std::string& warnfor, - int nargout, - const octave_value& val) + int nargout, const octave_value& val) { bool warned = false; int count = 0; + octave_value tmp = symbol_table::varval (".ignored."); + const Matrix ignored = tmp.is_defined () ? tmp.matrix_value () : Matrix (); + + octave_idx_type k = 0; + for (iterator p = begin (); p != end (); p++) { if (++count > nargout) @@ -145,10 +149,27 @@ { warned = true; - warning_with_id - ("Octave:undefined-return-values", - "%s: some elements in list of return values are undefined", - warnfor.c_str ()); + while (k < ignored.numel ()) + { + octave_idx_type l = ignored (k); + if (l == count) + { + warned = false; + break; + } + else if (l > count) + break; + else + k++; + } + + if (warned) + { + warning_with_id + ("Octave:undefined-return-values", + "%s: some elements in list of return values are undefined", + warnfor.c_str ()); + } } octave_lvalue tmp = elt->lvalue ();