GNU Octave  4.4.1
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
pt-arg-list.cc
Go to the documentation of this file.
1 /*
2 
3 Copyright (C) 1996-2018 John W. Eaton
4 
5 This file is part of Octave.
6 
7 Octave is free software: you can redistribute it and/or modify it
8 under the terms of the GNU General Public License as published by
9 the Free Software Foundation, either version 3 of the License, or
10 (at your option) any later version.
11 
12 Octave is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16 
17 You should have received a copy of the GNU General Public License
18 along with Octave; see the file COPYING. If not, see
19 <https://www.gnu.org/licenses/>.
20 
21 */
22 
23 #if defined (HAVE_CONFIG_H)
24 # include "config.h"
25 #endif
26 
27 #include <iostream>
28 #include <string>
29 
30 #include "str-vec.h"
31 
32 #include "defun.h"
33 #include "error.h"
34 #include "ovl.h"
35 #include "ov.h"
36 #include "ov-usr-fcn.h"
37 #include "parse.h"
38 #include "pt-arg-list.h"
39 #include "pt-eval.h"
40 #include "pt-exp.h"
41 #include "pt-id.h"
42 #include "pt-idx.h"
43 #include "pt-pr-code.h"
44 #include "pt-walk.h"
45 #include "interpreter.h"
46 #include "unwind-prot.h"
47 
48 namespace octave
49 {
50  // Argument lists.
51 
53  {
54  while (! empty ())
55  {
56  iterator p = begin ();
57  delete *p;
58  erase (p);
59  }
60  }
61 
62  bool
64  {
65  for (const tree_expression *elt : *this)
66  {
67  if (elt && ! elt->is_index_expression () && elt->has_magic_end ())
68  return true;
69  }
70 
71  return false;
72  }
73 
74  void
76  {
78 
79  if (! m_list_includes_magic_end && s && s->has_magic_end ())
81 
82  if (! m_list_includes_magic_tilde && s && s->is_identifier ())
83  {
84  tree_identifier *id = dynamic_cast<tree_identifier *> (s);
85  m_list_includes_magic_tilde = id && id->is_black_hole ();
86  }
87  }
88 
89  bool
91  {
92  for (const tree_expression *elt : *this)
93  {
94  if (! elt->is_constant ())
95  return false;
96  }
97 
98  return true;
99  }
100 
101  bool
103  {
104  bool retval = true;
105 
106  for (const tree_expression *elt : *this)
107  {
108  // There is no need for a separate check for the magic "~" because it
109  // is represented by tree_black_hole, and that is derived from
110  // tree_identifier.
111  if (! (elt->is_identifier () || elt->is_index_expression ()))
112  {
113  retval = false;
114  break;
115  }
116  }
117 
118  return retval;
119  }
120 }
121 
122 // FIXME: Is there a way to do this job without global data?
123 
124 static const octave_value *indexed_object = nullptr;
125 static int index_position = 0;
126 static int num_indices = 0;
127 
128 // END is documented in op-kw-docs.
129 DEFCONSTMETHOD (end, interp, , ,
130  doc: /* -*- texinfo -*-
131 @deftypefn {} {} end
132 Last element of an array or the end of any @code{for}, @code{parfor},
133 @code{if}, @code{do}, @code{while}, @code{function}, @code{switch},
134 @code{try}, or @code{unwind_protect} block.
135 
136 As an index of an array, the magic index @qcode{"end"} refers to the
137 last valid entry in an indexing operation.
138 
139 Example:
140 
141 @example
142 @group
143 @var{x} = [ 1 2 3; 4 5 6 ];
144 @var{x}(1,end)
145  @result{} 3
146 @var{x}(end,1)
147  @result{} 4
148 @var{x}(end,end)
149  @result{} 6
150 @end group
151 @end example
152 @seealso{for, parfor, if, do, while, function, switch, try, unwind_protect}
153 @end deftypefn */)
154 {
156 
157  if (! indexed_object)
158  error ("invalid use of end");
159 
160  if (indexed_object->isobject ())
161  {
162  octave_value_list args;
163 
164  args(2) = num_indices;
165  args(1) = index_position + 1;
166  args(0) = *indexed_object;
167 
168  std::string class_name = indexed_object->class_name ();
169 
170  octave::symbol_table& symtab = interp.get_symbol_table ();
171 
172  octave_value meth = symtab.find_method ("end", class_name);
173 
174  if (meth.is_defined ())
175  return octave::feval (meth.function_value (), args, 1);
176  }
177 
179  int ndims = dv.ndims ();
180 
181  if (num_indices < ndims)
182  {
183  for (int i = num_indices; i < ndims; i++)
184  dv(num_indices-1) *= dv(i);
185 
186  if (num_indices == 1)
187  {
188  ndims = 2;
189  dv.resize (ndims);
190  dv(1) = 1;
191  }
192  else
193  {
194  ndims = num_indices;
195  dv.resize (ndims);
196  }
197  }
198 
199  if (index_position < ndims)
201  else
202  retval = 1;
203 
204  return retval;
205 }
206 
207 namespace octave
208 {
211  const octave_value *object)
212  {
213  // END doesn't make sense for functions. Maybe we need a different
214  // way of asking an octave_value object this question?
215 
216  bool stash_object = (m_list_includes_magic_end
217  && object
218  && ! (object->is_function ()
219  || object->is_function_handle ()));
220 
221  unwind_protect frame;
222 
223  if (stash_object)
224  {
226 
228  }
229 
230  int len = length ();
231 
232  std::list<octave_value_list> args;
233 
234  iterator p = begin ();
235  for (int k = 0; k < len; k++)
236  {
237  if (stash_object)
238  {
241 
242  index_position = k;
243  num_indices = len;
244  }
245 
246  tree_expression *elt = *p++;
247 
248  if (elt)
249  {
250  octave_value tmp = tw->evaluate (elt);
251 
252  if (tmp.is_cs_list ())
253  args.push_back (tmp.list_value ());
254  else if (tmp.is_defined ())
255  args.push_back (tmp);
256  }
257  else
258  {
259  args.push_back (octave_value ());
260  break;
261  }
262  }
263 
264  return args;
265  }
266 
269  {
270  int len = length ();
271 
272  string_vector retval (len);
273 
274  int k = 0;
275 
276  for (tree_expression *elt : *this)
277  retval(k++) = elt->str_print_code ();
278 
279  return retval;
280  }
281 
282  std::list<std::string>
284  {
285  std::list<std::string> retval;
286 
287  for (tree_expression *elt : *this)
288  {
289  if (elt->is_identifier ())
290  {
291  tree_identifier *id = dynamic_cast<tree_identifier *> (elt);
292 
293  retval.push_back (id->name ());
294  }
295  else if (elt->is_index_expression ())
296  {
297  tree_index_expression *idx_expr
298  = dynamic_cast<tree_index_expression *> (elt);
299 
300  retval.push_back (idx_expr->name ());
301  }
302  }
303 
304  return retval;
305  }
306 
307  tree_argument_list *
308  tree_argument_list::dup (symbol_scope& scope) const
309  {
310  tree_argument_list *new_list = new tree_argument_list ();
311 
312  new_list->m_list_includes_magic_end = m_list_includes_magic_end;
313  new_list->m_simple_assign_lhs = m_simple_assign_lhs;
314 
315  for (const tree_expression *elt : *this)
316  new_list->append (elt ? elt->dup (scope) : nullptr);
317 
318  return new_list;
319  }
320 }
uint32_t id
Definition: graphics.cc:12193
OCTINTERP_API octave_value_list feval(const std::string &name, const octave_value_list &args=octave_value_list(), int nargout=0)
static int num_indices
Definition: pt-arg-list.cc:126
virtual bool has_magic_end(void) const =0
for large enough k
Definition: lu.cc:617
void resize(int n, int fill_value=0)
Definition: dim-vector.h:310
void error(const char *fmt,...)
Definition: error.cc:578
std::list< tree_expression * >::iterator iterator
Definition: base-list.h:40
bool is_defined(void) const
Definition: ov.h:523
tree_argument_list * dup(symbol_scope &scope) const
static int index_position
Definition: pt-arg-list.cc:125
iterator erase(iterator pos)
Definition: base-list.h:52
bool all_elements_are_constant(void) const
Definition: pt-arg-list.cc:90
#define DEFCONSTMETHOD(name, interp_name, args_name, nargout_name, doc)
Macro to define a builtin method that cannot be hidden by a variable.
Definition: defun.h:199
s
Definition: file-io.cc:2729
bool isobject(void) const
Definition: ov.h:608
create a structure array and initialize its values The dimensions of each cell array of values must match Singleton cells and non cell values are repeated so that they fill the entire array If the cells are create an empty structure array with the specified field names If the argument is an object
Definition: ov-struct.cc:1736
virtual bool is_index_expression(void) const
Definition: pt-exp.h:71
string_vector get_arg_names(void) const
dim_vector dims(void) const
Definition: ov.h:469
double tmp
Definition: data.cc:6252
octave_value retval
Definition: data.cc:6246
octave_function * function_value(bool silent=false) const
std::string class_name(void) const
Definition: ov.h:1291
octave_value find_method(const std::string &name, const std::string &dispatch_type)
Definition: symtab.h:200
virtual bool is_constant(void) const
Definition: pt-exp.h:63
std::list< std::string > variable_names(void) const
virtual bool is_identifier(void) const
Definition: pt-exp.h:69
octave::unwind_protect frame
Definition: graphics.cc:12190
static const octave_value * indexed_object
Definition: pt-arg-list.cc:124
void append(const element_type &s)
Definition: pt-arg-list.cc:75
p
Definition: lu.cc:138
for i
Definition: data.cc:5264
octave_value_list convert_to_const_vector(tree_evaluator *tw, const octave_value *object=nullptr)
bool has_magic_end(void) const
Definition: pt-arg-list.cc:63
octave_idx_type ndims(void) const
Number of dimensions.
Definition: dim-vector.h:295
void append(const elt_type &s)
Definition: base-list.h:110
Vector representing the dimensions (size) of an Array.
Definition: dim-vector.h:87
bool is_valid_lvalue_list(void) const
Definition: pt-arg-list.cc:102
If this string is the system will ring the terminal sometimes it is useful to be able to print the original representation of the string
Definition: utils.cc:888
dim_vector dv
Definition: sub2ind.cc:263