Mercurial > octave
changeset 25382:749d9e858553
move convert_to_const_vector from tree_argument_list to tree_evaluator
* pt-eval.h, pt-eval.cc (tree_evaluator::convert_to_const_vector):
Move here from pt-arg-list.h and pt-arg-list.cc: Change all uses.
(tree_evaluator::m_indexed_object, tree_evaluator::m_index_position,
tree_evaluator::m_num_indices): Move here from
(tree_evaluator::m_indexed_object, tree_evaluator::m_index_position,
tree_evaluator::num_indices): Provide accessors for corresponding
member variables.
(Fend): Move here from pt-arg-list.cc. Access indexed_object,
index_position, and num_indices from evaluator instead of file scope
static variables.
* pt-arg-list.h (tree_argument_list::includes_magic_end): New function.
author | John W. Eaton <jwe@octave.org> |
---|---|
date | Tue, 15 May 2018 17:05:47 -0400 |
parents | 072494014e76 |
children | d3a035528c9a |
files | libinterp/parse-tree/pt-arg-list.cc libinterp/parse-tree/pt-arg-list.h libinterp/parse-tree/pt-eval.cc libinterp/parse-tree/pt-eval.h libinterp/parse-tree/pt-idx.cc |
diffstat | 5 files changed, 187 insertions(+), 164 deletions(-) [+] |
line wrap: on
line diff
--- a/libinterp/parse-tree/pt-arg-list.cc Tue May 15 15:34:09 2018 -0400 +++ b/libinterp/parse-tree/pt-arg-list.cc Tue May 15 17:05:47 2018 -0400 @@ -29,21 +29,13 @@ #include "str-vec.h" -#include "defun.h" -#include "error.h" #include "ovl.h" #include "ov.h" -#include "ov-usr-fcn.h" -#include "parse.h" #include "pt-arg-list.h" -#include "pt-eval.h" #include "pt-exp.h" #include "pt-id.h" #include "pt-idx.h" #include "pt-pr-code.h" -#include "pt-walk.h" -#include "interpreter.h" -#include "unwind-prot.h" namespace octave { @@ -117,152 +109,6 @@ return retval; } -} - -// FIXME: Is there a way to do this job without global data? - -static const octave_value *indexed_object = nullptr; -static int index_position = 0; -static int num_indices = 0; - -// END is documented in op-kw-docs. -DEFCONSTMETHOD (end, interp, , , - doc: /* -*- texinfo -*- -@deftypefn {} {} end -Last element of an array or the end of any @code{for}, @code{parfor}, -@code{if}, @code{do}, @code{while}, @code{function}, @code{switch}, -@code{try}, or @code{unwind_protect} block. - -As an index of an array, the magic index @qcode{"end"} refers to the -last valid entry in an indexing operation. - -Example: - -@example -@group -@var{x} = [ 1 2 3; 4 5 6 ]; -@var{x}(1,end) - @result{} 3 -@var{x}(end,1) - @result{} 4 -@var{x}(end,end) - @result{} 6 -@end group -@end example -@seealso{for, parfor, if, do, while, function, switch, try, unwind_protect} -@end deftypefn */) -{ - octave_value retval; - - if (! indexed_object) - error ("invalid use of end"); - - if (indexed_object->isobject ()) - { - octave_value_list args; - - args(2) = num_indices; - args(1) = index_position + 1; - args(0) = *indexed_object; - - std::string class_name = indexed_object->class_name (); - - octave::symbol_table& symtab = interp.get_symbol_table (); - - octave_value meth = symtab.find_method ("end", class_name); - - if (meth.is_defined ()) - return octave::feval (meth.function_value (), args, 1); - } - - dim_vector dv = indexed_object->dims (); - int ndims = dv.ndims (); - - if (num_indices < ndims) - { - for (int i = num_indices; i < ndims; i++) - dv(num_indices-1) *= dv(i); - - if (num_indices == 1) - { - ndims = 2; - dv.resize (ndims); - dv(1) = 1; - } - else - { - ndims = num_indices; - dv.resize (ndims); - } - } - - if (index_position < ndims) - retval = dv(index_position); - else - retval = 1; - - return retval; -} - -namespace octave -{ - octave_value_list - tree_argument_list::convert_to_const_vector (tree_evaluator *tw, - const octave_value *object) - { - // END doesn't make sense for functions. Maybe we need a different - // way of asking an octave_value object this question? - - bool stash_object = (m_list_includes_magic_end - && object - && ! (object->is_function () - || object->is_function_handle ())); - - unwind_protect frame; - - if (stash_object) - { - frame.protect_var (indexed_object); - - indexed_object = object; - } - - int len = length (); - - std::list<octave_value_list> args; - - auto p = begin (); - for (int k = 0; k < len; k++) - { - if (stash_object) - { - frame.protect_var (index_position); - frame.protect_var (num_indices); - - index_position = k; - num_indices = len; - } - - tree_expression *elt = *p++; - - if (elt) - { - octave_value tmp = tw->evaluate (elt); - - if (tmp.is_cs_list ()) - args.push_back (tmp.list_value ()); - else if (tmp.is_defined ()) - args.push_back (tmp); - } - else - { - args.push_back (octave_value ()); - break; - } - } - - return args; - } string_vector tree_argument_list::get_arg_names (void) const
--- a/libinterp/parse-tree/pt-arg-list.h Tue May 15 15:34:09 2018 -0400 +++ b/libinterp/parse-tree/pt-arg-list.h Tue May 15 17:05:47 2018 -0400 @@ -67,10 +67,24 @@ ~tree_argument_list (void); + // FIXME: This does not recursively check elements of the list + // that are also index expressions. bool has_magic_end (void) const; + bool includes_magic_end (void) const + { + return m_list_includes_magic_end; + } + bool has_magic_tilde (void) const - { return m_list_includes_magic_tilde; } + { + return m_list_includes_magic_tilde; + } + + bool includes_magic_tilde (void) const + { + return m_list_includes_magic_tilde; + } tree_expression * remove_front (void) { @@ -90,10 +104,6 @@ bool is_valid_lvalue_list (void) const; - octave_value_list - convert_to_const_vector (tree_evaluator *tw, - const octave_value *object = nullptr); - string_vector get_arg_names (void) const; std::list<std::string> variable_names (void) const;
--- a/libinterp/parse-tree/pt-eval.cc Tue May 15 15:34:09 2018 -0400 +++ b/libinterp/parse-tree/pt-eval.cc Tue May 15 17:05:47 2018 -0400 @@ -583,6 +583,154 @@ ref.assign (octave_value::op_asn_eq, octave_value ()); } } +} + +// END is documented in op-kw-docs. +DEFCONSTMETHOD (end, interp, , , + doc: /* -*- texinfo -*- +@deftypefn {} {} end +Last element of an array or the end of any @code{for}, @code{parfor}, +@code{if}, @code{do}, @code{while}, @code{function}, @code{switch}, +@code{try}, or @code{unwind_protect} block. + +As an index of an array, the magic index @qcode{"end"} refers to the +last valid entry in an indexing operation. + +Example: + +@example +@group +@var{x} = [ 1 2 3; 4 5 6 ]; +@var{x}(1,end) + @result{} 3 +@var{x}(end,1) + @result{} 4 +@var{x}(end,end) + @result{} 6 +@end group +@end example +@seealso{for, parfor, if, do, while, function, switch, try, unwind_protect} +@end deftypefn */) +{ + octave_value retval; + + octave::tree_evaluator& tw = interp.get_evaluator (); + + const octave_value *indexed_object = tw.indexed_object (); + int index_position = tw.index_position (); + int num_indices = tw.num_indices (); + + if (! indexed_object) + error ("invalid use of end"); + + if (indexed_object->isobject ()) + { + octave_value_list args; + + args(2) = num_indices; + args(1) = index_position + 1; + args(0) = *indexed_object; + + std::string class_name = indexed_object->class_name (); + + octave::symbol_table& symtab = interp.get_symbol_table (); + + octave_value meth = symtab.find_method ("end", class_name); + + if (meth.is_defined ()) + return octave::feval (meth.function_value (), args, 1); + } + + dim_vector dv = indexed_object->dims (); + int ndims = dv.ndims (); + + if (num_indices < ndims) + { + for (int i = num_indices; i < ndims; i++) + dv(num_indices-1) *= dv(i); + + if (num_indices == 1) + { + ndims = 2; + dv.resize (ndims); + dv(1) = 1; + } + else + { + ndims = num_indices; + dv.resize (ndims); + } + } + + if (index_position < ndims) + retval = dv(index_position); + else + retval = 1; + + return retval; +} + +namespace octave +{ + octave_value_list + tree_evaluator::convert_to_const_vector (tree_argument_list *arg_list, + const octave_value *object) + { + // END doesn't make sense as a direct argument for a function (i.e., + // "fcn (end)" is invalid but "fcn (array (end))" is OK). Maybe we + // need a different way of asking an octave_value object this + // question? + + bool stash_object = (arg_list->includes_magic_end () + && object + && ! (object->is_function () + || object->is_function_handle ())); + + unwind_protect frame; + + if (stash_object) + { + frame.protect_var (m_indexed_object); + + m_indexed_object = object; + } + + int len = arg_list->length (); + + std::list<octave_value_list> args; + + auto p = arg_list->begin (); + for (int k = 0; k < len; k++) + { + if (stash_object) + { + frame.protect_var (m_index_position); + frame.protect_var (m_num_indices); + + m_index_position = k; + m_num_indices = len; + } + + tree_expression *elt = *p++; + + if (elt) + { + octave_value tmp = evaluate (elt); + + if (tmp.is_cs_list ()) + args.push_back (tmp.list_value ()); + else if (tmp.is_defined ()) + args.push_back (tmp); + } + else + { + args.push_back (octave_value ()); + break; + } + } + + return args; + } octave_value_list tree_evaluator::convert_return_list_to_const_vector @@ -1315,7 +1463,7 @@ &value_stack<const std::list<octave_lvalue>*>::pop); string_vector anm = *p_arg_nm; - first_args = al->convert_to_const_vector (this); + first_args = convert_to_const_vector (al); first_args.stash_name_tags (anm); } @@ -1769,7 +1917,7 @@ for (tree_argument_list *elt : expr) { - octave_value_list row = elt->convert_to_const_vector (this); + octave_value_list row = convert_to_const_vector (elt); if (nr == 1) // Optimize the single row case. @@ -2917,7 +3065,7 @@ && object->is_undefined ()) err_invalid_inquiry_subscript (); - retval = args->convert_to_const_vector (this, object); + retval = convert_to_const_vector (args, object); } octave_idx_type n = retval.length ();
--- a/libinterp/parse-tree/pt-eval.h Tue May 15 15:34:09 2018 -0400 +++ b/libinterp/parse-tree/pt-eval.h Tue May 15 17:05:47 2018 -0400 @@ -134,7 +134,8 @@ m_silent_functions (false), m_string_fill_char (' '), m_PS4 ("+ "), m_dbstep_flag (0), m_echo (ECHO_OFF), m_echo_state (false), m_echo_file_name (), m_echo_file_pos (1), - m_echo_files (), m_in_loop_command (false) + m_echo_files (), m_in_loop_command (false), + m_indexed_object (nullptr), m_index_position (0), m_num_indices (0) { } // No copying! @@ -359,6 +360,10 @@ void undefine_parameter_list (tree_parameter_list *param_list); octave_value_list + convert_to_const_vector (tree_argument_list *arg_list, + const octave_value *object = nullptr); + + octave_value_list convert_return_list_to_const_vector (tree_parameter_list *ret_list, int nargout, const Cell& varargout); @@ -423,6 +428,15 @@ return val; } + const octave_value * indexed_object (void) const + { + return m_indexed_object; + } + + int index_position (void) const { return m_index_position; } + + int num_indices (void) const { return m_num_indices; } + octave_value echo (const octave_value_list& args, int nargout); int echo (void) const { return m_echo; } @@ -545,6 +559,11 @@ // TRUE means we are evaluating some kind of looping construct. bool m_in_loop_command; + + // Used by END function. + const octave_value *m_indexed_object; + int m_index_position; + int m_num_indices; }; }
--- a/libinterp/parse-tree/pt-idx.cc Tue May 15 15:34:09 2018 -0400 +++ b/libinterp/parse-tree/pt-idx.cc Tue May 15 17:05:47 2018 -0400 @@ -158,7 +158,7 @@ && object->is_undefined ()) err_invalid_inquiry_subscript (); - retval = m_args->convert_to_const_vector (tw, object); + retval = tw->convert_to_const_vector (m_args, object); } octave_idx_type n = retval.length ();