GNU Octave  3.8.0
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
pt-arg-list.cc
Go to the documentation of this file.
1 /*
2 
3 Copyright (C) 1996-2013 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 the
9 Free Software Foundation; either version 3 of the License, or (at your
10 option) any later version.
11 
12 Octave is distributed in the hope that it will be useful, but WITHOUT
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 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 <http://www.gnu.org/licenses/>.
20 
21 */
22 
23 #ifdef 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 "oct-lvalue.h"
35 #include "oct-obj.h"
36 #include "ov.h"
37 #include "ov-usr-fcn.h"
38 #include "parse.h"
39 #include "pt-arg-list.h"
40 #include "pt-exp.h"
41 #include "pt-id.h"
42 #include "pt-pr-code.h"
43 #include "pt-walk.h"
44 #include "toplev.h"
45 #include "unwind-prot.h"
46 
47 // Argument lists.
48 
50 {
51  while (! empty ())
52  {
53  iterator p = begin ();
54  delete *p;
55  erase (p);
56  }
57 }
58 
59 bool
61 {
62  for (const_iterator p = begin (); p != end (); p++)
63  {
64  tree_expression *elt = *p;
65 
66  if (elt && elt->has_magic_end ())
67  return true;
68  }
69 
70  return false;
71 }
72 
73 void
75 {
77 
78  if (! list_includes_magic_end && s && s->has_magic_end ())
80 
81  if (! list_includes_magic_tilde && s && s->is_identifier ())
82  {
83  tree_identifier *id = dynamic_cast<tree_identifier *> (s);
84  list_includes_magic_tilde = id && id->is_black_hole ();
85  }
86 }
87 
88 bool
90 {
91  for (const_iterator p = begin (); p != end (); p++)
92  {
93  tree_expression *elt = *p;
94 
95  if (! elt->is_constant ())
96  return false;
97  }
98 
99  return true;
100 }
101 
102 bool
104 {
105  bool retval = true;
106 
107  for (const_iterator p = begin (); p != end (); p++)
108  {
109  tree_expression *elt = *p;
110 
111  // There is no need for a separate check for the magic "~" because
112  // it represented by tree_black_hole, and that is derived from
113  // tree_identifier.
114 
115  if (! (elt->is_identifier () || elt->is_index_expression ()))
116  {
117  retval = false;
118  break;
119  }
120  }
121 
122  return retval;
123 }
124 
125 static const octave_value *indexed_object = 0;
126 static int index_position = 0;
127 static int num_indices = 0;
128 
129 DEFCONSTFUN (end, , ,
130  "-*- texinfo -*-\n\
131 @deftypefn {Built-in Function} {} end\n\
132 The magic index @qcode{\"end\"} refers to the last valid entry in an indexing\n\
133 operation.\n\
134 \n\
135 Example:\n\
136 \n\
137 @example\n\
138 @group\n\
139 @var{x} = [ 1 2 3 \n\
140  4 5 6 ];\n\
141 @var{x}(1,end)\n\
142  @result{} 3\n\
143 @var{x}(end,1)\n\
144  @result{} 4\n\
145 @var{x}(end,end)\n\
146  @result{} 6\n\
147 @end group\n\
148 @end example\n\
149 @end deftypefn")
150 {
151  octave_value retval;
152 
153  if (indexed_object)
154  {
155  if (indexed_object->is_object ())
156  {
157  octave_value_list args;
158 
159  args(2) = num_indices;
160  args(1) = index_position + 1;
161  args(0) = *indexed_object;
162 
163  std::string class_name = indexed_object->class_name ();
164 
165  octave_value meth = symbol_table::find_method ("end", class_name);
166 
167  if (meth.is_defined ())
168  return feval (meth.function_value (), args, 1);
169  }
170 
171  dim_vector dv = indexed_object->dims ();
172  int ndims = dv.length ();
173 
174  if (num_indices < ndims)
175  {
176  for (int i = num_indices; i < ndims; i++)
177  dv(num_indices-1) *= dv(i);
178 
179  if (num_indices == 1)
180  {
181  ndims = 2;
182  dv.resize (ndims);
183  dv(1) = 1;
184  }
185  else
186  {
187  ndims = num_indices;
188  dv.resize (ndims);
189  }
190  }
191 
192  if (index_position < ndims)
193  retval = dv(index_position);
194  else
195  retval = 1;
196  }
197  else
198  ::error ("invalid use of end");
199 
200  return retval;
201 }
202 
205 {
206  // END doesn't make sense for functions. Maybe we need a different
207  // way of asking an octave_value object this question?
208 
209  bool stash_object = (list_includes_magic_end
210  && object
211  && ! (object->is_function ()
212  || object->is_function_handle ()));
213 
214  unwind_protect frame;
215 
216  if (stash_object)
217  {
218  frame.protect_var (indexed_object);
219 
220  indexed_object = object;
221  }
222 
223  int len = length ();
224 
225  std::list<octave_value_list> args;
226 
227  iterator p = begin ();
228  for (int k = 0; k < len; k++)
229  {
230  if (stash_object)
231  {
232  frame.protect_var (index_position);
233  frame.protect_var (num_indices);
234 
235  index_position = k;
236  num_indices = len;
237  }
238 
239  tree_expression *elt = *p++;
240 
241  if (elt)
242  {
243  octave_value tmp = elt->rvalue1 ();
244 
245  if (error_state)
246  {
247  ::error ("evaluating argument list element number %d", k+1);
248  args.clear ();
249  break;
250  }
251  else
252  {
253  if (tmp.is_cs_list ())
254  args.push_back (tmp.list_value ());
255  else if (tmp.is_defined ())
256  args.push_back (tmp);
257  }
258  }
259  else
260  {
261  args.push_back (octave_value ());
262  break;
263  }
264  }
265 
266  return args;
267 }
268 
269 std::list<octave_lvalue>
271 {
272  std::list<octave_lvalue> retval;
273 
275  p != end ();
276  p++)
277  {
278  tree_expression *elt = *p;
279 
280  retval.push_back (elt->lvalue ());
281  }
282 
283  return retval;
284 }
285 
288 {
289  int len = length ();
290 
291  string_vector retval (len);
292 
293  int k = 0;
294 
295  for (const_iterator p = begin (); p != end (); p++)
296  {
297  tree_expression *elt = *p;
298 
299  retval(k++) = elt->str_print_code ();
300  }
301 
302  return retval;
303 }
304 
305 std::list<std::string>
307 {
308  std::list<std::string> retval;
309 
310  for (const_iterator p = begin (); p != end (); p++)
311  {
312  tree_expression *elt = *p;
313 
314  if (elt->is_identifier ())
315  {
316  tree_identifier *id = dynamic_cast<tree_identifier *> (elt);
317 
318  retval.push_back (id->name ());
319  }
320  else if (elt->is_index_expression ())
321  {
322  tree_index_expression *idx_expr
323  = dynamic_cast<tree_index_expression *> (elt);
324 
325  retval.push_back (idx_expr->name ());
326  }
327  }
328 
329  return retval;
330 }
331 
335 {
336  tree_argument_list *new_list = new tree_argument_list ();
337 
340 
341  for (const_iterator p = begin (); p != end (); p++)
342  {
343  const tree_expression *elt = *p;
344 
345  new_list->append (elt ? elt->dup (scope, context) : 0);
346  }
347 
348  return new_list;
349 }
350 
351 void
353 {
354  tw.visit_argument_list (*this);
355 }