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-idx.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 "Cell.h"
28 #include "error.h"
29 #include "oct-map.h"
30 #include "oct-obj.h"
31 #include "oct-lvalue.h"
32 #include "ov.h"
33 #include "pager.h"
34 #include "pt-arg-list.h"
35 #include "pt-bp.h"
36 #include "pt-id.h"
37 #include "pt-idx.h"
38 #include "pt-walk.h"
39 #include "utils.h"
40 #include "variables.h"
41 #include "gripes.h"
42 
43 // Index expressions.
44 
46  : tree_expression (l, c), expr (0), args (0), type (),
47  arg_nm (), dyn_field () { }
48 
50  tree_argument_list *lst,
51  int l, int c, char t)
52  : tree_expression (l, c), expr (e), args (0), type (),
53  arg_nm (), dyn_field ()
54 {
55  append (lst, t);
56 }
57 
59  const std::string& n,
60  int l, int c)
61  : tree_expression (l, c), expr (e), args (0), type (),
62  arg_nm (), dyn_field ()
63 {
64  append (n);
65 }
66 
68  tree_expression *df,
69  int l, int c)
70  : tree_expression (l, c), expr (e), args (0), type (),
71  arg_nm (), dyn_field ()
72 {
73  append (df);
74 }
75 
76 void
78 {
79  args.push_back (lst);
80  type.append (1, t);
81  arg_nm.push_back (lst ? lst->get_arg_names () : string_vector ());
82  dyn_field.push_back (static_cast<tree_expression *> (0));
83 
84  if (lst && lst->has_magic_tilde ())
85  error ("invalid use of empty argument (~) in index expression");
86 }
87 
88 void
89 tree_index_expression::append (const std::string& n)
90 {
91  args.push_back (static_cast<tree_argument_list *> (0));
92  type.append (".");
93  arg_nm.push_back (n);
94  dyn_field.push_back (static_cast<tree_expression *> (0));
95 }
96 
97 void
99 {
100  args.push_back (static_cast<tree_argument_list *> (0));
101  type.append (".");
102  arg_nm.push_back ("");
103  dyn_field.push_back (df);
104 }
105 
107 {
108  delete expr;
109 
110  while (! args.empty ())
111  {
112  std::list<tree_argument_list *>::iterator p = args.begin ();
113  delete *p;
114  args.erase (p);
115  }
116 
117  while (! dyn_field.empty ())
118  {
119  std::list<tree_expression *>::iterator p = dyn_field.begin ();
120  delete *p;
121  dyn_field.erase (p);
122  }
123 }
124 
125 bool
127 {
128  for (std::list<tree_argument_list *>::const_iterator p = args.begin ();
129  p != args.end ();
130  p++)
131  {
132  tree_argument_list *elt = *p;
133 
134  if (elt && elt->has_magic_end ())
135  return true;
136  }
137 
138  return false;
139 }
140 
141 // This is useful for printing the name of the variable in an indexed
142 // assignment.
143 
144 std::string
146 {
147  return expr->name ();
148 }
149 
150 static Cell
152 {
153  Cell retval;
154 
155  octave_value_list arg_values;
156 
157  if (args)
158  arg_values = args->convert_to_const_vector ();
159 
160  if (! error_state)
161  {
162  int n = arg_values.length ();
163 
164  if (n > 0)
165  {
166  arg_values.stash_name_tags (arg_nm);
167 
168  retval.resize (dim_vector (1, n));
169 
170  for (int i = 0; i < n; i++)
171  retval(0,i) = arg_values(i);
172  }
173  }
174 
175  return retval;
176 }
177 
178 static inline octave_value_list
180  const octave_value *object, bool rvalue = true)
181 {
182  octave_value_list retval;
183 
184  if (args)
185  {
186  if (rvalue && object && args->has_magic_end () && object->is_undefined ())
188  else
189  retval = args->convert_to_const_vector (object);
190  }
191 
192  if (! error_state)
193  {
194  octave_idx_type n = retval.length ();
195 
196  if (n > 0)
197  retval.stash_name_tags (arg_nm);
198  }
199 
200  return retval;
201 }
202 
203 std::string
205  (std::list<string_vector>::const_iterator p_arg_nm,
206  std::list<tree_expression *>::const_iterator p_dyn_field) const
207 {
208  std::string fn = (*p_arg_nm)(0);
209 
210  if (fn.empty ())
211  {
212  tree_expression *df = *p_dyn_field;
213 
214  if (df)
215  {
216  octave_value t = df->rvalue1 ();
217 
218  if (! error_state)
219  {
220  if (t.is_string () && t.rows () == 1)
221  fn = t.string_value ();
222  else
223  error ("dynamic structure field names must be character strings");
224  }
225  }
226  else
227  panic_impossible ();
228  }
229 
230  return fn;
231 }
232 
235 {
236  int n = args.size ();
237 
238  Cell type_field (n, 1);
239  Cell subs_field (n, 1);
240 
241  std::list<tree_argument_list *>::const_iterator p_args = args.begin ();
242  std::list<string_vector>::const_iterator p_arg_nm = arg_nm.begin ();
243  std::list<tree_expression *>::const_iterator p_dyn_field = dyn_field.begin ();
244 
245  octave_map m;
246 
247  for (int i = 0; i < n; i++)
248  {
249  switch (type[i])
250  {
251  case '(':
252  subs_field(i) = make_subs_cell (*p_args, *p_arg_nm);
253  break;
254 
255  case '{':
256  subs_field(i) = make_subs_cell (*p_args, *p_arg_nm);
257  break;
258 
259  case '.':
260  subs_field(i) = get_struct_index (p_arg_nm, p_dyn_field);
261  break;
262 
263  default:
264  panic_impossible ();
265  }
266 
267  if (error_state)
268  return m;
269 
270  p_args++;
271  p_arg_nm++;
272  p_dyn_field++;
273  }
274 
275  m.assign ("type", type_field);
276  m.assign ("subs", subs_field);
277 
278  return m;
279 }
280 
283 {
284  return tree_index_expression::rvalue (nargout, 0);
285 }
286 
289  const std::list<octave_lvalue> *lvalue_list)
290 {
291  octave_value_list retval;
292 
293  if (error_state)
294  return retval;
295 
296  octave_value first_expr_val;
297 
298  octave_value_list first_args;
299 
300  bool have_args = false;
301 
302  if (expr->is_identifier () && type[0] == '(')
303  {
304  tree_identifier *id = dynamic_cast<tree_identifier *> (expr);
305 
306  if (! (id->is_variable () || args.empty ()))
307  {
308  tree_argument_list *al = *(args.begin ());
309 
310  size_t n = al ? al->length () : 0;
311 
312  if (n > 0)
313  {
314  string_vector anm = *(arg_nm.begin ());
315  have_args = true;
316  first_args = al -> convert_to_const_vector ();
317  first_args.stash_name_tags (anm);
318 
319  if (! error_state)
320  first_expr_val = id->do_lookup (first_args);
321  }
322  }
323  }
324 
325  if (! error_state)
326  {
327  if (first_expr_val.is_undefined ())
328  first_expr_val = expr->rvalue1 ();
329 
330  octave_value tmp = first_expr_val;
331  octave_idx_type tmpi = 0;
332 
333  std::list<octave_value_list> idx;
334 
335  int n = args.size ();
336 
337  std::list<tree_argument_list *>::iterator p_args = args.begin ();
338  std::list<string_vector>::iterator p_arg_nm = arg_nm.begin ();
339  std::list<tree_expression *>::iterator p_dyn_field = dyn_field.begin ();
340 
341  for (int i = 0; i < n; i++)
342  {
343  if (i > 0)
344  {
345  tree_argument_list *al = *p_args;
346 
347  // In Matlab, () can only be followed by . In Octave, we do not
348  // enforce this for rvalue expressions, but we'll split the
349  // evaluation at this point. This will, hopefully, allow Octave's
350  // looser rules apply smoothly for Matlab overloaded subsref
351  // codes.
352  bool force_split = type[i-1] == '(' && type[i] != '.';
353 
354  if (force_split || (al && al->has_magic_end ()))
355  {
356  // We have an expression like
357  //
358  // x{end}.a(end)
359  //
360  // and we are looking at the argument list that
361  // contains the second (or third, etc.) "end" token,
362  // so we must evaluate everything up to the point of
363  // that argument list so we can pass the appropriate
364  // value to the built-in end function.
365 
366  const octave_value_list tmp_list
367  = tmp.subsref (type.substr (tmpi, i - tmpi), idx, nargout);
368 
369  tmp = tmp_list.length () ? tmp_list(0) : octave_value ();
370  tmpi = i;
371  idx.clear ();
372 
373  if (tmp.is_cs_list ())
375 
376  if (error_state)
377  break;
378  }
379  }
380 
381  switch (type[i])
382  {
383  case '(':
384  if (have_args)
385  {
386  idx.push_back (first_args);
387  have_args = false;
388  }
389  else
390  idx.push_back (make_value_list (*p_args, *p_arg_nm, &tmp));
391  break;
392 
393  case '{':
394  idx.push_back (make_value_list (*p_args, *p_arg_nm, &tmp));
395  break;
396 
397  case '.':
398  idx.push_back (octave_value (get_struct_index (p_arg_nm,
399  p_dyn_field)));
400  break;
401 
402  default:
403  panic_impossible ();
404  }
405 
406  if (error_state)
407  break;
408 
409  p_args++;
410  p_arg_nm++;
411  p_dyn_field++;
412  }
413 
414  if (! error_state)
415  retval = tmp.subsref (type.substr (tmpi, n - tmpi), idx, nargout,
416  lvalue_list);
417  }
418 
419  return retval;
420 }
421 
424 {
425  octave_value retval;
426 
427  const octave_value_list tmp = rvalue (nargout);
428 
429  if (! tmp.empty ())
430  retval = tmp(0);
431 
432  return retval;
433 }
434 
437 {
438  octave_lvalue retval;
439 
440  std::list<octave_value_list> idx;
441  std::string tmp_type;
442 
443  int n = args.size ();
444 
445  std::list<tree_argument_list *>::iterator p_args = args.begin ();
446  std::list<string_vector>::iterator p_arg_nm = arg_nm.begin ();
447  std::list<tree_expression *>::iterator p_dyn_field = dyn_field.begin ();
448 
449  retval = expr->lvalue ();
450 
451  if (! error_state)
452  {
453  octave_value tmp = retval.value ();
454 
455  octave_idx_type tmpi = 0;
456  std::list<octave_value_list> tmpidx;
457 
458  for (int i = 0; i < n; i++)
459  {
460  if (retval.numel () != 1)
462  else if (tmpi < i)
463  {
464  tmp = tmp.subsref (type.substr (tmpi, i - tmpi), tmpidx, true);
465  tmpidx.clear ();
466  }
467 
468  if (error_state)
469  break;
470 
471  switch (type[i])
472  {
473  case '(':
474  {
475  octave_value_list tidx
476  = make_value_list (*p_args, *p_arg_nm, &tmp, false);
477 
478  idx.push_back (tidx);
479 
480  if (i < n - 1)
481  {
482  if (type[i+1] == '.')
483  {
484  tmpidx.push_back (tidx);
485  tmpi = i+1;
486  }
487  else
488  error ("() must be followed by . or close the index chain");
489  }
490  }
491  break;
492 
493  case '{':
494  {
495  octave_value_list tidx
496  = make_value_list (*p_args, *p_arg_nm, &tmp, false);
497 
498  if (tmp.is_undefined ())
499  {
500  if (tidx.has_magic_colon ())
502  else
503  tmp = Cell ();
504  }
505  else if (tmp.is_zero_by_zero ()
506  && (tmp.is_matrix_type () || tmp.is_string ()))
507  {
508  tmp = Cell ();
509  }
510 
511  retval.numel (tmp.numel (tidx));
512 
513  if (error_state)
514  break;
515 
516  idx.push_back (tidx);
517  tmpidx.push_back (tidx);
518  tmpi = i;
519  }
520  break;
521 
522  case '.':
523  {
524  octave_value tidx = get_struct_index (p_arg_nm, p_dyn_field);
525  if (error_state)
526  break;
527 
528  bool autoconv = (tmp.is_zero_by_zero ()
529  && (tmp.is_matrix_type () || tmp.is_string ()
530  || tmp.is_cell ()));
531 
532  if (i > 0 && type[i-1] == '(')
533  {
534  octave_value_list pidx = idx.back ();
535 
536  // Use octave_map, not octave_scalar_map so that the
537  // dimensions are 0x0, not 1x1.
538  if (tmp.is_undefined ())
539  {
540  if (pidx.has_magic_colon ())
542  else
543  tmp = octave_map ();
544  }
545  else if (autoconv)
546  tmp = octave_map ();
547 
548  retval.numel (tmp.numel (pidx));
549 
550  tmpi = i-1;
551  tmpidx.push_back (tidx);
552  }
553  else
554  {
555  if (tmp.is_undefined () || autoconv)
556  {
557  tmpi = i+1;
558  tmp = octave_value ();
559  }
560  else
561  {
562  retval.numel (tmp.numel (octave_value_list ()));
563 
564  tmpi = i;
565  tmpidx.push_back (tidx);
566  }
567  }
568 
569  if (error_state)
570  break;
571 
572  idx.push_back (tidx);
573  }
574  break;
575 
576  default:
577  panic_impossible ();
578  }
579 
580  if (idx.back ().empty ())
581  error ("invalid empty index list");
582 
583  if (error_state)
584  break;
585 
586  p_args++;
587  p_arg_nm++;
588  p_dyn_field++;
589  }
590 
591  if (! error_state)
592  retval.set_index (type, idx);
593 
594  }
595 
596  return retval;
597 }
598 
599 /*
600 %!test
601 %! clear x;
602 %! clear y;
603 %! y = 3;
604 %! x(y(end)) = 1;
605 %! assert (x, [0, 0, 1]);
606 %! clear x;
607 %! clear y;
608 %! y = {3};
609 %! x(y{end}) = 1;
610 %! assert (x, [0, 0, 1]);
611 
612 %!test
613 %! x = {1, 2, 3};
614 %! [x{:}] = deal (4, 5, 6);
615 %! assert (x, {4, 5, 6});
616 
617 %!test
618 %! [x.a, x.b.c] = deal (1, 2);
619 %! assert (x.a == 1 && x.b.c == 2);
620 
621 %!test
622 %! [x.a, x(2).b] = deal (1, 2);
623 %! assert (x(1).a == 1 && isempty (x(2).a) && isempty (x(1).b) && x(2).b == 2);
624 
625 %!test
626 %! x = struct (zeros (0, 1), {"a", "b"});
627 %! x(2).b = 1;
628 %! assert (x(2).b == 1);
629 
630 %!test
631 %! x = struct (zeros (0, 1), {"a", "b"});
632 %! x(2).b = 1;
633 %! assert (x(2).b == 1);
634 */
635 
639 {
640  tree_index_expression *new_idx_expr
641  = new tree_index_expression (line (), column ());
642 
643  new_idx_expr->expr = expr ? expr->dup (scope, context) : 0;
644 
645  std::list<tree_argument_list *> new_args;
646 
647  for (std::list<tree_argument_list *>::const_iterator p = args.begin ();
648  p != args.end ();
649  p++)
650  {
651  const tree_argument_list *elt = *p;
652 
653  new_args.push_back (elt ? elt->dup (scope, context) : 0);
654  }
655 
656  new_idx_expr->args = new_args;
657 
658  new_idx_expr->type = type;
659 
660  new_idx_expr->arg_nm = arg_nm;
661 
662  std::list<tree_expression *> new_dyn_field;
663 
664  for (std::list<tree_expression *>::const_iterator p = dyn_field.begin ();
665  p != dyn_field.end ();
666  p++)
667  {
668  const tree_expression *elt = *p;
669 
670  new_dyn_field.push_back (elt ? elt->dup (scope, context) : 0);
671  }
672 
673  new_idx_expr->dyn_field = new_dyn_field;
674 
675  new_idx_expr->copy_base (*this);
676 
677  return new_idx_expr;
678 }
679 
680 void
682 {
683  tw.visit_index_expression (*this);
684 }